sip_reg.c 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555
  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 <pjsip-ua/sip_regc.h>
  20. #include <pjsip/sip_endpoint.h>
  21. #include <pjsip/sip_parser.h>
  22. #include <pjsip/sip_module.h>
  23. #include <pjsip/sip_transaction.h>
  24. #include <pjsip/sip_event.h>
  25. #include <pjsip/sip_util.h>
  26. #include <pjsip/sip_auth_msg.h>
  27. #include <pjsip/sip_errno.h>
  28. #include <pj/assert.h>
  29. #include <pj/guid.h>
  30. #include <pj/lock.h>
  31. #include <pj/os.h>
  32. #include <pj/pool.h>
  33. #include <pj/log.h>
  34. #include <pj/rand.h>
  35. #include <pj/string.h>
  36. #define REFRESH_TIMER 1
  37. #define DELAY_BEFORE_REFRESH PJSIP_REGISTER_CLIENT_DELAY_BEFORE_REFRESH
  38. #define THIS_FILE "sip_reg.c"
  39. /* Outgoing transaction timeout when server sends 100 but never replies
  40. * with final response. Value is in MILISECONDS!
  41. */
  42. #define REGC_TSX_TIMEOUT 33000
  43. #define NOEXP PJSIP_REGC_EXPIRATION_NOT_SPECIFIED
  44. static const pj_str_t XUID_PARAM_NAME = { "x-uid", 5 };
  45. /* Current/pending operation */
  46. enum regc_op
  47. {
  48. REGC_IDLE,
  49. REGC_REGISTERING,
  50. REGC_UNREGISTERING
  51. };
  52. /**
  53. * SIP client registration structure.
  54. */
  55. struct pjsip_regc
  56. {
  57. pj_pool_t *pool;
  58. pjsip_endpoint *endpt;
  59. pj_lock_t *lock;
  60. pj_bool_t _delete_flag;
  61. pj_bool_t has_tsx;
  62. pj_atomic_t *busy_ctr;
  63. enum regc_op current_op;
  64. pj_bool_t add_xuid_param;
  65. void *token;
  66. pjsip_regc_cb *cb;
  67. pjsip_regc_tsx_cb *tsx_cb;
  68. pj_str_t str_srv_url;
  69. pjsip_uri *srv_url;
  70. pjsip_cid_hdr *cid_hdr;
  71. pjsip_cseq_hdr *cseq_hdr;
  72. pj_str_t from_uri;
  73. pjsip_from_hdr *from_hdr;
  74. pjsip_to_hdr *to_hdr;
  75. pjsip_contact_hdr contact_hdr_list;
  76. pjsip_contact_hdr removed_contact_hdr_list;
  77. pjsip_expires_hdr *expires_hdr;
  78. pj_uint32_t expires;
  79. pj_uint32_t expires_requested;
  80. pj_uint32_t delay_before_refresh;
  81. pjsip_route_hdr route_set;
  82. pjsip_hdr hdr_list;
  83. pjsip_host_port via_addr;
  84. const void *via_tp;
  85. /* Authorization sessions. */
  86. pjsip_auth_clt_sess auth_sess;
  87. /* Auto refresh registration. */
  88. pj_bool_t auto_reg;
  89. pj_time_val last_reg;
  90. pj_time_val next_reg;
  91. pj_timer_entry timer;
  92. /* Transport selector */
  93. pjsip_tpselector tp_sel;
  94. /* Last transport used. We acquire the transport to keep
  95. * it open.
  96. */
  97. pjsip_transport *last_transport;
  98. /* Transport being used by pending transaction, for informational purpose,
  99. * we don't keep this transport.
  100. */
  101. pjsip_transport *info_transport;
  102. };
  103. PJ_DEF(pj_status_t) pjsip_regc_create( pjsip_endpoint *endpt, void *token,
  104. pjsip_regc_cb *cb,
  105. pjsip_regc **p_regc)
  106. {
  107. pj_pool_t *pool;
  108. pjsip_regc *regc;
  109. pj_status_t status;
  110. /* Verify arguments. */
  111. PJ_ASSERT_RETURN(endpt && cb && p_regc, PJ_EINVAL);
  112. pool = pjsip_endpt_create_pool(endpt, "regc%p", 1024, 1024);
  113. PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
  114. regc = PJ_POOL_ZALLOC_T(pool, pjsip_regc);
  115. regc->pool = pool;
  116. regc->endpt = endpt;
  117. regc->token = token;
  118. regc->cb = cb;
  119. regc->expires = PJSIP_REGC_EXPIRATION_NOT_SPECIFIED;
  120. regc->add_xuid_param = pjsip_cfg()->regc.add_xuid_param;
  121. status = pj_lock_create_recursive_mutex(pool, pool->obj_name,
  122. &regc->lock);
  123. if (status != PJ_SUCCESS) {
  124. pj_pool_release(pool);
  125. return status;
  126. }
  127. status = pj_atomic_create(pool, 0, &regc->busy_ctr);
  128. if (status != PJ_SUCCESS) {
  129. pj_lock_destroy(regc->lock);
  130. pj_pool_release(pool);
  131. return status;
  132. }
  133. status = pjsip_auth_clt_init(&regc->auth_sess, endpt, regc->pool, 0);
  134. if (status != PJ_SUCCESS)
  135. return status;
  136. pj_list_init(&regc->route_set);
  137. pj_list_init(&regc->hdr_list);
  138. pj_list_init(&regc->contact_hdr_list);
  139. pj_list_init(&regc->removed_contact_hdr_list);
  140. /* Done */
  141. *p_regc = regc;
  142. return PJ_SUCCESS;
  143. }
  144. PJ_DEF(pj_status_t) pjsip_regc_destroy(pjsip_regc *regc)
  145. {
  146. return pjsip_regc_destroy2(regc, PJ_TRUE);
  147. }
  148. PJ_DEF(pj_status_t) pjsip_regc_destroy2(pjsip_regc *regc, pj_bool_t force)
  149. {
  150. PJ_ASSERT_RETURN(regc, PJ_EINVAL);
  151. pj_lock_acquire(regc->lock);
  152. if (!force && regc->has_tsx) {
  153. pj_lock_release(regc->lock);
  154. return PJ_EBUSY;
  155. }
  156. if (regc->has_tsx || pj_atomic_get(regc->busy_ctr) != 0) {
  157. regc->_delete_flag = 1;
  158. regc->cb = NULL;
  159. pj_lock_release(regc->lock);
  160. } else {
  161. pjsip_tpselector_dec_ref(&regc->tp_sel);
  162. if (regc->last_transport) {
  163. pjsip_transport_dec_ref(regc->last_transport);
  164. regc->last_transport = NULL;
  165. }
  166. if (regc->timer.id != 0) {
  167. pjsip_endpt_cancel_timer(regc->endpt, &regc->timer);
  168. regc->timer.id = 0;
  169. }
  170. pj_atomic_destroy(regc->busy_ctr);
  171. pj_lock_release(regc->lock);
  172. pj_lock_destroy(regc->lock);
  173. regc->lock = NULL;
  174. pjsip_auth_clt_deinit(&regc->auth_sess);
  175. pjsip_endpt_release_pool(regc->endpt, regc->pool);
  176. }
  177. return PJ_SUCCESS;
  178. }
  179. PJ_DEF(pj_status_t) pjsip_regc_get_info( pjsip_regc *regc,
  180. pjsip_regc_info *info )
  181. {
  182. PJ_ASSERT_RETURN(regc && info, PJ_EINVAL);
  183. pj_lock_acquire(regc->lock);
  184. info->server_uri = regc->str_srv_url;
  185. info->client_uri = regc->from_uri;
  186. info->is_busy = (pj_atomic_get(regc->busy_ctr) || regc->has_tsx);
  187. info->auto_reg = regc->auto_reg;
  188. info->interval = regc->expires;
  189. info->transport = regc->has_tsx? regc->info_transport :
  190. regc->last_transport;
  191. if (regc->has_tsx)
  192. info->next_reg = 0;
  193. else if (regc->auto_reg == 0)
  194. info->next_reg = 0;
  195. else if (regc->expires == PJSIP_REGC_EXPIRATION_NOT_SPECIFIED)
  196. info->next_reg = regc->expires;
  197. else {
  198. pj_time_val now, next_reg;
  199. next_reg = regc->next_reg;
  200. pj_gettimeofday(&now);
  201. if (PJ_TIME_VAL_GT(next_reg, now)) {
  202. PJ_TIME_VAL_SUB(next_reg, now);
  203. info->next_reg = next_reg.sec;
  204. } else {
  205. info->next_reg = 0;
  206. }
  207. }
  208. pj_lock_release(regc->lock);
  209. return PJ_SUCCESS;
  210. }
  211. PJ_DEF(pj_pool_t*) pjsip_regc_get_pool(pjsip_regc *regc)
  212. {
  213. return regc->pool;
  214. }
  215. static void set_expires( pjsip_regc *regc, pj_uint32_t expires)
  216. {
  217. if (expires != regc->expires) {
  218. regc->expires_hdr = pjsip_expires_hdr_create(regc->pool, expires);
  219. } else {
  220. regc->expires_hdr = NULL;
  221. }
  222. }
  223. static pj_status_t set_contact( pjsip_regc *regc,
  224. int contact_cnt,
  225. const pj_str_t contact[] )
  226. {
  227. const pj_str_t CONTACT = { "Contact", 7 };
  228. pjsip_contact_hdr *h;
  229. int i;
  230. /* Save existing contact list to removed_contact_hdr_list and
  231. * clear contact_hdr_list.
  232. */
  233. pj_list_merge_last(&regc->removed_contact_hdr_list,
  234. &regc->contact_hdr_list);
  235. /* Set the expiration of Contacts in to removed_contact_hdr_list
  236. * zero.
  237. */
  238. h = regc->removed_contact_hdr_list.next;
  239. while (h != &regc->removed_contact_hdr_list) {
  240. h->expires = 0;
  241. h = h->next;
  242. }
  243. /* Process new contacts */
  244. for (i=0; i<contact_cnt; ++i) {
  245. pjsip_contact_hdr *hdr;
  246. pj_str_t tmp;
  247. pj_strdup_with_null(regc->pool, &tmp, &contact[i]);
  248. hdr = (pjsip_contact_hdr*)
  249. pjsip_parse_hdr(regc->pool, &CONTACT, tmp.ptr, tmp.slen, NULL);
  250. if (hdr == NULL) {
  251. PJ_LOG(4,(THIS_FILE, "Invalid Contact: \"%.*s\"",
  252. (int)tmp.slen, tmp.ptr));
  253. return PJSIP_EINVALIDURI;
  254. }
  255. /* Find the new contact in old contact list. If found, remove
  256. * the old header from the old header list.
  257. */
  258. h = regc->removed_contact_hdr_list.next;
  259. while (h != &regc->removed_contact_hdr_list) {
  260. int rc;
  261. rc = pjsip_uri_cmp(PJSIP_URI_IN_CONTACT_HDR,
  262. h->uri, hdr->uri);
  263. if (rc == 0) {
  264. /* Match */
  265. pj_list_erase(h);
  266. break;
  267. }
  268. h = h->next;
  269. }
  270. /* If add_xuid_param option is enabled and Contact URI is sip/sips,
  271. * add xuid parameter to assist matching the Contact URI in the
  272. * REGISTER response later.
  273. */
  274. if (regc->add_xuid_param && (PJSIP_URI_SCHEME_IS_SIP(hdr->uri) ||
  275. PJSIP_URI_SCHEME_IS_SIPS(hdr->uri)))
  276. {
  277. pjsip_param *xuid_param;
  278. pjsip_sip_uri *sip_uri;
  279. xuid_param = PJ_POOL_ZALLOC_T(regc->pool, pjsip_param);
  280. xuid_param->name = XUID_PARAM_NAME;
  281. pj_create_unique_string(regc->pool, &xuid_param->value);
  282. sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(hdr->uri);
  283. pj_list_push_back(&sip_uri->other_param, xuid_param);
  284. }
  285. pj_list_push_back(&regc->contact_hdr_list, hdr);
  286. }
  287. return PJ_SUCCESS;
  288. }
  289. PJ_DEF(pj_status_t) pjsip_regc_init( pjsip_regc *regc,
  290. const pj_str_t *srv_url,
  291. const pj_str_t *from_url,
  292. const pj_str_t *to_url,
  293. int contact_cnt,
  294. const pj_str_t contact[],
  295. pj_uint32_t expires)
  296. {
  297. pj_str_t tmp;
  298. pj_status_t status;
  299. PJ_ASSERT_RETURN(regc && srv_url && from_url && to_url &&
  300. expires, PJ_EINVAL);
  301. /* Copy server URL. */
  302. pj_strdup_with_null(regc->pool, &regc->str_srv_url, srv_url);
  303. /* Set server URL. */
  304. tmp = regc->str_srv_url;
  305. regc->srv_url = pjsip_parse_uri( regc->pool, tmp.ptr, tmp.slen, 0);
  306. if (regc->srv_url == NULL) {
  307. return PJSIP_EINVALIDURI;
  308. }
  309. /* Set "From" header. */
  310. pj_strdup_with_null(regc->pool, &regc->from_uri, from_url);
  311. tmp = regc->from_uri;
  312. regc->from_hdr = pjsip_from_hdr_create(regc->pool);
  313. regc->from_hdr->uri = pjsip_parse_uri(regc->pool, tmp.ptr, tmp.slen,
  314. PJSIP_PARSE_URI_AS_NAMEADDR);
  315. if (!regc->from_hdr->uri) {
  316. PJ_LOG(4,(THIS_FILE, "regc: invalid source URI %.*s",
  317. (int)from_url->slen, from_url->ptr));
  318. return PJSIP_EINVALIDURI;
  319. }
  320. /* Set "To" header. */
  321. pj_strdup_with_null(regc->pool, &tmp, to_url);
  322. regc->to_hdr = pjsip_to_hdr_create(regc->pool);
  323. regc->to_hdr->uri = pjsip_parse_uri(regc->pool, tmp.ptr, tmp.slen,
  324. PJSIP_PARSE_URI_AS_NAMEADDR);
  325. if (!regc->to_hdr->uri) {
  326. PJ_LOG(4,(THIS_FILE, "regc: invalid target URI %.*s",
  327. (int)to_url->slen, to_url->ptr));
  328. return PJSIP_EINVALIDURI;
  329. }
  330. /* Set "Contact" header. */
  331. status = set_contact( regc, contact_cnt, contact);
  332. if (status != PJ_SUCCESS)
  333. return status;
  334. /* Set "Expires" header, if required. */
  335. set_expires( regc, expires);
  336. regc->delay_before_refresh = DELAY_BEFORE_REFRESH;
  337. /* Set "Call-ID" header. */
  338. regc->cid_hdr = pjsip_cid_hdr_create(regc->pool);
  339. pj_create_unique_string(regc->pool, &regc->cid_hdr->id);
  340. /* Set "CSeq" header. */
  341. regc->cseq_hdr = pjsip_cseq_hdr_create(regc->pool);
  342. regc->cseq_hdr->cseq = pj_rand() % 0xFFFF;
  343. pjsip_method_set( &regc->cseq_hdr->method, PJSIP_REGISTER_METHOD);
  344. /* Done. */
  345. return PJ_SUCCESS;
  346. }
  347. PJ_DEF(void) pjsip_regc_add_ref( pjsip_regc *regc )
  348. {
  349. pj_assert(regc);
  350. pj_atomic_inc(regc->busy_ctr);
  351. }
  352. PJ_DEF(pj_status_t) pjsip_regc_dec_ref( pjsip_regc *regc )
  353. {
  354. pj_assert(regc);
  355. if (pj_atomic_dec_and_get(regc->busy_ctr)==0 && regc->_delete_flag) {
  356. pjsip_regc_destroy(regc);
  357. return PJ_EGONE;
  358. }
  359. return PJ_SUCCESS;
  360. }
  361. PJ_DEF(pj_status_t) pjsip_regc_set_credentials( pjsip_regc *regc,
  362. int count,
  363. const pjsip_cred_info cred[] )
  364. {
  365. PJ_ASSERT_RETURN(regc && count && cred, PJ_EINVAL);
  366. return pjsip_auth_clt_set_credentials(&regc->auth_sess, count, cred);
  367. }
  368. PJ_DEF(pj_status_t) pjsip_regc_set_prefs( pjsip_regc *regc,
  369. const pjsip_auth_clt_pref *pref)
  370. {
  371. PJ_ASSERT_RETURN(regc && pref, PJ_EINVAL);
  372. return pjsip_auth_clt_set_prefs(&regc->auth_sess, pref);
  373. }
  374. PJ_DEF(pj_status_t) pjsip_regc_set_route_set( pjsip_regc *regc,
  375. const pjsip_route_hdr *route_set)
  376. {
  377. const pjsip_route_hdr *chdr;
  378. PJ_ASSERT_RETURN(regc && route_set, PJ_EINVAL);
  379. pj_list_init(&regc->route_set);
  380. chdr = route_set->next;
  381. while (chdr != route_set) {
  382. pj_list_push_back(&regc->route_set, pjsip_hdr_clone(regc->pool, chdr));
  383. chdr = chdr->next;
  384. }
  385. return PJ_SUCCESS;
  386. }
  387. /*
  388. * Bind client registration to a specific transport/listener.
  389. */
  390. PJ_DEF(pj_status_t) pjsip_regc_set_transport( pjsip_regc *regc,
  391. const pjsip_tpselector *sel)
  392. {
  393. PJ_ASSERT_RETURN(regc && sel, PJ_EINVAL);
  394. pjsip_tpselector_dec_ref(&regc->tp_sel);
  395. pj_memcpy(&regc->tp_sel, sel, sizeof(*sel));
  396. pjsip_tpselector_add_ref(&regc->tp_sel);
  397. return PJ_SUCCESS;
  398. }
  399. /* Release transport */
  400. PJ_DEF(pj_status_t) pjsip_regc_release_transport(pjsip_regc *regc)
  401. {
  402. PJ_ASSERT_RETURN(regc, PJ_EINVAL);
  403. if (regc->last_transport) {
  404. pjsip_transport_dec_ref(regc->last_transport);
  405. regc->last_transport = NULL;
  406. }
  407. return PJ_SUCCESS;
  408. }
  409. PJ_DEF(pj_status_t) pjsip_regc_add_headers( pjsip_regc *regc,
  410. const pjsip_hdr *hdr_list)
  411. {
  412. const pjsip_hdr *hdr;
  413. PJ_ASSERT_RETURN(regc && hdr_list, PJ_EINVAL);
  414. //This is "add" operation, so don't remove headers.
  415. //pj_list_init(&regc->hdr_list);
  416. hdr = hdr_list->next;
  417. while (hdr != hdr_list) {
  418. pj_list_push_back(&regc->hdr_list, pjsip_hdr_clone(regc->pool, hdr));
  419. hdr = hdr->next;
  420. }
  421. return PJ_SUCCESS;
  422. }
  423. static pj_status_t create_request(pjsip_regc *regc,
  424. pjsip_tx_data **p_tdata)
  425. {
  426. pj_status_t status;
  427. pjsip_tx_data *tdata;
  428. PJ_ASSERT_RETURN(regc && p_tdata, PJ_EINVAL);
  429. /* Create the request. */
  430. status = pjsip_endpt_create_request_from_hdr( regc->endpt,
  431. pjsip_get_register_method(),
  432. regc->srv_url,
  433. regc->from_hdr,
  434. regc->to_hdr,
  435. NULL,
  436. regc->cid_hdr,
  437. regc->cseq_hdr->cseq,
  438. NULL,
  439. &tdata);
  440. if (status != PJ_SUCCESS)
  441. return status;
  442. /* Add cached authorization headers. */
  443. pjsip_auth_clt_init_req( &regc->auth_sess, tdata );
  444. /* Add Route headers from route set, ideally after Via header */
  445. if (!pj_list_empty(&regc->route_set)) {
  446. pjsip_hdr *route_pos;
  447. const pjsip_route_hdr *route;
  448. route_pos = (pjsip_hdr*)
  449. pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
  450. if (!route_pos)
  451. route_pos = &tdata->msg->hdr;
  452. route = regc->route_set.next;
  453. while (route != &regc->route_set) {
  454. pjsip_hdr *new_hdr = (pjsip_hdr*)
  455. pjsip_hdr_clone(tdata->pool, route);
  456. pj_list_insert_after(route_pos, new_hdr);
  457. route_pos = new_hdr;
  458. route = route->next;
  459. }
  460. }
  461. /* Add additional request headers */
  462. if (!pj_list_empty(&regc->hdr_list)) {
  463. const pjsip_hdr *hdr;
  464. hdr = regc->hdr_list.next;
  465. while (hdr != &regc->hdr_list) {
  466. pjsip_hdr *new_hdr = (pjsip_hdr*)
  467. pjsip_hdr_clone(tdata->pool, hdr);
  468. pjsip_msg_add_hdr(tdata->msg, new_hdr);
  469. hdr = hdr->next;
  470. }
  471. }
  472. /* Done. */
  473. *p_tdata = tdata;
  474. return PJ_SUCCESS;
  475. }
  476. PJ_DEF(pj_status_t) pjsip_regc_register(pjsip_regc *regc, pj_bool_t autoreg,
  477. pjsip_tx_data **p_tdata)
  478. {
  479. pjsip_msg *msg;
  480. pjsip_contact_hdr *hdr;
  481. const pjsip_hdr *h_allow;
  482. pj_status_t status;
  483. pjsip_tx_data *tdata;
  484. PJ_ASSERT_RETURN(regc && p_tdata, PJ_EINVAL);
  485. pj_lock_acquire(regc->lock);
  486. regc->expires_requested = 1;
  487. status = create_request(regc, &tdata);
  488. if (status != PJ_SUCCESS) {
  489. pj_lock_release(regc->lock);
  490. return status;
  491. }
  492. msg = tdata->msg;
  493. /* Add Contact headers. */
  494. hdr = regc->contact_hdr_list.next;
  495. while (hdr != &regc->contact_hdr_list) {
  496. pjsip_msg_add_hdr(msg, (pjsip_hdr*)
  497. pjsip_hdr_clone(tdata->pool, hdr));
  498. hdr = hdr->next;
  499. }
  500. /* Also add bindings which are to be removed */
  501. while (!pj_list_empty(&regc->removed_contact_hdr_list)) {
  502. hdr = regc->removed_contact_hdr_list.next;
  503. pjsip_msg_add_hdr(msg, (pjsip_hdr*)
  504. pjsip_hdr_clone(tdata->pool, hdr));
  505. pj_list_erase(hdr);
  506. }
  507. if (regc->expires_hdr)
  508. pjsip_msg_add_hdr(msg, (pjsip_hdr*)
  509. pjsip_hdr_clone(tdata->pool,
  510. regc->expires_hdr));
  511. if (regc->timer.id != 0) {
  512. pjsip_endpt_cancel_timer(regc->endpt, &regc->timer);
  513. regc->timer.id = 0;
  514. }
  515. /* Add Allow header (https://github.com/pjsip/pjproject/issues/1039) */
  516. h_allow = pjsip_endpt_get_capability(regc->endpt, PJSIP_H_ALLOW, NULL);
  517. if (h_allow) {
  518. pjsip_msg_add_hdr(msg, (pjsip_hdr*)
  519. pjsip_hdr_clone(tdata->pool, h_allow));
  520. }
  521. regc->auto_reg = autoreg;
  522. pj_lock_release(regc->lock);
  523. /* Done */
  524. *p_tdata = tdata;
  525. return PJ_SUCCESS;
  526. }
  527. PJ_DEF(pj_status_t) pjsip_regc_unregister(pjsip_regc *regc,
  528. pjsip_tx_data **p_tdata)
  529. {
  530. pjsip_tx_data *tdata;
  531. pjsip_msg *msg;
  532. pjsip_hdr *hdr;
  533. pj_status_t status;
  534. PJ_ASSERT_RETURN(regc && p_tdata, PJ_EINVAL);
  535. pj_lock_acquire(regc->lock);
  536. if (regc->timer.id != 0) {
  537. pjsip_endpt_cancel_timer(regc->endpt, &regc->timer);
  538. regc->timer.id = 0;
  539. }
  540. regc->expires_requested = 0;
  541. status = create_request(regc, &tdata);
  542. if (status != PJ_SUCCESS) {
  543. pj_lock_release(regc->lock);
  544. return status;
  545. }
  546. msg = tdata->msg;
  547. /* Add Contact headers. */
  548. hdr = (pjsip_hdr*)regc->contact_hdr_list.next;
  549. while ((void*)hdr != (void*)&regc->contact_hdr_list) {
  550. pjsip_msg_add_hdr(msg, (pjsip_hdr*)
  551. pjsip_hdr_clone(tdata->pool, hdr));
  552. hdr = hdr->next;
  553. }
  554. /* Also add bindings which are to be removed */
  555. while (!pj_list_empty(&regc->removed_contact_hdr_list)) {
  556. hdr = (pjsip_hdr*)regc->removed_contact_hdr_list.next;
  557. pjsip_msg_add_hdr(msg, (pjsip_hdr*)
  558. pjsip_hdr_clone(tdata->pool, hdr));
  559. pj_list_erase(hdr);
  560. }
  561. /* Add Expires:0 header */
  562. hdr = (pjsip_hdr*) pjsip_expires_hdr_create(tdata->pool, 0);
  563. pjsip_msg_add_hdr(msg, hdr);
  564. pj_lock_release(regc->lock);
  565. *p_tdata = tdata;
  566. return PJ_SUCCESS;
  567. }
  568. PJ_DEF(pj_status_t) pjsip_regc_unregister_all(pjsip_regc *regc,
  569. pjsip_tx_data **p_tdata)
  570. {
  571. pjsip_tx_data *tdata;
  572. pjsip_contact_hdr *hcontact;
  573. pjsip_hdr *hdr;
  574. pjsip_msg *msg;
  575. pj_status_t status;
  576. PJ_ASSERT_RETURN(regc && p_tdata, PJ_EINVAL);
  577. pj_lock_acquire(regc->lock);
  578. if (regc->timer.id != 0) {
  579. pjsip_endpt_cancel_timer(regc->endpt, &regc->timer);
  580. regc->timer.id = 0;
  581. }
  582. status = create_request(regc, &tdata);
  583. if (status != PJ_SUCCESS) {
  584. pj_lock_release(regc->lock);
  585. return status;
  586. }
  587. msg = tdata->msg;
  588. /* Clear removed_contact_hdr_list */
  589. pj_list_init(&regc->removed_contact_hdr_list);
  590. /* Add Contact:* header */
  591. hcontact = pjsip_contact_hdr_create(tdata->pool);
  592. hcontact->star = 1;
  593. pjsip_msg_add_hdr(msg, (pjsip_hdr*)hcontact);
  594. /* Add Expires:0 header */
  595. hdr = (pjsip_hdr*) pjsip_expires_hdr_create(tdata->pool, 0);
  596. pjsip_msg_add_hdr(msg, hdr);
  597. pj_lock_release(regc->lock);
  598. *p_tdata = tdata;
  599. return PJ_SUCCESS;
  600. }
  601. PJ_DEF(pj_status_t) pjsip_regc_update_contact( pjsip_regc *regc,
  602. int contact_cnt,
  603. const pj_str_t contact[] )
  604. {
  605. pj_status_t status;
  606. PJ_ASSERT_RETURN(regc, PJ_EINVAL);
  607. pj_lock_acquire(regc->lock);
  608. status = set_contact( regc, contact_cnt, contact );
  609. pj_lock_release(regc->lock);
  610. return status;
  611. }
  612. PJ_DEF(pj_status_t) pjsip_regc_update_expires( pjsip_regc *regc,
  613. pj_uint32_t expires )
  614. {
  615. PJ_ASSERT_RETURN(regc, PJ_EINVAL);
  616. pj_lock_acquire(regc->lock);
  617. set_expires( regc, expires );
  618. pj_lock_release(regc->lock);
  619. return PJ_SUCCESS;
  620. }
  621. static void cbparam_init( struct pjsip_regc_cbparam *cbparam,
  622. pjsip_regc *regc,
  623. pj_status_t status, int st_code,
  624. const pj_str_t *reason,
  625. pjsip_rx_data *rdata, pj_uint32_t expiration,
  626. int contact_cnt, pjsip_contact_hdr *contact[],
  627. pj_bool_t is_unreg)
  628. {
  629. cbparam->regc = regc;
  630. cbparam->token = regc->token;
  631. cbparam->status = status;
  632. cbparam->code = st_code;
  633. cbparam->reason = *reason;
  634. cbparam->rdata = rdata;
  635. cbparam->contact_cnt = contact_cnt;
  636. cbparam->expiration = (expiration != PJSIP_REGC_EXPIRATION_NOT_SPECIFIED?
  637. expiration: regc->expires_requested);
  638. cbparam->is_unreg = is_unreg;
  639. if (contact_cnt) {
  640. pj_memcpy( cbparam->contact, contact,
  641. contact_cnt*sizeof(pjsip_contact_hdr*));
  642. }
  643. }
  644. static void call_callback(pjsip_regc *regc, pj_status_t status, int st_code,
  645. const pj_str_t *reason,
  646. pjsip_rx_data *rdata, pj_uint32_t expiration,
  647. int contact_cnt, pjsip_contact_hdr *contact[],
  648. pj_bool_t is_unreg)
  649. {
  650. struct pjsip_regc_cbparam cbparam;
  651. if (!regc->cb)
  652. return;
  653. cbparam_init(&cbparam, regc, status, st_code, reason, rdata, expiration,
  654. contact_cnt, contact, is_unreg);
  655. (*regc->cb)(&cbparam);
  656. }
  657. static void regc_refresh_timer_cb( pj_timer_heap_t *timer_heap,
  658. struct pj_timer_entry *entry)
  659. {
  660. pjsip_regc *regc = (pjsip_regc*) entry->user_data;
  661. pjsip_tx_data *tdata;
  662. pj_status_t status;
  663. PJ_UNUSED_ARG(timer_heap);
  664. /* Temporarily increase busy flag to prevent regc from being deleted
  665. * in pjsip_regc_send() or in the callback
  666. */
  667. pjsip_regc_add_ref(regc);
  668. entry->id = 0;
  669. status = pjsip_regc_register(regc, 1, &tdata);
  670. if (status == PJ_SUCCESS) {
  671. status = pjsip_regc_send(regc, tdata);
  672. }
  673. if (status != PJ_SUCCESS && regc->cb) {
  674. char errmsg[PJ_ERR_MSG_SIZE];
  675. pj_str_t reason = pj_strerror(status, errmsg, sizeof(errmsg));
  676. call_callback(regc, status, 400, &reason, NULL, NOEXP, 0, NULL,
  677. PJ_FALSE);
  678. }
  679. /* Delete the record if user destroy regc during the callback. */
  680. pjsip_regc_dec_ref(regc);
  681. }
  682. static void schedule_registration ( pjsip_regc *regc, pj_uint32_t expiration )
  683. {
  684. if (regc->auto_reg && expiration > 0 && expiration != NOEXP) {
  685. pj_time_val delay = { 0, 0};
  686. pj_timer_heap_cancel_if_active(pjsip_endpt_get_timer_heap(regc->endpt),
  687. &regc->timer, 0);
  688. delay.sec = expiration - regc->delay_before_refresh;
  689. if (regc->expires != PJSIP_REGC_EXPIRATION_NOT_SPECIFIED &&
  690. delay.sec > (pj_int32_t)regc->expires)
  691. {
  692. delay.sec = regc->expires;
  693. }
  694. if (delay.sec < DELAY_BEFORE_REFRESH)
  695. delay.sec = DELAY_BEFORE_REFRESH;
  696. regc->timer.cb = &regc_refresh_timer_cb;
  697. regc->timer.id = REFRESH_TIMER;
  698. regc->timer.user_data = regc;
  699. pjsip_endpt_schedule_timer( regc->endpt, &regc->timer, &delay);
  700. pj_gettimeofday(&regc->last_reg);
  701. regc->next_reg = regc->last_reg;
  702. regc->next_reg.sec += delay.sec;
  703. }
  704. }
  705. PJ_DEF(pj_status_t) pjsip_regc_set_reg_tsx_cb( pjsip_regc *regc,
  706. pjsip_regc_tsx_cb *tsx_cb)
  707. {
  708. PJ_ASSERT_RETURN(regc, PJ_EINVAL);
  709. regc->tsx_cb = tsx_cb;
  710. return PJ_SUCCESS;
  711. }
  712. PJ_DEF(pj_status_t) pjsip_regc_set_via_sent_by( pjsip_regc *regc,
  713. pjsip_host_port *via_addr,
  714. pjsip_transport *via_tp)
  715. {
  716. PJ_ASSERT_RETURN(regc, PJ_EINVAL);
  717. if (!via_addr)
  718. pj_bzero(&regc->via_addr, sizeof(regc->via_addr));
  719. else {
  720. if (pj_strcmp(&regc->via_addr.host, &via_addr->host))
  721. pj_strdup(regc->pool, &regc->via_addr.host, &via_addr->host);
  722. regc->via_addr.port = via_addr->port;
  723. }
  724. regc->via_tp = via_tp;
  725. return PJ_SUCCESS;
  726. }
  727. PJ_DEF(pj_status_t)
  728. pjsip_regc_set_delay_before_refresh( pjsip_regc *regc,
  729. pj_uint32_t delay )
  730. {
  731. PJ_ASSERT_RETURN(regc, PJ_EINVAL);
  732. if (delay > regc->expires)
  733. return PJ_ETOOBIG;
  734. pj_lock_acquire(regc->lock);
  735. if (regc->delay_before_refresh != delay)
  736. {
  737. regc->delay_before_refresh = delay;
  738. if (regc->timer.id != 0) {
  739. /* Cancel registration timer */
  740. pjsip_endpt_cancel_timer(regc->endpt, &regc->timer);
  741. regc->timer.id = 0;
  742. /* Schedule next registration */
  743. schedule_registration(regc, regc->expires);
  744. }
  745. }
  746. pj_lock_release(regc->lock);
  747. return PJ_SUCCESS;
  748. }
  749. static pj_uint32_t calculate_response_expiration(const pjsip_regc *regc,
  750. const pjsip_rx_data *rdata,
  751. unsigned *contact_cnt,
  752. unsigned max_contact,
  753. pjsip_contact_hdr *contacts[])
  754. {
  755. pj_uint32_t expiration = NOEXP;
  756. const pjsip_msg *msg = rdata->msg_info.msg;
  757. const pjsip_hdr *hdr;
  758. /* Enumerate all Contact headers in the response */
  759. *contact_cnt = 0;
  760. for (hdr=msg->hdr.next; hdr!=&msg->hdr; hdr=hdr->next) {
  761. if (hdr->type == PJSIP_H_CONTACT &&
  762. *contact_cnt < max_contact)
  763. {
  764. contacts[*contact_cnt] = (pjsip_contact_hdr*)hdr;
  765. ++(*contact_cnt);
  766. }
  767. }
  768. if (regc->current_op == REGC_REGISTERING) {
  769. pj_bool_t has_our_contact = PJ_FALSE;
  770. const pjsip_expires_hdr *expires;
  771. /* Get Expires header */
  772. expires = (const pjsip_expires_hdr*)
  773. pjsip_msg_find_hdr(msg, PJSIP_H_EXPIRES, NULL);
  774. /* Try to find the Contact URIs that we register, in the response
  775. * to get the expires value. We'll try both with comparing the URI
  776. * and comparing the extension param only.
  777. */
  778. if (pjsip_cfg()->regc.check_contact || regc->add_xuid_param) {
  779. unsigned i;
  780. for (i=0; i<*contact_cnt; ++i) {
  781. const pjsip_contact_hdr *our_hdr;
  782. our_hdr = (const pjsip_contact_hdr*)
  783. regc->contact_hdr_list.next;
  784. /* Match with our Contact header(s) */
  785. while ((void*)our_hdr != (void*)&regc->contact_hdr_list) {
  786. const pjsip_uri *uri1, *uri2;
  787. pj_bool_t matched = PJ_FALSE;
  788. /* Exclude the display name when comparing the URI
  789. * since server may not return it.
  790. */
  791. uri1 = (const pjsip_uri*)
  792. pjsip_uri_get_uri(contacts[i]->uri);
  793. uri2 = (const pjsip_uri*)
  794. pjsip_uri_get_uri(our_hdr->uri);
  795. /* First try with exact matching, according to RFC 3261
  796. * Section 19.1.4 URI Comparison
  797. */
  798. if (pjsip_cfg()->regc.check_contact) {
  799. matched = pjsip_uri_cmp(PJSIP_URI_IN_CONTACT_HDR,
  800. uri1, uri2)==0;
  801. }
  802. /* If no match is found, try with matching the extension
  803. * parameter only if extension parameter was added.
  804. */
  805. if (!matched && regc->add_xuid_param &&
  806. (PJSIP_URI_SCHEME_IS_SIP(uri1) ||
  807. PJSIP_URI_SCHEME_IS_SIPS(uri1)) &&
  808. (PJSIP_URI_SCHEME_IS_SIP(uri2) ||
  809. PJSIP_URI_SCHEME_IS_SIPS(uri2)))
  810. {
  811. const pjsip_sip_uri *sip_uri1, *sip_uri2;
  812. const pjsip_param *p1, *p2;
  813. sip_uri1 = (const pjsip_sip_uri*)uri1;
  814. sip_uri2 = (const pjsip_sip_uri*)uri2;
  815. p1 = pjsip_param_cfind(&sip_uri1->other_param,
  816. &XUID_PARAM_NAME);
  817. p2 = pjsip_param_cfind(&sip_uri2->other_param,
  818. &XUID_PARAM_NAME);
  819. matched = p1 && p2 &&
  820. pj_strcmp(&p1->value, &p2->value)==0;
  821. }
  822. if (matched) {
  823. has_our_contact = PJ_TRUE;
  824. if (contacts[i]->expires != PJSIP_EXPIRES_NOT_SPECIFIED
  825. && contacts[i]->expires < expiration)
  826. {
  827. /* Get the lowest expiration time. */
  828. expiration = contacts[i]->expires;
  829. }
  830. break;
  831. }
  832. our_hdr = our_hdr->next;
  833. } /* while ((void.. */
  834. } /* for (i=.. */
  835. /* If matching Contact header(s) are found but the
  836. * header doesn't contain expires parameter, get the
  837. * expiration value from the Expires header. And
  838. * if Expires header is not present, get the expiration
  839. * value from the request.
  840. */
  841. if (has_our_contact && expiration == NOEXP) {
  842. if (expires) {
  843. expiration = expires->ivalue;
  844. } else if (regc->expires_hdr) {
  845. expiration = regc->expires_hdr->ivalue;
  846. } else {
  847. /* We didn't request explicit expiration value,
  848. * and server doesn't specify it either. This
  849. * shouldn't happen unless we have a broken
  850. * registrar.
  851. */
  852. expiration = 3600;
  853. }
  854. }
  855. }
  856. /* If we still couldn't get matching Contact header(s), it means
  857. * there must be something wrong with the registrar (e.g. it may
  858. * have modified the URI's in the response, which is prohibited).
  859. */
  860. if (expiration==NOEXP) {
  861. /* If the number of Contact headers in the response matches
  862. * ours, they're all probably ours. Get the expiration
  863. * from there if this is the case, or from Expires header
  864. * if we don't have exact Contact header count, or
  865. * from the request as the last resort.
  866. */
  867. pj_size_t our_contact_cnt;
  868. our_contact_cnt = pj_list_size(&regc->contact_hdr_list);
  869. if (*contact_cnt == our_contact_cnt && *contact_cnt &&
  870. contacts[0]->expires != PJSIP_EXPIRES_NOT_SPECIFIED)
  871. {
  872. expiration = contacts[0]->expires;
  873. } else if (expires)
  874. expiration = expires->ivalue;
  875. else if (regc->expires_hdr)
  876. expiration = regc->expires_hdr->ivalue;
  877. else
  878. expiration = 3600;
  879. }
  880. } else {
  881. /* Just assume that the unregistration has been successful. */
  882. expiration = 0;
  883. }
  884. /* Must have expiration value by now */
  885. pj_assert(expiration != NOEXP);
  886. return expiration;
  887. }
  888. static void regc_tsx_callback(void *token, pjsip_event *event)
  889. {
  890. pj_status_t status;
  891. pjsip_regc *regc = (pjsip_regc*) token;
  892. pjsip_transaction *tsx = event->body.tsx_state.tsx;
  893. pj_bool_t handled = PJ_TRUE;
  894. pj_bool_t update_contact = PJ_FALSE;
  895. pjsip_regc_add_ref(regc);
  896. pj_lock_acquire(regc->lock);
  897. /* Decrement pending transaction counter. */
  898. pj_assert(regc->has_tsx);
  899. regc->has_tsx = PJ_FALSE;
  900. /* Add reference to the transport */
  901. if (tsx->transport != regc->last_transport) {
  902. if (regc->last_transport) {
  903. pjsip_transport_dec_ref(regc->last_transport);
  904. regc->last_transport = NULL;
  905. }
  906. if (tsx->transport) {
  907. regc->last_transport = tsx->transport;
  908. pjsip_transport_add_ref(regc->last_transport);
  909. }
  910. }
  911. if (regc->_delete_flag == 0 && regc->tsx_cb &&
  912. regc->current_op == REGC_REGISTERING)
  913. {
  914. struct pjsip_regc_tsx_cb_param param;
  915. param.contact_cnt = -1;
  916. cbparam_init(&param.cbparam, regc, PJ_SUCCESS, tsx->status_code,
  917. &tsx->status_text,
  918. (event->body.tsx_state.type==PJSIP_EVENT_RX_MSG) ?
  919. event->body.tsx_state.src.rdata : NULL,
  920. NOEXP, 0, NULL, PJ_FALSE);
  921. /* Call regc tsx callback before handling any response */
  922. pj_lock_release(regc->lock);
  923. (*regc->tsx_cb)(&param);
  924. pj_lock_acquire(regc->lock);
  925. if (param.contact_cnt >= 0) {
  926. /* Since we receive non-2xx response, it means that (some) contact
  927. * bindings haven't been established so we can safely remove these
  928. * contact headers. This is to avoid removing non-existent contact
  929. * bindings later.
  930. */
  931. if (tsx->status_code/100 != 2) {
  932. pjsip_contact_hdr *h;
  933. h = regc->contact_hdr_list.next;
  934. while (h != &regc->contact_hdr_list) {
  935. pjsip_contact_hdr *next = h->next;
  936. if (h->expires == PJSIP_EXPIRES_NOT_SPECIFIED) {
  937. pj_list_erase(h);
  938. }
  939. h = next;
  940. }
  941. }
  942. /* Update contact address */
  943. pjsip_regc_update_contact(regc, param.contact_cnt, param.contact);
  944. update_contact = PJ_TRUE;
  945. }
  946. }
  947. /* Handle 401/407 challenge (even when _delete_flag is set) */
  948. if (tsx->status_code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED ||
  949. tsx->status_code == PJSIP_SC_UNAUTHORIZED)
  950. {
  951. pjsip_rx_data *rdata = event->body.tsx_state.src.rdata;
  952. pjsip_tx_data *tdata;
  953. pj_bool_t is_unreg;
  954. /* reset current op */
  955. is_unreg = (regc->current_op == REGC_UNREGISTERING);
  956. regc->current_op = REGC_IDLE;
  957. if (update_contact) {
  958. pjsip_msg *msg;
  959. pjsip_hdr *hdr, *ins_hdr;
  960. pjsip_contact_hdr *chdr;
  961. /* Delete Contact headers, but we shouldn't delete headers
  962. * which are supposed to remove contact bindings since
  963. * we cannot reconstruct those headers.
  964. */
  965. msg = tsx->last_tx->msg;
  966. hdr = msg->hdr.next;
  967. ins_hdr = &msg->hdr;
  968. while (hdr != &msg->hdr) {
  969. pjsip_hdr *next = hdr->next;
  970. if (hdr->type == PJSIP_H_CONTACT) {
  971. chdr = (pjsip_contact_hdr *)hdr;
  972. if (chdr->expires != 0) {
  973. pj_list_erase(hdr);
  974. ins_hdr = next;
  975. }
  976. }
  977. hdr = next;
  978. }
  979. /* Add Contact headers. */
  980. chdr = regc->contact_hdr_list.next;
  981. while (chdr != &regc->contact_hdr_list) {
  982. pj_list_insert_before(ins_hdr, (pjsip_hdr*)
  983. pjsip_hdr_clone(tsx->last_tx->pool, chdr));
  984. chdr = chdr->next;
  985. }
  986. /* Also add bindings which are to be removed */
  987. while (!pj_list_empty(&regc->removed_contact_hdr_list)) {
  988. chdr = regc->removed_contact_hdr_list.next;
  989. pj_list_insert_before(ins_hdr, (pjsip_hdr*)
  990. pjsip_hdr_clone(tsx->last_tx->pool, chdr));
  991. pj_list_erase(chdr);
  992. }
  993. }
  994. status = pjsip_auth_clt_reinit_req( &regc->auth_sess,
  995. rdata,
  996. tsx->last_tx,
  997. &tdata);
  998. if (status == PJ_SUCCESS) {
  999. /* Need to unlock the regc temporarily while sending the message
  1000. * to prevent deadlock (see ticket #2260 and #1247).
  1001. * It should be safe to do this since the regc's refcount has been
  1002. * incremented.
  1003. */
  1004. pj_lock_release(regc->lock);
  1005. status = pjsip_regc_send(regc, tdata);
  1006. pj_lock_acquire(regc->lock);
  1007. }
  1008. if (status != PJ_SUCCESS) {
  1009. /* Only call callback if application is still interested
  1010. * in it.
  1011. */
  1012. if (regc->_delete_flag == 0) {
  1013. /* Should be safe to release the lock temporarily.
  1014. * We do this to avoid deadlock.
  1015. */
  1016. pj_lock_release(regc->lock);
  1017. call_callback(regc, status, tsx->status_code,
  1018. &rdata->msg_info.msg->line.status.reason,
  1019. rdata, NOEXP, 0, NULL, is_unreg);
  1020. pj_lock_acquire(regc->lock);
  1021. }
  1022. }
  1023. } else if (regc->_delete_flag) {
  1024. /* User has called pjsip_regc_destroy(), so don't call callback.
  1025. * This regc will be destroyed later in this function.
  1026. */
  1027. /* Just reset current op */
  1028. regc->current_op = REGC_IDLE;
  1029. } else if (tsx->status_code == PJSIP_SC_INTERVAL_TOO_BRIEF &&
  1030. regc->current_op == REGC_REGISTERING)
  1031. {
  1032. /* Handle 423 response automatically:
  1033. * - set requested expiration to Min-Expires header, ONLY IF
  1034. * the original request is a registration (as opposed to
  1035. * unregistration) and the requested expiration was indeed
  1036. * lower than Min-Expires)
  1037. * - resend the request
  1038. */
  1039. pjsip_rx_data *rdata = event->body.tsx_state.src.rdata;
  1040. pjsip_min_expires_hdr *me_hdr;
  1041. pjsip_tx_data *tdata;
  1042. pj_uint32_t min_exp;
  1043. /* reset current op */
  1044. regc->current_op = REGC_IDLE;
  1045. /* Update requested expiration */
  1046. me_hdr = (pjsip_min_expires_hdr*)
  1047. pjsip_msg_find_hdr(rdata->msg_info.msg,
  1048. PJSIP_H_MIN_EXPIRES, NULL);
  1049. if (me_hdr) {
  1050. min_exp = me_hdr->ivalue;
  1051. } else {
  1052. /* Broken server, Min-Expires doesn't exist.
  1053. * Just guestimate then, BUT ONLY if if this is the
  1054. * first time we received such response.
  1055. */
  1056. enum {
  1057. /* Note: changing this value would require changing couple of
  1058. * Python test scripts.
  1059. */
  1060. UNSPECIFIED_MIN_EXPIRES = 3601
  1061. };
  1062. if (!regc->expires_hdr ||
  1063. regc->expires_hdr->ivalue != UNSPECIFIED_MIN_EXPIRES)
  1064. {
  1065. min_exp = UNSPECIFIED_MIN_EXPIRES;
  1066. } else {
  1067. handled = PJ_FALSE;
  1068. PJ_LOG(4,(THIS_FILE, "Registration failed: 423 response "
  1069. "without Min-Expires header is invalid"));
  1070. goto handle_err;
  1071. }
  1072. }
  1073. if (regc->expires_hdr && regc->expires_hdr->ivalue >= min_exp) {
  1074. /* But we already send with greater expiration time, why does
  1075. * the server send us with 423? Oh well, just fail the request.
  1076. */
  1077. handled = PJ_FALSE;
  1078. PJ_LOG(4,(THIS_FILE, "Registration failed: invalid "
  1079. "Min-Expires header value in response"));
  1080. goto handle_err;
  1081. }
  1082. set_expires(regc, min_exp);
  1083. status = pjsip_regc_register(regc, regc->auto_reg, &tdata);
  1084. if (status == PJ_SUCCESS) {
  1085. /* Need to unlock the regc temporarily while sending the message
  1086. * to prevent deadlock (see ticket #2260 and #1247).
  1087. * It should be safe to do this since the regc's refcount has been
  1088. * incremented.
  1089. */
  1090. pj_lock_release(regc->lock);
  1091. status = pjsip_regc_send(regc, tdata);
  1092. pj_lock_acquire(regc->lock);
  1093. }
  1094. if (status != PJ_SUCCESS) {
  1095. /* Only call callback if application is still interested
  1096. * in it.
  1097. */
  1098. if (!regc->_delete_flag) {
  1099. /* Should be safe to release the lock temporarily.
  1100. * We do this to avoid deadlock.
  1101. */
  1102. pj_lock_release(regc->lock);
  1103. call_callback(regc, status, tsx->status_code,
  1104. &rdata->msg_info.msg->line.status.reason,
  1105. rdata, NOEXP, 0, NULL, PJ_FALSE);
  1106. pj_lock_acquire(regc->lock);
  1107. }
  1108. }
  1109. } else {
  1110. handled = PJ_FALSE;
  1111. }
  1112. handle_err:
  1113. if (!handled) {
  1114. pjsip_rx_data *rdata;
  1115. pj_uint32_t expiration = NOEXP;
  1116. unsigned contact_cnt = 0;
  1117. pjsip_contact_hdr *contact[PJSIP_REGC_MAX_CONTACT];
  1118. pj_bool_t is_unreg;
  1119. if (tsx->status_code/100 == 2) {
  1120. rdata = event->body.tsx_state.src.rdata;
  1121. /* Calculate expiration */
  1122. expiration = calculate_response_expiration(regc, rdata,
  1123. &contact_cnt,
  1124. PJSIP_REGC_MAX_CONTACT,
  1125. contact);
  1126. #if PJSIP_REGISTER_ALLOW_EXP_REFRESH
  1127. if (expiration == 0 && regc->current_op != REGC_UNREGISTERING) {
  1128. /* Response contain expires contact param 0, allow client to
  1129. * continue refresh registration.
  1130. * Refer to: https://github.com/pjsip/pjproject/pull/2809
  1131. */
  1132. const pjsip_msg *msg = rdata->msg_info.msg;
  1133. const pjsip_expires_hdr *expires;
  1134. expires = (const pjsip_expires_hdr*) pjsip_msg_find_hdr(msg,
  1135. PJSIP_H_EXPIRES, NULL);
  1136. if (expires) {
  1137. expiration = expires->ivalue;
  1138. } else if (regc->expires_hdr && regc->expires_hdr->ivalue) {
  1139. expiration = regc->expires_hdr->ivalue;
  1140. } else {
  1141. expiration = 3600;
  1142. }
  1143. PJ_LOG(4, (THIS_FILE, "Modify response's expiration from 0 "
  1144. "to %d", expiration));
  1145. }
  1146. #endif
  1147. /* Schedule next registration */
  1148. schedule_registration(regc, expiration);
  1149. } else {
  1150. rdata = (event->body.tsx_state.type==PJSIP_EVENT_RX_MSG) ?
  1151. event->body.tsx_state.src.rdata : NULL;
  1152. }
  1153. /* Update registration */
  1154. // if (expiration==NOEXP) expiration=-1;
  1155. regc->expires = expiration;
  1156. /* Mark operation as complete */
  1157. is_unreg = (regc->current_op == REGC_UNREGISTERING);
  1158. regc->current_op = REGC_IDLE;
  1159. /* Call callback. */
  1160. /* Should be safe to release the lock temporarily.
  1161. * We do this to avoid deadlock.
  1162. */
  1163. pj_lock_release(regc->lock);
  1164. call_callback(regc, PJ_SUCCESS, tsx->status_code,
  1165. (rdata ? &rdata->msg_info.msg->line.status.reason
  1166. : &tsx->status_text),
  1167. rdata, expiration,
  1168. contact_cnt, contact, is_unreg);
  1169. pj_lock_acquire(regc->lock);
  1170. }
  1171. pj_lock_release(regc->lock);
  1172. /* Delete the record if user destroy regc during the callback. */
  1173. pjsip_regc_dec_ref(regc);
  1174. }
  1175. PJ_DEF(pj_status_t) pjsip_regc_send(pjsip_regc *regc, pjsip_tx_data *tdata)
  1176. {
  1177. pj_status_t status;
  1178. pjsip_cseq_hdr *cseq_hdr;
  1179. pjsip_expires_hdr *expires_hdr;
  1180. pj_int32_t cseq;
  1181. pjsip_regc_add_ref(regc);
  1182. pj_lock_acquire(regc->lock);
  1183. /* Make sure we don't have pending transaction. */
  1184. if (regc->has_tsx) {
  1185. PJ_LOG(4,(THIS_FILE, "Unable to send request, regc has another "
  1186. "transaction pending"));
  1187. pjsip_tx_data_dec_ref( tdata );
  1188. pj_lock_release(regc->lock);
  1189. pj_atomic_dec(regc->busy_ctr);
  1190. return PJSIP_EBUSY;
  1191. }
  1192. /* Just regc->has_tsx check above should be enough. This assertion check
  1193. * may cause problem, e.g: when regc_tsx_callback() invokes callback,
  1194. * lock is released and 'has_tsx' is set to FALSE and 'current_op' has
  1195. * not been updated to REGC_IDLE yet.
  1196. */
  1197. //pj_assert(regc->current_op == REGC_IDLE);
  1198. /* Invalidate message buffer. */
  1199. pjsip_tx_data_invalidate_msg(tdata);
  1200. /* Increment CSeq */
  1201. cseq = ++regc->cseq_hdr->cseq;
  1202. cseq_hdr = (pjsip_cseq_hdr*)
  1203. pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL);
  1204. cseq_hdr->cseq = cseq;
  1205. /* Find Expires header */
  1206. expires_hdr = (pjsip_expires_hdr*)
  1207. pjsip_msg_find_hdr(tdata->msg, PJSIP_H_EXPIRES, NULL);
  1208. /* Bind to transport selector */
  1209. pjsip_tx_data_set_transport(tdata, &regc->tp_sel);
  1210. regc->has_tsx = PJ_TRUE;
  1211. /* Set current operation based on the value of Expires header */
  1212. if (expires_hdr && expires_hdr->ivalue==0)
  1213. regc->current_op = REGC_UNREGISTERING;
  1214. else
  1215. regc->current_op = REGC_REGISTERING;
  1216. if (expires_hdr && expires_hdr->ivalue)
  1217. regc->expires_requested = expires_hdr->ivalue;
  1218. /* Prevent deletion of tdata, e.g: when something wrong in sending,
  1219. * we need tdata to retrieve the transport.
  1220. */
  1221. pjsip_tx_data_add_ref(tdata);
  1222. /* If via_addr is set, use this address for the Via header. */
  1223. if (regc->via_addr.host.slen > 0) {
  1224. tdata->via_addr = regc->via_addr;
  1225. tdata->via_tp = regc->via_tp;
  1226. }
  1227. /* Need to unlock the regc temporarily while sending the message to
  1228. * prevent deadlock (https://github.com/pjsip/pjproject/issues/1247).
  1229. * It should be safe to do this since the regc's refcount has been
  1230. * incremented.
  1231. */
  1232. pj_lock_release(regc->lock);
  1233. /* Now send the message */
  1234. status = pjsip_endpt_send_request(regc->endpt, tdata, REGC_TSX_TIMEOUT,
  1235. regc, &regc_tsx_callback);
  1236. /* Reacquire the lock */
  1237. pj_lock_acquire(regc->lock);
  1238. if (status!=PJ_SUCCESS) {
  1239. /* On failure, regc_tsx_callback() may not be called, so we need
  1240. * to reset regc->has_tsx here (see also ticket #1936).
  1241. * But note that we are releasing the lock when sending the request
  1242. * above, so there can be a race with another registration send.
  1243. */
  1244. if (cseq == regc->cseq_hdr->cseq) {
  1245. regc->has_tsx = PJ_FALSE;
  1246. }
  1247. PJ_PERROR(4,(THIS_FILE, status, "Error sending request"));
  1248. }
  1249. /* Get last transport used and add reference to it */
  1250. //if (tdata->tp_info.transport != regc->last_transport &&
  1251. // status==PJ_SUCCESS)
  1252. //{
  1253. // if (regc->last_transport) {
  1254. // pjsip_transport_dec_ref(regc->last_transport);
  1255. // regc->last_transport = NULL;
  1256. // }
  1257. // if (tdata->tp_info.transport) {
  1258. // regc->last_transport = tdata->tp_info.transport;
  1259. // pjsip_transport_add_ref(regc->last_transport);
  1260. // }
  1261. //}
  1262. // Update: don't add_ref() or use the transport info from tdata other than
  1263. // for informational purpose (e.g: comparing the pointers to check
  1264. // if a disconnected transport is the registration transport), see
  1265. // pjsip_tx_data.tp_info docs about its valid period.
  1266. // Note that the send operation may be async and transport may
  1267. // have been destroyed here.
  1268. regc->info_transport = status==PJ_SUCCESS? tdata->tp_info.transport :
  1269. NULL;
  1270. /* Release tdata */
  1271. pjsip_tx_data_dec_ref(tdata);
  1272. pj_lock_release(regc->lock);
  1273. /* Delete the record if user destroy regc during the callback. */
  1274. pjsip_regc_dec_ref(regc);
  1275. return status;
  1276. }