inv_offer_answer_test.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  1. /*
  2. * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
  3. * Copyright (C) 2003-2008 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. #include "test.h"
  20. #include <pjsip_ua.h>
  21. #include <pjsip.h>
  22. #include <pjlib.h>
  23. #define THIS_FILE "inv_offer_answer_test.c"
  24. #define PORT 5068
  25. #define CONTACT "sip:127.0.0.1:5068"
  26. #define TRACE_(x) PJ_LOG(3,x)
  27. static struct oa_sdp_t
  28. {
  29. const char *offer;
  30. const char *answer;
  31. unsigned pt_result;
  32. } oa_sdp[] =
  33. {
  34. {
  35. /* Offer: */
  36. "v=0\r\n"
  37. "o=alice 1 1 IN IP4 host.anywhere.com\r\n"
  38. "s= \r\n"
  39. "c=IN IP4 host.anywhere.com\r\n"
  40. "t=0 0\r\n"
  41. "m=audio 49170 RTP/AVP 0\r\n"
  42. "a=rtpmap:0 PCMU/8000\r\n",
  43. /* Answer: */
  44. "v=0\r\n"
  45. "o=bob 1 1 IN IP4 host.example.com\r\n"
  46. "s= \r\n"
  47. "c=IN IP4 host.example.com\r\n"
  48. "t=0 0\r\n"
  49. "m=audio 49920 RTP/AVP 0\r\n"
  50. "a=rtpmap:0 PCMU/8000\r\n"
  51. "m=video 0 RTP/AVP 31\r\n",
  52. 0
  53. },
  54. {
  55. /* Offer: */
  56. "v=0\r\n"
  57. "o=alice 2 2 IN IP4 host.anywhere.com\r\n"
  58. "s= \r\n"
  59. "c=IN IP4 host.anywhere.com\r\n"
  60. "t=0 0\r\n"
  61. "m=audio 49170 RTP/AVP 8\r\n"
  62. "a=rtpmap:0 PCMA/8000\r\n",
  63. /* Answer: */
  64. "v=0\r\n"
  65. "o=bob 2 2 IN IP4 host.example.com\r\n"
  66. "s= \r\n"
  67. "c=IN IP4 host.example.com\r\n"
  68. "t=0 0\r\n"
  69. "m=audio 49920 RTP/AVP 8\r\n"
  70. "a=rtpmap:0 PCMA/8000\r\n",
  71. 8
  72. },
  73. {
  74. /* Offer: */
  75. "v=0\r\n"
  76. "o=alice 3 3 IN IP4 host.anywhere.com\r\n"
  77. "s= \r\n"
  78. "c=IN IP4 host.anywhere.com\r\n"
  79. "t=0 0\r\n"
  80. "m=audio 49170 RTP/AVP 3\r\n",
  81. /* Answer: */
  82. "v=0\r\n"
  83. "o=bob 3 3 IN IP4 host.example.com\r\n"
  84. "s= \r\n"
  85. "c=IN IP4 host.example.com\r\n"
  86. "t=0 0\r\n"
  87. "m=audio 49920 RTP/AVP 3\r\n",
  88. 3
  89. },
  90. {
  91. /* Offer: */
  92. "v=0\r\n"
  93. "o=alice 4 4 IN IP4 host.anywhere.com\r\n"
  94. "s= \r\n"
  95. "c=IN IP4 host.anywhere.com\r\n"
  96. "t=0 0\r\n"
  97. "m=audio 49170 RTP/AVP 4\r\n",
  98. /* Answer: */
  99. "v=0\r\n"
  100. "o=bob 4 4 IN IP4 host.example.com\r\n"
  101. "s= \r\n"
  102. "c=IN IP4 host.example.com\r\n"
  103. "t=0 0\r\n"
  104. "m=audio 49920 RTP/AVP 4\r\n",
  105. 4
  106. }
  107. };
  108. typedef enum oa_t
  109. {
  110. OFFERER_NONE,
  111. OFFERER_UAC,
  112. OFFERER_UAS
  113. } oa_t;
  114. typedef struct inv_test_param_t
  115. {
  116. char *title;
  117. unsigned inv_option;
  118. pj_bool_t need_established;
  119. unsigned count;
  120. oa_t oa[4];
  121. pj_bool_t multipart_body;
  122. } inv_test_param_t;
  123. typedef struct inv_test_t
  124. {
  125. inv_test_param_t param;
  126. pjsip_inv_session *uac;
  127. pjsip_inv_session *uas;
  128. pj_bool_t complete;
  129. pj_bool_t uas_complete,
  130. uac_complete;
  131. unsigned oa_index;
  132. unsigned uac_update_cnt,
  133. uas_update_cnt;
  134. } inv_test_t;
  135. /**************** GLOBALS ******************/
  136. static inv_test_t inv_test;
  137. static unsigned job_cnt;
  138. typedef enum job_type
  139. {
  140. SEND_OFFER,
  141. ESTABLISH_CALL
  142. } job_type;
  143. typedef struct job_t
  144. {
  145. job_type type;
  146. pjsip_role_e who;
  147. } job_t;
  148. static job_t jobs[128];
  149. /**************** UTILS ******************/
  150. static pjmedia_sdp_session *create_sdp(pj_pool_t *pool, const char *body)
  151. {
  152. pjmedia_sdp_session *sdp;
  153. pj_str_t dup;
  154. pj_status_t status;
  155. pj_strdup2_with_null(pool, &dup, body);
  156. status = pjmedia_sdp_parse(pool, dup.ptr, dup.slen, &sdp);
  157. pj_assert(status == PJ_SUCCESS);
  158. PJ_UNUSED_ARG(status);
  159. return sdp;
  160. }
  161. /**************** INVITE SESSION CALLBACKS ******************/
  162. static void on_rx_offer(pjsip_inv_session *inv,
  163. const pjmedia_sdp_session *offer)
  164. {
  165. pjmedia_sdp_session *sdp;
  166. PJ_UNUSED_ARG(offer);
  167. sdp = create_sdp(inv->dlg->pool, oa_sdp[inv_test.oa_index].answer);
  168. pjsip_inv_set_sdp_answer(inv, sdp);
  169. if (inv_test.oa_index == inv_test.param.count-1 &&
  170. inv_test.param.need_established)
  171. {
  172. jobs[job_cnt].type = ESTABLISH_CALL;
  173. jobs[job_cnt].who = PJSIP_ROLE_UAS;
  174. job_cnt++;
  175. }
  176. }
  177. static void on_create_offer(pjsip_inv_session *inv,
  178. pjmedia_sdp_session **p_offer)
  179. {
  180. PJ_UNUSED_ARG(inv);
  181. PJ_UNUSED_ARG(p_offer);
  182. pj_assert(!"Should not happen");
  183. }
  184. static void on_media_update(pjsip_inv_session *inv_ses,
  185. pj_status_t status)
  186. {
  187. PJ_UNUSED_ARG(status);
  188. if (inv_ses == inv_test.uas) {
  189. inv_test.uas_update_cnt++;
  190. pj_assert(inv_test.uas_update_cnt - inv_test.uac_update_cnt <= 1);
  191. TRACE_((THIS_FILE, " Callee media is established"));
  192. } else if (inv_ses == inv_test.uac) {
  193. inv_test.uac_update_cnt++;
  194. pj_assert(inv_test.uac_update_cnt - inv_test.uas_update_cnt <= 1);
  195. TRACE_((THIS_FILE, " Caller media is established"));
  196. } else {
  197. pj_assert(!"Unknown session!");
  198. }
  199. if (inv_test.uac_update_cnt == inv_test.uas_update_cnt) {
  200. inv_test.oa_index++;
  201. if (inv_test.oa_index < inv_test.param.count) {
  202. switch (inv_test.param.oa[inv_test.oa_index]) {
  203. case OFFERER_UAC:
  204. jobs[job_cnt].type = SEND_OFFER;
  205. jobs[job_cnt].who = PJSIP_ROLE_UAC;
  206. job_cnt++;
  207. break;
  208. case OFFERER_UAS:
  209. jobs[job_cnt].type = SEND_OFFER;
  210. jobs[job_cnt].who = PJSIP_ROLE_UAS;
  211. job_cnt++;
  212. break;
  213. default:
  214. pj_assert(!"Invalid oa");
  215. }
  216. }
  217. /* Special handling for standard offer/answer */
  218. if (inv_test.param.count == 1 &&
  219. inv_test.param.oa[0] == OFFERER_UAC &&
  220. inv_test.param.need_established)
  221. {
  222. jobs[job_cnt].type = ESTABLISH_CALL;
  223. jobs[job_cnt].who = PJSIP_ROLE_UAS;
  224. job_cnt++;
  225. TRACE_((THIS_FILE, " C+++"));
  226. }
  227. pj_assert(job_cnt <= PJ_ARRAY_SIZE(jobs));
  228. }
  229. }
  230. static void on_state_changed(pjsip_inv_session *inv, pjsip_event *e)
  231. {
  232. const char *who = NULL;
  233. PJ_UNUSED_ARG(e);
  234. if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
  235. TRACE_((THIS_FILE, " %s call disconnected",
  236. (inv==inv_test.uas ? "Callee" : "Caller")));
  237. return;
  238. }
  239. if (inv->state != PJSIP_INV_STATE_CONFIRMED)
  240. return;
  241. if (inv == inv_test.uas) {
  242. inv_test.uas_complete = PJ_TRUE;
  243. who = "Callee";
  244. } else if (inv == inv_test.uac) {
  245. inv_test.uac_complete = PJ_TRUE;
  246. who = "Caller";
  247. } else
  248. pj_assert(!"No session");
  249. TRACE_((THIS_FILE, " %s call is confirmed", who));
  250. if (inv_test.uac_complete && inv_test.uas_complete)
  251. inv_test.complete = PJ_TRUE;
  252. }
  253. /**************** MODULE TO RECEIVE INITIAL INVITE ******************/
  254. static pj_bool_t on_rx_request(pjsip_rx_data *rdata)
  255. {
  256. if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG &&
  257. rdata->msg_info.msg->line.req.method.id == PJSIP_INVITE_METHOD)
  258. {
  259. pjsip_dialog *dlg;
  260. pjmedia_sdp_session *sdp = NULL;
  261. pj_str_t uri;
  262. pjsip_tx_data *tdata;
  263. pj_status_t status;
  264. /*
  265. * Create UAS
  266. */
  267. uri = pj_str(CONTACT);
  268. status = pjsip_dlg_create_uas_and_inc_lock(pjsip_ua_instance(), rdata,
  269. &uri, &dlg);
  270. pj_assert(status == PJ_SUCCESS);
  271. if (inv_test.param.oa[0] == OFFERER_UAC)
  272. sdp = create_sdp(rdata->tp_info.pool, oa_sdp[0].answer);
  273. else if (inv_test.param.oa[0] == OFFERER_UAS)
  274. sdp = create_sdp(rdata->tp_info.pool, oa_sdp[0].offer);
  275. else
  276. pj_assert(!"Invalid offerer type");
  277. status = pjsip_inv_create_uas(dlg, rdata, sdp, inv_test.param.inv_option, &inv_test.uas);
  278. pj_assert(status == PJ_SUCCESS);
  279. pjsip_dlg_dec_lock(dlg);
  280. TRACE_((THIS_FILE, " Sending 183 with SDP"));
  281. /*
  282. * Answer with 183
  283. */
  284. status = pjsip_inv_initial_answer(inv_test.uas, rdata, 183, NULL,
  285. NULL, &tdata);
  286. pj_assert(status == PJ_SUCCESS);
  287. /* Use multipart body, if configured */
  288. if (sdp && inv_test.param.multipart_body) {
  289. status = pjsip_create_multipart_sdp_body(
  290. tdata->pool,
  291. pjmedia_sdp_session_clone(tdata->pool, sdp),
  292. &tdata->msg->body);
  293. }
  294. pj_assert(status == PJ_SUCCESS);
  295. status = pjsip_inv_send_msg(inv_test.uas, tdata);
  296. pj_assert(status == PJ_SUCCESS);
  297. return (status == PJ_SUCCESS);
  298. }
  299. return PJ_FALSE;
  300. }
  301. static pjsip_module mod_inv_oa_test =
  302. {
  303. NULL, NULL, /* prev, next. */
  304. { "mod-inv-oa-test", 15 }, /* Name. */
  305. -1, /* Id */
  306. PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
  307. NULL, /* load() */
  308. NULL, /* start() */
  309. NULL, /* stop() */
  310. NULL, /* unload() */
  311. &on_rx_request, /* on_rx_request() */
  312. NULL, /* on_rx_response() */
  313. NULL, /* on_tx_request. */
  314. NULL, /* on_tx_response() */
  315. NULL, /* on_tsx_state() */
  316. };
  317. /**************** THE TEST ******************/
  318. static void run_job(job_t *j)
  319. {
  320. pjsip_inv_session *inv;
  321. pjsip_tx_data *tdata;
  322. pjmedia_sdp_session *sdp;
  323. pj_status_t status;
  324. if (j->who == PJSIP_ROLE_UAC)
  325. inv = inv_test.uac;
  326. else
  327. inv = inv_test.uas;
  328. switch (j->type) {
  329. case SEND_OFFER:
  330. sdp = create_sdp(inv->dlg->pool, oa_sdp[inv_test.oa_index].offer);
  331. TRACE_((THIS_FILE, " Sending UPDATE with offer"));
  332. status = pjsip_inv_update(inv, NULL, sdp, &tdata);
  333. pj_assert(status == PJ_SUCCESS);
  334. status = pjsip_inv_send_msg(inv, tdata);
  335. pj_assert(status == PJ_SUCCESS);
  336. break;
  337. case ESTABLISH_CALL:
  338. TRACE_((THIS_FILE, " Sending 200/OK"));
  339. status = pjsip_inv_answer(inv, 200, NULL, NULL, &tdata);
  340. pj_assert(status == PJ_SUCCESS);
  341. status = pjsip_inv_send_msg(inv, tdata);
  342. pj_assert(status == PJ_SUCCESS);
  343. break;
  344. }
  345. PJ_UNUSED_ARG(status);
  346. }
  347. static int perform_test(inv_test_param_t *param)
  348. {
  349. pj_str_t uri;
  350. pjsip_dialog *dlg;
  351. pjmedia_sdp_session *sdp;
  352. pjsip_tx_data *tdata;
  353. pj_status_t status;
  354. PJ_LOG(3,(THIS_FILE, " %s", param->title));
  355. pj_bzero(&inv_test, sizeof(inv_test));
  356. pj_memcpy(&inv_test.param, param, sizeof(*param));
  357. job_cnt = 0;
  358. uri = pj_str(CONTACT);
  359. /*
  360. * Create UAC
  361. */
  362. status = pjsip_dlg_create_uac(pjsip_ua_instance(),
  363. &uri, &uri, &uri, &uri, &dlg);
  364. PJ_ASSERT_RETURN(status==PJ_SUCCESS, -10);
  365. if (inv_test.param.oa[0] == OFFERER_UAC)
  366. sdp = create_sdp(dlg->pool, oa_sdp[0].offer);
  367. else
  368. sdp = NULL;
  369. status = pjsip_inv_create_uac(dlg, sdp, inv_test.param.inv_option, &inv_test.uac);
  370. //inv_test.uac->create_multipart = param->multipart_body;
  371. PJ_ASSERT_RETURN(status==PJ_SUCCESS, -20);
  372. TRACE_((THIS_FILE, " Sending INVITE %s offer", (sdp ? "with" : "without")));
  373. /*
  374. * Make call!
  375. */
  376. status = pjsip_inv_invite(inv_test.uac, &tdata);
  377. PJ_ASSERT_RETURN(status==PJ_SUCCESS, -30);
  378. /* Use multipart body, if configured */
  379. if (sdp && param->multipart_body) {
  380. status = pjsip_create_multipart_sdp_body(
  381. tdata->pool,
  382. pjmedia_sdp_session_clone(tdata->pool, sdp),
  383. &tdata->msg->body);
  384. }
  385. PJ_ASSERT_RETURN(status==PJ_SUCCESS, -40);
  386. status = pjsip_inv_send_msg(inv_test.uac, tdata);
  387. PJ_ASSERT_RETURN(status==PJ_SUCCESS, -50);
  388. /*
  389. * Wait until test completes
  390. */
  391. while (!inv_test.complete) {
  392. pj_time_val delay = {0, 20};
  393. pjsip_endpt_handle_events(endpt, &delay);
  394. while (job_cnt) {
  395. job_t j;
  396. j = jobs[0];
  397. pj_array_erase(jobs, sizeof(jobs[0]), job_cnt, 0);
  398. --job_cnt;
  399. run_job(&j);
  400. }
  401. }
  402. flush_events(100);
  403. /*
  404. * Hangup
  405. */
  406. TRACE_((THIS_FILE, " Disconnecting call"));
  407. status = pjsip_inv_end_session(inv_test.uas, PJSIP_SC_DECLINE, 0, &tdata);
  408. pj_assert(status == PJ_SUCCESS);
  409. if (tdata) {
  410. status = pjsip_inv_send_msg(inv_test.uas, tdata);
  411. pj_assert(status == PJ_SUCCESS);
  412. }
  413. flush_events(500);
  414. return 0;
  415. }
  416. static pj_bool_t log_on_rx_msg(pjsip_rx_data *rdata)
  417. {
  418. pjsip_msg *msg = rdata->msg_info.msg;
  419. char info[80];
  420. if (msg->type == PJSIP_REQUEST_MSG)
  421. pj_ansi_snprintf(info, sizeof(info), "%.*s",
  422. (int)msg->line.req.method.name.slen,
  423. msg->line.req.method.name.ptr);
  424. else
  425. pj_ansi_snprintf(info, sizeof(info), "%d/%.*s",
  426. msg->line.status.code,
  427. (int)rdata->msg_info.cseq->method.name.slen,
  428. rdata->msg_info.cseq->method.name.ptr);
  429. TRACE_((THIS_FILE, " Received %s %s sdp", info,
  430. (msg->body ? "with" : "without")));
  431. return PJ_FALSE;
  432. }
  433. /* Message logger module. */
  434. static pjsip_module mod_msg_logger =
  435. {
  436. NULL, NULL, /* prev and next */
  437. { "mod-msg-loggee", 14}, /* Name. */
  438. -1, /* Id */
  439. PJSIP_MOD_PRIORITY_TRANSPORT_LAYER-1,/* Priority */
  440. NULL, /* load() */
  441. NULL, /* start() */
  442. NULL, /* stop() */
  443. NULL, /* unload() */
  444. &log_on_rx_msg, /* on_rx_request() */
  445. &log_on_rx_msg, /* on_rx_response() */
  446. NULL, /* on_tx_request() */
  447. NULL, /* on_tx_response() */
  448. NULL, /* on_tsx_state() */
  449. };
  450. static inv_test_param_t test_params[] =
  451. {
  452. /* Normal scenario:
  453. UAC UAS
  454. INVITE (offer) -->
  455. 200/INVITE (answer) <--
  456. ACK -->
  457. */
  458. #if 1
  459. {
  460. "Standard INVITE with offer",
  461. 0,
  462. PJ_TRUE,
  463. 1,
  464. { OFFERER_UAC },
  465. PJ_FALSE
  466. },
  467. {
  468. "Standard INVITE with offer, with 100rel",
  469. PJSIP_INV_REQUIRE_100REL,
  470. PJ_TRUE,
  471. 1,
  472. { OFFERER_UAC },
  473. PJ_FALSE
  474. },
  475. {
  476. "Standard INVITE with offer, with Multipart",
  477. 0,
  478. PJ_TRUE,
  479. 1,
  480. { OFFERER_UAC },
  481. PJ_TRUE
  482. },
  483. {
  484. "Standard INVITE with offer, with 100rel, with Multipart",
  485. PJSIP_INV_REQUIRE_100REL,
  486. PJ_TRUE,
  487. 1,
  488. { OFFERER_UAC },
  489. PJ_TRUE
  490. },
  491. #endif
  492. /* Delayed offer:
  493. UAC UAS
  494. INVITE (no SDP) -->
  495. 200/INVITE (offer) <--
  496. ACK (answer) -->
  497. */
  498. #if 1
  499. {
  500. "INVITE with no offer",
  501. 0,
  502. PJ_TRUE,
  503. 1,
  504. { OFFERER_UAS },
  505. PJ_FALSE
  506. },
  507. {
  508. "INVITE with no offer, with 100rel",
  509. PJSIP_INV_REQUIRE_100REL,
  510. PJ_TRUE,
  511. 1,
  512. { OFFERER_UAS },
  513. PJ_FALSE
  514. },
  515. {
  516. "INVITE with no offer, with Multipart",
  517. 0,
  518. PJ_TRUE,
  519. 1,
  520. { OFFERER_UAS },
  521. PJ_TRUE
  522. },
  523. {
  524. "INVITE with no offer, with 100rel, with Multipart",
  525. PJSIP_INV_REQUIRE_100REL,
  526. PJ_TRUE,
  527. 1,
  528. { OFFERER_UAS },
  529. PJ_TRUE
  530. },
  531. #endif
  532. /* Subsequent UAC offer with UPDATE:
  533. UAC UAS
  534. INVITE (offer) -->
  535. 180/rel (answer) <--
  536. UPDATE (offer) --> inv_update() on_rx_offer()
  537. set_sdp_answer()
  538. 200/UPDATE (answer) <--
  539. 200/INVITE <--
  540. ACK -->
  541. */
  542. #if 1
  543. #if !PJSIP_INV_UPDATE_EARLY_CHECK_RELIABLE
  544. {
  545. "INVITE and UPDATE by UAC",
  546. 0,
  547. PJ_TRUE,
  548. 2,
  549. { OFFERER_UAC, OFFERER_UAC },
  550. PJ_FALSE
  551. },
  552. #endif
  553. {
  554. "INVITE and UPDATE by UAC, with Multipart, with 100rel",
  555. PJSIP_INV_REQUIRE_100REL,
  556. PJ_TRUE,
  557. 2,
  558. { OFFERER_UAC, OFFERER_UAC },
  559. PJ_TRUE
  560. },
  561. {
  562. "INVITE and UPDATE by UAC, with 100rel",
  563. PJSIP_INV_REQUIRE_100REL,
  564. PJ_TRUE,
  565. 2,
  566. { OFFERER_UAC, OFFERER_UAC },
  567. PJ_FALSE
  568. },
  569. #endif
  570. /* Subsequent UAS offer with UPDATE:
  571. INVITE (offer -->
  572. 180/rel (answer) <--
  573. UPDATE (offer) <-- inv_update()
  574. on_rx_offer()
  575. set_sdp_answer()
  576. 200/UPDATE (answer) -->
  577. UPDATE (offer) --> on_rx_offer()
  578. set_sdp_answer()
  579. 200/UPDATE (answer) <--
  580. 200/INVITE <--
  581. ACK -->
  582. */
  583. {
  584. "INVITE and many UPDATE by UAC and UAS, with 100rel",
  585. PJSIP_INV_REQUIRE_100REL,
  586. PJ_TRUE,
  587. 4,
  588. { OFFERER_UAC, OFFERER_UAS, OFFERER_UAC, OFFERER_UAS }
  589. },
  590. {
  591. "INVITE and many UPDATE by UAC and UAS, with Multipart, with 100rel",
  592. PJSIP_INV_REQUIRE_100REL,
  593. PJ_TRUE,
  594. 4,
  595. { OFFERER_UAC, OFFERER_UAS, OFFERER_UAC, OFFERER_UAS },
  596. PJ_TRUE
  597. },
  598. };
  599. static pjsip_dialog* on_dlg_forked(pjsip_dialog *first_set, pjsip_rx_data *res)
  600. {
  601. PJ_UNUSED_ARG(first_set);
  602. PJ_UNUSED_ARG(res);
  603. return NULL;
  604. }
  605. static void on_new_session(pjsip_inv_session *inv, pjsip_event *e)
  606. {
  607. PJ_UNUSED_ARG(inv);
  608. PJ_UNUSED_ARG(e);
  609. }
  610. int inv_offer_answer_test(void)
  611. {
  612. unsigned i;
  613. int rc = 0;
  614. /* Init UA layer */
  615. if (pjsip_ua_instance()->id == -1) {
  616. pjsip_ua_init_param ua_param;
  617. pj_bzero(&ua_param, sizeof(ua_param));
  618. ua_param.on_dlg_forked = &on_dlg_forked;
  619. pjsip_ua_init_module(endpt, &ua_param);
  620. }
  621. /* Init inv-usage */
  622. if (pjsip_inv_usage_instance()->id == -1) {
  623. pjsip_inv_callback inv_cb;
  624. pj_bzero(&inv_cb, sizeof(inv_cb));
  625. inv_cb.on_media_update = &on_media_update;
  626. inv_cb.on_rx_offer = &on_rx_offer;
  627. inv_cb.on_create_offer = &on_create_offer;
  628. inv_cb.on_state_changed = &on_state_changed;
  629. inv_cb.on_new_session = &on_new_session;
  630. pjsip_inv_usage_init(endpt, &inv_cb);
  631. }
  632. /* 100rel module */
  633. pjsip_100rel_init_module(endpt);
  634. /* Our module */
  635. pjsip_endpt_register_module(endpt, &mod_inv_oa_test);
  636. pjsip_endpt_register_module(endpt, &mod_msg_logger);
  637. /* Create SIP UDP transport */
  638. {
  639. pj_sockaddr_in addr;
  640. pjsip_transport *tp;
  641. pj_status_t status;
  642. pj_sockaddr_in_init(&addr, NULL, PORT);
  643. status = pjsip_udp_transport_start(endpt, &addr, NULL, 1, &tp);
  644. pj_assert(status == PJ_SUCCESS);
  645. PJ_UNUSED_ARG(status);
  646. }
  647. /* Do tests */
  648. for (i=0; i<PJ_ARRAY_SIZE(test_params); ++i) {
  649. rc = perform_test(&test_params[i]);
  650. if (rc != 0)
  651. goto on_return;
  652. }
  653. on_return:
  654. return rc;
  655. }