Codebase list telepathy-rakia / c7d953c
Merge commit 'upstream/0.7.1' into debian Laurent Bigonville 13 years ago
24 changed file(s) with 1541 addition(s) and 156 deletion(s). Raw diff Collapse all Expand all
0 Mikhail Zabaluev <first.surname@nokia.com>
0 Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
11 Kai Vehmanen <first.surname@nokia.com>
22 Martti Mela <first.surname@nokia.com>
33 Simon McVittie <simon.mcvittie@collabora.co.uk>
44 Rob Taylor <rob.taylor@collabora.co.uk>
55 Senko Rasic <senko.rasic@collabora.co.uk>
6 Jonny Lamb <jonny.lamb@collabora.co.uk>
7 David Laban <david.laban@collabora.co.uk>
68
79 Authors for original telepathy-gabble code:
810 Robert McQueen <robert.mcqueen@collabora.co.uk>
0 commit b3d95a10e75eece58379c93308a88f58560a769e
1 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
2 Date: 2011-02-01 21:15:06 +0200
3
4 Version 0.7.1
5
6 commit 0ec7a23893b4c85a359f6349578ed34cf5e595ea
7 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
8 Date: 2011-02-01 21:34:26 +0200
9
10 voip_test is not a test script, move it to EXTRA_DIST
11
12 commit 1f51b77c6df5e5af0bd6aca31927e842a4d86b72
13 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
14 Date: 2011-02-01 21:28:35 +0200
15
16 Added voip_test to dist files
17
18 commit 95e060c7696c93d92b151651cff758015b5a9405
19 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
20 Date: 2011-02-01 21:14:07 +0200
21
22 Added Jonny Lamb and David Laban to the list of authors
23
24 commit e4006c401c93e57b337249fd8c2891bff32dc894
25 Author: David Laban <david.laban@collabora.co.uk>
26 Date: 2011-01-31 18:47:01 +0000
27
28 Add test for fd.o:33716
29
30 commit b47726b065fb5e054bc2ab096755c989d294a3c1
31 Author: David Laban <david.laban@collabora.co.uk>
32 Date: 2011-01-31 19:08:19 +0000
33
34 remove references to twisted.words.xish
35
36 commit e0b4d040e816d1918913bdebcdc156351a679476
37 Author: David Laban <david.laban@collabora.co.uk>
38 Date: 2011-01-31 19:00:38 +0000
39
40 Revert "Check for Python module twisted.words.xish as required for unit tests"
41
42 This reverts commit dfb7be1f4d652d48ac001f9e496abd97006c1ba3.
43
44 Sorry. That was sloppy of me. I don't actually use xpath.
45
46 commit dfb7be1f4d652d48ac001f9e496abd97006c1ba3
47 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
48 Date: 2011-01-31 20:46:33 +0200
49
50 Check for Python module twisted.words.xish as required for unit tests
51
52 commit df7937078faa3211a8eaae0342cd7bf297b4fc20
53 Merge: 776194c f69dc4b
54 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
55 Date: 2011-01-31 20:37:37 +0200
56
57 Merge branch 'invite-from-self'
58
59 commit 776194c93cc447aede374f011dff5b1d49b2b0ed
60 Merge: abcfb59 2cf3c1e
61 Author: David Laban <david.laban@collabora.co.uk>
62 Date: 2011-01-31 18:23:54 +0000
63
64 Merge remote branch 'alsuren/streamedmedia_tests'
65
66 Reviewed-by: Will Thompson <will.thompson@collabora.co.uk>
67
68 commit f69dc4be0e713eef64ecb65c84ded2fa357b39b9
69 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
70 Date: 2011-01-31 19:46:47 +0200
71
72 Reject incoming calls from the same URI as the local user (fd.o #33716)
73
74 This is not supported in StreamedMedia channels, and an assertion
75 in tpsip_media_channel_receive_invite() sees to it.
76
77 commit c4cffddbaea180ba3fddebed81097c03e2cca959
78 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
79 Date: 2011-01-29 13:45:31 +0200
80
81 Nano version 0.6.5.1
82
83 commit a6c7d52dac100d5f9ea97c68e7197f6d41756435
84 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
85 Date: 2011-01-29 00:40:32 +0200
86
87 Version 0.6.5
88
89 commit abcfb59b2ae9613585515fd887f026591ffe77fd
90 Merge: 9eb2013 68b99ed
91 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
92 Date: 2011-01-28 21:18:51 +0200
93
94 Merge branch 'signed-param-fix'
95
96 commit 68b99ed09a29fa567d0a49789389ba8b545d0226
97 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
98 Date: 2011-01-28 20:36:42 +0200
99
100 Changed the size parameter type to signed in tpsip_unquote_string()
101
102 The special value of -1 implies that the type should be signed.
103
104 commit caf244b6d1b38cc42291ce0697374fae6f5a4148
105 Merge: 8932d71 09dd7ac
106 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
107 Date: 2011-01-28 20:54:36 +0200
108
109 Backported fixes to fd.o #31720 onto telepathy-sofiasip-0.6
110
111 commit 09dd7ac499d83eb40154c6415a77fa89cfaac880
112 Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
113 Date: 2010-11-18 13:46:18 +0000
114
115 fd.o #31720: use TpDBusDaemon to export media streams
116
117 commit 91e347eaf9e1a75b81943286c7308164663c9010
118 Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
119 Date: 2010-11-18 13:46:06 +0000
120
121 fd.o #31720: use TpDBusDaemon to export media sessions
122
123 commit 9486db40a0f0836b65d46ea925216126c6fe2709
124 Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
125 Date: 2010-11-18 13:45:40 +0000
126
127 Backported fix to fd.o #31720: use TpDBusDaemon to export channel objects
128
129 Backported to telepathy-sofiasip-0.6
130
131 commit 2cf3c1e745c27dd48d71b05e5daa68479333885b
132 Author: David Laban <david.laban@collabora.co.uk>
133 Date: 2011-01-26 17:12:09 +0000
134
135 Fix group flags for streamedmedia calls.
136
137 We start off with lots of flags, and then delete them as we work out what
138 kind of channel we are, rather than trying to track what we need to
139 add/remove over time. We should always have the right flags before we are
140 advertised on the bus.
141
142 Note that adding members to a channel made using Create isn't *strictly*
143 correct way to do it, but it isn't special-cased in any of the code, and
144 I don't want to set flags that are lies so I've just updated the tests
145 accordingly.
146
147 Also, converting the flags to their binary representation makes failed
148 assertions a lot easier to debug (and I honestly don't care about speed).
149
150 commit c10bee3f1c4f02f1ca758999ef420c21a4996443
151 Author: David Laban <david.laban@collabora.co.uk>
152 Date: 2011-01-26 15:35:03 +0000
153
154 sip-media-channel clean up group members
155
156 Use tp_intset_new_containing() wherever it's sensible
157 This makes sets with only one member simpler and less think-o prone.
158 (We still use tp_intset_new() for groups with more than one member)
159
160 Use better variable names for clarity.
161 (We still use "set" in priv_session_state_changed_cb() to avoid too much
162 code churn)
163
164 commit 630113129f088d29aa4be60bcfbe66a3cd564a55
165 Author: David Laban <david.laban@collabora.co.uk>
166 Date: 2011-01-26 14:20:17 +0000
167
168 voip tests: BYE message needs a reply. Add to tests.
169
170 commit e5bf266a20d817a22c70efc31fc5d34913c1f3df
171 Author: David Laban <david.laban@collabora.co.uk>
172 Date: 2011-01-26 14:09:47 +0000
173
174 Fix review comments for tests.
175
176 commit c40b48866b7bd04308b26725368304c555cc69fd
177 Author: David Laban <david.laban@collabora.co.uk>
178 Date: 2010-12-07 19:53:37 +0000
179
180 add new tests to make check
181
182 commit 3683f1b456ef9baa2fefc885fe1e458b769647bf
183 Author: David Laban <david.laban@collabora.co.uk>
184 Date: 2010-12-07 18:39:31 +0000
185
186 Fix up incoming-basics.py
187
188 * Same deal as outgoing-basics, but in one commit.
189 * Also, expect the NewChannels signal rather than NewChannel.
190 * Add context.send_message() and implement .incoming_call(), .ack() and
191 .terminate() based on it.
192 * FIXME #32189: group flags are borked.
193
194 commit 8f241d940ecfcc366ce3dedb5b077d73d379965c
195 Author: David Laban <david.laban@collabora.co.uk>
196 Date: 2010-12-07 18:09:33 +0000
197
198 Complete outgoing-basics.py
199
200 sofiatest.py:
201 * add sip headers to Events for convenience
202
203 voip_test.py:VoipTestContext:
204 * add {get, check}_call_sdp()
205 * add accept() (secretly also records call-id)
206
207 outgoing_basics.py:
208 * Call NativeCandidatesPrepared() because RAWUDP requires it.
209 * Expect sip-* events rather than stream-iq ones.
210
211 commit 744205d25b59848c56902a4fdfd7134d575f8794
212 Author: David Laban <david.laban@collabora.co.uk>
213 Date: 2010-12-07 17:45:57 +0000
214
215 Update the groups interface when remote user accepts the call.
216
217 commit 76cba776cacd54b3994a590e572b1a51c2217761
218 Author: David Laban <david.laban@collabora.co.uk>
219 Date: 2010-12-06 18:49:40 +0000
220
221 import incoming-basics from gabble
222
223 commit 364ff37b08cc76841312b04450cb8de9541f2ada
224 Author: David Laban <david.laban@collabora.co.uk>
225 Date: 2010-12-06 16:59:29 +0000
226
227 Don't call priv_outbound_call (self, 0)
228
229 This previously happened if the client requested an anonymous
230 streamedmedia channel, but doing so would cause a crash.
231
232 commit 1de34ce405c9df7ea0953604ebfa19fc04b92f9d
233 Author: David Laban <david.laban@collabora.co.uk>
234 Date: 2010-12-07 19:46:53 +0000
235
236 Make outgoing-basics test work up until the first network traffic event.
237
238 * Change from gabbletest to sofiatest, and import bits of gabble's
239 jingletest2.py as voip_test.py
240 * Get rid of JingleProtocol args to tests
241 * Change variable names s/stream/sip_proxy/ and s/jt2/context/
242 * Change jids to sip uris.
243 * Don't restrict ordering of NewStreamHandler signal emission, when
244 all sane StreamEngine implementations do state recovery anyway.
245 * Early-return before we expect any network traffic
246 * Channel.Type.Call is not a requestable type.
247 * change test_all_dialects back to exec_test calls.
248
249 Things I'm not sure about:
250 * FIXME: 32189: group flags are borked.
251 * Are sofiasip's pending send flags correct?
252
253 commit 85b5c6a95151c73fbd8a62fd541cadbbc81bf32a
254 Author: David Laban <david.laban@collabora.co.uk>
255 Date: 2010-12-03 18:54:36 +0000
256
257 implement tpsip_media_channel_get_handle() properly.
258
259 commit a9f18ec9ffe748c2078886cbc51c28babc3ce944
260 Author: David Laban <david.laban@collabora.co.uk>
261 Date: 2010-12-03 16:38:38 +0000
262
263 initial import of outgoing-basics.py from gabble
264
265 commit 63dc72f4e45d249dc7cbccf9e721dc3ec07e2dc1
266 Author: David Laban <david.laban@collabora.co.uk>
267 Date: 2010-12-07 19:34:56 +0000
268
269 Hacks to allow running multiple tests per process
270
271 * Pick a random port to create the server on each run (since
272 IListeningPort.stopListening() isn't guaranteed to have freed the port
273 by the time it returns)
274 * Don't install the colourer more than once
275 * Fix the colourer to deal with "took $seconds" misc.
276
277 We should probably try to consolidate these hacks with whatever gabbletest
278 does, or maybe try to push more stuff into servicetest to make it easier
279 to maintain, but let's wait until sofiasip has more tests before we start
280 doing that.
281
282 commit 9eb2013202cc29017c1925bd0e1d7c1906bf209b
283 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
284 Date: 2011-01-03 18:26:27 +0200
285
286 Added a NEWS item for the upcoming release with warning about legacy loggers
287
288 commit 79ff96db9d46dfe0c94442b954cf8b5c67b7df0b
289 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
290 Date: 2011-01-03 17:56:45 +0200
291
292 Test the message-sent timestamp header with a fixed value
293
294 commit 248b7a0c9b0efac2653c3e2659cbec1eda01d238
295 Merge: c89168e 6ef183a
296 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
297 Date: 2011-01-03 17:45:15 +0200
298
299 Merge branch 'master' into messages-retouch
300
301 commit 6ef183a45800b000fe1c402255e822963f90dc0c
302 Author: Jonny Lamb <jonny.lamb@collabora.co.uk>
303 Date: 2010-12-15 14:42:50 +0000
304
305 configure: increase version of tp-glib required
306
307 This is required for TpBaseProtocolClass->dup_authentication_types.
308
309 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
310
311 commit 96c98cfc3a7f59d0c04573098e498503b4ae4a47
312 Author: Jonny Lamb <jonny.lamb@collabora.co.uk>
313 Date: 2010-12-15 14:38:27 +0000
314
315 protocol: implement TpBaseProtocolClass->dup_authentication_types
316
317 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
318
319 commit fd3166fc69faa317c2d7d9f9770c6471d57e5a8d
320 Author: David Laban <david.laban@collabora.co.uk>
321 Date: 2010-12-13 20:34:52 +0000
322
323 test registering without a password
324
325 and using a sasl channel to request the password if the server challenges,
326 or not asking for a password if the server doesn't challenge.
327
328 commit d2a65899f22ea3d91d7c47793298c55082668be1
329 Author: David Laban <david.laban@collabora.co.uk>
330 Date: 2010-12-13 17:33:56 +0000
331
332 Don't ask the user for a password on connect
333
334 We don't need to do this until the server asks us to authenticate.
335
336 commit 75a2d3a792b54c328b809e1f260ad1e49632fb6e
337 Author: David Laban <david.laban@collabora.co.uk>
338 Date: 2010-12-13 17:13:01 +0000
339
340 Ask for a password in priv_handle_auth() if not given.
341
342 This requires a call to tp_simple_password_manager_prompt_async(), so
343 we create a data struct to help us split the function in half.
344
345 Also, we move all checks from the second half of the function into the
346 first, so they can be handled synchronously.
347
348 The diff is clearer if you use git diff --patience.
349
350 commit ef71b9dd869a46476fff2a49b942eb04d9928832
351 Author: Jonny Lamb <jonny.lamb@collabora.co.uk>
352 Date: 2010-12-07 16:52:04 +0000
353
354 configure: depend on new enough tp-glib for TpSimplePasswordManager
355
356 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
357
358 commit 04540e3ae94b618270bd3bb43b9ca6d75bf06ab8
359 Author: Jonny Lamb <jonny.lamb@collabora.co.uk>
360 Date: 2010-12-07 16:43:34 +0000
361
362 connection: only disconnect if we're not already disconnected
363
364 If we don't check this, tp-glib will give us a nice big fat warning.
365
366 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
367
368 commit 9b24bd79a3f9437ea406ef4c412ff5aae84da2ce
369 Author: Jonny Lamb <jonny.lamb@collabora.co.uk>
370 Date: 2010-11-25 11:52:31 +0000
371
372 connection: use disconnect_with_dbus_error
373
374 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
375
376 commit 7fd45d95dc7909585976670a77243a175d977734
377 Author: Jonny Lamb <jonny.lamb@collabora.co.uk>
378 Date: 2010-11-24 16:26:08 +0000
379
380 connection: use TpSimplePasswordManager to get a password if one was not given
381
382 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
383
384 commit d8e180b6f802cccea36fee81714d82203cba1f5b
385 Author: Jonny Lamb <jonny.lamb@collabora.co.uk>
386 Date: 2010-11-24 16:06:04 +0000
387
388 protocol: when hitting a special parameter, just skip it, not all the others too
389
390 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
391 Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
392
393 commit 825053fad9ac2b08ef47bb21a1dc29b0ca7be77f
394 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
395 Date: 2010-11-23 19:31:28 +0200
396
397 Version 0.7.0.1 for development
398
0399 commit 15349832aea5b9c4a673e65f4099c116b24522e6
1400 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
2401 Date: 2010-11-23 18:54:20 +0200
118517
119518 fd.o #31720: use TpDBusDaemon to export channel objects
120519
520 commit c89168ecb97280c6e1f732c659c800af832bd7ab
521 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
522 Date: 2010-11-03 17:39:58 +0200
523
524 Function call whitespace
525
526 commit eaafc38c7f7252ea8d5792c14cd2499a6b9e1269
527 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
528 Date: 2010-11-03 17:39:34 +0200
529
530 Fix header value types for timestamps
531
532 commit 4ae2883e410af411acc0d1c9096e3e11137cba81
533 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
534 Date: 2010-11-03 16:54:03 +0200
535
536 Test message headers "message-sent" and "message-received"
537
538 commit 2c4c217d0b8320b86101200b80be35c03654d6f7
539 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
540 Date: 2010-11-03 16:53:44 +0200
541
542 Test "message-token"
543
544 commit 90c49625330dd1f2dfa0c075271490fa1cad9518
545 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
546 Date: 2010-11-03 16:49:35 +0200
547
548 Add the header "message-sent" to received messages in Chan.I.Messages
549
550 As retrieved from the Date header.
551
552 commit 6b3085a3e3f0a310dc0625d8fd0e5b62241efd10
553 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
554 Date: 2010-11-03 16:47:58 +0200
555
556 Offer the header "message-token" on received messages in chan.I.Messages
557
121558 commit 1c9931a882038ac20ab45fe6de015cb8b76a841b
122559 Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
123560 Date: 2010-10-27 16:33:46 +0200
149586 Date: 2010-10-27 10:14:21 +0200
150587
151588 depends on tp-glib 0.12.0
589
590 commit 8932d71d3ead32065bd070a87b3cee811f6892ed
591 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
592 Date: 2010-08-27 20:36:08 +0300
593
594 Nano version 0.6.4.1
595
596 commit 9cfa07f7dbabcf4faeff3e447aa743c118d4a012
597 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
598 Date: 2010-08-27 20:24:06 +0300
599
600 Version 0.6.4
152601
153602 commit b80fdcb30fb9f37eeb042beade15e862f5d0b14c
154603 Merge: 1cc6e02 fa3ba5a
55 recent at the top).
66
77 See also ChangeLog.
8
9 telepathy-sofiasip 0.7.1 (2011-02-01)
10 -------------------------------------
11
12 The "cross country" release.
13
14 New features:
15
16 - Added 'message-token' and 'message-sent' headers to incoming messages,
17 derived from SIP message headers (fd.o #32607).
18 NOTE: some existing clients logging messages, notably the one released
19 in Maemo 5, make unrealistically strict assumptions about the uniqueness of
20 'message-token' values. These logging implementations may exhibit problems
21 with handling collisions in token values if used with this or later versions
22 of Telpathy-SofiaSIP. Such collisions are unlikely, but possible if a
23 remote endpoint generating the SIP Call-ID headers does not use an algorithm
24 compliant with the SIP specification to provide sufficient uniqueness.
25 - Authentication channels implemented as a simple password challenge.
26
27 Bugfixes:
28
29 - Reject incoming calls from the same URI as the local user, rather than
30 crashing apologetically (fd.o #33716).
31
32 Other enhancements:
33
34 - Test suite pulled up to Gabble standards.
35 - Tests for basic StreamedMedia call cases (fd.o #32085)
36 - Changed the type of the size parameter to gssize in tpsip_unquote_string().
37
38 Dependencies:
39
40 - telepathy-glib >= 0.13.9
841
942 telepathy-sofiasip 0.7.0 (2010-11-23)
1043 -------------------------------------
00 #! /bin/sh
11 # Guess values for system-dependent variables and create Makefiles.
2 # Generated by GNU Autoconf 2.67 for telepathy-sofiasip 0.7.0.
2 # Generated by GNU Autoconf 2.67 for telepathy-sofiasip 0.7.1.
33 #
44 #
55 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
697697 # Identity of this package.
698698 PACKAGE_NAME='telepathy-sofiasip'
699699 PACKAGE_TARNAME='telepathy-sofiasip'
700 PACKAGE_VERSION='0.7.0'
701 PACKAGE_STRING='telepathy-sofiasip 0.7.0'
700 PACKAGE_VERSION='0.7.1'
701 PACKAGE_STRING='telepathy-sofiasip 0.7.1'
702702 PACKAGE_BUGREPORT=''
703703 PACKAGE_URL=''
704704
14791479 # Omit some internal or obsolete options to make the list less imposing.
14801480 # This message is too long to be a string in the A/UX 3.1 sh.
14811481 cat <<_ACEOF
1482 \`configure' configures telepathy-sofiasip 0.7.0 to adapt to many kinds of systems.
1482 \`configure' configures telepathy-sofiasip 0.7.1 to adapt to many kinds of systems.
14831483
14841484 Usage: $0 [OPTION]... [VAR=VALUE]...
14851485
15501550
15511551 if test -n "$ac_init_help"; then
15521552 case $ac_init_help in
1553 short | recursive ) echo "Configuration of telepathy-sofiasip 0.7.0:";;
1553 short | recursive ) echo "Configuration of telepathy-sofiasip 0.7.1:";;
15541554 esac
15551555 cat <<\_ACEOF
15561556
16781678 test -n "$ac_init_help" && exit $ac_status
16791679 if $ac_init_version; then
16801680 cat <<\_ACEOF
1681 telepathy-sofiasip configure 0.7.0
1681 telepathy-sofiasip configure 0.7.1
16821682 generated by GNU Autoconf 2.67
16831683
16841684 Copyright (C) 2010 Free Software Foundation, Inc.
19561956 This file contains any messages produced by compilers while
19571957 running configure, to aid debugging if configure makes a mistake.
19581958
1959 It was created by telepathy-sofiasip $as_me 0.7.0, which was
1959 It was created by telepathy-sofiasip $as_me 0.7.1, which was
19601960 generated by GNU Autoconf 2.67. Invocation command line was
19611961
19621962 $ $0 $@
23102310 PACKAGE=telepathy-sofiasip
23112311 TELEPATHY_SIP_VERSION_MAJOR=0
23122312 TELEPATHY_SIP_VERSION_MINOR=7
2313 TELEPATHY_SIP_VERSION_MICRO=0
2313 TELEPATHY_SIP_VERSION_MICRO=1
23142314 NANO=0
23152315 TELEPATHY_SIP_VERSION_NANO=$NANO
23162316 if test "x$NANO" = "x" || test "x$NANO" = "x0";
23172317 then
23182318 { $as_echo "$as_me:${as_lineno-$LINENO}: configuring telepathy-sofiasip for release" >&5
23192319 $as_echo "$as_me: configuring telepathy-sofiasip for release" >&6;}
2320 VERSION=0.7.0
2320 VERSION=0.7.1
23212321 TELEPATHY_SIP_VERSION_RELEASE=1
23222322 WERROR="no"
23232323 else
23242324 { $as_echo "$as_me:${as_lineno-$LINENO}: configuring telepathy-sofiasip for development with nano $NANO" >&5
23252325 $as_echo "$as_me: configuring telepathy-sofiasip for development with nano $NANO" >&6;}
2326 VERSION=0.7.0.$NANO
2326 VERSION=0.7.1.$NANO
23272327 TELEPATHY_SIP_VERSION_RELEASE=0.`date +%Y%m%d.%H%M%S`
23282328 WERROR="yes"
23292329 fi
28272827
28282828 # Define the identity of the package.
28292829 PACKAGE='telepathy-sofiasip'
2830 VERSION='0.7.0'
2830 VERSION='0.7.1'
28312831
28322832
28332833 cat >>confdefs.h <<_ACEOF
1154911549 pkg_cv_TELEPATHY_GLIB_CFLAGS="$TELEPATHY_GLIB_CFLAGS"
1155011550 elif test -n "$PKG_CONFIG"; then
1155111551 if test -n "$PKG_CONFIG" && \
11552 { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"telepathy-glib >= 0.12\""; } >&5
11553 ($PKG_CONFIG --exists --print-errors "telepathy-glib >= 0.12") 2>&5
11552 { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"telepathy-glib >= 0.13.9\""; } >&5
11553 ($PKG_CONFIG --exists --print-errors "telepathy-glib >= 0.13.9") 2>&5
1155411554 ac_status=$?
1155511555 $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
1155611556 test $ac_status = 0; }; then
11557 pkg_cv_TELEPATHY_GLIB_CFLAGS=`$PKG_CONFIG --cflags "telepathy-glib >= 0.12" 2>/dev/null`
11557 pkg_cv_TELEPATHY_GLIB_CFLAGS=`$PKG_CONFIG --cflags "telepathy-glib >= 0.13.9" 2>/dev/null`
1155811558 else
1155911559 pkg_failed=yes
1156011560 fi
1156511565 pkg_cv_TELEPATHY_GLIB_LIBS="$TELEPATHY_GLIB_LIBS"
1156611566 elif test -n "$PKG_CONFIG"; then
1156711567 if test -n "$PKG_CONFIG" && \
11568 { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"telepathy-glib >= 0.12\""; } >&5
11569 ($PKG_CONFIG --exists --print-errors "telepathy-glib >= 0.12") 2>&5
11568 { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"telepathy-glib >= 0.13.9\""; } >&5
11569 ($PKG_CONFIG --exists --print-errors "telepathy-glib >= 0.13.9") 2>&5
1157011570 ac_status=$?
1157111571 $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
1157211572 test $ac_status = 0; }; then
11573 pkg_cv_TELEPATHY_GLIB_LIBS=`$PKG_CONFIG --libs "telepathy-glib >= 0.12" 2>/dev/null`
11573 pkg_cv_TELEPATHY_GLIB_LIBS=`$PKG_CONFIG --libs "telepathy-glib >= 0.13.9" 2>/dev/null`
1157411574 else
1157511575 pkg_failed=yes
1157611576 fi
1159011590 _pkg_short_errors_supported=no
1159111591 fi
1159211592 if test $_pkg_short_errors_supported = yes; then
11593 TELEPATHY_GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "telepathy-glib >= 0.12" 2>&1`
11593 TELEPATHY_GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "telepathy-glib >= 0.13.9" 2>&1`
1159411594 else
11595 TELEPATHY_GLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors "telepathy-glib >= 0.12" 2>&1`
11595 TELEPATHY_GLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors "telepathy-glib >= 0.13.9" 2>&1`
1159611596 fi
1159711597 # Put the nasty error message in config.log where it belongs
1159811598 echo "$TELEPATHY_GLIB_PKG_ERRORS" >&5
1159911599
11600 as_fn_error $? "Package requirements (telepathy-glib >= 0.12) were not met:
11600 as_fn_error $? "Package requirements (telepathy-glib >= 0.13.9) were not met:
1160111601
1160211602 $TELEPATHY_GLIB_PKG_ERRORS
1160311603
1255012550 # report actual input values of CONFIG_FILES etc. instead of their
1255112551 # values after options handling.
1255212552 ac_log="
12553 This file was extended by telepathy-sofiasip $as_me 0.7.0, which was
12553 This file was extended by telepathy-sofiasip $as_me 0.7.1, which was
1255412554 generated by GNU Autoconf 2.67. Invocation command line was
1255512555
1255612556 CONFIG_FILES = $CONFIG_FILES
1261612616 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
1261712617 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
1261812618 ac_cs_version="\\
12619 telepathy-sofiasip config.status 0.7.0
12619 telepathy-sofiasip config.status 0.7.1
1262012620 configured by $0, generated by GNU Autoconf 2.67,
1262112621 with options \\"\$ac_cs_config\\"
1262212622
22 m4_define([THIS_PACKAGE],[telepathy-sofiasip])
33 m4_define([VERSION_MAJOR],[0])
44 m4_define([VERSION_MINOR],[7])
5 m4_define([VERSION_MICRO],[0])
5 m4_define([VERSION_MICRO],[1])
66 m4_define([VERSION_NANO],[0])
77
88 m4_define([BASE_VERSION],[VERSION_MAJOR.VERSION_MINOR.VERSION_MICRO])
8484 AC_SUBST(SOFIA_SIP_UA_VERSION)
8585
8686 dnl Check for telepathy-glib
87 PKG_CHECK_MODULES(TELEPATHY_GLIB, [telepathy-glib >= 0.12])
87 PKG_CHECK_MODULES(TELEPATHY_GLIB, [telepathy-glib >= 0.13.9])
8888 AC_SUBST(TELEPATHY_GLIB_CFLAGS)
8989 AC_SUBST(TELEPATHY_GLIB_LIBS)
9090
356356 DEBUG("Got incoming invite from <%s>",
357357 tp_handle_inspect (contact_repo, handle));
358358
359 if (handle == conn->self_handle)
360 {
361 DEBUG("cannot handle calls from self");
362 nua_respond (ev->nua_handle, 501, "Calls from self are not supported", TAG_END());
363 return TRUE;
364 }
365
359366 channel = new_media_channel (fac, handle, handle, channel_flags);
360367
361368 tp_handle_unref (contact_repo, handle);
313313 if (tpsip_params[i].offset == PARAM_SET_SEPARATELY)
314314 {
315315 DEBUG ("Parameter %s is handled specially", tpsip_params[i].name);
316 break;
316 continue;
317317 }
318318
319319 g_assert (tpsip_params[i].offset == PARAM_EASY);
438438 }
439439 }
440440
441 static GStrv
442 dup_authentication_types (TpBaseProtocol *base)
443 {
444 const gchar * const types[] = {
445 TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION,
446 NULL
447 };
448
449 return g_strdupv ((GStrv) types);
450 }
451
441452 static void
442453 tpsip_protocol_get_property (GObject *object,
443454 guint property_id,
493504 base_class->identify_account = identify_account;
494505 base_class->get_interfaces = get_interfaces;
495506 base_class->get_connection_details = get_connection_details;
507 base_class->dup_authentication_types = dup_authentication_types;
496508
497509 object_class->get_property = tpsip_protocol_get_property;
498510 object_class->set_property = tpsip_protocol_set_property;
2626 #include <tpsip/sofia-decls.h>
2727 #include <sofia-sip/sresolv.h>
2828
29 #include <telepathy-glib/simple-password-manager.h>
30
2931 #ifdef HAVE_LIBIPHB
3032 #include <libiphb.h>
3133 #endif
5052 gchar *registrar_realm;
5153
5254 TpsipMediaFactory *media_factory;
55 TpSimplePasswordManager *password_manager;
5356
5457 gchar *address;
5558 gchar *auth_user;
159159 "connection", self, NULL);
160160 g_ptr_array_add (channel_managers, priv->media_factory);
161161
162 priv->password_manager = tp_simple_password_manager_new (
163 conn);
164 g_ptr_array_add (channel_managers, priv->password_manager);
165
162166 return channel_managers;
163167 }
164168
599603 G_STRUCT_OFFSET (TpsipConnectionClass, contacts_class));
600604 }
601605
606 typedef struct {
607 TpsipConnection* self;
608 nua_handle_t *nh;
609 gchar *method;
610 gchar *realm;
611 gchar *user;
612 } PrivHandleAuthData;
613
614 static PrivHandleAuthData *
615 priv_handle_auth_data_new (TpsipConnection* self,
616 nua_handle_t *nh,
617 const gchar *method,
618 const gchar *realm,
619 const gchar *user)
620 {
621 PrivHandleAuthData *data = g_slice_new (PrivHandleAuthData);
622
623 data->self = g_object_ref (self);
624 data->nh = nua_handle_ref (nh);
625 data->method = g_strdup (method);
626 data->realm = g_strdup (realm);
627 data->user = g_strdup (user);
628
629 return data;
630 }
631
632 static void
633 priv_handle_auth_data_free (PrivHandleAuthData *data)
634 {
635 g_object_unref (data->self);
636 nua_handle_unref (data->nh);
637 g_free (data->method);
638 g_free (data->realm);
639 g_free (data->user);
640
641 g_slice_free (PrivHandleAuthData, data);
642 }
643
644 static void priv_password_manager_prompt_cb (GObject *source_object,
645 GAsyncResult *result,
646 gpointer user_data);
647 static void priv_handle_auth_continue (TpsipConnection* self,
648 nua_handle_t *nh,
649 const gchar *method,
650 const gchar *realm,
651 const gchar *user,
652 const gchar *password);
653
602654 static gboolean
603655 priv_handle_auth (TpsipConnection* self,
604656 int status,
613665 const char *realm = NULL;
614666 const char *user = NULL;
615667 const char *password = NULL;
616 gchar *auth = NULL;
617668
618669 if (status != 401 && status != 407)
619670 return FALSE;
638689 if (realm == NULL)
639690 {
640691 WARNING ("no realm presented for authentication");
692 return FALSE;
693 }
694
695 if (method == NULL)
696 {
697 WARNING ("no method presented for authentication");
641698 return FALSE;
642699 }
643700
674731 /* fall back to the main username */
675732 user = priv->auth_user;
676733 password = priv->extra_auth_password;
734 if (password == NULL)
735 /* note that this prevents asking the user for a password */
736 password = "";
677737
678738 DEBUG("using the extra auth credentials");
679739 }
684744 if (sipfrom && sipfrom->a_url[0].url_user)
685745 /* or use the userpart in "From" header */
686746 user = sipfrom->a_url[0].url_user;
747 else
748 return FALSE;
687749 }
688750
689751 if (password == NULL)
690 password = "";
752 {
753 PrivHandleAuthData *data = NULL;
754
755 DEBUG("asking the user for a password.");
756 data = priv_handle_auth_data_new (self, nh, method, realm,
757 user);
758 tp_simple_password_manager_prompt_async (priv->password_manager,
759 priv_password_manager_prompt_cb, data);
760 /* Promise that we'll handle it eventually, even if we end up just
761 * handling it with a blank password. */
762 return TRUE;
763 }
764
765 priv_handle_auth_continue (self, nh, method, realm,
766 user, password);
767 return TRUE;
768 }
769
770 static void
771 priv_password_manager_prompt_cb (GObject *source_object,
772 GAsyncResult *result,
773 gpointer user_data)
774 {
775 PrivHandleAuthData *data = user_data;
776 GError *error = NULL;
777 const GString *password_string;
778 const gchar *password;
779
780 password_string = tp_simple_password_manager_prompt_finish (
781 TP_SIMPLE_PASSWORD_MANAGER (source_object), result, &error);
782
783 if (error != NULL)
784 {
785 /* we promised to handle the auth challenge in priv_handle_auth() by
786 * returning TRUE, so we need to handle it anyway, even if it means
787 * doing it with a blank password.
788 */
789 DEBUG ("Auth channel failed: %s. Using blank password.", error->message);
790
791 password = "";
792
793 g_error_free (error);
794 }
795 else
796 {
797 TpsipConnectionPrivate *priv =
798 TPSIP_CONNECTION_GET_PRIVATE (data->self);
799
800 password = password_string->str;
801 /* also save it for later. */
802 g_free (priv->password);
803 priv->password = g_strdup (password);
804 }
805
806 priv_handle_auth_continue (data->self, data->nh, data->method, data->realm,
807 data->user, password);
808
809 priv_handle_auth_data_free (data);
810 }
811
812 static void
813 priv_handle_auth_continue (TpsipConnection* self,
814 nua_handle_t *nh,
815 const gchar *method,
816 const gchar *realm,
817 const gchar *user,
818 const gchar *password)
819 {
820 gchar *auth = NULL;
691821
692822 /* step: if all info is available, create an authorization response */
693823 g_assert (realm != NULL);
694 if (user && method) {
695 if (realm[0] == '"')
696 auth = g_strdup_printf ("%s:%s:%s:%s",
697 method, realm, user, password);
698 else
699 auth = g_strdup_printf ("%s:\"%s\":%s:%s",
700 method, realm, user, password);
701
702 DEBUG("%s authenticating user='%s' realm=%s",
703 wa ? "server" : "proxy", user, realm);
704 }
705
706 if (auth == NULL)
707 {
708 WARNING ("authentication data are incomplete");
709 return FALSE;
710 }
824 g_assert (method != NULL);
825 g_assert (user != NULL);
826 g_assert (password != NULL);
827
828 if (realm[0] == '"')
829 auth = g_strdup_printf ("%s:%s:%s:%s",
830 method, realm, user, password);
831 else
832 auth = g_strdup_printf ("%s:\"%s\":%s:%s",
833 method, realm, user, password);
834
835 DEBUG ("%s-authenticating user='%s' realm=%s",
836 method, user, realm);
711837
712838 /* step: authenticate */
713839 nua_authenticate(nh, NUTAG_AUTH(auth), TAG_END());
714840
715841 g_free (auth);
716
717 return TRUE;
718842 }
719843
720844 static gboolean
190190 G_OBJECT_CLASS (tpsip_media_channel_parent_class);
191191 TpDBusDaemon *bus;
192192 TpHandleRepoIface *contact_repo;
193 TpIntSet *set;
193 TpIntSet *add;
194194
195195 if (parent_object_class->constructed != NULL)
196196 parent_object_class->constructed (obj);
218218 g_assert (priv->initiator != 0);
219219 tp_handle_ref (contact_repo, priv->initiator);
220220
221 set = tp_intset_new ();
222 tp_intset_add (set, priv->initiator);
223
224 tp_group_mixin_change_members (obj, "", set, NULL, NULL, NULL, 0, 0);
225
226 tp_intset_destroy (set);
227
228 /* Allow member adding; also, we implement the 0.17.6 properties */
221 add = tp_intset_new_containing (priv->initiator);
222 tp_group_mixin_change_members (obj, "", add, NULL, NULL, NULL, 0, 0);
223 tp_intset_destroy (add);
224
225 /* We start off with lots of flags, and then delete them as we work out what
226 * kind of channel we are, rather than trying to track what we need to
227 * add/remove over time. We should always have the right flags before we are
228 * advertised on the bus. */
229229 tp_group_mixin_change_flags (obj,
230 TP_CHANNEL_GROUP_FLAG_CAN_ADD | TP_CHANNEL_GROUP_FLAG_PROPERTIES, 0);
230 TP_CHANNEL_GROUP_FLAG_CAN_ADD | TP_CHANNEL_GROUP_FLAG_CAN_REMOVE |
231 TP_CHANNEL_GROUP_FLAG_CAN_RESCIND | TP_CHANNEL_GROUP_FLAG_PROPERTIES, 0);
231232 }
232233
233234 static void tpsip_media_channel_dispose (GObject *object);
746747 tpsip_media_channel_get_handle (TpSvcChannel *iface,
747748 DBusGMethodInvocation *context)
748749 {
749 tp_svc_channel_return_from_get_handle (context, 0, 0);
750 TpsipMediaChannel *self = TPSIP_MEDIA_CHANNEL (iface);
751 TpsipMediaChannelPrivate *priv = TPSIP_MEDIA_CHANNEL_GET_PRIVATE (self);
752
753 if (priv->handle != 0)
754 tp_svc_channel_return_from_get_handle (context, TP_HANDLE_TYPE_CONTACT,
755 priv->handle);
756 else
757 tp_svc_channel_return_from_get_handle (context, TP_HANDLE_TYPE_NONE, 0);
750758 }
751759
752760 /**
10301038 TpsipMediaChannelPrivate *priv = TPSIP_MEDIA_CHANNEL_GET_PRIVATE (self);
10311039
10321040 g_assert (priv->initiator != priv->handle);
1041
1042 /* RequestChannel(None, 0) => channel is anonymous:
1043 * caller uses RequestStreams to set the peer and start the call. */
1044 if (priv->handle == 0)
1045 return;
10331046
10341047 priv_outbound_call (self, priv->handle);
10351048
11341147 const char* message)
11351148 {
11361149 TpGroupMixin *mixin = TP_GROUP_MIXIN (self);
1137 TpIntSet *set;
1150 TpIntSet *remove;
11381151 guint reason = TP_CHANNEL_GROUP_CHANGE_REASON_ERROR;
11391152
11401153 switch (status)
11711184 if (message == NULL || !g_utf8_validate (message, -1, NULL))
11721185 message = "";
11731186
1174 set = tp_intset_new ();
1175 tp_intset_add (set, peer);
1176 tp_intset_add (set, mixin->self_handle);
1187 remove = tp_intset_new ();
1188 tp_intset_add (remove, peer);
1189 tp_intset_add (remove, mixin->self_handle);
11771190 tp_group_mixin_change_members ((GObject *)self, message,
1178 NULL, set, NULL, NULL, peer, reason);
1179 tp_intset_destroy (set);
1191 NULL, remove, NULL, NULL, peer, reason);
1192 tp_intset_destroy (remove);
11801193 }
11811194
11821195 guint
12201233 {
12211234 TpsipMediaChannelPrivate *priv = TPSIP_MEDIA_CHANNEL_GET_PRIVATE (self);
12221235 TpGroupMixin *mixin = TP_GROUP_MIXIN (self);
1223 TpIntSet *set;
1236 TpIntSet *remove;
12241237 TpHandle peer;
12251238
12261239 g_return_val_if_fail (priv->session != NULL, FALSE);
12271240
12281241 peer = tpsip_media_session_get_peer (priv->session);
1229 set = tp_intset_new ();
1230 tp_intset_add (set, peer);
1231 tp_intset_add (set, mixin->self_handle);
1232
1233 tp_group_mixin_change_members ((GObject *) self,
1234 "",
1235 NULL, /* add */
1236 set, /* remove */
1237 NULL,
1238 NULL,
1239 peer,
1240 TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
1241
1242 tp_intset_destroy (set);
1242 remove = tp_intset_new ();
1243 tp_intset_add (remove, peer);
1244 tp_intset_add (remove, mixin->self_handle);
1245
1246 tp_group_mixin_change_members ((GObject *) self, "",
1247 NULL, remove, NULL, NULL,
1248 peer, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
1249
1250 tp_intset_destroy (remove);
12431251
12441252 return TRUE;
12451253 }
12521260 {
12531261 TpsipMediaChannelPrivate *priv = TPSIP_MEDIA_CHANNEL_GET_PRIVATE (self);
12541262 TpGroupMixin *mixin = TP_GROUP_MIXIN (self);
1255 TpIntSet *set;
1263 TpIntSet *remove;
12561264 TpHandle actor = 0;
12571265 TpHandle peer;
12581266 const sip_reason_t *reason;
12961304 if (message == NULL || !g_utf8_validate (message, -1, NULL))
12971305 message = "";
12981306
1299 set = tp_intset_new ();
1300 tp_intset_add (set, peer);
1301 tp_intset_add (set, mixin->self_handle);
1302
1303 tp_group_mixin_change_members ((GObject *) self,
1304 message,
1305 NULL, /* add */
1306 set, /* remove */
1307 NULL,
1308 NULL,
1309 actor,
1310 TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
1311
1312 tp_intset_destroy (set);
1307 remove = tp_intset_new ();
1308 tp_intset_add (remove, peer);
1309 tp_intset_add (remove, mixin->self_handle);
1310
1311 tp_group_mixin_change_members ((GObject *) self, message,
1312 NULL, remove, NULL, NULL,
1313 actor, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
1314
1315 tp_intset_destroy (remove);
13131316
13141317 return TRUE;
13151318 }
13901393 TPSIP_CHANNEL_CALL_STATE_PROCEEDING_MASK);
13911394
13921395 if (status < 300)
1393 tpsip_media_session_accept (priv->session);
1396 {
1397 TpIntSet *add = tp_intset_new_containing (peer);
1398
1399 tp_group_mixin_change_members ((GObject *) self,
1400 "",
1401 add, /* add */
1402 NULL, /* remove */
1403 NULL,
1404 NULL,
1405 peer,
1406 TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
1407
1408 tp_intset_destroy (add);
1409
1410 tpsip_media_session_accept (priv->session);
1411 }
13941412 else if (status == 491)
13951413 tpsip_media_session_resolve_glare (priv->session);
13961414 else
14441462 switch (state)
14451463 {
14461464 case TPSIP_MEDIA_SESSION_STATE_INVITE_SENT:
1447 set = tp_intset_new ();
1448
14491465 g_assert (priv->initiator == self_handle);
14501466
14511467 /* add the peer to remote pending */
1452 tp_intset_add (set, peer);
1468 set = tp_intset_new_containing (peer);
14531469 tp_group_mixin_change_members ((GObject *)channel,
14541470 "",
14551471 NULL, /* add */
14591475 self_handle, /* actor */
14601476 TP_CHANNEL_GROUP_CHANGE_REASON_INVITED);
14611477
1462 /* update flags: allow removal and rescinding, no more adding */
1463 tp_group_mixin_change_flags ((GObject *)channel,
1464 TP_CHANNEL_GROUP_FLAG_CAN_REMOVE | TP_CHANNEL_GROUP_FLAG_CAN_RESCIND,
1478 /* update flags: no more adding */
1479 tp_group_mixin_change_flags ((GObject *)channel, 0,
14651480 TP_CHANNEL_GROUP_FLAG_CAN_ADD);
14661481
14671482 break;
14681483
14691484 case TPSIP_MEDIA_SESSION_STATE_INVITE_RECEIVED:
1470 set = tp_intset_new ();
1471
14721485 /* add ourself to local pending */
1473 tp_intset_add (set, self_handle);
1486 set = tp_intset_new_containing (self_handle);
14741487 tp_group_mixin_change_members ((GObject *) channel, "",
14751488 NULL, /* add */
14761489 NULL, /* remove */
14791492 priv->initiator, /* actor */
14801493 TP_CHANNEL_GROUP_CHANGE_REASON_INVITED);
14811494
1482 /* No adding more members to the incoming call, removing is OK */
1483 tp_group_mixin_change_flags ((GObject *) channel,
1484 TP_CHANNEL_GROUP_FLAG_CAN_REMOVE,
1485 TP_CHANNEL_GROUP_FLAG_CAN_ADD);
1495 /* No adding more members to the incoming call. Therefore also not
1496 * possible to add anyone to remote-pending, so rescinding would make
1497 * utterly no sense. We also disallow removing the remote peer if
1498 * we are not the initiator, so disallow that too.
1499 * Removing yourself to end the call is not represented by group flags.
1500 */
1501 tp_group_mixin_change_flags ((GObject *) channel, 0,
1502 TP_CHANNEL_GROUP_FLAG_CAN_ADD | TP_CHANNEL_GROUP_FLAG_CAN_REMOVE |
1503 TP_CHANNEL_GROUP_FLAG_CAN_RESCIND);
14861504
14871505 break;
14881506
14921510 if (!tp_handle_set_is_member (mixin->remote_pending, peer))
14931511 break; /* no-op */
14941512
1495 set = tp_intset_new ();
1496
14971513 /* the peer has promoted itself to members */
1498 tp_intset_add (set, peer);
1514 set = tp_intset_new_containing (peer);
14991515 tp_group_mixin_change_members ((GObject *)channel, "",
15001516 set, /* add */
15011517 NULL, /* remove */
15081524 if (!tp_handle_set_is_member (mixin->local_pending, self_handle))
15091525 break; /* no-op */
15101526
1511 set = tp_intset_new ();
1512
15131527 /* promote ourselves to members */
1514 tp_intset_add (set, self_handle);
1528 set = tp_intset_new_containing (self_handle);
15151529 tp_group_mixin_change_members ((GObject *)channel, "",
15161530 set, /* add */
15171531 NULL, /* remove */
15201534 self_handle, 0);
15211535 }
15221536
1523 /* update flags: allow removal, deny adding and rescinding */
1524 tp_group_mixin_change_flags ((GObject *)channel,
1525 TP_CHANNEL_GROUP_FLAG_CAN_REMOVE,
1526 TP_CHANNEL_GROUP_FLAG_CAN_ADD
1527 | TP_CHANNEL_GROUP_FLAG_CAN_RESCIND);
1537 /* update flags: deny adding and rescinding. Removing the remote peer is
1538 * still allowed.
1539 * Removing yourself to end the call is not represented by group flags.
1540 */
1541 tp_group_mixin_change_flags ((GObject *)channel, 0,
1542 TP_CHANNEL_GROUP_FLAG_CAN_ADD | TP_CHANNEL_GROUP_FLAG_CAN_RESCIND);
15281543
15291544 break;
15301545
17161731
17171732 if (priv->initiator == mixin->self_handle)
17181733 {
1719 TpIntSet *set;
1734 TpIntSet *remote_pending;
17201735
17211736 /* case a: an old-school outbound call
17221737 * (we are the initiator, a new handle added with AddMembers) */
17261741 /* Backwards compatible behavior:
17271742 * add the peer to remote pending without waiting for the actual request
17281743 * to be sent */
1729 set = tp_intset_new ();
1730 tp_intset_add (set, handle);
1744 remote_pending = tp_intset_new_containing (handle);
17311745 tp_group_mixin_change_members (iface,
17321746 "",
17331747 NULL, /* add */
17341748 NULL, /* remove */
17351749 NULL, /* local pending */
1736 set, /* remote pending */
1750 remote_pending, /* remote pending */
17371751 mixin->self_handle, /* actor */
17381752 TP_CHANNEL_GROUP_CHANGE_REASON_INVITED);
1739 tp_intset_destroy (set);
1740
1741 /* update flags: allow removal and rescinding, no more adding */
1742 tp_group_mixin_change_flags (iface,
1743 TP_CHANNEL_GROUP_FLAG_CAN_REMOVE | TP_CHANNEL_GROUP_FLAG_CAN_RESCIND,
1753 tp_intset_destroy (remote_pending);
1754
1755 /* update flags: no more adding.
1756 * Removal and rescinding are still allowed. */
1757 tp_group_mixin_change_flags (iface, 0,
17441758 TP_CHANNEL_GROUP_FLAG_CAN_ADD);
17451759
17461760 return TRUE;
4242 #include "sip-connection.h"
4343 #include "sip-connection-helpers.h"
4444
45 #include <sofia-sip/sip_protos.h>
4546 #include <sofia-sip/sip_status.h>
4647
4748 #define DEBUG_FLAG TPSIP_DEBUG_IM
879880 }
880881
881882 void tpsip_text_channel_receive(TpsipTextChannel *chan,
882 nua_t *nua,
883 const sip_t *sip,
883884 TpHandle sender,
884885 const char *text,
885886 gsize len)
887888 TpsipTextChannelPrivate *priv = TPSIP_TEXT_CHANNEL_GET_PRIVATE (chan);
888889 TpMessage *msg;
889890 TpBaseConnection *base_conn;
891 sip_call_id_t *hdr_call_id;
892 sip_cseq_t *hdr_cseq;
893 sip_date_t *hdr_date_sent;
890894
891895 base_conn = (TpBaseConnection *) priv->conn;
892896 msg = tp_message_new (base_conn, 2, 2);
896900 /* Header */
897901 tp_message_set_handle (msg, 0, "message-sender", TP_HANDLE_TYPE_CONTACT,
898902 sender);
899 tp_message_set_uint64 (msg, 0, "message-received", time (NULL));
903 tp_message_set_int64 (msg, 0, "message-received", time (NULL));
904
905 hdr_date_sent = sip_date (sip);
906 if (hdr_date_sent != NULL)
907 {
908 tp_message_set_int64 (msg, 0, "message-sent",
909 hdr_date_sent->d_time - SU_TIME_EPOCH);
910 }
911
912 /* Create a message token out of globally unique SIP header values.
913 * As MESSAGE requests can be sent within a dialog, we have to append
914 * the Call-ID value with the sequence number in CSeq. */
915 hdr_call_id = sip_call_id (sip);
916 hdr_cseq = sip_cseq (sip);
917 if (hdr_call_id != NULL && hdr_cseq != NULL)
918 {
919 tp_message_set_string_printf (msg, 0, "message-token", "%s;cseq=%u",
920 hdr_call_id->i_id, (guint) hdr_cseq->cs_seq);
921 }
900922
901923 /* Body */
902924 tp_message_set_string (msg, 1, "content-type", "text/plain");
6161 (G_TYPE_INSTANCE_GET_CLASS ((obj), TPSIP_TYPE_TEXT_CHANNEL, TpsipTextChannelClass))
6262
6363 void tpsip_text_channel_receive (TpsipTextChannel *obj,
64 nua_t *nua,
64 const sip_t *sip,
6565 TpHandle sender,
6666 const char *text,
6767 gsize len);
585585 handle, handle, NULL);
586586
587587 tpsip_text_channel_receive (channel,
588 ev->nua, handle, text, len);
588 sip, handle, text, len);
589589
590590 tp_handle_unref (contact_repo, handle);
591591
0 NULL =
1
02 TWISTED_TESTS = \
13 cm/protocol.py \
24 test-register.py \
35 test-register-fail.py \
6 test-register-sasl.py \
47 test-handle-normalisation.py \
58 test-message.py \
69 test-self-alias.py \
7 text/initiate-requestotron.py
10 text/initiate-requestotron.py \
11 voip/incoming-basics.py \
12 voip/outgoing-basics.py \
13 $(NULL)
814
915 TESTS =
1016
2935 $(TWISTED_TESTS) \
3036 constants.py \
3137 sofiatest.py \
32 servicetest.py
38 servicetest.py \
39 voip/voip_test.py
3340
3441 CLEANFILES = sofiasip-[1-9]*.log *.pyc */*.pyc
3542
247247 top_build_prefix = @top_build_prefix@
248248 top_builddir = @top_builddir@
249249 top_srcdir = @top_srcdir@
250 NULL =
250251 TWISTED_TESTS = \
251252 cm/protocol.py \
252253 test-register.py \
253254 test-register-fail.py \
255 test-register-sasl.py \
254256 test-handle-normalisation.py \
255257 test-message.py \
256258 test-self-alias.py \
257 text/initiate-requestotron.py
259 text/initiate-requestotron.py \
260 voip/incoming-basics.py \
261 voip/outgoing-basics.py \
262 $(NULL)
258263
259264 TESTS_ENVIRONMENT = \
260265 PYTHONPATH=@abs_top_srcdir@/tests/twisted
264269 $(TWISTED_TESTS) \
265270 constants.py \
266271 sofiatest.py \
267 servicetest.py
272 servicetest.py \
273 voip/voip_test.py
268274
269275 CLEANFILES = sofiasip-[1-9]*.log *.pyc */*.pyc
270276 check_misc_sources = $(TESTS)
88
99 import os
1010 import sys
11 import random
12
1113 import dbus
1214 import dbus.glib
1315
1921
2022 def register(self, message, host, port):
2123 if hasattr(self, 'registrar_handler'):
24 self.event_func(servicetest.Event('sip-register',
25 uri=str(message.uri), headers=message.headers, body=message.body,
26 sip_message=message, host=host, port=port))
2227 if self.registrar_handler(message, host, port):
2328 sip.RegisterProxy.register(self, message, host, port)
2429 else:
2732 def handle_request(self, message, addr):
2833 if message.method == 'REGISTER':
2934 return sip.RegisterProxy.handle_request(self, message, addr)
30 if message.method == 'MESSAGE':
31 self.event_func(servicetest.Event('sip-message',
35 elif message.method == 'OPTIONS' and \
36 'REGISTRATION PROBE' == message.headers.get('subject','')[0]:
37 self.deliverResponse(self.responseFromRequest(200, message))
38 else:
39 headers = {}
40 for key, values in message.headers.items():
41 headers[key.replace('-', '_')] = values[0]
42 self.event_func(servicetest.Event('sip-%s' % message.method.lower(),
3243 uri=str(message.uri), headers=message.headers, body=message.body,
33 sip_message=message))
44 sip_message=message, **headers))
3445
3546 def handle_response(self, message, addr):
47 headers = {}
48 for key, values in message.headers.items():
49 headers[key.replace('-', '_')] = values[0]
3650 self.event_func(servicetest.Event('sip-response',
3751 code=message.code, headers=message.headers, body=message.body,
38 sip_message=message))
52 sip_message=message, **headers))
3953
4054 def prepare_test(event_func, register_cb, params=None):
4155 actual_params = {
4256 'account': 'testacc@127.0.0.1',
4357 'password': 'testpwd',
4458 'proxy-host': '127.0.0.1',
45 'port': dbus.UInt16(9090),
59 'port': dbus.UInt16(random.randint(9090, 9999)),
4660 'local-ip-address': '127.0.0.1'
4761 }
4862
4963 if params is not None:
50 actual_params.update(params)
64 for k, v in params.items():
65 if v is None:
66 actual_params.pop(k, None)
67 else:
68 actual_params[k] = v
5169
5270 bus = dbus.SessionBus()
5371 conn = servicetest.make_connection(bus, event_func,
106124 return '\x1b[32m%s\x1b[0m' % s
107125
108126 patterns = {
109 'handled': green,
110 'not handled': red,
127 'handled,': green,
128 'not hand': red,
111129 }
112130
113131 class Colourer:
116134 self.patterns = patterns
117135
118136 def write(self, s):
119 f = self.patterns.get(s, lambda x: x)
137 f = self.patterns.get(s[:len('handled,')], lambda x: x)
120138 self.fh.write(f(s))
139
140 def isatty(self):
141 return False
121142
122143 sys.stdout = Colourer(sys.stdout, patterns)
123144
55 import twisted.protocols.sip
66
77 import dbus
8 import email.utils
9 import time
810 import uuid
911
1012 # Test message channels
8486
8587 conn.ReleaseHandles(1, [handle])
8688
87 url = twisted.protocols.sip.parseURL(self_uri)
88 msg = twisted.protocols.sip.Request('MESSAGE', url)
89 send_message(sip, ua_via, 'Hi')
89 call_id = 'XYZ@localhost'
90 send_message(sip, ua_via, 'Hi', call_id=call_id, time=1234567890)
9091
9192 incoming_obj, handle = test_new_channel (q, bus, conn,
9293 target_uri=FROM_URL,
9899 name = conn.InspectHandles(1, [handle])[0]
99100 assert name == FROM_URL
100101
101 event = q.expect('dbus-signal', signal='Received')
102 assert event.args[5] == 'Hi'
102 event = q.expect('dbus-signal', signal='MessageReceived')
103 msg = event.args[0]
104 now = time.time()
105 assert msg[0]['message-token'] == "%s;cseq=%u" % (call_id, cseq_num)
106 assert now - 10 < msg[0]['message-received'] < now + 10
107 assert msg[0]['message-sent'] == 1234567890
108 assert msg[1]['content-type'] == 'text/plain'
109 assert msg[1]['content'] == 'Hi'
103110
104111 # FIXME: times out for some reason, the response is in fact sent;
105112 # race condition with the earlier wait for 'dbus-signal'?
106113 #event = q.expect('sip-response', code=200)
107114
108 iface.AcknowledgePendingMessages([event.args[0]])
115 iface.AcknowledgePendingMessages([msg[0]['pending-message-id']])
109116
110117 # Test conversion from an 8-bit encoding.
111118 # Due to limited set of encodings available in some environments,
194201 q.expect('dbus-signal', signal='StatusChanged', args=[2,1])
195202
196203 cseq_num = 1
197 def send_message(sip, destVia, body, encoding=None, sender=FROM_URL):
204 def send_message(sip, destVia, body,
205 encoding=None, sender=FROM_URL, call_id=None, time=None):
198206 global cseq_num
199207 cseq_num += 1
200208 url = twisted.protocols.sip.parseURL('sip:testacc@127.0.0.1')
209217 else:
210218 msg.addHeader('content-type', 'text/plain; charset=%s' % encoding)
211219 msg.addHeader('content-length', '%d' % len(msg.body))
212 msg.addHeader('call-id', uuid.uuid4().hex)
220 msg.addHeader('call-id', call_id or uuid.uuid4().hex)
221 if time is not None:
222 msg.addHeader('date', email.utils.formatdate(time, False, True))
213223 via = sip.getVia()
214224 via.branch = 'z9hG4bKXYZ'
215225 msg.addHeader('via', via.toString())
0 """
1 Test SIP registration failure.
2 """
3
4 import dbus
5
6 from sofiatest import exec_test
7
8 def test(q, bus, conn, sip):
9 conn.Connect()
10 q.expect('dbus-signal', signal='StatusChanged', args=[1, 1])
11
12 q.expect('sip-register')
13
14 nc = q.expect('dbus-signal', signal='NewChannels')
15 (((path, props),),) = nc.args
16 assert props['org.freedesktop.Telepathy.Channel.ChannelType'] == \
17 'org.freedesktop.Telepathy.Channel.Type.ServerAuthentication'
18 assert props['org.freedesktop.Telepathy.Channel.Interface.SASLAuthentication.AvailableMechanisms'] == \
19 ['X-TELEPATHY-PASSWORD']
20
21 chan = dbus.Interface(bus.get_object(conn._named_service, path),
22 "org.freedesktop.Telepathy.Channel.Interface.SASLAuthentication")
23
24 chan.StartMechanismWithData('X-TELEPATHY-PASSWORD', 'wrong password')
25 chan.AcceptSASL()
26
27 q.expect('sip-register')
28
29 q.expect('dbus-signal', signal='StatusChanged', args=[2, 3])
30 return True
31
32 if __name__ == '__main__':
33 exec_test(test, register_cb=lambda *args: False,
34 params={"password": None})
35
1212 return True
1313
1414 if __name__ == '__main__':
15 exec_test(test)
15 exec_test(test, params={"password": None})
1616
0 """
1 Test incoming call handling.
2 """
3
4 import dbus
5
6 from sofiatest import exec_test
7 from servicetest import (
8 make_channel_proxy, wrap_channel,
9 EventPattern, call_async,
10 assertEquals, assertContains, assertLength,
11 )
12 import constants as cs
13 from voip_test import VoipTestContext
14
15 def test(q, bus, conn, sip_proxy, peer='foo@bar.com'):
16 conn.Connect()
17 q.expect('dbus-signal', signal='StatusChanged', args=[0, 1])
18
19 context = VoipTestContext(q, conn, bus, sip_proxy, 'sip:testacc@127.0.0.1', peer)
20
21 self_handle = conn.GetSelfHandle()
22 remote_handle = conn.RequestHandles(cs.HT_CONTACT, [context.peer])[0]
23
24 # Try making a call to ourself. StreamedMedia should refuse this because
25 # the API doesn't support it.
26 context.incoming_call_from_self()
27 q.expect('sip-response', code=501)
28
29 # Remote end calls us
30 context.incoming_call()
31
32 nc, e = q.expect_many(
33 EventPattern('dbus-signal', signal='NewChannels'),
34 EventPattern('dbus-signal', signal='NewSessionHandler'),
35 )[0:2]
36
37 path, props = nc.args[0][0]
38 ct = props[cs.CHANNEL_TYPE]
39 ht = props[cs.CHANNEL + '.TargetHandleType']
40 h = props[cs.CHANNEL + '.TargetHandle']
41
42 assert ct == cs.CHANNEL_TYPE_STREAMED_MEDIA, ct
43 assert ht == cs.HT_CONTACT, ht
44 assert h == remote_handle, h
45
46 media_chan = make_channel_proxy(conn, path, 'Channel.Interface.Group')
47 media_iface = make_channel_proxy(conn, path, 'Channel.Type.StreamedMedia')
48
49 # S-E was notified about new session handler, and calls Ready on it
50 assert e.args[1] == 'rtp'
51 session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler')
52 session_handler.Ready()
53
54 nsh_event = q.expect('dbus-signal', signal='NewStreamHandler')
55
56 # S-E gets notified about a newly-created stream
57 stream_handler = make_channel_proxy(conn, nsh_event.args[0],
58 'Media.StreamHandler')
59
60 streams = media_iface.ListStreams()
61 assertLength(1, streams)
62
63 stream_id, stream_handle, stream_type, _, stream_direction, pending_flags =\
64 streams[0]
65 assertEquals(remote_handle, stream_handle)
66 assertEquals(cs.MEDIA_STREAM_TYPE_AUDIO, stream_type)
67 assertEquals(cs.MEDIA_STREAM_DIRECTION_RECEIVE, stream_direction)
68 assertEquals(cs.MEDIA_STREAM_PENDING_LOCAL_SEND, pending_flags)
69
70 # Exercise channel properties
71 channel_props = media_chan.GetAll(
72 cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE)
73 assertEquals(remote_handle, channel_props['TargetHandle'])
74 assertEquals(cs.HT_CONTACT, channel_props['TargetHandleType'])
75 assertEquals((cs.HT_CONTACT, remote_handle),
76 media_chan.GetHandle(dbus_interface=cs.CHANNEL))
77 assertEquals(context.peer_id, channel_props['TargetID'])
78 assertEquals(context.peer_id, channel_props['InitiatorID'])
79 assertEquals(remote_handle, channel_props['InitiatorHandle'])
80 assertEquals(False, channel_props['Requested'])
81
82 group_props = media_chan.GetAll(
83 cs.CHANNEL_IFACE_GROUP, dbus_interface=dbus.PROPERTIES_IFACE)
84
85 assert group_props['SelfHandle'] == self_handle, \
86 (group_props['SelfHandle'], self_handle)
87
88 flags = group_props['GroupFlags']
89 assert flags & cs.GF_PROPERTIES, flags
90 # Changing members in any way other than adding or removing yourself is
91 # meaningless for incoming calls, and the flags need not be sent to change
92 # your own membership.
93 assert not flags & cs.GF_CAN_ADD, flags
94 assert not flags & cs.GF_CAN_REMOVE, flags
95 assert not flags & cs.GF_CAN_RESCIND, flags
96
97 assert group_props['Members'] == [remote_handle], group_props['Members']
98 assert group_props['RemotePendingMembers'] == [], \
99 group_props['RemotePendingMembers']
100 # We're local pending because remote_handle invited us.
101 assert group_props['LocalPendingMembers'] == \
102 [(self_handle, remote_handle, cs.GC_REASON_INVITED, '')], \
103 unwrap(group_props['LocalPendingMembers'])
104
105 streams = media_chan.ListStreams(
106 dbus_interface=cs.CHANNEL_TYPE_STREAMED_MEDIA)
107 assert len(streams) == 1, streams
108 assert len(streams[0]) == 6, streams[0]
109 # streams[0][0] is the stream identifier, which in principle we can't
110 # make any assertion about (although in practice it's probably 1)
111 assert streams[0][1] == remote_handle, (streams[0], remote_handle)
112 assert streams[0][2] == cs.MEDIA_STREAM_TYPE_AUDIO, streams[0]
113 # We haven't connected yet
114 assert streams[0][3] == cs.MEDIA_STREAM_STATE_DISCONNECTED, streams[0]
115 # In Gabble, incoming streams start off with remote send enabled, and
116 # local send requested
117 assert streams[0][4] == cs.MEDIA_STREAM_DIRECTION_RECEIVE, streams[0]
118 assert streams[0][5] == cs.MEDIA_STREAM_PENDING_LOCAL_SEND, streams[0]
119
120 # Connectivity checks happen before we have accepted the call
121 stream_handler.NewNativeCandidate("fake", context.get_remote_transports_dbus())
122 stream_handler.NativeCandidatesPrepared()
123 stream_handler.Ready(context.get_audio_codecs_dbus())
124 stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED)
125 stream_handler.SupportedCodecs(context.get_audio_codecs_dbus())
126
127 # At last, accept the call
128 media_chan.AddMembers([self_handle], 'accepted')
129
130 # Call is accepted, we become a member, and the stream that was pending
131 # local send is now sending.
132 memb, acc, _, _, _ = q.expect_many(
133 EventPattern('dbus-signal', signal='MembersChanged',
134 args=[u'', [self_handle], [], [], [], self_handle,
135 cs.GC_REASON_NONE]),
136 EventPattern('sip-response', call_id=context.call_id, code=200),
137 EventPattern('dbus-signal', signal='SetStreamSending', args=[True]),
138 EventPattern('dbus-signal', signal='SetStreamPlaying', args=[True]),
139 EventPattern('dbus-signal', signal='StreamDirectionChanged',
140 args=[stream_id, cs.MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, 0]),
141 )
142
143 context.check_call_sdp(acc.sip_message.body)
144
145 context.ack(acc.sip_message)
146
147 # we are now both in members
148 members = media_chan.GetMembers()
149 assert set(members) == set([self_handle, remote_handle]), members
150
151 # Connected! Blah, blah, ...
152
153 # 'Nuff said
154 bye_msg = context.terminate()
155
156 q.expect_many(EventPattern('dbus-signal', signal='Closed', path=path),
157 EventPattern('sip-response', cseq=bye_msg.headers['cseq'][0]))
158
159 if __name__ == '__main__':
160 exec_test(test)
161 exec_test(lambda q, bus, conn, stream:
162 test(q, bus, conn, stream, 'foo@sip.bar.com'))
0 """
1 Test basic outgoing call handling, using CreateChannel and all three variations
2 of RequestChannel.
3 """
4
5 import dbus
6
7 from sofiatest import exec_test
8 from servicetest import (
9 make_channel_proxy, wrap_channel,
10 EventPattern, call_async,
11 assertEquals, assertContains, assertLength,
12 )
13 import constants as cs
14 from voip_test import VoipTestContext
15
16 # There are various deprecated APIs for requesting calls, documented at
17 # <http://telepathy.freedesktop.org/wiki/Requesting StreamedMedia channels>.
18 # These are ordered from most recent to most deprecated.
19 CREATE = 0 # CreateChannel({TargetHandleType: Contact, TargetHandle: h});
20 # RequestStreams()
21 REQUEST_ANONYMOUS = 1 # RequestChannel(HandleTypeNone, 0); RequestStreams()
22 REQUEST_ANONYMOUS_AND_ADD = 2 # RequestChannel(HandleTypeNone, 0);
23 # AddMembers([h], ...); RequestStreams(h,...)
24 REQUEST_NONYMOUS = 3 # RequestChannel(HandleTypeContact, h);
25 # RequestStreams(h, ...)
26
27 def create(q, bus, conn, sip_proxy, peer='foo@bar.com'):
28 worker(q, bus, conn, sip_proxy, CREATE, peer)
29
30 def request_anonymous(q, bus, conn, sip_proxy, peer='publish@foo.com'):
31 worker(q, bus, conn, sip_proxy, REQUEST_ANONYMOUS, peer)
32
33 def request_anonymous_and_add(q, bus, conn, sip_proxy,
34 peer='publish-subscribe@foo.com/Res'):
35 worker(q, bus, conn, sip_proxy, REQUEST_ANONYMOUS_AND_ADD, peer)
36
37 def request_nonymous(q, bus, conn, sip_proxy, peer='subscribe@foo.com'):
38 worker(q, bus, conn, sip_proxy, REQUEST_NONYMOUS, peer)
39
40 def worker(q, bus, conn, sip_proxy, variant, peer):
41 conn.Connect()
42 q.expect('dbus-signal', signal='StatusChanged', args=[0, 1])
43
44 self_handle = conn.GetSelfHandle()
45 context = VoipTestContext(q, conn, bus, sip_proxy, 'sip:testacc@127.0.0.1', peer)
46
47 self_handle = conn.GetSelfHandle()
48 remote_handle = conn.RequestHandles(1, [context.peer])[0]
49
50 if variant == REQUEST_NONYMOUS:
51 path = conn.RequestChannel(cs.CHANNEL_TYPE_STREAMED_MEDIA,
52 cs.HT_CONTACT, remote_handle, True)
53 elif variant == CREATE:
54 path = conn.Requests.CreateChannel({
55 cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA,
56 cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
57 cs.TARGET_HANDLE: remote_handle,
58 })[0]
59 else:
60 path = conn.RequestChannel(cs.CHANNEL_TYPE_STREAMED_MEDIA,
61 cs.HT_NONE, 0, True)
62
63 old_sig, new_sig = q.expect_many(
64 EventPattern('dbus-signal', signal='NewChannel',
65 predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args),
66 EventPattern('dbus-signal', signal='NewChannels',
67 predicate=lambda e:
68 cs.CHANNEL_TYPE_CONTACT_LIST not in e.args[0][0][1].values()),
69 )
70
71 if variant == REQUEST_NONYMOUS or variant == CREATE:
72 assertEquals( [path, cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.HT_CONTACT,
73 remote_handle, True], old_sig.args)
74 else:
75 assertEquals( [path, cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.HT_NONE, 0,
76 True], old_sig.args)
77
78 assertLength(1, new_sig.args)
79 assertLength(1, new_sig.args[0]) # one channel
80 assertLength(2, new_sig.args[0][0]) # two struct members
81 emitted_props = new_sig.args[0][0][1]
82
83 assertEquals(
84 cs.CHANNEL_TYPE_STREAMED_MEDIA, emitted_props[cs.CHANNEL_TYPE])
85
86 if variant == REQUEST_NONYMOUS or variant == CREATE:
87 assertEquals(remote_handle, emitted_props[cs.TARGET_HANDLE])
88 assertEquals(cs.HT_CONTACT, emitted_props[cs.TARGET_HANDLE_TYPE])
89 assertEquals(context.peer_id, emitted_props[cs.TARGET_ID])
90 else:
91 assertEquals(0, emitted_props[cs.TARGET_HANDLE])
92 assertEquals(cs.HT_NONE, emitted_props[cs.TARGET_HANDLE_TYPE])
93 assertEquals('', emitted_props[cs.TARGET_ID])
94
95 assertEquals(True, emitted_props[cs.REQUESTED])
96 assertEquals(self_handle, emitted_props[cs.INITIATOR_HANDLE])
97 assertEquals('sip:testacc@127.0.0.1', emitted_props[cs.INITIATOR_ID])
98
99 chan = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamedMedia',
100 ['MediaSignalling'])
101
102 # Exercise basic Channel Properties
103 channel_props = chan.Properties.GetAll(cs.CHANNEL)
104
105 assertEquals(cs.CHANNEL_TYPE_STREAMED_MEDIA,
106 channel_props.get('ChannelType'))
107
108 if variant == REQUEST_NONYMOUS or variant == CREATE:
109 assertEquals(remote_handle, channel_props['TargetHandle'])
110 assertEquals(cs.HT_CONTACT, channel_props['TargetHandleType'])
111 assertEquals(context.peer_id, channel_props['TargetID'])
112 assertEquals((cs.HT_CONTACT, remote_handle), chan.GetHandle())
113 else:
114 assertEquals(0, channel_props['TargetHandle'])
115 assertEquals(cs.HT_NONE, channel_props['TargetHandleType'])
116 assertEquals('', channel_props['TargetID'])
117 assertEquals((cs.HT_NONE, 0), chan.GetHandle())
118
119 for interface in [
120 cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_MEDIA_SIGNALLING,
121 cs.TP_AWKWARD_PROPERTIES, cs.CHANNEL_IFACE_HOLD]:
122 assertContains(interface, channel_props['Interfaces'])
123
124 assertEquals(True, channel_props['Requested'])
125 assertEquals('sip:testacc@127.0.0.1', channel_props['InitiatorID'])
126 assertEquals(conn.GetSelfHandle(), channel_props['InitiatorHandle'])
127
128 # Exercise Group Properties
129 group_props = chan.Properties.GetAll(cs.CHANNEL_IFACE_GROUP)
130
131 assertEquals([self_handle], group_props['Members'])
132 assertEquals([], group_props['LocalPendingMembers'])
133
134 if variant == REQUEST_NONYMOUS:
135 # In this variant, they're meant to be in RP even though we've sent
136 # nothing
137 assertEquals([remote_handle], group_props['RemotePendingMembers'])
138 else:
139 # For an anonymous channel, the peer isn't yet known; for a Create-d
140 # channel, the peer only appears in RP when we actually send them the
141 # session-initiate
142 assertEquals([], group_props['RemotePendingMembers'])
143
144 if variant == REQUEST_ANONYMOUS_AND_ADD:
145 # but we should be allowed to add the peer.
146 chan.Group.AddMembers([remote_handle], 'I love backwards compat')
147
148 base_flags = cs.GF_PROPERTIES | cs.GF_CAN_REMOVE | cs.GF_CAN_RESCIND
149
150 if variant in [REQUEST_ANONYMOUS_AND_ADD, REQUEST_ANONYMOUS, CREATE]:
151 expected_flags = base_flags | cs.GF_CAN_ADD
152 else:
153 expected_flags = base_flags
154
155 assertEquals(bin(expected_flags), bin(group_props['GroupFlags']))
156 assertEquals({}, group_props['HandleOwners'])
157
158 assertEquals([], chan.StreamedMedia.ListStreams())
159 streams = chan.StreamedMedia.RequestStreams(remote_handle,
160 [cs.MEDIA_STREAM_TYPE_AUDIO])
161 assertEquals(streams, chan.StreamedMedia.ListStreams())
162 assertLength(1, streams)
163
164 # streams[0][0] is the stream identifier, which in principle we can't
165 # make any assertion about (although in practice it's probably 1)
166
167 assertEquals((
168 remote_handle,
169 cs.MEDIA_STREAM_TYPE_AUDIO,
170 # We haven't connected yet
171 cs.MEDIA_STREAM_STATE_DISCONNECTED,
172 # In Gabble, requested streams start off bidirectional
173 cs.MEDIA_STREAM_DIRECTION_BIDIRECTIONAL,
174 cs.MEDIA_STREAM_PENDING_REMOTE_SEND),
175 streams[0][1:])
176
177 # S-E does state recovery to get the session handler, and calls Ready on it
178 session_handlers = chan.MediaSignalling.GetSessionHandlers()
179 sh_path, sh_type = session_handlers[0]
180
181 assert sh_type == 'rtp'
182
183 session_handler = make_channel_proxy(conn, sh_path, 'Media.SessionHandler')
184 session_handler.Ready()
185
186 e = q.expect('dbus-signal', signal='NewStreamHandler')
187
188 stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler')
189
190 stream_handler.NewNativeCandidate("fake", context.get_remote_transports_dbus())
191 stream_handler.NativeCandidatesPrepared()
192 stream_handler.Ready(context.get_audio_codecs_dbus())
193 stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED)
194
195 sh_props = stream_handler.GetAll(
196 cs.STREAM_HANDLER, dbus_interface=dbus.PROPERTIES_IFACE)
197 assertEquals('none', sh_props['NATTraversal'])
198 assertEquals(True, sh_props['CreatedLocally'])
199
200 if variant == CREATE:
201 # When we actually send INVITE to the peer, they should pop up in remote
202 # pending.
203 invite_event, _ = q.expect_many(
204 EventPattern('sip-invite'),
205 EventPattern('dbus-signal', signal='MembersChanged',
206 args=["", [], [], [], [remote_handle], self_handle,
207 cs.GC_REASON_INVITED]),
208 )
209 else:
210 invite_event = q.expect('sip-invite')
211
212 # Check the Group interface's properties again. Regardless of the call
213 # requesting API in use, the state should be the same here:
214 group_props = chan.Properties.GetAll(cs.CHANNEL_IFACE_GROUP)
215 assertContains('HandleOwners', group_props)
216 assertEquals([self_handle], group_props['Members'])
217 assertEquals([], group_props['LocalPendingMembers'])
218 assertEquals([remote_handle], group_props['RemotePendingMembers'])
219
220 context.check_call_sdp(invite_event.sip_message.body)
221 context.accept(invite_event.sip_message)
222
223 ack_cseq = "%s ACK" % invite_event.cseq.split()[0]
224 q.expect_many(
225 EventPattern('sip-ack', cseq=ack_cseq),
226 # Call accepted
227 EventPattern('dbus-signal', signal='MembersChanged',
228 args=['', [remote_handle], [], [], [], remote_handle,
229 cs.GC_REASON_NONE]),
230 )
231
232 # Time passes ... afterwards we close the chan
233
234 chan.Group.RemoveMembers([self_handle], 'closed')
235
236
237 mc_event, _, bye_event = q.expect_many(
238 EventPattern('dbus-signal', signal='MembersChanged'),
239 EventPattern('dbus-signal', signal='Close'),
240 EventPattern('sip-bye', call_id=context.call_id),
241 )
242 # Check that we're the actor
243 assertEquals(self_handle, mc_event.args[5])
244
245 # For completeness, reply to the BYE.
246 bye_response = sip_proxy.responseFromRequest(200, bye_event.sip_message)
247 sip_proxy.deliverResponse(bye_response)
248
249 def rccs(q, bus, conn, stream):
250 """
251 Tests that the connection's RequestableChannelClasses for StreamedMedia are
252 sane.
253 """
254 conn.Connect()
255
256 q.expect('dbus-signal', signal='StatusChanged',
257 args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])
258
259 rccs = conn.Properties.Get(cs.CONN_IFACE_REQUESTS,
260 'RequestableChannelClasses')
261
262 # Test Channel.Type.StreamedMedia
263 media_classes = [ rcc for rcc in rccs
264 if rcc[0][cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAMED_MEDIA ]
265
266 assertLength(1, media_classes)
267
268 fixed, allowed = media_classes[0]
269
270 assertEquals(cs.HT_CONTACT, fixed[cs.TARGET_HANDLE_TYPE])
271
272 expected_allowed = [
273 cs.TARGET_ID, cs.TARGET_HANDLE,
274 cs.INITIAL_VIDEO, cs.INITIAL_AUDIO
275 ]
276
277 allowed.sort()
278 expected_allowed.sort()
279 assertEquals(expected_allowed, allowed)
280
281 if __name__ == '__main__':
282
283 exec_test(rccs)
284 exec_test(create)
285 exec_test(request_anonymous)
286 exec_test(request_anonymous_and_add)
287 exec_test(request_nonymous)
288 exec_test(lambda q, b, c, s:
289 create(q, b, c, s, peer='foo@gw.bar.com'))
290 exec_test(lambda q, b, c, s:
291 request_anonymous(q, b, c, s, peer='foo@gw.bar.com'))
292 exec_test(lambda q, b, c, s:
293 request_anonymous_and_add(q, b, c, s, peer='foo@gw.bar.com'))
294 exec_test(lambda q, b, c, s:
295 request_nonymous(q, b, c, s, peer='foo@gw.bar.com'))
0
1 import dbus
2 import uuid
3
4 import twisted.protocols.sip
5
6 from servicetest import assertContains
7
8 class VoipTestContext(object):
9 # Default audio codecs for the remote end
10 audio_codecs = [ ('GSM', 3, 8000, {}),
11 ('PCMA', 8, 8000, {}),
12 ('PCMU', 0, 8000, {}) ]
13
14 # Default video codecs for the remote end. I have no idea what's
15 # a suitable value here...
16 video_codecs = [ ('WTF', 42, 80000, {}) ]
17
18 # Default candidates for the remote end
19 remote_transports = [
20 ( "192.168.0.1", # host
21 666, # port
22 0, # protocol = TP_MEDIA_STREAM_BASE_PROTO_UDP
23 "RTP", # protocol subtype
24 "AVP", # profile
25 1.0, # preference
26 0, # transport type = TP_MEDIA_STREAM_TRANSPORT_TYPE_LOCAL,
27 "username",
28 "password" ) ]
29
30 _mline_template = 'm=audio %(port)s %(subtype)s/%(profile)s %(codec_ids)s'
31 _aline_template = 'a=rtpmap:%(codec_id)s %(name)s/%(rate)s'
32
33 def __init__(self, q, conn, bus, sip_proxy, our_uri, peer):
34 self.bus = bus
35 self.conn = conn
36 self.q = q
37 self.our_uri = our_uri
38 self.peer = peer
39 self.peer_id = "sip:" + peer
40 self.sip_proxy = sip_proxy
41 self._cseq_id = 1
42
43 def dbusify_codecs(self, codecs):
44 dbussed_codecs = [ (id, name, 0, rate, 0, params )
45 for (name, id, rate, params) in codecs ]
46 return dbus.Array(dbussed_codecs, signature='(usuuua{ss})')
47
48 def dbusify_codecs_with_params (self, codecs):
49 return self.dbusify_codecs(codecs)
50
51 def get_audio_codecs_dbus(self):
52 return self.dbusify_codecs(self.audio_codecs)
53
54 def get_video_codecs_dbus(self):
55 return self.dbusify_codecs(self.video_codecs)
56
57 def dbusify_call_codecs(self, codecs):
58 dbussed_codecs = [ (id, name, rate, 0, params)
59 for (name, id, rate, params) in codecs ]
60 return dbus.Array(dbussed_codecs, signature='(usuua{ss})')
61
62 def dbusify_call_codecs_with_params(self, codecs):
63 return dbusify_call_codecs (self, codecs)
64
65 def get_call_audio_codecs_dbus(self):
66 return self.dbusify_call_codecs(self.audio_codecs)
67
68 def get_call_video_codecs_dbus(self):
69 return self.dbusify_call_codecs(self.video_codecs)
70
71
72 def get_remote_transports_dbus(self):
73 return dbus.Array([
74 (dbus.UInt32(1 + i), host, port, proto, subtype,
75 profile, pref, transtype, user, pwd)
76 for i, (host, port, proto, subtype, profile,
77 pref, transtype, user, pwd)
78 in enumerate(self.remote_transports) ],
79 signature='(usuussduss)')
80
81 def get_call_remote_transports_dbus(self):
82 return dbus.Array([
83 (1 , host, port,
84 { "Type": transtype,
85 "Foundation": "",
86 "Protocol": proto,
87 "Priority": int((1+i) * 65536),
88 "Username": user,
89 "Password": pwd }
90 ) for i, (host, port, proto, subtype, profile,
91 pref, transtype, user, pwd)
92 in enumerate(self.remote_transports) ],
93 signature='(usqa{sv})')
94
95 def get_call_sdp(self):
96 (ip, port, protocol, subtype, profile, preference,
97 transport, username, password) = self.remote_transports[0]
98
99 codec_id_list = []
100 codec_list = []
101 for name, codec_id, rate, _misc in self.audio_codecs:
102 codec_list.append('a=rtpmap:%(codec_id)s %(name)s/%(rate)s' % locals())
103 codec_id_list.append(str(codec_id))
104 codec_ids = ' '.join(codec_id_list)
105 codecs = '\r\n'.join(codec_list)
106
107 sdp_string = ('v=0\r\n'
108 'o=- 7047265765596858314 2813734028456100815 IN IP4 %(ip)s\r\n'
109 's=-\r\n'
110 't=0 0\r\n'
111 'm=audio %(port)s RTP/AVP 3 8 0\r\n'
112 'c=IN IP4 %(ip)s\r\n'
113 '%(codecs)s\r\n') % locals()
114 return sdp_string
115
116 def check_call_sdp(self, sdp_string):
117 codec_id_list = []
118 for name, codec_id, rate, _misc in self.audio_codecs:
119 assertContains (self._aline_template % locals(), sdp_string)
120 codec_id_list.append(str(codec_id))
121 codec_ids = ' '.join(codec_id_list)
122
123 (ip, port, protocol, subtype, profile, preference,
124 transport, username, password) = self.remote_transports[0]
125 assert self._mline_template % locals() in sdp_string
126
127 def send_message(self, message_type, body='', to_=None, from_=None,
128 **additional_headers):
129 url = twisted.protocols.sip.parseURL('sip:testacc@127.0.0.1')
130 msg = twisted.protocols.sip.Request(message_type, url)
131 if body:
132 msg.body = body
133 msg.addHeader('content-length', '%d' % len(msg.body))
134 msg.addHeader('from', from_ or '<%s>;tag=XYZ' % self.peer_id)
135 msg.addHeader('to', to_ or '<sip:testacc@127.0.0.1>')
136 self._cseq_id += 1
137 additional_headers.setdefault('cseq', '%d %s' % (self._cseq_id, message_type))
138 for key, vals in additional_headers.items():
139 if not isinstance(vals, list):
140 vals = [vals]
141 k = key.replace('_', '-')
142 for v in vals:
143 msg.addHeader(k, v)
144 via = self.sip_proxy.getVia()
145 via.branch = 'z9hG4bKXYZ'
146 msg.addHeader('via', via.toString())
147 _expire, destination = self.sip_proxy.registry.users['testacc']
148 self.sip_proxy.sendMessage(destination, msg)
149 return msg
150
151 def accept(self, invite_message):
152 self.call_id = invite_message.headers['call-id'][0]
153 response = self.sip_proxy.responseFromRequest(200, invite_message)
154 # Echo sofiasip's SDP back to it. It doesn't care.
155 response.addHeader('content-type', 'application/sdp')
156 response.body = invite_message.body
157 response.addHeader('content-length', '%d' % len(response.body))
158 self.sip_proxy.deliverResponse(response)
159 return response
160
161 def ack(self, ok_message):
162 cseq = '%s ACK' % ok_message.headers['cseq'][0].split()[0]
163 self.send_message('ACK', call_id=self.call_id, cseq=cseq)
164
165 def incoming_call(self):
166 self.call_id = uuid.uuid4().hex
167 body = self.get_call_sdp()
168 return self.send_message('INVITE', body, content_type='application/sdp',
169 supported='timer, 100rel', call_id=self.call_id)
170
171 def incoming_call_from_self(self):
172 self.call_id = uuid.uuid4().hex
173 body = self.get_call_sdp()
174 return self.send_message('INVITE', body, content_type='application/sdp',
175 supported='timer, 100rel', call_id=self.call_id,
176 from_='<sip:testacc@127.0.0.1>')
177
178 def terminate(self):
179 return self.send_message('BYE', call_id=self.call_id)
115115 * The string is to be freed with g_free().
116116 */
117117 gchar *
118 tpsip_unquote_string (const gchar *src, gsize len)
118 tpsip_unquote_string (const gchar *src, gssize len)
119119 {
120120 gchar *res;
121121 gchar *p;
2626
2727 gchar * tpsip_quote_string (const gchar *src);
2828
29 gchar * tpsip_unquote_string (const gchar *src, gsize len);
29 gchar * tpsip_unquote_string (const gchar *src, gssize len);
3030
3131 void tpsip_string_append_quoted (GString *buf, const gchar *text);
3232