SipStack.cxx 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. /*
  2. * Copyright (C) 2010-2011 Mamadou Diop.
  3. *
  4. * Contact: Mamadou Diop <diopmamadou(at)doubango.org>
  5. *
  6. * This file is part of Open Source Doubango Framework.
  7. *
  8. * DOUBANGO is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * DOUBANGO is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with DOUBANGO.
  20. *
  21. */
  22. #include "SipStack.h"
  23. #include "SipSession.h"
  24. #include "SipEvent.h"
  25. #include "DDebug.h"
  26. #include "Common.h"
  27. bool SipStack::g_bInitialized = false;
  28. /* === ANSI-C functions (local use) === */
  29. static int stack_callback(const tsip_event_t *sipevent);
  30. static int session_handle_event(const tsip_event_t *sipevent);
  31. SipStack::SipStack(SipCallback* pCallback, const char* realm_uri, const char* impi_uri, const char* impu_uri)
  32. :SafeObject()
  33. {
  34. m_pDebugCallback = tsk_null;
  35. m_pCallback = pCallback;
  36. /* Initialize network and media layers */
  37. if(!SipStack::initialize()) {
  38. return;// isValid() will be false
  39. }
  40. /* Creates stack handle */
  41. m_pHandle = tsip_stack_create(stack_callback, realm_uri, impi_uri, impu_uri,
  42. TSIP_STACK_SET_USERDATA(this), /* used as context (useful for server-initiated requests) */
  43. TSIP_STACK_SET_NULL());
  44. }
  45. SipStack::~SipStack()
  46. {
  47. this->stop();
  48. /* Destroy stack handle */
  49. TSK_OBJECT_SAFE_FREE(m_pHandle);
  50. }
  51. bool SipStack::start()
  52. {
  53. bool ret = (tsip_stack_start(m_pHandle) == 0);
  54. return ret;
  55. }
  56. bool SipStack::setDebugCallback(DDebugCallback* pCallback)
  57. {
  58. if(pCallback) {
  59. m_pDebugCallback = pCallback;
  60. tsk_debug_set_arg_data(this);
  61. tsk_debug_set_info_cb(DDebugCallback::debug_info_cb);
  62. tsk_debug_set_warn_cb(DDebugCallback::debug_warn_cb);
  63. tsk_debug_set_error_cb(DDebugCallback::debug_error_cb);
  64. tsk_debug_set_fatal_cb(DDebugCallback::debug_fatal_cb);
  65. }
  66. else {
  67. m_pDebugCallback = tsk_null;
  68. tsk_debug_set_arg_data(tsk_null);
  69. tsk_debug_set_info_cb(tsk_null);
  70. tsk_debug_set_warn_cb(tsk_null);
  71. tsk_debug_set_error_cb(tsk_null);
  72. tsk_debug_set_fatal_cb(tsk_null);
  73. }
  74. return true;
  75. }
  76. bool SipStack::setDisplayName(const char* display_name)
  77. {
  78. int ret = tsip_stack_set(m_pHandle,
  79. TSIP_STACK_SET_DISPLAY_NAME(display_name),
  80. TSIP_STACK_SET_NULL());
  81. return (ret == 0);
  82. }
  83. bool SipStack::setRealm(const char* realm_uri)
  84. {
  85. int ret = tsip_stack_set(m_pHandle,
  86. TSIP_STACK_SET_REALM(realm_uri),
  87. TSIP_STACK_SET_NULL());
  88. return (ret == 0);
  89. }
  90. bool SipStack::setIMPI(const char* impi)
  91. {
  92. return (tsip_stack_set(m_pHandle,
  93. TSIP_STACK_SET_IMPI(impi),
  94. TSIP_STACK_SET_NULL()) == 0);
  95. }
  96. bool SipStack::setIMPU(const char* impu_uri)
  97. {
  98. return (tsip_stack_set(m_pHandle,
  99. TSIP_STACK_SET_IMPU(impu_uri),
  100. TSIP_STACK_SET_NULL()) == 0);
  101. }
  102. bool SipStack::setPassword(const char* password)
  103. {
  104. return (tsip_stack_set(m_pHandle,
  105. TSIP_STACK_SET_PASSWORD(password),
  106. TSIP_STACK_SET_NULL()) == 0);
  107. }
  108. bool SipStack::setAMF(const char* amf)
  109. {
  110. uint16_t _amf = (uint16_t)tsk_atox(amf);
  111. return (tsip_stack_set(m_pHandle,
  112. TSIP_STACK_SET_IMS_AKA_AMF(_amf),
  113. TSIP_STACK_SET_NULL()) == 0);
  114. }
  115. bool SipStack::setOperatorId(const char* opid)
  116. {
  117. return (tsip_stack_set(m_pHandle,
  118. TSIP_STACK_SET_IMS_AKA_OPERATOR_ID(opid),
  119. TSIP_STACK_SET_NULL()) == 0);
  120. }
  121. bool SipStack::setProxyCSCF(const char* fqdn, unsigned short port, const char* transport, const char* ipversion)
  122. {
  123. unsigned _port = port;//promote
  124. return (tsip_stack_set(m_pHandle,
  125. TSIP_STACK_SET_PROXY_CSCF(fqdn, _port, transport, ipversion),
  126. TSIP_STACK_SET_NULL()) == 0);
  127. }
  128. bool SipStack::setLocalIP(const char* ip, const char* transport/*=tsk_null*/)
  129. {
  130. return (tsip_stack_set(m_pHandle,
  131. TSIP_STACK_SET_LOCAL_IP_2(transport, ip),
  132. TSIP_STACK_SET_NULL()) == 0);
  133. }
  134. bool SipStack::setLocalPort(unsigned short port, const char* transport/*=tsk_null*/)
  135. {
  136. unsigned _port = port;//promote
  137. return (tsip_stack_set(m_pHandle,
  138. TSIP_STACK_SET_LOCAL_PORT_2(transport, _port),
  139. TSIP_STACK_SET_NULL()) == 0);
  140. }
  141. bool SipStack::setEarlyIMS(bool enabled)
  142. {
  143. return (tsip_stack_set(m_pHandle,
  144. TSIP_STACK_SET_EARLY_IMS(enabled? tsk_true : tsk_false),
  145. TSIP_STACK_SET_NULL()) == 0);
  146. }
  147. bool SipStack::addHeader(const char* name, const char* value)
  148. {
  149. return (tsip_stack_set(m_pHandle,
  150. TSIP_STACK_SET_HEADER(name, value),
  151. TSIP_STACK_SET_NULL()) == 0);
  152. }
  153. bool SipStack::removeHeader(const char* name)
  154. {
  155. return (tsip_stack_set(m_pHandle,
  156. TSIP_STACK_UNSET_HEADER(name),
  157. TSIP_STACK_SET_NULL()) == 0);
  158. }
  159. bool SipStack::addDnsServer(const char* ip)
  160. {
  161. return (tsip_stack_set(m_pHandle,
  162. TSIP_STACK_SET_DNS_SERVER(ip),
  163. TSIP_STACK_SET_NULL()) == 0);
  164. }
  165. bool SipStack::setDnsDiscovery(bool enabled)
  166. {
  167. tsk_bool_t _enabled = enabled;// 32bit/64bit workaround
  168. return (tsip_stack_set(m_pHandle,
  169. TSIP_STACK_SET_DISCOVERY_NAPTR(_enabled),
  170. TSIP_STACK_SET_NULL()) == 0);
  171. }
  172. bool SipStack::setAoR(const char* ip, int port)
  173. {
  174. return (tsip_stack_set(m_pHandle,
  175. TSIP_STACK_SET_AOR(ip, port),
  176. TSIP_STACK_SET_NULL()) == 0);
  177. }
  178. bool SipStack::setMode(enum tsip_stack_mode_e mode)
  179. {
  180. return (tsip_stack_set(m_pHandle,
  181. TSIP_STACK_SET_MODE(mode),
  182. TSIP_STACK_SET_NULL()) == 0);
  183. }
  184. bool SipStack::setSigCompParams(unsigned dms, unsigned sms, unsigned cpb, bool enablePresDict)
  185. {
  186. tsk_bool_t _enablePresDict= enablePresDict;// 32bit/64bit workaround
  187. return (tsip_stack_set(m_pHandle,
  188. TSIP_STACK_SET_SIGCOMP(dms, sms, cpb, _enablePresDict),
  189. TSIP_STACK_SET_NULL()) == 0);
  190. }
  191. bool SipStack::addSigCompCompartment(const char* compId)
  192. {
  193. return (tsip_stack_set(m_pHandle,
  194. TSIP_STACK_SET_SIGCOMP_NEW_COMPARTMENT(compId),
  195. TSIP_STACK_SET_NULL()) == 0);
  196. }
  197. bool SipStack::removeSigCompCompartment(const char* compId)
  198. {
  199. return (tsip_stack_set(m_pHandle,
  200. TSIP_STACK_UNSET_SIGCOMP_COMPARTMENT(compId),
  201. TSIP_STACK_SET_NULL()) == 0);
  202. }
  203. // @deprecated
  204. bool SipStack::setSTUNEnabledForICE(bool enabled)
  205. {
  206. #if 0
  207. tsk_bool_t _enabled = enabled ? tsk_true : tsk_false;
  208. return (tsip_stack_set(m_pHandle,
  209. TSIP_STACK_SET_ICE_STUN_ENABLED(_enabled),
  210. TSIP_STACK_SET_NULL()) == 0);
  211. #else
  212. // set global value
  213. return (tmedia_defaults_set_icestun_enabled(enabled ? tsk_true : tsk_false) == 0);
  214. // to set the value per session, use "CallSession::setICEStun()"
  215. #endif
  216. }
  217. // @deprecated
  218. bool SipStack::setSTUNServer(const char* hostname, unsigned short port)
  219. {
  220. #if 0
  221. unsigned _port = port;//promote
  222. return (tsip_stack_set(m_pHandle,
  223. TSIP_STACK_SET_STUN_SERVER(hostname, _port),
  224. TSIP_STACK_SET_NULL()) == 0);
  225. #else
  226. // set global value
  227. return (tmedia_defaults_set_stun_server(hostname, port) == 0);
  228. // to set the value per session, use "CallSession::setSTUNServer()"
  229. #endif
  230. }
  231. // @deprecated
  232. bool SipStack::setSTUNCred(const char* login, const char* password)
  233. {
  234. #if 0
  235. return (tsip_stack_set(m_pHandle,
  236. TSIP_STACK_SET_STUN_CRED(login, password),
  237. TSIP_STACK_SET_NULL()) == 0);
  238. #else
  239. // set global value
  240. return (tmedia_defaults_set_stun_cred(login, password) == 0);
  241. // to set the value per session, use "CallSession::setSTUNCred()"
  242. #endif
  243. }
  244. bool SipStack::setSTUNEnabled(bool enabled)
  245. {
  246. tsk_bool_t _enabled = enabled ? tsk_true : tsk_false;
  247. return (tsip_stack_set(m_pHandle,
  248. TSIP_STACK_SET_STUN_ENABLED(_enabled),
  249. TSIP_STACK_SET_NULL()) == 0);
  250. }
  251. bool SipStack::setTLSSecAgree(bool enabled)
  252. {
  253. tsk_bool_t _enable = enabled ? tsk_true : tsk_false;
  254. return (tsip_stack_set(m_pHandle,
  255. TSIP_STACK_SET_SECAGREE_TLS(_enable),
  256. TSIP_STACK_SET_NULL()) == 0);
  257. }
  258. /*@deprecated: typo */
  259. bool SipStack::setSSLCretificates(const char* privKey, const char* pubKey, const char* caKey, bool verify/* = false*/)
  260. {
  261. return setSSLCertificates(privKey, pubKey, caKey, verify);
  262. }
  263. bool SipStack::setSSLCertificates(const char* privKey, const char* pubKey, const char* caKey, bool verify/* = false*/)
  264. {
  265. return (tsip_stack_set(m_pHandle,
  266. TSIP_STACK_SET_TLS_CERTS_2(caKey, pubKey, privKey, (verify ? tsk_true : tsk_false)),
  267. TSIP_STACK_SET_NULL()) == 0);
  268. }
  269. bool SipStack::setIPSecSecAgree(bool enabled)
  270. {
  271. tsk_bool_t _enable = enabled;
  272. return (tsip_stack_set(m_pHandle,
  273. TSIP_STACK_SET_SECAGREE_IPSEC(_enable),
  274. TSIP_STACK_SET_NULL()) == 0);
  275. }
  276. bool SipStack::setIPSecParameters(const char* algo, const char* ealgo, const char* mode, const char* proto)
  277. {
  278. return (tsip_stack_set(m_pHandle,
  279. TSIP_STACK_SET_IPSEC_PARAMS(algo, ealgo, mode, proto),
  280. TSIP_STACK_SET_NULL()) == 0);
  281. }
  282. char* SipStack::dnsENUM(const char* service, const char* e164num, const char* domain)
  283. {
  284. tnet_dns_ctx_t* dnsctx = tsip_stack_get_dnsctx(m_pHandle);
  285. char* uri = tsk_null;
  286. if(dnsctx) {
  287. if(!(uri = tnet_dns_enum_2(dnsctx, service, e164num, domain))) {
  288. TSK_DEBUG_ERROR("ENUM(%s) failed", e164num);
  289. }
  290. tsk_object_unref(dnsctx);
  291. return uri;
  292. }
  293. else {
  294. TSK_DEBUG_ERROR("No DNS Context could be found");
  295. return tsk_null;
  296. }
  297. }
  298. char* SipStack::dnsNaptrSrv(const char* domain, const char* service, unsigned short *OUTPUT)
  299. {
  300. tnet_dns_ctx_t* dnsctx = tsip_stack_get_dnsctx(m_pHandle);
  301. char* ip = tsk_null;
  302. tnet_port_t port;
  303. *OUTPUT = 0;
  304. if(dnsctx) {
  305. if(!tnet_dns_query_naptr_srv(dnsctx, domain, service, &ip, &port)) {
  306. *OUTPUT = port;
  307. }
  308. tsk_object_unref(dnsctx);
  309. return ip;
  310. }
  311. else {
  312. TSK_DEBUG_ERROR("No DNS Context could be found");
  313. return tsk_null;
  314. }
  315. }
  316. char* SipStack::dnsSrv(const char* service, unsigned short* OUTPUT)
  317. {
  318. tnet_dns_ctx_t* dnsctx = tsip_stack_get_dnsctx(m_pHandle);
  319. char* ip = tsk_null;
  320. tnet_port_t port = 0;
  321. *OUTPUT = 0;
  322. if(dnsctx) {
  323. if(!tnet_dns_query_srv(dnsctx, service, &ip, &port)) {
  324. *OUTPUT = port;
  325. }
  326. tsk_object_unref(dnsctx);
  327. return ip;
  328. }
  329. else {
  330. TSK_DEBUG_ERROR("No DNS Context could be found");
  331. return tsk_null;
  332. }
  333. }
  334. bool SipStack::setMaxFDs(unsigned max_fds)
  335. {
  336. return (tsip_stack_set(m_pHandle,
  337. TSIP_STACK_SET_MAX_FDS(max_fds),
  338. TSIP_STACK_SET_NULL()) == 0);
  339. }
  340. char* SipStack::getLocalIPnPort(const char* protocol, unsigned short* OUTPUT)
  341. {
  342. tnet_ip_t ip;
  343. tnet_port_t port;
  344. int ret;
  345. if(!OUTPUT || !protocol) {
  346. TSK_DEBUG_ERROR("invalid parameter");
  347. return tsk_null;
  348. }
  349. if((ret = tsip_stack_get_local_ip_n_port(m_pHandle, protocol, &port, &ip))) {
  350. TSK_DEBUG_ERROR("Failed to get local ip and port with error code=%d", ret);
  351. return tsk_null;
  352. }
  353. *OUTPUT = port;
  354. return tsk_strdup(ip); // See Swig %newobject
  355. }
  356. char* SipStack::getPreferredIdentity()
  357. {
  358. tsip_uri_t* ppid = tsip_stack_get_preferred_id(m_pHandle);
  359. char* str_ppid = tsk_null;
  360. if(ppid) {
  361. str_ppid = tsip_uri_tostring(ppid, tsk_false, tsk_false);
  362. TSK_OBJECT_SAFE_FREE(ppid);
  363. }
  364. return str_ppid;
  365. }
  366. bool SipStack::isValid()
  367. {
  368. return (m_pHandle != tsk_null);
  369. }
  370. bool SipStack::stop()
  371. {
  372. int ret = tsip_stack_stop(m_pHandle);
  373. return (ret == 0);
  374. }
  375. bool SipStack::initialize()
  376. {
  377. if (!g_bInitialized) {
  378. int ret;
  379. if((ret = tnet_startup())) {
  380. TSK_DEBUG_ERROR("tnet_startup failed with error code=%d", ret);
  381. return false;
  382. }
  383. if((ret = thttp_startup())) {
  384. TSK_DEBUG_ERROR("thttp_startup failed with error code=%d", ret);
  385. return false;
  386. }
  387. if((ret = tdav_init())) {
  388. TSK_DEBUG_ERROR("tdav_init failed with error code=%d", ret);
  389. return false;
  390. }
  391. g_bInitialized = true;
  392. }
  393. return true;
  394. }
  395. bool SipStack::deInitialize()
  396. {
  397. if (SipStack::g_bInitialized) {
  398. tdav_deinit();
  399. thttp_cleanup();
  400. tnet_cleanup();
  401. SipStack::g_bInitialized = false;
  402. }
  403. return false;
  404. }
  405. void SipStack::setCodecs(tdav_codec_id_t codecs)
  406. {
  407. tdav_set_codecs(codecs);
  408. }
  409. void SipStack::setCodecs_2(int64_t codecs) // For stupid languages
  410. {
  411. SipStack::setCodecs((tdav_codec_id_t)codecs);
  412. }
  413. bool SipStack::setCodecPriority(tdav_codec_id_t codec_id, int priority)
  414. {
  415. return tdav_codec_set_priority(codec_id, priority) == 0;
  416. }
  417. bool SipStack::setCodecPriority_2(int codec_id, int priority)// For stupid languages
  418. {
  419. return SipStack::setCodecPriority((tdav_codec_id_t)codec_id, priority);
  420. }
  421. bool SipStack::isCodecSupported(tdav_codec_id_t codec_id)
  422. {
  423. return tdav_codec_is_supported(codec_id) ? true : false;
  424. }
  425. bool SipStack::isIPSecSupported()
  426. {
  427. return tdav_ipsec_is_supported() ? true : false;
  428. }
  429. static int stack_callback(const tsip_event_t *sipevent)
  430. {
  431. int ret = 0;
  432. const SipStack* sipStack = tsk_null;
  433. SipEvent* e = tsk_null;
  434. if(!sipevent) { /* should never happen ...but who know? */
  435. TSK_DEBUG_WARN("Null SIP event.");
  436. return -1;
  437. }
  438. else {
  439. if(sipevent->type == tsip_event_stack && sipevent->userdata) {
  440. /* sessionless event */
  441. sipStack = dyn_cast<const SipStack*>((const SipStack*)sipevent->userdata);
  442. }
  443. else {
  444. const void* userdata;
  445. /* gets the stack from the session */
  446. const tsip_stack_handle_t* stack_handle = tsip_ssession_get_stack(sipevent->ss);
  447. if(stack_handle && (userdata = tsip_stack_get_userdata(stack_handle))) {
  448. sipStack = dyn_cast<const SipStack*>((const SipStack*)userdata);
  449. }
  450. }
  451. }
  452. if(!sipStack) {
  453. TSK_DEBUG_WARN("Invalid SIP event (Stack is Null).");
  454. return -2;
  455. }
  456. sipStack->Lock();
  457. switch(sipevent->type) {
  458. case tsip_event_register: {
  459. /* REGISTER */
  460. if(sipStack->getCallback()) {
  461. e = new RegistrationEvent(sipevent);
  462. sipStack->getCallback()->OnRegistrationEvent((const RegistrationEvent*)e);
  463. }
  464. break;
  465. }
  466. case tsip_event_invite: {
  467. /* INVITE */
  468. if(sipStack->getCallback()) {
  469. e = new InviteEvent(sipevent);
  470. sipStack->getCallback()->OnInviteEvent((const InviteEvent*)e);
  471. }
  472. break;
  473. }
  474. case tsip_event_message: {
  475. /* MESSAGE */
  476. if(sipStack->getCallback()) {
  477. e = new MessagingEvent(sipevent);
  478. sipStack->getCallback()->OnMessagingEvent((const MessagingEvent*)e);
  479. }
  480. break;
  481. }
  482. case tsip_event_info: {
  483. /* INFO */
  484. if(sipStack->getCallback()) {
  485. e = new InfoEvent(sipevent);
  486. sipStack->getCallback()->OnInfoEvent((const InfoEvent*)e);
  487. }
  488. break;
  489. }
  490. case tsip_event_options: {
  491. /* OPTIONS */
  492. if(sipStack->getCallback()) {
  493. e = new OptionsEvent(sipevent);
  494. sipStack->getCallback()->OnOptionsEvent((const OptionsEvent*)e);
  495. }
  496. break;
  497. }
  498. case tsip_event_publish: {
  499. /* PUBLISH */
  500. if(sipStack->getCallback()) {
  501. e = new PublicationEvent(sipevent);
  502. sipStack->getCallback()->OnPublicationEvent((const PublicationEvent*)e);
  503. }
  504. break;
  505. }
  506. case tsip_event_subscribe: {
  507. /* SUBSCRIBE */
  508. if(sipStack->getCallback()) {
  509. e = new SubscriptionEvent(sipevent);
  510. sipStack->getCallback()->OnSubscriptionEvent((const SubscriptionEvent*)e);
  511. }
  512. break;
  513. }
  514. case tsip_event_dialog: {
  515. /* Common to all dialogs */
  516. if(sipStack->getCallback()) {
  517. e = new DialogEvent(sipevent);
  518. sipStack->getCallback()->OnDialogEvent((const DialogEvent*)e);
  519. }
  520. break;
  521. }
  522. case tsip_event_stack: {
  523. /* Stack event */
  524. if(sipStack->getCallback()) {
  525. e = new StackEvent(sipevent);
  526. sipStack->getCallback()->OnStackEvent((const StackEvent*)e);
  527. }
  528. break;
  529. }
  530. default: {
  531. /* Unsupported */
  532. TSK_DEBUG_WARN("%d not supported as SIP event.", sipevent->type);
  533. ret = -3;
  534. break;
  535. }
  536. }
  537. sipStack->UnLock();
  538. if(e) {
  539. delete e;
  540. }
  541. return ret;
  542. }