1# $Id$
2import time
3import imp
4import sys
5import inc_const as const
6from inc_cfg import *
7
8# Load configuration
9cfg_file = imp.load_source("cfg_file", ARGS[1])
10
11# Trigger address switch for media flow between ua1 and ua2.
12# When the receiver uses STUN while both sides are actually in the same
13# private network, initial media packets may be sent to public IP address
14# as specified in the receiver SDP and those packets may not be delivered
15# if the NAT does not support hairpinning. This function will make both
16# sides to send some initial packets to trigger destination address switch
17# in media transport, so future packets will be delivered to the correct
18# address (private IP address).
19def hole_punch(ua1, ua2):
20    if ua1.use_telnet:
21        ua1.send("# 987")
22    else:
23        ua1.send("#")
24        ua1.expect("#")
25        ua1.send("987")
26
27    if ua2.use_telnet:
28        ua2.send("# 789")
29    else:
30        ua2.send("#")
31        ua2.expect("#")
32        ua2.send("789")
33
34    time.sleep(0.1)
35
36
37# Check media flow between ua1 and ua2
38def check_media(ua1, ua2):
39    if ua1.use_telnet:
40        ua1.send("# 1122")
41    else:
42        ua1.send("#")
43        ua1.expect("#")
44        ua1.send("1122")
45    ua2.expect(const.RX_DTMF + "1")
46    ua2.expect(const.RX_DTMF + "1")
47    ua2.expect(const.RX_DTMF + "2")
48    ua2.expect(const.RX_DTMF + "2")
49
50
51# Test body function
52def test_func(t):
53    callee = t.process[0]
54    caller = t.process[1]
55
56    # if have_reg then wait for couple of seconds for PUBLISH
57    # to complete (just in case pUBLISH is used)
58    if callee.inst_param.have_reg:
59        time.sleep(1)
60    if caller.inst_param.have_reg:
61        time.sleep(1)
62
63    # Check if ICE is used
64    use_ice = ("--use-ice" in caller.inst_param.arg) and ("--use-ice" in callee.inst_param.arg)
65
66    # Check if STUN is used (by either side)
67    use_stun = ("--stun-srv" in caller.inst_param.arg) or ("--stun-srv" in callee.inst_param.arg)
68
69    # Check if DTLS-SRTP is used
70    use_dtls_srtp = "--srtp-keying=1" in caller.inst_param.arg
71
72    # Caller making call
73    if caller.use_telnet:
74        caller.send("call new " + t.inst_params[0].uri)
75    else:
76        caller.send("m")
77        caller.send(t.inst_params[0].uri)
78    caller.expect(const.STATE_CALLING)
79
80    # Callee waits for call and answers with 180/Ringing
81    time.sleep(0.2)
82    callee.expect(const.EVENT_INCOMING_CALL)
83    if callee.use_telnet:
84        callee.send("call answer 180")
85    else:
86        callee.send("a")
87        callee.send("180")
88    callee.expect("SIP/2.0 180")
89    caller.expect("SIP/2.0 180")
90
91    # Synchronize stdout
92    caller.sync_stdout()
93    callee.sync_stdout()
94
95    # Callee answers with 200/OK
96    if callee.use_telnet:
97        callee.send("call answer 200")
98    else:
99        callee.send("a")
100        callee.send("200")
101
102    # Wait until call is connected in both endpoints
103    ##time.sleep(0.2)
104    caller.expect(const.STATE_CONFIRMED)
105    callee.expect(const.STATE_CONFIRMED)
106
107    # Synchronize stdout
108    caller.sync_stdout()
109    callee.sync_stdout()
110    ##time.sleep(0.1)
111    caller.sync_stdout()
112    callee.sync_stdout()
113
114    # Wait ICE nego before checking media
115    if use_ice:
116        # Unfortunately ICE nego may race with STATE_CONFIRMED (esp. on callee side), so let's just sleep
117        #caller.expect("ICE negotiation success")
118        #callee.expect("ICE negotiation success")
119        # Additional wait for ICE updating address (via UPDATE/re-INVITE)
120        time.sleep(0.5)
121
122    # Wait DTLS-SRTP nego before checking media
123    if use_dtls_srtp:
124        # Unfortunately DTLS-SRTP nego may race with STATE_CONFIRMED, so let's just sleep
125        #caller.expect("SRTP started, keying=DTLS-SRTP")
126        #callee.expect("SRTP started, keying=DTLS-SRTP")
127        time.sleep(0.5)
128
129    # Trigger address switch before checking media
130    if use_stun and not use_ice:
131        hole_punch(caller, callee)
132
133    # Test that media is okay
134    check_media(caller, callee)
135    check_media(callee, caller)
136
137    # Hold call by caller
138    if caller.use_telnet:
139        caller.send("call hold")
140    else:
141        caller.send("H")
142    caller.expect("INVITE sip:")
143    callee.expect("INVITE sip:")
144    callee.expect(const.MEDIA_HOLD)
145    caller.expect(const.MEDIA_HOLD)
146
147    # Synchronize stdout
148    caller.sync_stdout()
149    callee.sync_stdout()
150
151    # Release hold
152    ##time.sleep(0.5)
153    if caller.use_telnet:
154        caller.send("call reinvite")
155    else:
156        caller.send("v")
157    caller.expect("INVITE sip:")
158    callee.expect("INVITE sip:")
159    callee.expect(const.MEDIA_ACTIVE, title="waiting for media active after call hold")
160    caller.expect(const.MEDIA_ACTIVE, title="waiting for media active after call hold")
161
162    # Synchronize stdout
163    caller.sync_stdout()
164    callee.sync_stdout()
165
166    # Trigger address switch before checking media
167    if use_stun and not use_ice:
168        hole_punch(caller, callee)
169
170    # Test that media is okay
171    check_media(caller, callee)
172    check_media(callee, caller)
173
174    # Synchronize stdout
175    caller.sync_stdout()
176    callee.sync_stdout()
177
178    # Hold call by callee
179    if callee.use_telnet:
180        callee.send("call hold")
181    else:
182        callee.send("H")
183    callee.expect("INVITE sip:")
184    caller.expect("INVITE sip:")
185    caller.expect(const.MEDIA_HOLD)
186    callee.expect(const.MEDIA_HOLD)
187
188    # Synchronize stdout
189    caller.sync_stdout()
190    callee.sync_stdout()
191
192    # Release hold
193    ##time.sleep(0.1)
194    if callee.use_telnet:
195        callee.send("call reinvite")
196    else:
197        callee.send("v")
198    callee.expect("INVITE sip:")
199    caller.expect("INVITE sip:")
200    caller.expect(const.MEDIA_ACTIVE, title="waiting for media active after call hold")
201    callee.expect(const.MEDIA_ACTIVE, title="waiting for media active after call hold")
202
203    # Synchronize stdout
204    caller.sync_stdout()
205    callee.sync_stdout()
206
207    # Trigger address switch before checking media
208    if use_stun and not use_ice:
209        hole_punch(caller, callee)
210
211    # Test that media is okay
212    # Wait for some time for ICE negotiation
213    ##time.sleep(0.6)
214    check_media(caller, callee)
215    check_media(callee, caller)
216
217    # Synchronize stdout
218    caller.sync_stdout()
219    callee.sync_stdout()
220
221    # UPDATE (by caller)
222    if caller.use_telnet:
223        caller.send("call update")
224    else:
225        caller.send("U")
226    #caller.sync_stdout()
227    callee.expect(const.MEDIA_ACTIVE, title="waiting for media active with UPDATE")
228    caller.expect(const.MEDIA_ACTIVE, title="waiting for media active with UPDATE")
229
230    # Synchronize stdout
231    caller.sync_stdout()
232    callee.sync_stdout()
233
234    # Trigger address switch before checking media
235    if use_stun and not use_ice:
236        hole_punch(caller, callee)
237
238    # Test that media is okay
239    ##time.sleep(0.1)
240    check_media(caller, callee)
241    check_media(callee, caller)
242
243    # UPDATE (by callee)
244    if callee.use_telnet:
245        callee.send("call update")
246    else:
247        callee.send("U")
248    callee.expect("UPDATE sip:")
249    caller.expect("UPDATE sip:")
250    caller.expect(const.MEDIA_ACTIVE, title="waiting for media active with UPDATE")
251    callee.expect(const.MEDIA_ACTIVE, title="waiting for media active with UPDATE")
252
253    # Synchronize stdout
254    caller.sync_stdout()
255    callee.sync_stdout()
256
257    # Trigger address switch before checking media
258    if use_stun and not use_ice:
259        hole_punch(caller, callee)
260
261    # Test that media is okay
262    ##time.sleep(0.1)
263    check_media(caller, callee)
264    check_media(callee, caller)
265
266    # Synchronize stdout
267    caller.sync_stdout()
268    callee.sync_stdout()
269
270    # Set codecs in both caller and callee so that there is
271    # no common codec between them.
272    # In caller we only enable PCMU, in callee we only enable PCMA
273    if caller.use_telnet:
274        caller.send("Cp * 0")
275        caller.send("Cp")
276        caller.expect("PCMU/8000.* prio: 0")
277        caller.send("Cp PCMU 120")
278        caller.send("Cp")
279        caller.expect("PCMU/8000.* prio: 120")
280    else:
281        caller.send("Cp")
282        caller.expect("Enter codec")
283        caller.send("* 0")
284        caller.send("Cp")
285        caller.expect("Enter codec")
286        caller.send("pcmu 120")
287
288    if callee.use_telnet:
289        callee.send("Cp * 0")
290        callee.send("Cp")
291        callee.expect("PCMA/8000.* prio: 0")
292        callee.send("Cp PCMA 120")
293        callee.send("Cp")
294        callee.expect("PCMA/8000.* prio: 120")
295    else:
296        callee.send("Cp")
297        callee.expect("Enter codec")
298        callee.send("* 0")
299        callee.send("Cp")
300        callee.expect("Enter codec")
301        callee.send("pcma 120")
302
303    # Test when UPDATE fails (by callee)
304    if callee.use_telnet:
305        callee.send("call update")
306    else:
307        callee.send("U")
308    caller.expect("SIP/2.0 488")
309    callee.expect("SIP/2.0 488")
310    callee.sync_stdout()
311    caller.sync_stdout()
312
313    # Test that media is still okay
314    ##time.sleep(0.1)
315    check_media(caller, callee)
316    check_media(callee, caller)
317
318    # Test when UPDATE fails (by caller)
319    if caller.use_telnet:
320        caller.send("call update")
321    else:
322        caller.send("U")
323    caller.expect("UPDATE sip:")
324    callee.expect("UPDATE sip:")
325    callee.expect("SIP/2.0 488")
326    caller.expect("SIP/2.0 488")
327    caller.sync_stdout()
328    callee.sync_stdout()
329
330    # Test that media is still okay
331    ##time.sleep(0.1)
332    check_media(callee, caller)
333    check_media(caller, callee)
334
335    # Hangup call
336    ##time.sleep(0.1)
337    if caller.use_telnet:
338        caller.send("call hangup")
339    else:
340        caller.send("h")
341
342    # Wait until calls are cleared in both endpoints
343    caller.expect(const.STATE_DISCONNECTED)
344    callee.expect(const.STATE_DISCONNECTED)
345
346
347# Here where it all comes together
348test = cfg_file.test_param
349test.test_func = test_func
350
351