2
0

s2sip.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. /*
  2. * This file is part of the Sofia-SIP package
  3. *
  4. * Copyright (C) 2008 Nokia Corporation.
  5. *
  6. * Contact: Pekka Pessi <pekka.pessi@nokia.com>
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public License
  10. * as published by the Free Software Foundation; either version 2.1 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  21. * 02110-1301 USA
  22. *
  23. */
  24. /**@CFILE s2sip.c
  25. * @brief Check-Based Test Suite for Sofia SIP
  26. *
  27. * @author Pekka Pessi <Pekka.Pessi@nokia.com>
  28. *
  29. * @date Created: Wed Apr 30 12:48:27 EEST 2008 ppessi
  30. */
  31. #include "config.h"
  32. #undef NDEBUG
  33. #define TP_STACK_T struct s2sip
  34. #define TP_MAGIC_T struct tp_magic_s
  35. #define SU_ROOT_MAGIC_T struct s2sip
  36. #include "s2sip.h"
  37. #include "s2base.h"
  38. #include "s2dns.h"
  39. #include <sofia-sip/sip_header.h>
  40. #include <sofia-sip/sip_status.h>
  41. #include <sofia-sip/sip_tag.h>
  42. #include <sofia-sip/msg_addr.h>
  43. #include <sofia-sip/su_log.h>
  44. #include <sofia-sip/su_tagarg.h>
  45. #include <sofia-sip/su_alloc.h>
  46. #include <sofia-sip/su_string.h>
  47. #include <sofia-sip/sresolv.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #include <assert.h>
  51. #include <limits.h>
  52. #include <time.h>
  53. /* -- Module types ------------------------------------------------------ */
  54. struct tp_magic_s
  55. {
  56. sip_via_t *via;
  57. sip_contact_t *contact;
  58. };
  59. /* -- Module prototypes ------------------------------------------------- */
  60. static msg_t *s2_msg(int flags);
  61. static int s2_complete_response(msg_t *response,
  62. int status, char const *phrase,
  63. msg_t *request);
  64. /* -- Module globals ---------------------------------------------------- */
  65. struct s2sip *s2sip;
  66. /* ---------------------------------------------------------------------- */
  67. char *
  68. s2_sip_generate_tag(su_home_t *home)
  69. {
  70. static unsigned s2_tag_generator = 0;
  71. return su_sprintf(home, "tag=%s-%s/%u", _s2_suite, _s2_case, ++s2_tag_generator);
  72. }
  73. /* ---------------------------------------------------------------------- */
  74. /* SIP messages */
  75. struct message *
  76. s2_sip_remove_message(struct message *m)
  77. {
  78. if ((*m->prev = m->next))
  79. m->next->prev = m->prev;
  80. m->prev = NULL, m->next = NULL;
  81. return m;
  82. }
  83. void
  84. s2_sip_free_message(struct message *m)
  85. {
  86. if (m) {
  87. if (m->prev) {
  88. if ((*m->prev = m->next))
  89. m->next->prev = m->prev;
  90. }
  91. msg_destroy(m->msg);
  92. tport_unref(m->tport);
  93. free(m);
  94. }
  95. }
  96. void s2_sip_flush_messages(void)
  97. {
  98. while (s2sip->received) {
  99. s2_sip_free_message(s2sip->received);
  100. }
  101. }
  102. struct message *
  103. s2_sip_next_response(void)
  104. {
  105. struct message *m;
  106. for (;;) {
  107. for (m = s2sip->received; m; m = m->next) {
  108. if (m->sip->sip_status)
  109. return s2_sip_remove_message(m);
  110. }
  111. s2_step();
  112. }
  113. }
  114. struct message *
  115. s2_sip_wait_for_response(int status, sip_method_t method, char const *name)
  116. {
  117. struct message *m;
  118. for (;;) {
  119. for (m = s2sip->received; m; m = m->next) {
  120. if (!m->sip->sip_status)
  121. continue;
  122. if (status != 0 && m->sip->sip_status->st_status != status)
  123. continue;
  124. if (method == sip_method_unknown && name == NULL)
  125. break;
  126. if (m->sip->sip_cseq == NULL)
  127. continue;
  128. if (m->sip->sip_cseq->cs_method != method)
  129. continue;
  130. if (name == NULL)
  131. break;
  132. if (strcmp(m->sip->sip_cseq->cs_method_name, name) == 0)
  133. break;
  134. }
  135. if (m)
  136. return s2_sip_remove_message(m);
  137. s2_step();
  138. }
  139. }
  140. int
  141. s2_sip_check_response(int status, sip_method_t method, char const *name)
  142. {
  143. struct message *m = s2_sip_wait_for_response(status, method, name);
  144. s2_sip_free_message(m);
  145. return m != NULL;
  146. }
  147. int
  148. s2_check_in_response(struct dialog *dialog,
  149. int status, sip_method_t method, char const *name)
  150. {
  151. struct message *m = s2_sip_wait_for_response(status, method, name);
  152. s2_sip_update_dialog(dialog, m);
  153. s2_sip_free_message(m);
  154. return m != NULL;
  155. }
  156. struct message *
  157. s2_sip_next_request(sip_method_t method, char const *name)
  158. {
  159. struct message *m;
  160. for (m = s2sip->received; m; m = m->next) {
  161. if (m->sip->sip_request)
  162. if (method == sip_method_unknown && name == NULL)
  163. return s2_sip_remove_message(m);
  164. if (m->sip->sip_request->rq_method == method &&
  165. strcmp(m->sip->sip_request->rq_method_name, name) == 0)
  166. return s2_sip_remove_message(m);
  167. }
  168. return NULL;
  169. }
  170. struct message *
  171. s2_sip_wait_for_request(sip_method_t method, char const *name)
  172. {
  173. return s2_sip_wait_for_request_timeout(method, name, (unsigned)-1);
  174. }
  175. struct message *
  176. s2_sip_wait_for_request_timeout(sip_method_t method, char const *name, unsigned steps)
  177. {
  178. struct message *m;
  179. for (; steps > 0; steps--, s2_step()) {
  180. for (m = s2sip->received; m; m = m->next) {
  181. if (m->sip->sip_request) {
  182. if (method == sip_method_unknown && name == NULL)
  183. return s2_sip_remove_message(m);
  184. if (m->sip->sip_request->rq_method == method &&
  185. strcmp(m->sip->sip_request->rq_method_name, name) == 0)
  186. return s2_sip_remove_message(m);
  187. }
  188. }
  189. }
  190. return NULL;
  191. }
  192. int
  193. s2_sip_check_request(sip_method_t method, char const *name)
  194. {
  195. struct message *m = s2_sip_wait_for_request(method, name);
  196. if (m) s2_sip_free_message(m);
  197. return m != NULL;
  198. }
  199. int
  200. s2_sip_check_request_timeout(sip_method_t method,
  201. char const *name,
  202. unsigned timeout)
  203. {
  204. struct message *m = s2_sip_wait_for_request_timeout(method, name, timeout);
  205. if (m) s2_sip_free_message(m);
  206. return m != NULL;
  207. }
  208. void
  209. s2_sip_save_uas_dialog(struct dialog *d, sip_t *sip)
  210. {
  211. if (d && !d->local) {
  212. assert(sip->sip_request);
  213. d->local = sip_from_dup(d->home, sip->sip_to);
  214. if (d->local->a_tag == NULL)
  215. sip_from_tag(d->home, d->local, s2_sip_generate_tag(d->home));
  216. d->remote = sip_to_dup(d->home, sip->sip_from);
  217. d->call_id = sip_call_id_dup(d->home, sip->sip_call_id);
  218. d->rseq = sip->sip_cseq->cs_seq;
  219. /* d->route = sip_route_dup(d->home, sip->sip_record_route); */
  220. d->target = sip_contact_dup(d->home, sip->sip_contact);
  221. }
  222. }
  223. struct message *
  224. s2_sip_respond_to(struct message *m, struct dialog *d,
  225. int status, char const *phrase,
  226. tag_type_t tag, tag_value_t value, ...)
  227. {
  228. ta_list ta;
  229. msg_t *reply;
  230. sip_t *sip;
  231. su_home_t *home;
  232. tp_name_t tpn[1];
  233. char *rport;
  234. assert(m); assert(m->msg); assert(m->tport);
  235. assert(100 <= status && status < 700);
  236. s2_sip_save_uas_dialog(d, m->sip);
  237. ta_start(ta, tag, value);
  238. reply = s2_msg(0); sip = sip_object(reply); home = msg_home(reply);
  239. assert(reply && home && sip);
  240. if (sip_add_tl(reply, sip, ta_tags(ta)) < 0) {
  241. abort();
  242. }
  243. s2_complete_response(reply, status, phrase, m->msg);
  244. if (sip->sip_status && sip->sip_status->st_status > 100 &&
  245. sip->sip_to && !sip->sip_to->a_tag &&
  246. sip->sip_cseq && sip->sip_cseq->cs_method != sip_method_cancel) {
  247. char const *ltag = NULL;
  248. if (d && d->local)
  249. ltag = d->local->a_tag;
  250. if (ltag == NULL)
  251. ltag = s2_sip_generate_tag(home);
  252. if (sip_to_tag(msg_home(reply), sip->sip_to, ltag) < 0) {
  253. assert(!"add To tag");
  254. }
  255. }
  256. if (d && !d->contact) {
  257. d->contact = sip_contact_dup(d->home, sip->sip_contact);
  258. }
  259. *tpn = *tport_name(m->tport);
  260. rport = su_sprintf(home, "rport=%u",
  261. ntohs(((su_sockaddr_t *)
  262. msg_addrinfo(m->msg)->ai_addr)->su_port));
  263. if (s2sip->server_uses_rport &&
  264. sip->sip_via->v_rport &&
  265. sip->sip_via->v_rport[0] == '\0') {
  266. msg_header_add_param(home, sip->sip_via->v_common, rport);
  267. }
  268. tpn->tpn_port = rport + strlen("rport=");
  269. tport_tsend(m->tport, reply, tpn, TPTAG_MTU(INT_MAX), ta_tags(ta));
  270. msg_destroy(reply);
  271. ta_end(ta);
  272. return m;
  273. }
  274. /** Add headers from the request to the response message. */
  275. static int
  276. s2_complete_response(msg_t *response,
  277. int status, char const *phrase,
  278. msg_t *request)
  279. {
  280. su_home_t *home = msg_home(response);
  281. sip_t *response_sip = sip_object(response);
  282. sip_t const *request_sip = sip_object(request);
  283. int incomplete = 0;
  284. if (!response_sip || !request_sip || !request_sip->sip_request)
  285. return -1;
  286. if (!response_sip->sip_status)
  287. response_sip->sip_status = sip_status_create(home, status, phrase, NULL);
  288. if (!response_sip->sip_via)
  289. response_sip->sip_via = sip_via_dup(home, request_sip->sip_via);
  290. if (!response_sip->sip_from)
  291. response_sip->sip_from = sip_from_dup(home, request_sip->sip_from);
  292. if (!response_sip->sip_to)
  293. response_sip->sip_to = sip_to_dup(home, request_sip->sip_to);
  294. if (!response_sip->sip_call_id)
  295. response_sip->sip_call_id =
  296. sip_call_id_dup(home, request_sip->sip_call_id);
  297. if (!response_sip->sip_cseq)
  298. response_sip->sip_cseq = sip_cseq_dup(home, request_sip->sip_cseq);
  299. if (!response_sip->sip_record_route && request_sip->sip_record_route)
  300. sip_add_dup(response, response_sip, (void*)request_sip->sip_record_route);
  301. incomplete = sip_complete_message(response) < 0;
  302. msg_serialize(response, (msg_pub_t *)response_sip);
  303. if (incomplete ||
  304. !response_sip->sip_status ||
  305. !response_sip->sip_via ||
  306. !response_sip->sip_from ||
  307. !response_sip->sip_to ||
  308. !response_sip->sip_call_id ||
  309. !response_sip->sip_cseq ||
  310. !response_sip->sip_content_length ||
  311. !response_sip->sip_separator ||
  312. (request_sip->sip_record_route && !response_sip->sip_record_route))
  313. return -1;
  314. return 0;
  315. }
  316. /* Send request (updating dialog).
  317. *
  318. * Return zero upon success, nonzero upon failure.
  319. */
  320. int
  321. s2_sip_request_to(struct dialog *d,
  322. sip_method_t method, char const *name,
  323. tport_t *tport,
  324. tag_type_t tag, tag_value_t value, ...)
  325. {
  326. ta_list ta;
  327. tagi_t const *tags;
  328. msg_t *msg = s2_msg(0);
  329. sip_t *sip = sip_object(msg);
  330. url_t const *target = NULL;
  331. sip_cseq_t cseq[1];
  332. sip_via_t via[1]; char const *v_params[8];
  333. sip_content_length_t l[1];
  334. tp_name_t tpn[1];
  335. tp_magic_t *magic;
  336. int user_via = 0;
  337. ta_start(ta, tag, value);
  338. tags = ta_args(ta);
  339. if (sip_add_tagis(msg, sip, &tags) < 0)
  340. goto error;
  341. if (sip->sip_request)
  342. target = sip->sip_request->rq_url;
  343. else if (d->target)
  344. target = d->target->m_url;
  345. else if (s2sip->sut.contact)
  346. target = s2sip->sut.contact->m_url;
  347. else
  348. target = NULL;
  349. if (target == NULL)
  350. goto error;
  351. if (!sip->sip_request) {
  352. sip_request_t *rq;
  353. rq = sip_request_create(msg_home(msg), method, name,
  354. (url_string_t *)target, NULL);
  355. sip_header_insert(msg, sip, (sip_header_t *)rq);
  356. }
  357. if (!d->local && sip->sip_from)
  358. d->local = sip_from_dup(d->home, sip->sip_from);
  359. if (!d->contact && sip->sip_contact)
  360. d->contact = sip_contact_dup(d->home, sip->sip_contact);
  361. if (!d->remote && sip->sip_to)
  362. d->remote = sip_to_dup(d->home, sip->sip_to);
  363. if (!d->target && sip->sip_request)
  364. d->target = sip_contact_create(d->home,
  365. (url_string_t *)sip->sip_request->rq_url,
  366. NULL);
  367. if (!d->call_id && sip->sip_call_id)
  368. d->call_id = sip_call_id_dup(d->home, sip->sip_call_id);
  369. if (!d->lseq && sip->sip_cseq)
  370. d->lseq = sip->sip_cseq->cs_seq;
  371. if (!d->local)
  372. d->local = sip_from_dup(d->home, s2sip->aor);
  373. if (!d->contact)
  374. d->contact = sip_contact_dup(d->home, s2sip->contact);
  375. if (!d->remote)
  376. d->remote = sip_to_dup(d->home, s2sip->sut.aor);
  377. if (!d->call_id)
  378. d->call_id = sip_call_id_create(d->home, NULL);
  379. assert(d->local && d->contact);
  380. assert(d->remote && d->target);
  381. assert(d->call_id);
  382. if (tport == NULL)
  383. tport = d->tport;
  384. if (tport == NULL)
  385. tport = s2sip->sut.tport;
  386. if (tport == NULL && d->target->m_url->url_type == url_sips)
  387. tport = s2sip->tls.tport;
  388. if (tport == NULL)
  389. tport = s2sip->udp.tport;
  390. else if (tport == NULL)
  391. tport = s2sip->tcp.tport;
  392. else if (tport == NULL)
  393. tport = s2sip->tls.tport;
  394. assert(tport);
  395. *tpn = *tport_name(tport);
  396. if (tport_is_primary(tport)) {
  397. tpn->tpn_host = target->url_host;
  398. tpn->tpn_port = url_port(target);
  399. if (!tpn->tpn_port || !tpn->tpn_port[0])
  400. tpn->tpn_port = url_port_default(target->url_type);
  401. }
  402. magic = tport_magic(tport);
  403. assert(magic != NULL);
  404. sip_cseq_init(cseq);
  405. cseq->cs_method = method;
  406. cseq->cs_method_name = name;
  407. if (d->invite && (method == sip_method_ack || method == sip_method_cancel)) {
  408. cseq->cs_seq = sip_object(d->invite)->sip_cseq->cs_seq;
  409. }
  410. else {
  411. cseq->cs_seq = ++d->lseq;
  412. }
  413. if (sip->sip_via) {
  414. user_via = 1;
  415. }
  416. else if (d->invite && method == sip_method_cancel) {
  417. *via = *sip_object(d->invite)->sip_via;
  418. }
  419. else {
  420. *via = *magic->via;
  421. via->v_params = v_params;
  422. v_params[0] = su_sprintf(msg_home(msg), "branch=z9hG4bK%lx", ++s2sip->tid);
  423. v_params[1] = NULL;
  424. }
  425. sip_content_length_init(l);
  426. if (sip->sip_payload)
  427. l->l_length = sip->sip_payload->pl_len;
  428. if (d->local->a_tag == NULL) {
  429. char const *ltag = s2_sip_generate_tag(d->home);
  430. if (sip_from_tag(d->home, d->local, ltag) < 0) {
  431. assert(!"add To tag");
  432. }
  433. if (sip->sip_from && sip->sip_from->a_tag == NULL) {
  434. if (sip_from_tag(msg_home(msg), sip->sip_from, ltag) < 0) {
  435. assert(!"add To tag");
  436. }
  437. }
  438. }
  439. sip_add_tl(msg, sip,
  440. TAG_IF(!sip->sip_from, SIPTAG_FROM(d->local)),
  441. TAG_IF(!sip->sip_contact, SIPTAG_CONTACT(d->contact)),
  442. TAG_IF(!sip->sip_to, SIPTAG_TO(d->remote)),
  443. TAG_IF(!sip->sip_call_id, SIPTAG_CALL_ID(d->call_id)),
  444. TAG_IF(!sip->sip_cseq, SIPTAG_CSEQ(cseq)),
  445. TAG_IF(!user_via, SIPTAG_VIA(via)),
  446. TAG_IF(!sip->sip_content_length, SIPTAG_CONTENT_LENGTH(l)),
  447. TAG_IF(!sip->sip_separator, SIPTAG_SEPARATOR_STR("\r\n")),
  448. TAG_END());
  449. msg_serialize(msg, NULL);
  450. if (method == sip_method_invite) {
  451. msg_destroy(d->invite);
  452. d->invite = msg_ref_create(msg);
  453. }
  454. tport = tport_tsend(tport, msg, tpn, ta_tags(ta));
  455. ta_end(ta);
  456. if (d->tport != tport) {
  457. tport_unref(d->tport);
  458. d->tport = tport_ref(tport);
  459. }
  460. return tport ? 0 : -1;
  461. error:
  462. ta_end(ta);
  463. return -1;
  464. }
  465. /** Save information from response.
  466. *
  467. * Send ACK for error messages to INVITE.
  468. */
  469. int s2_sip_update_dialog(struct dialog *d, struct message *m)
  470. {
  471. int status = 0;
  472. if (m->sip->sip_status)
  473. status = m->sip->sip_status->st_status;
  474. if (100 < status && status < 300) {
  475. d->remote = sip_to_dup(d->home, m->sip->sip_to);
  476. if (m->sip->sip_contact)
  477. d->contact = sip_contact_dup(d->home, m->sip->sip_contact);
  478. }
  479. if (300 <= status && m->sip->sip_cseq &&
  480. m->sip->sip_cseq->cs_method == sip_method_invite &&
  481. d->invite) {
  482. msg_t *ack = s2_msg(0);
  483. sip_t *sip = sip_object(ack);
  484. sip_t *invite = sip_object(d->invite);
  485. sip_request_t rq[1];
  486. sip_cseq_t cseq[1];
  487. tp_name_t tpn[1];
  488. *rq = *invite->sip_request;
  489. rq->rq_method = sip_method_ack, rq->rq_method_name = "ACK";
  490. *cseq = *invite->sip_cseq;
  491. cseq->cs_method = sip_method_ack, cseq->cs_method_name = "ACK";
  492. sip_add_tl(ack, sip,
  493. SIPTAG_REQUEST(rq),
  494. SIPTAG_VIA(invite->sip_via),
  495. SIPTAG_FROM(invite->sip_from),
  496. SIPTAG_TO(invite->sip_to),
  497. SIPTAG_CALL_ID(invite->sip_call_id),
  498. SIPTAG_CSEQ(cseq),
  499. SIPTAG_CONTENT_LENGTH_STR("0"),
  500. SIPTAG_SEPARATOR_STR("\r\n"),
  501. TAG_END());
  502. *tpn = *tport_name(d->tport);
  503. if (!tport_is_secondary(d->tport) ||
  504. !tport_is_clear_to_send(d->tport)) {
  505. tpn->tpn_host = rq->rq_url->url_host;
  506. tpn->tpn_port = rq->rq_url->url_port;
  507. }
  508. msg_serialize(ack, NULL);
  509. tport_tsend(d->tport, ack, tpn, TAG_END());
  510. }
  511. return 0;
  512. }
  513. /* ---------------------------------------------------------------------- */
  514. /* tport interface */
  515. static void
  516. s2_sip_stack_recv(struct s2sip *s2,
  517. tport_t *tp,
  518. msg_t *msg,
  519. tp_magic_t *magic,
  520. su_time_t now)
  521. {
  522. struct message *next = calloc(1, sizeof *next), **prev;
  523. next->msg = msg;
  524. next->sip = sip_object(msg);
  525. next->when = now;
  526. next->tport = tport_ref(tp);
  527. #if 0
  528. if (next->sip->sip_request)
  529. printf("%s: sent: %s\n", s2tester, next->sip->sip_request->rq_method_name);
  530. else
  531. printf("%s: sent: SIP/2.0 %u %s\n", s2tester,
  532. next->sip->sip_status->st_status,
  533. next->sip->sip_status->st_phrase);
  534. #endif
  535. for (prev = &s2->received; *prev; prev = &(*prev)->next)
  536. ;
  537. next->prev = prev, *prev = next;
  538. }
  539. static void
  540. s2_sip_stack_error(struct s2sip *s2,
  541. tport_t *tp,
  542. int errcode,
  543. char const *remote)
  544. {
  545. fprintf(stderr, "%s(%p): error %d (%s) from %s\n",
  546. "s2_sip_error",
  547. (void *)tp, errcode, su_strerror(errcode),
  548. remote ? remote : "<unknown destination>");
  549. }
  550. static msg_t *
  551. s2_sip_stack_alloc(struct s2sip *s2sip, int flags,
  552. char const data[], usize_t size,
  553. tport_t const *tport,
  554. tp_client_t *tpc)
  555. {
  556. return msg_create(s2sip->mclass, flags | s2sip->flags);
  557. }
  558. static msg_t *
  559. s2_msg(int flags)
  560. {
  561. return msg_create(s2sip->mclass, flags | s2sip->flags);
  562. }
  563. tp_stack_class_t const s2_sip_stack[1] =
  564. {{
  565. /* tpac_size */ (sizeof s2_sip_stack),
  566. /* tpac_recv */ s2_sip_stack_recv,
  567. /* tpac_error */ s2_sip_stack_error,
  568. /* tpac_alloc */ s2_sip_stack_alloc,
  569. }};
  570. static char const *default_protocols[] = { "udp", "tcp", NULL };
  571. /** Setup for SIP transports */
  572. void s2_sip_setup(char const *hostname,
  573. char const * const *protocols,
  574. tag_type_t tag, tag_value_t value, ...)
  575. {
  576. su_home_t *home;
  577. ta_list ta;
  578. tp_name_t tpn[1];
  579. int bound;
  580. tport_t *tp;
  581. assert(s2base != NULL);
  582. assert(s2sip == NULL);
  583. s2sip = su_home_new(sizeof *s2sip);
  584. home = s2sip->home;
  585. s2sip->root = su_root_clone(s2base->root, s2sip);
  586. s2sip->aor = sip_from_format(home, "Bob <sip:bob@%s>",
  587. hostname ? hostname : "example.net");
  588. if (hostname == NULL)
  589. hostname = "127.0.0.1";
  590. s2sip->hostname = hostname;
  591. s2sip->tid = (unsigned long)time(NULL) * 510633671UL;
  592. ta_start(ta, tag, value);
  593. s2sip->master = tport_tcreate(s2sip, s2_sip_stack, s2sip->root,
  594. TPTAG_LOG(getenv("S2_TPORT_LOG") != NULL),
  595. ta_tags(ta));
  596. assert(s2sip->master);
  597. s2sip->mclass = sip_default_mclass();
  598. s2sip->flags = 0;
  599. memset(tpn, 0, (sizeof tpn));
  600. tpn->tpn_proto = "*";
  601. tpn->tpn_host = "*";
  602. tpn->tpn_port = "*";
  603. if (protocols == NULL)
  604. protocols = default_protocols;
  605. bound = tport_tbind(s2sip->master, tpn, protocols,
  606. TPTAG_SERVER(1),
  607. ta_tags(ta));
  608. assert(bound != -1);
  609. tp = tport_primaries(s2sip->master);
  610. *tpn = *tport_name(tp);
  611. s2sip->contact = sip_contact_format(home, "<sip:%s:%s>",
  612. tpn->tpn_host,
  613. tpn->tpn_port);
  614. for (;tp; tp = tport_next(tp)) {
  615. sip_via_t *v;
  616. sip_contact_t *m;
  617. tp_magic_t *magic;
  618. if (tport_magic(tp))
  619. continue;
  620. *tpn = *tport_name(tp);
  621. v = sip_via_format(home, "SIP/2.0/%s %s:%s",
  622. tpn->tpn_proto,
  623. tpn->tpn_host,
  624. tpn->tpn_port);
  625. assert(v != NULL);
  626. if (!su_casenmatch(tpn->tpn_proto, "tls", 3)) {
  627. m = sip_contact_format(home, "<sip:%s:%s;transport=%s>",
  628. tpn->tpn_host,
  629. tpn->tpn_port,
  630. tpn->tpn_proto);
  631. if (s2sip->udp.contact == NULL && su_casematch(tpn->tpn_proto, "udp")) {
  632. s2sip->udp.tport = tport_ref(tp);
  633. s2sip->udp.contact = m;
  634. }
  635. if (s2sip->tcp.contact == NULL && su_casematch(tpn->tpn_proto, "tcp")) {
  636. s2sip->tcp.tport = tport_ref(tp);
  637. s2sip->tcp.contact = m;
  638. }
  639. }
  640. else if (!su_casematch(tpn->tpn_proto, "tls")) {
  641. m = sip_contact_format(s2sip->home, "<sips:%s:%s;transport=%s>",
  642. tpn->tpn_host,
  643. tpn->tpn_port,
  644. tpn->tpn_proto);
  645. }
  646. else {
  647. m = sip_contact_format(s2sip->home, "<sips:%s:%s>",
  648. tpn->tpn_host,
  649. tpn->tpn_port);
  650. if (s2sip->tls.contact == NULL) {
  651. s2sip->tls.tport = tport_ref(tp);
  652. s2sip->tls.contact = m;
  653. }
  654. }
  655. assert(m != NULL);
  656. magic = su_zalloc(home, (sizeof *magic));
  657. magic->via = v, magic->contact = m;
  658. if (s2sip->contact == NULL)
  659. s2sip->contact = m;
  660. tport_set_magic(tp, magic);
  661. }
  662. }
  663. void
  664. s2_sip_teardown(void)
  665. {
  666. if (s2sip) {
  667. tport_destroy(s2sip->master), s2sip->master = NULL;
  668. su_root_destroy(s2sip->root), s2sip->root = NULL;
  669. su_home_unref(s2sip->home);
  670. s2sip = NULL;
  671. }
  672. }