blob: c699bc54b388177ac7911727b1b5305d314856db [file] [log] [blame]
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001/* $Id$ */
2/*
3 * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include "test.h"
Benny Prijono40f2f642006-01-30 18:40:05 +000021#include <pjsip.h>
Benny Prijonofa73e3e2006-01-05 23:35:46 +000022#include <pjlib.h>
23
Benny Prijono85598d92006-01-07 18:44:25 +000024#define THIS_FILE "tsx_uac_test.c"
25
26
Benny Prijonofa73e3e2006-01-05 23:35:46 +000027/*****************************************************************************
28 **
Benny Prijono85598d92006-01-07 18:44:25 +000029 ** UAC tests.
Benny Prijonofa73e3e2006-01-05 23:35:46 +000030 **
Benny Prijono85598d92006-01-07 18:44:25 +000031 ** This file performs various tests for UAC transactions. Each test will have
32 ** a different Via branch param so that message receiver module and
33 ** transaction user module can identify which test is being carried out.
Benny Prijonofa73e3e2006-01-05 23:35:46 +000034 **
Benny Prijono85598d92006-01-07 18:44:25 +000035 ** TEST1_BRANCH_ID
36 ** Perform basic retransmission and timeout test. Message receiver will
37 ** verify that retransmission is received at correct time.
38 ** This test verifies the following requirements:
39 ** - retransmit timer doubles for INVITE
40 ** - retransmit timer doubles and caps off for non-INVITE
41 ** - retransmit timer timer is precise
42 ** - correct timeout and retransmission count
43 ** Requirements not tested:
44 ** - retransmit timer only starts after resolving has completed.
45 **
46 ** TEST2_BRANCH_ID
47 ** Test scenario where resolver is unable to resolve destination host.
48 **
49 ** TEST3_BRANCH_ID
50 ** Test scenario where transaction is terminated while resolver is still
51 ** running.
52 **
53 ** TEST4_BRANCH_ID
54 ** Test scenario where transport failed after several retransmissions.
55 **
56 ** TEST5_BRANCH_ID
57 ** Test scenario where transaction is terminated by user after several
58 ** retransmissions.
59 **
60 ** TEST6_BRANCH_ID
61 ** Test successfull non-INVITE transaction.
62 ** It tests the following requirements:
63 ** - transaction correctly moves to COMPLETED state.
64 ** - retransmission must cease.
65 ** - tx_data must be maintained until state is terminated.
66 **
67 ** TEST7_BRANCH_ID
68 ** Test successfull non-INVITE transaction, with provisional response.
69 **
70 ** TEST8_BRANCH_ID
71 ** Test failed INVITE transaction (e.g. ACK must be received)
72 **
73 ** TEST9_BRANCH_ID
74 ** Test failed INVITE transaction with provisional response.
75 **
76 **
Benny Prijonofa73e3e2006-01-05 23:35:46 +000077 *****************************************************************************
78 */
79
Benny Prijonodbe337a2006-01-08 23:57:52 +000080static char *TEST1_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test1";
81static char *TEST2_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test2";
82static char *TEST3_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test3";
83static char *TEST4_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test4";
84static char *TEST5_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test5";
85static char *TEST6_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test6";
86static char *TEST7_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test7";
87static char *TEST8_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test8";
88static char *TEST9_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test9";
Benny Prijono85598d92006-01-07 18:44:25 +000089
90#define TEST1_ALLOWED_DIFF (150)
91#define TEST4_RETRANSMIT_CNT 3
92#define TEST5_RETRANSMIT_CNT 3
93
94
Benny Prijonofa73e3e2006-01-05 23:35:46 +000095static void tsx_user_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e);
96static pj_bool_t msg_receiver_on_rx_request(pjsip_rx_data *rdata);
97
98/* UAC transaction user module. */
99static pjsip_module tsx_user =
100{
101 NULL, NULL, /* prev and next */
Benny Prijonodbe337a2006-01-08 23:57:52 +0000102 { "Tsx-UAC-User", 12}, /* Name. */
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000103 -1, /* Id */
104 PJSIP_MOD_PRIORITY_APPLICATION-1, /* Priority */
105 NULL, /* User data. */
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000106 NULL, /* load() */
107 NULL, /* start() */
108 NULL, /* stop() */
109 NULL, /* unload() */
110 NULL, /* on_rx_request() */
111 NULL, /* on_rx_response() */
Benny Prijono85598d92006-01-07 18:44:25 +0000112 NULL, /* on_tx_request() */
113 NULL, /* on_tx_response() */
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000114 &tsx_user_on_tsx_state, /* on_tsx_state() */
115};
116
117/* Module to receive the loop-backed request. */
118static pjsip_module msg_receiver =
119{
120 NULL, NULL, /* prev and next */
Benny Prijonodbe337a2006-01-08 23:57:52 +0000121 { "Msg-Receiver", 12}, /* Name. */
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000122 -1, /* Id */
123 PJSIP_MOD_PRIORITY_APPLICATION-1, /* Priority */
124 NULL, /* User data. */
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000125 NULL, /* load() */
126 NULL, /* start() */
127 NULL, /* stop() */
128 NULL, /* unload() */
129 &msg_receiver_on_rx_request, /* on_rx_request() */
130 NULL, /* on_rx_response() */
Benny Prijono85598d92006-01-07 18:44:25 +0000131 NULL, /* on_tx_request() */
132 NULL, /* on_tx_response() */
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000133 NULL, /* on_tsx_state() */
134};
135
Benny Prijono85598d92006-01-07 18:44:25 +0000136/* Static vars, which will be reset on each test. */
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000137static int recv_count;
138static pj_time_val recv_last;
139static pj_bool_t test_complete;
140
Benny Prijono85598d92006-01-07 18:44:25 +0000141/* Loop transport instance. */
142static pjsip_transport *loop;
143
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000144/* General timer entry to be used by tests. */
145static pj_timer_entry timer;
146
Benny Prijono85598d92006-01-07 18:44:25 +0000147/*
148 * This is the handler to receive state changed notification from the
149 * transaction. It is used to verify that the transaction behaves according
150 * to the test scenario.
151 */
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000152static void tsx_user_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e)
153{
Benny Prijono85598d92006-01-07 18:44:25 +0000154 if (pj_strcmp2(&tsx->branch, TEST1_BRANCH_ID)==0) {
155 /*
156 * Transaction with TEST1_BRANCH_ID should terminate with transaction
157 * timeout status.
158 */
159 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
160
161 if (test_complete == 0)
162 test_complete = 1;
163
164 /* Test the status code. */
165 if (tsx->status_code != PJSIP_SC_TSX_TIMEOUT) {
166 PJ_LOG(3,(THIS_FILE,
167 " error: status code is %d instead of %d",
168 tsx->status_code, PJSIP_SC_TSX_TIMEOUT));
169 test_complete = -710;
170 }
171 }
172
173 } else if (pj_strcmp2(&tsx->branch, TEST2_BRANCH_ID)==0) {
174 /*
175 * Transaction with TEST2_BRANCH_ID should terminate with transport error.
176 */
177 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
178
179 /* Test the status code. */
180 if (tsx->status_code != PJSIP_SC_TSX_TRANSPORT_ERROR) {
181 PJ_LOG(3,(THIS_FILE,
182 " error: status code is %d instead of %d",
183 tsx->status_code, PJSIP_SC_TSX_TRANSPORT_ERROR));
184 test_complete = -720;
185 }
186
187 if (test_complete == 0)
188 test_complete = 1;
189 }
190
191 } else if (pj_strcmp2(&tsx->branch, TEST3_BRANCH_ID)==0) {
192 /*
193 * This test terminates the transaction while resolver is still
194 * running.
195 */
196 if (tsx->state == PJSIP_TSX_STATE_CALLING) {
197
198 /* Terminate the transaction. */
199 pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED);
200
201 } else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
202
203 /* Check if status code is correct. */
204 if (tsx->status_code != PJSIP_SC_REQUEST_TERMINATED) {
205 PJ_LOG(3,(THIS_FILE,
206 " error: status code is %d instead of %d",
207 tsx->status_code, PJSIP_SC_REQUEST_TERMINATED));
208 test_complete = -730;
209 }
210
211 if (test_complete == 0)
212 test_complete = 1;
213
214 }
215
216 } else if (pj_strcmp2(&tsx->branch, TEST4_BRANCH_ID)==0) {
217 /*
218 * This test simulates transport failure after several
219 * retransmissions.
220 */
221 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
222
223 /* Status code must be transport error. */
224 if (tsx->status_code != PJSIP_SC_TSX_TRANSPORT_ERROR) {
225 PJ_LOG(3,(THIS_FILE,
226 " error: status code is %d instead of %d",
227 tsx->status_code, PJSIP_SC_TSX_TRANSPORT_ERROR));
228 test_complete = -730;
229 }
230
231 /* Must have correct retransmission count. */
232 if (tsx->retransmit_count != TEST4_RETRANSMIT_CNT) {
233 PJ_LOG(3,(THIS_FILE,
234 " error: retransmit cnt is %d instead of %d",
235 tsx->retransmit_count, TEST4_RETRANSMIT_CNT));
236 test_complete = -731;
237 }
238
239 if (test_complete == 0)
240 test_complete = 1;
241 }
242
243
244 } else if (pj_strcmp2(&tsx->branch, TEST5_BRANCH_ID)==0) {
245 /*
246 * This test simulates transport failure after several
247 * retransmissions.
248 */
249 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
250
251 /* Status code must be PJSIP_SC_REQUEST_TERMINATED. */
252 if (tsx->status_code != PJSIP_SC_REQUEST_TERMINATED) {
253 PJ_LOG(3,(THIS_FILE,
254 " error: status code is %d instead of %d",
255 tsx->status_code, PJSIP_SC_REQUEST_TERMINATED));
256 test_complete = -733;
257 }
258
259 /* Must have correct retransmission count. */
260 if (tsx->retransmit_count != TEST5_RETRANSMIT_CNT) {
261 PJ_LOG(3,(THIS_FILE,
262 " error: retransmit cnt is %d instead of %d",
263 tsx->retransmit_count, TEST5_RETRANSMIT_CNT));
264 test_complete = -734;
265 }
266
267 if (test_complete == 0)
268 test_complete = 1;
269 }
270
271
272 } else if (pj_strcmp2(&tsx->branch, TEST6_BRANCH_ID)==0) {
273 /*
274 * Successfull non-INVITE transaction.
275 */
276 if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
277
278 /* Status code must be 202. */
279 if (tsx->status_code != 202) {
280 PJ_LOG(3,(THIS_FILE,
281 " error: status code is %d instead of %d",
282 tsx->status_code, 202));
283 test_complete = -736;
284 }
285
286 /* Must have correct retransmission count. */
287 if (tsx->retransmit_count != 0) {
288 PJ_LOG(3,(THIS_FILE,
289 " error: retransmit cnt is %d instead of %d",
290 tsx->retransmit_count, 0));
291 test_complete = -737;
292 }
293
294 /* Must still keep last_tx */
295 if (tsx->last_tx == NULL) {
296 PJ_LOG(3,(THIS_FILE,
297 " error: transaction lost last_tx"));
298 test_complete = -738;
299 }
300
301 if (test_complete == 0) {
302 test_complete = 1;
303 pjsip_tsx_terminate(tsx, 202);
304 }
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000305
306 } else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
307
308 /* Previous state must be COMPLETED. */
309 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
310 test_complete = -7381;
311 }
312
Benny Prijono85598d92006-01-07 18:44:25 +0000313 }
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000314
315 } else if (pj_strcmp2(&tsx->branch, TEST7_BRANCH_ID)==0) {
316 /*
317 * Successfull non-INVITE transaction.
318 */
319 if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
320
321 /* Check prev state. */
322 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_PROCEEDING) {
323 PJ_LOG(3,(THIS_FILE,
324 " error: prev state is %s instead of %s",
325 pjsip_tsx_state_str(e->body.tsx_state.prev_state),
326 pjsip_tsx_state_str(PJSIP_TSX_STATE_PROCEEDING)));
327 test_complete = -739;
328 }
329
330 /* Status code must be 202. */
331 if (tsx->status_code != 202) {
332 PJ_LOG(3,(THIS_FILE,
333 " error: status code is %d instead of %d",
334 tsx->status_code, 202));
335 test_complete = -740;
336 }
337
338 /* Must have correct retransmission count. */
339 if (tsx->retransmit_count != 0) {
340 PJ_LOG(3,(THIS_FILE,
341 " error: retransmit cnt is %d instead of %d",
342 tsx->retransmit_count, 0));
343 test_complete = -741;
344 }
345
346 /* Must still keep last_tx */
347 if (tsx->last_tx == NULL) {
348 PJ_LOG(3,(THIS_FILE,
349 " error: transaction lost last_tx"));
350 test_complete = -741;
351 }
352
353 if (test_complete == 0) {
354 test_complete = 1;
355 pjsip_tsx_terminate(tsx, 202);
356 }
357
358 } else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
359
360 /* Previous state must be COMPLETED. */
361 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
362 test_complete = -742;
363 }
364
365 }
366
367
368 } else if (pj_strcmp2(&tsx->branch, TEST8_BRANCH_ID)==0) {
369 /*
370 * Failed INVITE transaction.
371 */
372 if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
373
374 /* Status code must be 301. */
375 if (tsx->status_code != 301) {
376 PJ_LOG(3,(THIS_FILE,
377 " error: status code is %d instead of %d",
378 tsx->status_code, 301));
379 test_complete = -745;
380 }
381
382 /* Must have correct retransmission count. */
383 if (tsx->retransmit_count != 0) {
384 PJ_LOG(3,(THIS_FILE,
385 " error: retransmit cnt is %d instead of %d",
386 tsx->retransmit_count, 0));
387 test_complete = -746;
388 }
389
390 /* Must still keep last_tx */
391 if (tsx->last_tx == NULL) {
392 PJ_LOG(3,(THIS_FILE,
393 " error: transaction lost last_tx"));
394 test_complete = -747;
395 }
396
Benny Prijono728a9052006-01-18 23:34:15 +0000397 /* last_tx MUST be the INVITE request
398 * (authorization depends on this behavior)
399 */
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000400 if (tsx->last_tx && tsx->last_tx->msg->line.req.method.id !=
Benny Prijono728a9052006-01-18 23:34:15 +0000401 PJSIP_INVITE_METHOD)
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000402 {
403 PJ_LOG(3,(THIS_FILE,
Benny Prijono728a9052006-01-18 23:34:15 +0000404 " error: last_tx is not INVITE"));
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000405 test_complete = -748;
406 }
407 }
408 else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
409
410 test_complete = 1;
411
412 /* Previous state must be COMPLETED. */
413 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
414 test_complete = -750;
415 }
416
417 /* Status code must be 301. */
418 if (tsx->status_code != 301) {
419 PJ_LOG(3,(THIS_FILE,
420 " error: status code is %d instead of %d",
421 tsx->status_code, 301));
422 test_complete = -751;
423 }
424
425 }
426
427
428 } else if (pj_strcmp2(&tsx->branch, TEST9_BRANCH_ID)==0) {
429 /*
430 * Failed INVITE transaction with provisional response.
431 */
432 if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
433
434 /* Previous state must be PJSIP_TSX_STATE_PROCEEDING. */
435 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_PROCEEDING) {
436 test_complete = -760;
437 }
438
439 /* Status code must be 302. */
440 if (tsx->status_code != 302) {
441 PJ_LOG(3,(THIS_FILE,
442 " error: status code is %d instead of %d",
443 tsx->status_code, 302));
444 test_complete = -761;
445 }
446
447 /* Must have correct retransmission count. */
448 if (tsx->retransmit_count != 0) {
449 PJ_LOG(3,(THIS_FILE,
450 " error: retransmit cnt is %d instead of %d",
451 tsx->retransmit_count, 0));
452 test_complete = -762;
453 }
454
455 /* Must still keep last_tx */
456 if (tsx->last_tx == NULL) {
457 PJ_LOG(3,(THIS_FILE,
458 " error: transaction lost last_tx"));
459 test_complete = -763;
460 }
461
Benny Prijono728a9052006-01-18 23:34:15 +0000462 /* last_tx MUST be INVITE.
463 * (authorization depends on this behavior)
464 */
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000465 if (tsx->last_tx && tsx->last_tx->msg->line.req.method.id !=
Benny Prijono728a9052006-01-18 23:34:15 +0000466 PJSIP_INVITE_METHOD)
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000467 {
468 PJ_LOG(3,(THIS_FILE,
Benny Prijono728a9052006-01-18 23:34:15 +0000469 " error: last_tx is not INVITE"));
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000470 test_complete = -764;
471 }
472
473 }
474 else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
475
476 test_complete = 1;
477
478 /* Previous state must be COMPLETED. */
479 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
480 test_complete = -767;
481 }
482
483 /* Status code must be 302. */
484 if (tsx->status_code != 302) {
485 PJ_LOG(3,(THIS_FILE,
486 " error: status code is %d instead of %d",
487 tsx->status_code, 302));
488 test_complete = -768;
489 }
490
491 }
492
Benny Prijono85598d92006-01-07 18:44:25 +0000493 }
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000494}
495
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000496/*
497 * This timer callback is called to send delayed response.
498 */
499struct response
500{
501 pjsip_response_addr res_addr;
502 pjsip_tx_data *tdata;
503};
504
505static void send_response_callback( pj_timer_heap_t *timer_heap,
506 struct pj_timer_entry *entry)
507{
508 struct response *r = entry->user_data;
509 pjsip_transport *tp = r->res_addr.transport;
510
511 pjsip_endpt_send_response(endpt, &r->res_addr, r->tdata, NULL, NULL);
512 if (tp)
513 pjsip_transport_dec_ref(tp);
514}
515
516/* Timer callback to terminate a transaction. */
517static void terminate_tsx_callback( pj_timer_heap_t *timer_heap,
518 struct pj_timer_entry *entry)
519{
520 pjsip_transaction *tsx = entry->user_data;
521 int status_code = entry->id;
522
523 if (tsx) {
524 pjsip_tsx_terminate(tsx, status_code);
525 }
526}
527
528
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000529#define DIFF(a,b) ((a<b) ? (b-a) : (a-b))
530
Benny Prijono85598d92006-01-07 18:44:25 +0000531/*
532 * This is the handler to receive message for this test. It is used to
533 * control and verify the behavior of the message transmitted by the
534 * transaction.
535 */
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000536static pj_bool_t msg_receiver_on_rx_request(pjsip_rx_data *rdata)
537{
Benny Prijono85598d92006-01-07 18:44:25 +0000538 if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST1_BRANCH_ID) == 0) {
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000539 /*
Benny Prijono85598d92006-01-07 18:44:25 +0000540 * The TEST1_BRANCH_ID test performs the verifications for transaction
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000541 * retransmission mechanism. It will not answer the incoming request
542 * with any response.
543 */
544 pjsip_msg *msg = rdata->msg_info.msg;
545
Benny Prijono85598d92006-01-07 18:44:25 +0000546 PJ_LOG(4,(THIS_FILE, " received request"));
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000547
548 /* Only wants to take INVITE or OPTIONS method. */
549 if (msg->line.req.method.id != PJSIP_INVITE_METHOD &&
550 msg->line.req.method.id != PJSIP_OPTIONS_METHOD)
551 {
Benny Prijono85598d92006-01-07 18:44:25 +0000552 PJ_LOG(3,(THIS_FILE, " error: received unexpected method %.*s",
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000553 msg->line.req.method.name.slen,
554 msg->line.req.method.name.ptr));
555 test_complete = -600;
556 return PJ_TRUE;
557 }
558
559 if (recv_count == 0) {
560 recv_count++;
Benny Prijono85598d92006-01-07 18:44:25 +0000561 //pj_gettimeofday(&recv_last);
562 recv_last = rdata->pkt_info.timestamp;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000563 } else {
564 pj_time_val now;
565 unsigned msec_expected, msec_elapsed;
Benny Prijono85598d92006-01-07 18:44:25 +0000566 int max_received;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000567
Benny Prijono85598d92006-01-07 18:44:25 +0000568 //pj_gettimeofday(&now);
569 now = rdata->pkt_info.timestamp;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000570 PJ_TIME_VAL_SUB(now, recv_last);
571 msec_elapsed = now.sec*1000 + now.msec;
572
573 ++recv_count;
574 msec_expected = (1<<(recv_count-2))*PJSIP_T1_TIMEOUT;
575
576 if (msg->line.req.method.id != PJSIP_INVITE_METHOD) {
577 if (msec_expected > PJSIP_T2_TIMEOUT)
578 msec_expected = PJSIP_T2_TIMEOUT;
Benny Prijono85598d92006-01-07 18:44:25 +0000579 max_received = 11;
580 } else {
581 max_received = 7;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000582 }
583
Benny Prijono85598d92006-01-07 18:44:25 +0000584 if (DIFF(msec_expected, msec_elapsed) > TEST1_ALLOWED_DIFF) {
585 PJ_LOG(3,(THIS_FILE,
586 " error: expecting retransmission no. %d in %d "
587 "ms, received in %d ms",
588 recv_count-1, msec_expected, msec_elapsed));
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000589 test_complete = -610;
590 }
591
Benny Prijono85598d92006-01-07 18:44:25 +0000592
593 if (recv_count > max_received) {
594 PJ_LOG(3,(THIS_FILE,
595 " error: too many messages (%d) received",
596 recv_count));
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000597 test_complete = -620;
598 }
599
Benny Prijono85598d92006-01-07 18:44:25 +0000600 //pj_gettimeofday(&recv_last);
601 recv_last = rdata->pkt_info.timestamp;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000602 }
603 return PJ_TRUE;
Benny Prijono85598d92006-01-07 18:44:25 +0000604
605 } else
606 if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST4_BRANCH_ID) == 0) {
607 /*
608 * The TEST4_BRANCH_ID test simulates transport failure after several
609 * retransmissions.
610 */
611 recv_count++;
612
613 if (recv_count == TEST4_RETRANSMIT_CNT) {
614 /* Simulate transport failure. */
615 pjsip_loop_set_failure(loop, 2, NULL);
616
617 } else if (recv_count > TEST4_RETRANSMIT_CNT) {
618 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
619 recv_count));
620 test_complete = -631;
621 }
622
623 return PJ_TRUE;
624
625
626 } else
627 if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST5_BRANCH_ID) == 0) {
628 /*
629 * The TEST5_BRANCH_ID test simulates user terminating the transaction
630 * after several retransmissions.
631 */
632 recv_count++;
633
634 if (recv_count == TEST5_RETRANSMIT_CNT+1) {
635 pj_str_t key;
636 pjsip_transaction *tsx;
637
638 pjsip_tsx_create_key( rdata->tp_info.pool, &key, PJSIP_ROLE_UAC,
639 &rdata->msg_info.msg->line.req.method, rdata);
640 tsx = pjsip_tsx_layer_find_tsx(&key, PJ_TRUE);
641 if (tsx) {
642 pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED);
643 pj_mutex_unlock(tsx->mutex);
644 } else {
645 PJ_LOG(3,(THIS_FILE, " error: uac transaction not found!"));
646 test_complete = -633;
647 }
648
649 } else if (recv_count > TEST5_RETRANSMIT_CNT+1) {
650 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
651 recv_count));
652 test_complete = -634;
653 }
654
655 return PJ_TRUE;
656
657 } else
658 if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST6_BRANCH_ID) == 0) {
659 /*
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000660 * The TEST6_BRANCH_ID test successfull non-INVITE transaction.
Benny Prijono85598d92006-01-07 18:44:25 +0000661 */
Benny Prijono85598d92006-01-07 18:44:25 +0000662 pj_status_t status;
663
664 recv_count++;
665
666 if (recv_count > 1) {
667 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
668 recv_count));
669 test_complete = -635;
670 }
671
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000672 status = pjsip_endpt_respond_stateless(endpt, rdata, 202, NULL,
673 NULL, NULL);
Benny Prijono85598d92006-01-07 18:44:25 +0000674 if (status != PJ_SUCCESS) {
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000675 app_perror(" error: unable to send response", status);
Benny Prijono85598d92006-01-07 18:44:25 +0000676 test_complete = -636;
677 }
678
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000679 return PJ_TRUE;
680
681
682 } else
683 if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST7_BRANCH_ID) == 0) {
684 /*
685 * The TEST7_BRANCH_ID test successfull non-INVITE transaction
686 * with provisional response.
687 */
688 pj_status_t status;
689 pjsip_response_addr res_addr;
690 struct response *r;
691 pjsip_tx_data *tdata;
692 pj_time_val delay = { 2, 0 };
693
694 recv_count++;
695
696 if (recv_count > 1) {
697 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
698 recv_count));
699 test_complete = -640;
700 return PJ_TRUE;
Benny Prijono85598d92006-01-07 18:44:25 +0000701 }
702
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000703 /* Respond with provisional response */
704 status = pjsip_endpt_create_response(endpt, rdata, 100, NULL, &tdata);
705 pj_assert(status == PJ_SUCCESS);
706
707 status = pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
708 pj_assert(status == PJ_SUCCESS);
709
710 status = pjsip_endpt_send_response(endpt, &res_addr, tdata,
711 NULL, NULL);
712 pj_assert(status == PJ_SUCCESS);
713
714 /* Create the final response. */
715 status = pjsip_endpt_create_response(endpt, rdata, 202, NULL, &tdata);
716 pj_assert(status == PJ_SUCCESS);
717
718 /* Schedule sending final response in couple of of secs. */
719 r = pj_pool_alloc(tdata->pool, sizeof(*r));
720 r->res_addr = res_addr;
721 r->tdata = tdata;
722 if (r->res_addr.transport)
723 pjsip_transport_add_ref(r->res_addr.transport);
724
725 timer.cb = &send_response_callback;
726 timer.user_data = r;
727 pjsip_endpt_schedule_timer(endpt, &timer, &delay);
728
729 return PJ_TRUE;
730
731
732 } else
733 if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST8_BRANCH_ID) == 0) {
734 /*
735 * The TEST8_BRANCH_ID test failed INVITE transaction.
736 */
737 pjsip_method *method;
738 pj_status_t status;
739
740 method = &rdata->msg_info.msg->line.req.method;
741
742 recv_count++;
743
744 if (method->id == PJSIP_INVITE_METHOD) {
745
746 if (recv_count > 1) {
747 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
748 recv_count));
749 test_complete = -635;
750 }
751
752 status = pjsip_endpt_respond_stateless(endpt, rdata, 301, NULL,
753 NULL, NULL);
754 if (status != PJ_SUCCESS) {
755 app_perror(" error: unable to send response", status);
756 test_complete = -636;
757 }
758
759 } else if (method->id == PJSIP_ACK_METHOD) {
760
761 if (recv_count == 2) {
762 pj_str_t key;
763 pj_time_val delay = { 5, 0 };
764
765 /* Schedule timer to destroy transaction after 5 seconds.
766 * This is to make sure that transaction does not
767 * retransmit ACK.
768 */
769 pjsip_tsx_create_key(rdata->tp_info.pool, &key,
770 PJSIP_ROLE_UAC, &pjsip_invite_method,
771 rdata);
772
773 timer.user_data = pjsip_tsx_layer_find_tsx(&key, PJ_FALSE);
774 timer.id = 301;
775 timer.cb = &terminate_tsx_callback;
776
777 pjsip_endpt_schedule_timer(endpt, &timer, &delay);
778 }
779
780 if (recv_count > 2) {
781 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
782 recv_count));
783 test_complete = -638;
784 }
785
786
787 } else {
788 PJ_LOG(3,(THIS_FILE," error: not expecting %s",
789 pjsip_rx_data_get_info(rdata)));
790 test_complete = -639;
791
792 }
793
794
795 } else
796 if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST9_BRANCH_ID) == 0) {
797 /*
798 * The TEST9_BRANCH_ID test failed INVITE transaction with
799 * provisional response.
800 */
801 pjsip_method *method;
802 pj_status_t status;
803
804 method = &rdata->msg_info.msg->line.req.method;
805
806 recv_count++;
807
808 if (method->id == PJSIP_INVITE_METHOD) {
809
810 pjsip_response_addr res_addr;
811 struct response *r;
812 pjsip_tx_data *tdata;
813 pj_time_val delay = { 2, 0 };
814
815 if (recv_count > 1) {
816 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
817 recv_count));
818 test_complete = -650;
819 return PJ_TRUE;
820 }
821
822 /* Respond with provisional response */
823 status = pjsip_endpt_create_response(endpt, rdata, 100, NULL,
824 &tdata);
825 pj_assert(status == PJ_SUCCESS);
826
827 status = pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
828 pj_assert(status == PJ_SUCCESS);
829
830 status = pjsip_endpt_send_response(endpt, &res_addr, tdata,
831 NULL, NULL);
832 pj_assert(status == PJ_SUCCESS);
833
834 /* Create the final response. */
835 status = pjsip_endpt_create_response(endpt, rdata, 302, NULL,
836 &tdata);
837 pj_assert(status == PJ_SUCCESS);
838
839 /* Schedule sending final response in couple of of secs. */
840 r = pj_pool_alloc(tdata->pool, sizeof(*r));
841 r->res_addr = res_addr;
842 r->tdata = tdata;
843 if (r->res_addr.transport)
844 pjsip_transport_add_ref(r->res_addr.transport);
845
846 timer.cb = &send_response_callback;
847 timer.user_data = r;
848 pjsip_endpt_schedule_timer(endpt, &timer, &delay);
849
850 } else if (method->id == PJSIP_ACK_METHOD) {
851
852 if (recv_count == 2) {
853 pj_str_t key;
854 pj_time_val delay = { 5, 0 };
855
856 /* Schedule timer to destroy transaction after 5 seconds.
857 * This is to make sure that transaction does not
858 * retransmit ACK.
859 */
860 pjsip_tsx_create_key(rdata->tp_info.pool, &key,
861 PJSIP_ROLE_UAC, &pjsip_invite_method,
862 rdata);
863
864 timer.user_data = pjsip_tsx_layer_find_tsx(&key, PJ_FALSE);
865 timer.id = 302;
866 timer.cb = &terminate_tsx_callback;
867
868 pjsip_endpt_schedule_timer(endpt, &timer, &delay);
869 }
870
871 if (recv_count > 2) {
872 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
873 recv_count));
874 test_complete = -638;
875 }
876
877
878 } else {
879 PJ_LOG(3,(THIS_FILE," error: not expecting %s",
880 pjsip_rx_data_get_info(rdata)));
881 test_complete = -639;
882
Benny Prijono85598d92006-01-07 18:44:25 +0000883 }
884
885 return PJ_TRUE;
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000886
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000887 }
Benny Prijono85598d92006-01-07 18:44:25 +0000888
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000889 return PJ_FALSE;
890}
891
Benny Prijono85598d92006-01-07 18:44:25 +0000892/*
893 * The generic test framework, used by most of the tests.
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000894 */
Benny Prijono85598d92006-01-07 18:44:25 +0000895static int perform_tsx_test(int dummy, char *target_uri, char *from_uri,
896 char *branch_param, int test_time,
897 const pjsip_method *method)
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000898{
899 pjsip_tx_data *tdata;
900 pjsip_transaction *tsx;
Benny Prijono85598d92006-01-07 18:44:25 +0000901 pj_str_t target, from, tsx_key;
902 pjsip_via_hdr *via;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000903 pj_time_val timeout;
904 pj_status_t status;
905
Benny Prijono85598d92006-01-07 18:44:25 +0000906 PJ_LOG(3,(THIS_FILE,
907 " please standby, this will take at most %d seconds..",
908 test_time));
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000909
Benny Prijono85598d92006-01-07 18:44:25 +0000910 /* Reset test. */
911 recv_count = 0;
912 test_complete = 0;
913
914 /* Init headers. */
915 target = pj_str(target_uri);
916 from = pj_str(from_uri);
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000917
918 /* Create request. */
919 status = pjsip_endpt_create_request( endpt, method, &target,
Benny Prijono85598d92006-01-07 18:44:25 +0000920 &from, &target, NULL, NULL, -1,
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000921 NULL, &tdata);
922 if (status != PJ_SUCCESS) {
923 app_perror(" Error: unable to create request", status);
Benny Prijono85598d92006-01-07 18:44:25 +0000924 return -100;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000925 }
926
Benny Prijono85598d92006-01-07 18:44:25 +0000927 /* Set the branch param for test 1. */
928 via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
929 via->branch_param = pj_str(branch_param);
930
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000931 /* Add additional reference to tdata to prevent transaction from
932 * deleting it.
933 */
934 pjsip_tx_data_add_ref(tdata);
935
936 /* Create transaction. */
937 status = pjsip_tsx_create_uac( &tsx_user, tdata, &tsx);
938 if (status != PJ_SUCCESS) {
939 app_perror(" Error: unable to create UAC transaction", status);
Benny Prijono85598d92006-01-07 18:44:25 +0000940 pjsip_tx_data_dec_ref(tdata);
941 return -110;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000942 }
943
944 /* Get transaction key. */
945 pj_strdup(tdata->pool, &tsx_key, &tsx->transaction_key);
946
947 /* Send the message. */
948 status = pjsip_tsx_send_msg(tsx, NULL);
Benny Prijono85598d92006-01-07 18:44:25 +0000949 // Ignore send result. Some tests do deliberately triggers error
950 // when sending message.
951 //if (status != PJ_SUCCESS) {
952 // app_perror(" Error: unable to send request", status);
953 // pjsip_tx_data_dec_ref(tdata);
954 // return -120;
955 //}
956
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000957
958 /* Set test completion time. */
959 pj_gettimeofday(&timeout);
Benny Prijono85598d92006-01-07 18:44:25 +0000960 timeout.sec += test_time;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000961
962 /* Wait until test complete. */
963 while (!test_complete) {
Benny Prijono85598d92006-01-07 18:44:25 +0000964 pj_time_val now, poll_delay = {0, 10};
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000965
Benny Prijono85598d92006-01-07 18:44:25 +0000966 pjsip_endpt_handle_events(endpt, &poll_delay);
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000967
968 pj_gettimeofday(&now);
969 if (now.sec > timeout.sec) {
Benny Prijono85598d92006-01-07 18:44:25 +0000970 PJ_LOG(3,(THIS_FILE, " Error: test has timed out"));
971 pjsip_tx_data_dec_ref(tdata);
972 return -130;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000973 }
974 }
975
Benny Prijono85598d92006-01-07 18:44:25 +0000976 if (test_complete < 0) {
977 tsx = pjsip_tsx_layer_find_tsx(&tsx_key, PJ_TRUE);
978 if (tsx) {
979 pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED);
980 pj_mutex_unlock(tsx->mutex);
981 flush_events(1000);
982 }
983 pjsip_tx_data_dec_ref(tdata);
984 return test_complete;
985 }
986
987 /* Allow transaction to destroy itself */
988 flush_events(500);
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000989
990 /* Make sure transaction has been destroyed. */
991 if (pjsip_tsx_layer_find_tsx(&tsx_key, PJ_FALSE) != NULL) {
Benny Prijono85598d92006-01-07 18:44:25 +0000992 PJ_LOG(3,(THIS_FILE, " Error: transaction has not been destroyed"));
993 pjsip_tx_data_dec_ref(tdata);
994 return -140;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000995 }
996
997 /* Check tdata reference counter. */
998 if (pj_atomic_get(tdata->ref_cnt) != 1) {
Benny Prijono85598d92006-01-07 18:44:25 +0000999 PJ_LOG(3,(THIS_FILE, " Error: tdata reference counter is %d",
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001000 pj_atomic_get(tdata->ref_cnt)));
Benny Prijono85598d92006-01-07 18:44:25 +00001001 pjsip_tx_data_dec_ref(tdata);
1002 return -150;
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001003 }
1004
1005 /* Destroy txdata */
1006 pjsip_tx_data_dec_ref(tdata);
1007
1008 return PJ_SUCCESS;
1009}
1010
1011/*****************************************************************************
1012 **
Benny Prijono85598d92006-01-07 18:44:25 +00001013 ** TEST1_BRANCH_ID: UAC basic retransmission and timeout test.
1014 **
1015 ** This will test the retransmission of the UAC transaction. Remote will not
1016 ** answer the transaction, so the transaction should fail. The Via branch prm
1017 ** TEST1_BRANCH_ID will be used for this test.
1018 **
1019 *****************************************************************************
1020 */
1021static int tsx_uac_retransmit_test(void)
1022{
1023 int status, enabled;
1024 int i;
1025 struct {
1026 const pjsip_method *method;
1027 unsigned delay;
1028 } sub_test[] =
1029 {
1030 { &pjsip_invite_method, 0},
1031 { &pjsip_invite_method, TEST1_ALLOWED_DIFF*2},
1032 { &pjsip_options_method, 0},
1033 { &pjsip_options_method, TEST1_ALLOWED_DIFF*2}
1034 };
1035
1036 PJ_LOG(3,(THIS_FILE, " test1: basic uac retransmit and timeout test"));
1037
1038
1039 /* For this test. message printing shound be disabled because it makes
1040 * incorrect timing.
1041 */
1042 enabled = msg_logger_set_enabled(0);
1043
1044 for (i=0; i<PJ_ARRAY_SIZE(sub_test); ++i) {
1045
1046 PJ_LOG(3,(THIS_FILE,
1047 " variant %c: %s with %d ms network delay",
1048 ('a' + i),
1049 sub_test[i].method->name.ptr,
1050 sub_test[i].delay));
1051
1052 /* Configure transport */
1053 pjsip_loop_set_failure(loop, 0, NULL);
1054 pjsip_loop_set_recv_delay(loop, sub_test[i].delay, NULL);
1055
1056 /* Do the test. */
1057 status = perform_tsx_test(-500, "sip:bob@127.0.0.1;transport=loop-dgram",
1058 "sip:alice@127.0.0.1;transport=loop-dgram",
1059 TEST1_BRANCH_ID,
1060 35, sub_test[i].method);
1061 if (status != 0)
1062 break;
1063 }
1064
1065 /* Restore transport. */
1066 pjsip_loop_set_recv_delay(loop, 0, NULL);
1067
1068 /* Restore msg logger. */
1069 msg_logger_set_enabled(enabled);
1070
1071 /* Done. */
1072 return status;
1073}
1074
1075/*****************************************************************************
1076 **
1077 ** TEST2_BRANCH_ID: UAC resolve error test.
1078 **
1079 ** Test the scenario where destination host is unresolvable. There are
1080 ** two variants:
1081 ** (a) resolver returns immediate error
1082 ** (b) resolver returns error via the callback.
1083 **
1084 *****************************************************************************
1085 */
1086static int tsx_resolve_error_test(void)
1087{
1088 int status;
1089
1090 PJ_LOG(3,(THIS_FILE, " test2: resolve error test"));
1091
1092 /*
1093 * Variant (a): immediate resolve error.
1094 */
1095 PJ_LOG(3,(THIS_FILE, " variant a: immediate resolving error"));
1096
1097 status = perform_tsx_test(-800,
1098 "sip:bob@unresolved-host;transport=loop-dgram",
1099 "sip:alice@127.0.0.1;transport=loop-dgram",
1100 TEST2_BRANCH_ID, 10,
1101 &pjsip_options_method);
1102 if (status != 0)
1103 return status;
1104
1105 /*
1106 * Variant (b): error via callback.
1107 */
1108 PJ_LOG(3,(THIS_FILE, " variant b: error via callback"));
1109
1110 /* Set loop transport to return delayed error. */
1111 pjsip_loop_set_failure(loop, 2, NULL);
1112 pjsip_loop_set_send_callback_delay(loop, 10, NULL);
1113
1114 status = perform_tsx_test(-800, "sip:bob@127.0.0.1;transport=loop-dgram",
1115 "sip:alice@127.0.0.1;transport=loop-dgram",
1116 TEST2_BRANCH_ID, 2,
1117 &pjsip_options_method);
1118 if (status != 0)
1119 return status;
1120
1121 /* Restore loop transport settings. */
1122 pjsip_loop_set_failure(loop, 0, NULL);
1123 pjsip_loop_set_send_callback_delay(loop, 0, NULL);
1124
1125 return status;
1126}
1127
1128
1129/*****************************************************************************
1130 **
1131 ** TEST3_BRANCH_ID: UAC terminate while resolving test.
1132 **
1133 ** Terminate the transaction while resolver is still running.
1134 **
1135 *****************************************************************************
1136 */
1137static int tsx_terminate_resolving_test(void)
1138{
1139 unsigned prev_delay;
1140 pj_status_t status;
1141
1142 PJ_LOG(3,(THIS_FILE, " test3: terminate while resolving test"));
1143
1144 /* Configure transport delay. */
1145 pjsip_loop_set_send_callback_delay(loop, 100, &prev_delay);
1146
1147 /* Start the test. */
1148 status = perform_tsx_test(-900, "sip:127.0.0.1;transport=loop-dgram",
1149 "sip:127.0.0.1;transport=loop-dgram",
1150 TEST3_BRANCH_ID, 2, &pjsip_options_method);
1151
1152 /* Restore delay. */
1153 pjsip_loop_set_send_callback_delay(loop, prev_delay, NULL);
1154
1155 return status;
1156}
1157
1158
1159/*****************************************************************************
1160 **
1161 ** TEST4_BRANCH_ID: Transport failed after several retransmissions
1162 **
1163 ** There are two variants of this test: (a) failure occurs immediately when
1164 ** transaction calls pjsip_transport_send() or (b) failure is reported via
1165 ** transport callback.
1166 **
1167 *****************************************************************************
1168 */
1169static int tsx_retransmit_fail_test(void)
1170{
1171 int i;
1172 unsigned delay[] = {0, 10};
1173 pj_status_t status;
1174
1175 PJ_LOG(3,(THIS_FILE,
1176 " test4: transport fails after several retransmissions test"));
1177
1178
1179 for (i=0; i<PJ_ARRAY_SIZE(delay); ++i) {
1180
1181 PJ_LOG(3,(THIS_FILE,
1182 " variant %c: transport delay %d ms", ('a'+i), delay[i]));
1183
1184 /* Configure transport delay. */
1185 pjsip_loop_set_send_callback_delay(loop, delay[i], NULL);
1186
1187 /* Restore transport failure mode. */
1188 pjsip_loop_set_failure(loop, 0, 0);
1189
1190 /* Start the test. */
1191 status = perform_tsx_test(-1000, "sip:127.0.0.1;transport=loop-dgram",
1192 "sip:127.0.0.1;transport=loop-dgram",
1193 TEST4_BRANCH_ID, 6, &pjsip_options_method);
1194
1195 if (status != 0)
1196 break;
1197
1198 }
1199
1200 /* Restore delay. */
1201 pjsip_loop_set_send_callback_delay(loop, 0, NULL);
1202
1203 /* Restore transport failure mode. */
1204 pjsip_loop_set_failure(loop, 0, 0);
1205
1206 return status;
1207}
1208
1209
1210/*****************************************************************************
1211 **
1212 ** TEST5_BRANCH_ID: Terminate transaction after several retransmissions
1213 **
1214 *****************************************************************************
1215 */
1216static int tsx_terminate_after_retransmit_test(void)
1217{
1218 int status;
1219
1220 PJ_LOG(3,(THIS_FILE, " test5: terminate after retransmissions"));
1221
1222 /* Do the test. */
1223 status = perform_tsx_test(-1100, "sip:bob@127.0.0.1;transport=loop-dgram",
1224 "sip:alice@127.0.0.1;transport=loop-dgram",
1225 TEST5_BRANCH_ID,
1226 6, &pjsip_options_method);
1227
1228 /* Done. */
1229 return status;
1230}
1231
1232
1233/*****************************************************************************
1234 **
1235 ** TEST6_BRANCH_ID: Successfull non-invite transaction
Benny Prijono9c1d9f52006-01-07 23:01:56 +00001236 ** TEST7_BRANCH_ID: Successfull non-invite transaction with provisional
1237 ** TEST8_BRANCH_ID: Failed invite transaction
1238 ** TEST9_BRANCH_ID: Failed invite transaction with provisional
Benny Prijono85598d92006-01-07 18:44:25 +00001239 **
1240 *****************************************************************************
1241 */
Benny Prijono9c1d9f52006-01-07 23:01:56 +00001242static int perform_generic_test( const char *title,
1243 char *branch_id,
1244 const pjsip_method *method)
Benny Prijono85598d92006-01-07 18:44:25 +00001245{
1246 int i, status;
1247 unsigned delay[] = { 1, 200 };
1248
Benny Prijonoe8a2ff52006-01-07 23:36:57 +00001249 PJ_LOG(3,(THIS_FILE, " %s", title));
Benny Prijono85598d92006-01-07 18:44:25 +00001250
1251 /* Do the test. */
1252 for (i=0; i<PJ_ARRAY_SIZE(delay); ++i) {
1253
1254 PJ_LOG(3,(THIS_FILE, " variant %c: with %d ms transport delay",
1255 ('a'+i), delay[i]));
1256
1257 pjsip_loop_set_delay(loop, delay[i]);
1258
1259 status = perform_tsx_test(-1200,
1260 "sip:bob@127.0.0.1;transport=loop-dgram",
1261 "sip:alice@127.0.0.1;transport=loop-dgram",
Benny Prijono9c1d9f52006-01-07 23:01:56 +00001262 branch_id,
1263 10, method);
Benny Prijono85598d92006-01-07 18:44:25 +00001264 if (status != 0)
1265 return status;
1266 }
1267
1268 pjsip_loop_set_delay(loop, 0);
1269
1270 /* Done. */
1271 return status;
1272}
1273
1274
1275/*****************************************************************************
1276 **
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001277 ** UAC Transaction Test.
1278 **
1279 *****************************************************************************
1280 */
1281int tsx_uac_test(void)
1282{
1283 pj_sockaddr_in addr;
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001284 pj_status_t status;
1285
Benny Prijono85598d92006-01-07 18:44:25 +00001286 /* Check if loop transport is configured. */
1287 status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_LOOP_DGRAM,
1288 &addr, sizeof(addr), &loop);
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001289 if (status != PJ_SUCCESS) {
Benny Prijono85598d92006-01-07 18:44:25 +00001290 PJ_LOG(3,(THIS_FILE, " Error: loop transport is not configured!"));
1291 return -10;
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001292 }
1293
1294 /* Register modules. */
1295 status = pjsip_endpt_register_module(endpt, &tsx_user);
1296 if (status != PJ_SUCCESS) {
1297 app_perror(" Error: unable to register module", status);
1298 return -30;
1299 }
1300 status = pjsip_endpt_register_module(endpt, &msg_receiver);
1301 if (status != PJ_SUCCESS) {
1302 app_perror(" Error: unable to register module", status);
Benny Prijono85598d92006-01-07 18:44:25 +00001303 return -40;
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001304 }
1305
Benny Prijono85598d92006-01-07 18:44:25 +00001306 /* TEST1_BRANCH_ID: Basic retransmit and timeout test. */
1307 status = tsx_uac_retransmit_test();
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001308 if (status != 0)
1309 return status;
1310
Benny Prijono85598d92006-01-07 18:44:25 +00001311 /* TEST2_BRANCH_ID: Resolve error test. */
1312 status = tsx_resolve_error_test();
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001313 if (status != 0)
1314 return status;
1315
Benny Prijono85598d92006-01-07 18:44:25 +00001316 /* TEST3_BRANCH_ID: UAC terminate while resolving test. */
1317 status = tsx_terminate_resolving_test();
1318 if (status != 0)
1319 return status;
1320
1321 /* TEST4_BRANCH_ID: Transport failed after several retransmissions */
1322 status = tsx_retransmit_fail_test();
1323 if (status != 0)
1324 return status;
1325
1326 /* TEST5_BRANCH_ID: Terminate transaction after several retransmissions */
1327 status = tsx_terminate_after_retransmit_test();
1328 if (status != 0)
1329 return status;
Benny Prijono85598d92006-01-07 18:44:25 +00001330
1331 /* TEST6_BRANCH_ID: Successfull non-invite transaction */
Benny Prijonoe8a2ff52006-01-07 23:36:57 +00001332 status = perform_generic_test("test6: successfull non-invite transaction",
Benny Prijono9c1d9f52006-01-07 23:01:56 +00001333 TEST6_BRANCH_ID, &pjsip_options_method);
1334 if (status != 0)
1335 return status;
1336
1337 /* TEST7_BRANCH_ID: Successfull non-invite transaction */
Benny Prijonoe8a2ff52006-01-07 23:36:57 +00001338 status = perform_generic_test("test7: successfull non-invite transaction "
Benny Prijono9c1d9f52006-01-07 23:01:56 +00001339 "with provisional response",
1340 TEST7_BRANCH_ID, &pjsip_options_method);
1341 if (status != 0)
1342 return status;
1343
1344 /* TEST8_BRANCH_ID: Failed invite transaction */
Benny Prijonoe8a2ff52006-01-07 23:36:57 +00001345 status = perform_generic_test("test8: failed invite transaction",
Benny Prijono9c1d9f52006-01-07 23:01:56 +00001346 TEST8_BRANCH_ID, &pjsip_invite_method);
1347 if (status != 0)
1348 return status;
1349
1350 /* TEST9_BRANCH_ID: Failed invite transaction with provisional response */
Benny Prijonoe8a2ff52006-01-07 23:36:57 +00001351 status = perform_generic_test("test9: failed invite transaction with "
Benny Prijono9c1d9f52006-01-07 23:01:56 +00001352 "provisional response",
1353 TEST9_BRANCH_ID, &pjsip_invite_method);
Benny Prijono85598d92006-01-07 18:44:25 +00001354 if (status != 0)
1355 return status;
1356
1357
1358 pjsip_transport_dec_ref(loop);
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001359 return 0;
1360}
Benny Prijono85598d92006-01-07 18:44:25 +00001361