nua_common.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. /*
  2. * This file is part of the Sofia-SIP package
  3. *
  4. * Copyright (C) 2005 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 nua_common.c
  25. * @brief Function common to both stack and application side.
  26. *
  27. * @author Pekka.Pessi@nokia.com
  28. *
  29. * @date Created: Tue Apr 26 13:23:17 2005 ppessi
  30. *
  31. */
  32. #include "config.h"
  33. #include <stddef.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <assert.h>
  37. #include <sofia-sip/su_tag_class.h>
  38. #include <sofia-sip/su_tag_class.h>
  39. #include <sofia-sip/su_tagarg.h>
  40. #include <sofia-sip/su_uniqueid.h>
  41. #include <stdio.h>
  42. #include <sofia-sip/su_tag_io.h>
  43. #define SU_LOG (nua_log)
  44. #include <sofia-sip/su_debug.h>
  45. #define SU_ROOT_MAGIC_T struct nua_s
  46. #include <sofia-sip/su_wait.h>
  47. #include <sofia-sip/su_string.h>
  48. #include <sofia-sip/su_strlst.h>
  49. #include "sofia-sip/nua.h"
  50. #include "sofia-sip/nua_tag.h"
  51. #include <sofia-sip/sip_protos.h>
  52. #include <sofia-sip/nta.h>
  53. #include <sofia-sip/nea.h>
  54. #include <sofia-sip/auth_client.h>
  55. #if HAVE_SMIME /* Start NRC Boston */
  56. #include "smimec.h"
  57. #endif /* End NRC Boston */
  58. #include <sofia-sip/sdp.h>
  59. #include "nua_stack.h"
  60. static void nh_destructor(void *arg);
  61. /**@internal
  62. * Create an operation handle
  63. *
  64. * Allocates a new operation handle and associated storage.
  65. *
  66. * @param nua Pointer to NUA stack object
  67. * @param hmagic Pointer to callback context
  68. * @param tags List of tagged parameters
  69. *
  70. * @retval non-NULL Pointer to operation handle
  71. * @retval NULL Creation failed
  72. *
  73. * @par Related tags:
  74. * Creates a copy of the provided tags which will
  75. * be used with every operation.
  76. *
  77. * @par Events:
  78. * none
  79. *
  80. * @note
  81. * This function is called by both stack and application sides.
  82. */
  83. nua_handle_t *nh_create_handle(nua_t *nua,
  84. nua_hmagic_t *hmagic,
  85. tagi_t *tags)
  86. {
  87. nua_handle_t *nh;
  88. static int8_t _handle_lifetime = 1;
  89. enter;
  90. assert(nua->nua_home);
  91. //if ((nh = su_home_clone(nua->nua_home, sizeof(*nh)))) {
  92. if ((nh = su_home_new(sizeof(*nh)))) {
  93. nh->nh_valid = nua_valid_handle_cookie;
  94. nh->nh_nua = nua;
  95. nh->nh_magic = hmagic;
  96. nh->nh_prefs = nua->nua_dhandle->nh_prefs;
  97. nh->nh_ds->ds_owner = nh;
  98. if (nua_handle_save_tags(nh, tags) < 0) {
  99. SU_DEBUG_5(("nua(%p): creating handle %p failed\n",
  100. (void *)nua, (void *)nh));
  101. su_home_unref(nh->nh_home), nh = NULL;
  102. }
  103. if (nh && su_home_is_threadsafe(nua->nua_home)) {
  104. if (su_home_threadsafe(nh->nh_home) < 0) {
  105. su_home_unref(nh->nh_home);
  106. nh = NULL;
  107. }
  108. }
  109. if (nh && _handle_lifetime) {
  110. /* This far, we have nothing real to destruct but
  111. * when _NUA_HANDLE_DEBUG is set, we add destructor
  112. * and get more entertaining debugging output */
  113. if (_handle_lifetime == 1 && !getenv("_NUA_HANDLE_DEBUG")) {
  114. _handle_lifetime = 0;
  115. }
  116. else {
  117. _handle_lifetime = 2;
  118. SU_DEBUG_0(("nh_handle_create(%p)\n", (void *)nh));
  119. su_home_destructor(nh->nh_home, nh_destructor);
  120. }
  121. }
  122. }
  123. return nh;
  124. }
  125. /**@var _NUA_HANDLE_DEBUG
  126. *
  127. * If this environment variable is set, nua stack logs a message whenever a
  128. * handle is created and when it is destroyed. This is mainly useful when
  129. * debugging #nua_handle_t leaks.
  130. *
  131. * @sa nua_handle(), nua_handle_destroy()
  132. */
  133. extern char const _NUA_HANDLE_DEBUG[];
  134. /* nua handle destructor. It does nothing. */
  135. static void nh_destructor(void *arg)
  136. {
  137. nua_handle_t *nh = arg;
  138. SU_DEBUG_0(("nh_destructor(%p)\n", (void *)nh));
  139. }
  140. #if HAVE_MEMLEAK_LOG
  141. nua_handle_t *
  142. _nua_handle_ref_by(nua_handle_t *nh,
  143. char const *file, unsigned line,
  144. char const *function)
  145. {
  146. #if (HAVE_MEMLEAK_LOG == 1)
  147. if (nh)
  148. SU_DEBUG_0(("%p - nua_handle_ref() => "MOD_ZU" by %s:%u: %s()\n",
  149. nh, su_home_refcount((su_home_t *)nh) + 1, file, line, function));
  150. return (nua_handle_t *)su_home_ref((su_home_t *)nh);
  151. #else
  152. return (nua_handle_t *)_su_home_ref_by((su_home_t *)nh, file, line, function);
  153. #endif
  154. }
  155. int
  156. _nua_handle_unref_by(nua_handle_t *nh,
  157. char const *file, unsigned line,
  158. char const *function)
  159. {
  160. #if (HAVE_MEMLEAK_LOG == 1)
  161. if (nh) {
  162. size_t refcount = su_home_refcount((su_home_t *)nh) - 1;
  163. int freed = su_home_unref((su_home_t *)nh);
  164. if (freed) refcount = 0;
  165. SU_DEBUG_0(("%p - nua_handle_unref() => "MOD_ZU" by %s:%u: %s()\n",
  166. nh, refcount, file, line, function));
  167. return freed;
  168. }
  169. return 0;
  170. #else
  171. return _su_home_unref_by((su_home_t *)nh, file, line, function);
  172. #endif
  173. }
  174. #else
  175. /** Make a new reference to handle.
  176. *
  177. * The handles use reference counting for memory management. In addition to
  178. * the memory management, there is protocol state associated with the
  179. * handles. The protocol state is terminated with nua_handle_destroy(). In
  180. * order to make it more convenient for programmer, nua_handle_destroy()
  181. * decreases the reference count, too.
  182. *
  183. * @note All handle references are destroyed when the nua object is destroyed.
  184. *
  185. * @sa nua_handle_unref(), nua_handle(), nua_handle_destroy().
  186. */
  187. nua_handle_t *nua_handle_ref(nua_handle_t *nh)
  188. {
  189. return (nua_handle_t *)su_home_ref(nh->nh_home);
  190. }
  191. /** Destroy reference to handle.
  192. *
  193. * The handles use reference counting for memory management. In addition to
  194. * the memory management, there is protocol state associated with the
  195. * handles. The protocol state is terminated with nua_handle_destroy(). In
  196. * order to make it more convenient for programmer, nua_handle_destroy()
  197. * decreases the reference count, too.
  198. *
  199. * @sa nua_handle_ref(), nua_handle(), nua_handle_destroy().
  200. */
  201. int nua_handle_unref(nua_handle_t *nh)
  202. {
  203. return su_home_unref(nh->nh_home);
  204. }
  205. #endif
  206. /** Generate an instance identifier. */
  207. char const *nua_generate_instance_identifier(su_home_t *home)
  208. {
  209. char str[su_guid_strlen + 1];
  210. su_guid_t guid[1];
  211. su_guid_generate(guid);
  212. /*
  213. * Guid looks like "NNNNNNNN-NNNN-NNNN-NNNN-XXXXXXXXXXXX"
  214. * where NNNNNNNN-NNNN-NNNN-NNNN is timestamp and XX is MAC address
  215. * (but we use usually random ID for MAC because we do not have
  216. * guid generator available for all processes within node)
  217. */
  218. su_guid_sprintf(str, su_guid_strlen + 1, guid);
  219. return su_strdup(home, str);
  220. }
  221. /** Check if event is a request that can be responded with nua_respond().
  222. *
  223. * Note that if event status is 200 or greater, it already has been
  224. * responded. This function is provided for compatibility with future
  225. * versions of nua. An unknown event can always be handled in the event
  226. * callback like this:
  227. * @code
  228. * switch (event) {
  229. * ...
  230. * default:
  231. * if (status < 200 && nua_event_is_incoming_request(event))
  232. * nua_respond(nh, SIP_501_NOT_IMPLEMENTED,
  233. * NUTAG_WITH_THIS(nua), TAG_END());
  234. * if (hmagic == NULL)
  235. * nua_handle_destroy(nh);
  236. * return;
  237. * ...
  238. * @endcode
  239. *
  240. * @sa nua_respond(), #nua_event_e, #nua_event_t, nua_event_name()
  241. *
  242. * @NEW_1_12_6.
  243. */
  244. int nua_event_is_incoming_request(nua_event_t event)
  245. {
  246. switch (event) {
  247. case nua_i_invite: return 1;
  248. case nua_i_cancel: return 1;
  249. case nua_i_register: return 1;
  250. case nua_i_bye: return 1;
  251. case nua_i_options: return 1;
  252. case nua_i_refer: return 1;
  253. case nua_i_publish: return 1;
  254. case nua_i_prack: return 1;
  255. case nua_i_info: return 1;
  256. case nua_i_update: return 1;
  257. case nua_i_message: return 1;
  258. case nua_i_subscribe: return 1;
  259. case nua_i_notify: return 1;
  260. case nua_i_method: return 1;
  261. default: return 0;
  262. }
  263. }
  264. /** Get name for a NUA event.
  265. *
  266. * @sa #nua_event_e, #nua_event_t, nua_callstate_name(), nua_substate_name()
  267. */
  268. char const *nua_event_name(nua_event_t event)
  269. {
  270. switch (event) {
  271. case nua_i_none: return "nua_i_none";
  272. case nua_i_error: return "nua_i_error";
  273. case nua_i_invite: return "nua_i_invite";
  274. case nua_i_cancel: return "nua_i_cancel";
  275. case nua_i_ack: return "nua_i_ack";
  276. case nua_i_register: return "nua_i_register";
  277. case nua_i_fork: return "nua_i_fork";
  278. case nua_i_active: return "nua_i_active";
  279. case nua_i_terminated: return "nua_i_terminated";
  280. case nua_i_state: return "nua_i_state";
  281. case nua_i_outbound: return "nua_i_outbound";
  282. case nua_i_bye: return "nua_i_bye";
  283. case nua_i_options: return "nua_i_options";
  284. case nua_i_refer: return "nua_i_refer";
  285. case nua_i_publish: return "nua_i_publish";
  286. case nua_i_prack: return "nua_i_prack";
  287. case nua_i_info: return "nua_i_info";
  288. case nua_i_update: return "nua_i_update";
  289. case nua_i_message: return "nua_i_message";
  290. case nua_i_chat: return "nua_i_chat";
  291. case nua_i_subscribe: return "nua_i_subscribe";
  292. case nua_i_subscription: return "nua_i_subscription";
  293. case nua_i_notify: return "nua_i_notify";
  294. case nua_i_method: return "nua_i_method";
  295. case nua_i_media_error: return "nua_i_media_error";
  296. /* Responses */
  297. case nua_r_get_params: return "nua_r_get_params";
  298. case nua_r_shutdown: return "nua_r_shutdown";
  299. case nua_r_notifier: return "nua_r_notifier";
  300. case nua_r_terminate: return "nua_r_terminate";
  301. case nua_r_register: return "nua_r_register";
  302. case nua_r_unregister: return "nua_r_unregister";
  303. case nua_r_invite: return "nua_r_invite";
  304. case nua_r_bye: return "nua_r_bye";
  305. case nua_r_options: return "nua_r_options";
  306. case nua_r_refer: return "nua_r_refer";
  307. case nua_r_publish: return "nua_r_publish";
  308. case nua_r_unpublish: return "nua_r_unpublish";
  309. case nua_r_info: return "nua_r_info";
  310. case nua_r_prack: return "nua_r_prack";
  311. case nua_r_update: return "nua_r_update";
  312. case nua_r_message: return "nua_r_message";
  313. case nua_r_chat: return "nua_r_chat";
  314. case nua_r_subscribe: return "nua_r_subscribe";
  315. case nua_r_unsubscribe: return "nua_r_unsubscribe";
  316. case nua_r_notify: return "nua_r_notify";
  317. case nua_r_method: return "nua_r_method";
  318. case nua_r_cancel: return "nua_r_cancel";
  319. case nua_r_authenticate: return "nua_r_authenticate";
  320. case nua_r_authorize: return "nua_r_authorize";
  321. case nua_r_redirect: return "nua_r_redirect";
  322. case nua_r_destroy: return "nua_r_destroy";
  323. case nua_r_respond: return "nua_r_respond";
  324. case nua_r_nit_respond: return "nua_r_nit_respond";
  325. case nua_r_set_params: return "nua_r_set_params";
  326. case nua_r_ack: return "nua_r_ack";
  327. case nua_r_handle_unref: return "nua_r_handle_unref";
  328. case nua_r_unref: return "nua_r_unref";
  329. default: return "NUA_UNKNOWN";
  330. }
  331. }
  332. /** Return name of call state.
  333. *
  334. * @sa enum #nua_callstate, nua_event_name(), nua_substate_name()
  335. */
  336. char const *nua_callstate_name(enum nua_callstate state)
  337. {
  338. switch (state) {
  339. case nua_callstate_init: return "init";
  340. case nua_callstate_authenticating: return "authenticating";
  341. case nua_callstate_calling: return "calling";
  342. case nua_callstate_proceeding: return "proceeding";
  343. case nua_callstate_completing: return "completing";
  344. case nua_callstate_received: return "received";
  345. case nua_callstate_early: return "early";
  346. case nua_callstate_completed: return "completed";
  347. case nua_callstate_ready: return "ready";
  348. case nua_callstate_terminating: return "terminating";
  349. case nua_callstate_terminated: return "terminated";
  350. default: return "UNKNOWN";
  351. }
  352. }
  353. /** Return name of subscription state. @NEW_1_12_5.
  354. *
  355. * @sa enum #nua_substate, nua_event_name(), nua_callstate_name()
  356. */
  357. char const *nua_substate_name(enum nua_substate substate)
  358. {
  359. switch (substate) {
  360. case nua_substate_embryonic:
  361. /*FALLTHROUGH*/
  362. case nua_substate_pending:
  363. return "pending";
  364. case nua_substate_terminated:
  365. return "terminated";
  366. case nua_substate_active:
  367. /*FALLTHROUGH*/
  368. default:
  369. return "active";
  370. }
  371. }
  372. /** Convert string to enum nua_substate. @NEW_1_12_5. */
  373. enum nua_substate nua_substate_make(char const *sip_substate)
  374. {
  375. if (sip_substate == NULL)
  376. return nua_substate_active;
  377. else if (su_casematch(sip_substate, "terminated"))
  378. return nua_substate_terminated;
  379. else if (su_casematch(sip_substate, "pending"))
  380. return nua_substate_pending;
  381. else /* if (su_casematch(sip_substate, "active")) */
  382. return nua_substate_active;
  383. }