dialplan_functions.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2013, Digium, Inc.
  5. *
  6. * See http://www.asterisk.org for more information about
  7. * the Asterisk project. Please do not directly contact
  8. * any of the maintainers of this project for assistance;
  9. * the project provides a web site, mailing lists and IRC
  10. * channels for your use.
  11. *
  12. * This program is free software, distributed under the terms of
  13. * the GNU General Public License Version 2. See the LICENSE file
  14. * at the top of the source tree.
  15. */
  16. /*!
  17. * \file
  18. *
  19. * \author \verbatim Joshua Colp <jcolp@digium.com> \endverbatim
  20. * \author \verbatim Matt Jordan <mjordan@digium.com> \endverbatim
  21. *
  22. * \ingroup functions
  23. *
  24. * \brief PJSIP channel dialplan functions
  25. */
  26. /*** MODULEINFO
  27. <support_level>core</support_level>
  28. ***/
  29. /*** DOCUMENTATION
  30. <function name="PJSIP_DIAL_CONTACTS" language="en_US">
  31. <synopsis>
  32. Return a dial string for dialing all contacts on an AOR.
  33. </synopsis>
  34. <syntax>
  35. <parameter name="endpoint" required="true">
  36. <para>Name of the endpoint</para>
  37. </parameter>
  38. <parameter name="aor" required="false">
  39. <para>Name of an AOR to use, if not specified the configured AORs on the endpoint are used</para>
  40. </parameter>
  41. <parameter name="request_user" required="false">
  42. <para>Optional request user to use in the request URI</para>
  43. </parameter>
  44. </syntax>
  45. <description>
  46. <para>Returns a properly formatted dial string for dialing all contacts on an AOR.</para>
  47. </description>
  48. </function>
  49. <function name="PJSIP_MEDIA_OFFER" language="en_US">
  50. <synopsis>
  51. Media and codec offerings to be set on an outbound SIP channel prior to dialing.
  52. </synopsis>
  53. <syntax>
  54. <parameter name="media" required="true">
  55. <para>types of media offered</para>
  56. </parameter>
  57. </syntax>
  58. <description>
  59. <para>Returns the codecs offered based upon the media choice</para>
  60. </description>
  61. </function>
  62. <info name="PJSIPCHANNEL" language="en_US" tech="PJSIP">
  63. <enumlist>
  64. <enum name="rtp">
  65. <para>R/O Retrieve media related information.</para>
  66. <parameter name="type" required="true">
  67. <para>When <replaceable>rtp</replaceable> is specified, the
  68. <literal>type</literal> parameter must be provided. It specifies
  69. which RTP parameter to read.</para>
  70. <enumlist>
  71. <enum name="src">
  72. <para>Retrieve the local address for RTP.</para>
  73. </enum>
  74. <enum name="dest">
  75. <para>Retrieve the remote address for RTP.</para>
  76. </enum>
  77. <enum name="direct">
  78. <para>If direct media is enabled, this address is the remote address
  79. used for RTP.</para>
  80. </enum>
  81. <enum name="secure">
  82. <para>Whether or not the media stream is encrypted.</para>
  83. <enumlist>
  84. <enum name="0">
  85. <para>The media stream is not encrypted.</para>
  86. </enum>
  87. <enum name="1">
  88. <para>The media stream is encrypted.</para>
  89. </enum>
  90. </enumlist>
  91. </enum>
  92. <enum name="hold">
  93. <para>Whether or not the media stream is currently restricted
  94. due to a call hold.</para>
  95. <enumlist>
  96. <enum name="0">
  97. <para>The media stream is not held.</para>
  98. </enum>
  99. <enum name="1">
  100. <para>The media stream is held.</para>
  101. </enum>
  102. </enumlist>
  103. </enum>
  104. </enumlist>
  105. </parameter>
  106. <parameter name="media_type" required="false">
  107. <para>When <replaceable>rtp</replaceable> is specified, the
  108. <literal>media_type</literal> parameter may be provided. It specifies
  109. which media stream the chosen RTP parameter should be retrieved
  110. from.</para>
  111. <enumlist>
  112. <enum name="audio">
  113. <para>Retrieve information from the audio media stream.</para>
  114. <note><para>If not specified, <literal>audio</literal> is used
  115. by default.</para></note>
  116. </enum>
  117. <enum name="video">
  118. <para>Retrieve information from the video media stream.</para>
  119. </enum>
  120. </enumlist>
  121. </parameter>
  122. </enum>
  123. <enum name="rtcp">
  124. <para>R/O Retrieve RTCP statistics.</para>
  125. <parameter name="statistic" required="true">
  126. <para>When <replaceable>rtcp</replaceable> is specified, the
  127. <literal>statistic</literal> parameter must be provided. It specifies
  128. which RTCP statistic parameter to read.</para>
  129. <enumlist>
  130. <enum name="all">
  131. <para>Retrieve a summary of all RTCP statistics.</para>
  132. <para>The following data items are returned in a semi-colon
  133. delineated list:</para>
  134. <enumlist>
  135. <enum name="ssrc">
  136. <para>Our Synchronization Source identifier</para>
  137. </enum>
  138. <enum name="themssrc">
  139. <para>Their Synchronization Source identifier</para>
  140. </enum>
  141. <enum name="lp">
  142. <para>Our lost packet count</para>
  143. </enum>
  144. <enum name="rxjitter">
  145. <para>Received packet jitter</para>
  146. </enum>
  147. <enum name="rxcount">
  148. <para>Received packet count</para>
  149. </enum>
  150. <enum name="txjitter">
  151. <para>Transmitted packet jitter</para>
  152. </enum>
  153. <enum name="txcount">
  154. <para>Transmitted packet count</para>
  155. </enum>
  156. <enum name="rlp">
  157. <para>Remote lost packet count</para>
  158. </enum>
  159. <enum name="rtt">
  160. <para>Round trip time</para>
  161. </enum>
  162. </enumlist>
  163. </enum>
  164. <enum name="all_jitter">
  165. <para>Retrieve a summary of all RTCP Jitter statistics.</para>
  166. <para>The following data items are returned in a semi-colon
  167. delineated list:</para>
  168. <enumlist>
  169. <enum name="minrxjitter">
  170. <para>Our minimum jitter</para>
  171. </enum>
  172. <enum name="maxrxjitter">
  173. <para>Our max jitter</para>
  174. </enum>
  175. <enum name="avgrxjitter">
  176. <para>Our average jitter</para>
  177. </enum>
  178. <enum name="stdevrxjitter">
  179. <para>Our jitter standard deviation</para>
  180. </enum>
  181. <enum name="reported_minjitter">
  182. <para>Their minimum jitter</para>
  183. </enum>
  184. <enum name="reported_maxjitter">
  185. <para>Their max jitter</para>
  186. </enum>
  187. <enum name="reported_avgjitter">
  188. <para>Their average jitter</para>
  189. </enum>
  190. <enum name="reported_stdevjitter">
  191. <para>Their jitter standard deviation</para>
  192. </enum>
  193. </enumlist>
  194. </enum>
  195. <enum name="all_loss">
  196. <para>Retrieve a summary of all RTCP packet loss statistics.</para>
  197. <para>The following data items are returned in a semi-colon
  198. delineated list:</para>
  199. <enumlist>
  200. <enum name="minrxlost">
  201. <para>Our minimum lost packets</para>
  202. </enum>
  203. <enum name="maxrxlost">
  204. <para>Our max lost packets</para>
  205. </enum>
  206. <enum name="avgrxlost">
  207. <para>Our average lost packets</para>
  208. </enum>
  209. <enum name="stdevrxlost">
  210. <para>Our lost packets standard deviation</para>
  211. </enum>
  212. <enum name="reported_minlost">
  213. <para>Their minimum lost packets</para>
  214. </enum>
  215. <enum name="reported_maxlost">
  216. <para>Their max lost packets</para>
  217. </enum>
  218. <enum name="reported_avglost">
  219. <para>Their average lost packets</para>
  220. </enum>
  221. <enum name="reported_stdevlost">
  222. <para>Their lost packets standard deviation</para>
  223. </enum>
  224. </enumlist>
  225. </enum>
  226. <enum name="all_rtt">
  227. <para>Retrieve a summary of all RTCP round trip time information.</para>
  228. <para>The following data items are returned in a semi-colon
  229. delineated list:</para>
  230. <enumlist>
  231. <enum name="minrtt">
  232. <para>Minimum round trip time</para>
  233. </enum>
  234. <enum name="maxrtt">
  235. <para>Maximum round trip time</para>
  236. </enum>
  237. <enum name="avgrtt">
  238. <para>Average round trip time</para>
  239. </enum>
  240. <enum name="stdevrtt">
  241. <para>Standard deviation round trip time</para>
  242. </enum>
  243. </enumlist>
  244. </enum>
  245. <enum name="txcount"><para>Transmitted packet count</para></enum>
  246. <enum name="rxcount"><para>Received packet count</para></enum>
  247. <enum name="txjitter"><para>Transmitted packet jitter</para></enum>
  248. <enum name="rxjitter"><para>Received packet jitter</para></enum>
  249. <enum name="remote_maxjitter"><para>Their max jitter</para></enum>
  250. <enum name="remote_minjitter"><para>Their minimum jitter</para></enum>
  251. <enum name="remote_normdevjitter"><para>Their average jitter</para></enum>
  252. <enum name="remote_stdevjitter"><para>Their jitter standard deviation</para></enum>
  253. <enum name="local_maxjitter"><para>Our max jitter</para></enum>
  254. <enum name="local_minjitter"><para>Our minimum jitter</para></enum>
  255. <enum name="local_normdevjitter"><para>Our average jitter</para></enum>
  256. <enum name="local_stdevjitter"><para>Our jitter standard deviation</para></enum>
  257. <enum name="txploss"><para>Transmitted packet loss</para></enum>
  258. <enum name="rxploss"><para>Received packet loss</para></enum>
  259. <enum name="remote_maxrxploss"><para>Their max lost packets</para></enum>
  260. <enum name="remote_minrxploss"><para>Their minimum lost packets</para></enum>
  261. <enum name="remote_normdevrxploss"><para>Their average lost packets</para></enum>
  262. <enum name="remote_stdevrxploss"><para>Their lost packets standard deviation</para></enum>
  263. <enum name="local_maxrxploss"><para>Our max lost packets</para></enum>
  264. <enum name="local_minrxploss"><para>Our minimum lost packets</para></enum>
  265. <enum name="local_normdevrxploss"><para>Our average lost packets</para></enum>
  266. <enum name="local_stdevrxploss"><para>Our lost packets standard deviation</para></enum>
  267. <enum name="rtt"><para>Round trip time</para></enum>
  268. <enum name="maxrtt"><para>Maximum round trip time</para></enum>
  269. <enum name="minrtt"><para>Minimum round trip time</para></enum>
  270. <enum name="normdevrtt"><para>Average round trip time</para></enum>
  271. <enum name="stdevrtt"><para>Standard deviation round trip time</para></enum>
  272. <enum name="local_ssrc"><para>Our Synchronization Source identifier</para></enum>
  273. <enum name="remote_ssrc"><para>Their Synchronization Source identifier</para></enum>
  274. </enumlist>
  275. </parameter>
  276. <parameter name="media_type" required="false">
  277. <para>When <replaceable>rtcp</replaceable> is specified, the
  278. <literal>media_type</literal> parameter may be provided. It specifies
  279. which media stream the chosen RTCP parameter should be retrieved
  280. from.</para>
  281. <enumlist>
  282. <enum name="audio">
  283. <para>Retrieve information from the audio media stream.</para>
  284. <note><para>If not specified, <literal>audio</literal> is used
  285. by default.</para></note>
  286. </enum>
  287. <enum name="video">
  288. <para>Retrieve information from the video media stream.</para>
  289. </enum>
  290. </enumlist>
  291. </parameter>
  292. </enum>
  293. <enum name="endpoint">
  294. <para>R/O The name of the endpoint associated with this channel.
  295. Use the <replaceable>PJSIP_ENDPOINT</replaceable> function to obtain
  296. further endpoint related information.</para>
  297. </enum>
  298. <enum name="contact">
  299. <para>R/O The name of the contact associated with this channel.
  300. Use the <replaceable>PJSIP_CONTACT</replaceable> function to obtain
  301. further contact related information. Note this may not be present and if so
  302. is only available on outgoing legs.</para>
  303. </enum>
  304. <enum name="aor">
  305. <para>R/O The name of the AOR associated with this channel.
  306. Use the <replaceable>PJSIP_AOR</replaceable> function to obtain
  307. further AOR related information. Note this may not be present and if so
  308. is only available on outgoing legs.</para>
  309. </enum>
  310. <enum name="pjsip">
  311. <para>R/O Obtain information about the current PJSIP channel and its
  312. session.</para>
  313. <parameter name="type" required="true">
  314. <para>When <replaceable>pjsip</replaceable> is specified, the
  315. <literal>type</literal> parameter must be provided. It specifies
  316. which signalling parameter to read.</para>
  317. <enumlist>
  318. <enum name="secure">
  319. <para>Whether or not the signalling uses a secure transport.</para>
  320. <enumlist>
  321. <enum name="0"><para>The signalling uses a non-secure transport.</para></enum>
  322. <enum name="1"><para>The signalling uses a secure transport.</para></enum>
  323. </enumlist>
  324. </enum>
  325. <enum name="target_uri">
  326. <para>The request URI of the <literal>INVITE</literal> request associated with the creation of this channel.</para>
  327. </enum>
  328. <enum name="local_uri">
  329. <para>The local URI.</para>
  330. </enum>
  331. <enum name="remote_uri">
  332. <para>The remote URI.</para>
  333. </enum>
  334. <enum name="t38state">
  335. <para>The current state of any T.38 fax on this channel.</para>
  336. <enumlist>
  337. <enum name="DISABLED"><para>T.38 faxing is disabled on this channel.</para></enum>
  338. <enum name="LOCAL_REINVITE"><para>Asterisk has sent a <literal>re-INVITE</literal> to the remote end to initiate a T.38 fax.</para></enum>
  339. <enum name="REMOTE_REINVITE"><para>The remote end has sent a <literal>re-INVITE</literal> to Asterisk to initiate a T.38 fax.</para></enum>
  340. <enum name="ENABLED"><para>A T.38 fax session has been enabled.</para></enum>
  341. <enum name="REJECTED"><para>A T.38 fax session was attempted but was rejected.</para></enum>
  342. </enumlist>
  343. </enum>
  344. <enum name="local_addr">
  345. <para>On inbound calls, the full IP address and port number that
  346. the <literal>INVITE</literal> request was received on. On outbound
  347. calls, the full IP address and port number that the <literal>INVITE</literal>
  348. request was transmitted from.</para>
  349. </enum>
  350. <enum name="remote_addr">
  351. <para>On inbound calls, the full IP address and port number that
  352. the <literal>INVITE</literal> request was received from. On outbound
  353. calls, the full IP address and port number that the <literal>INVITE</literal>
  354. request was transmitted to.</para>
  355. </enum>
  356. </enumlist>
  357. </parameter>
  358. </enum>
  359. </enumlist>
  360. </info>
  361. ***/
  362. #include "asterisk.h"
  363. #include <pjsip.h>
  364. #include <pjlib.h>
  365. #include <pjsip_ua.h>
  366. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  367. #include "asterisk/astobj2.h"
  368. #include "asterisk/module.h"
  369. #include "asterisk/acl.h"
  370. #include "asterisk/app.h"
  371. #include "asterisk/channel.h"
  372. #include "asterisk/format.h"
  373. #include "asterisk/pbx.h"
  374. #include "asterisk/res_pjsip.h"
  375. #include "asterisk/res_pjsip_session.h"
  376. #include "include/chan_pjsip.h"
  377. #include "include/dialplan_functions.h"
  378. /*!
  379. * \brief String representations of the T.38 state enum
  380. */
  381. static const char *t38state_to_string[T38_MAX_ENUM] = {
  382. [T38_DISABLED] = "DISABLED",
  383. [T38_LOCAL_REINVITE] = "LOCAL_REINVITE",
  384. [T38_PEER_REINVITE] = "REMOTE_REINVITE",
  385. [T38_ENABLED] = "ENABLED",
  386. [T38_REJECTED] = "REJECTED",
  387. };
  388. /*!
  389. * \internal \brief Handle reading RTP information
  390. */
  391. static int channel_read_rtp(struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
  392. {
  393. struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
  394. struct chan_pjsip_pvt *pvt;
  395. struct ast_sip_session_media *media = NULL;
  396. struct ast_sockaddr addr;
  397. if (!channel) {
  398. ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
  399. return -1;
  400. }
  401. pvt = channel->pvt;
  402. if (!pvt) {
  403. ast_log(AST_LOG_WARNING, "Channel %s has no chan_pjsip pvt!\n", ast_channel_name(chan));
  404. return -1;
  405. }
  406. if (ast_strlen_zero(type)) {
  407. ast_log(AST_LOG_WARNING, "You must supply a type field for 'rtp' information\n");
  408. return -1;
  409. }
  410. if (ast_strlen_zero(field) || !strcmp(field, "audio")) {
  411. media = pvt->media[SIP_MEDIA_AUDIO];
  412. } else if (!strcmp(field, "video")) {
  413. media = pvt->media[SIP_MEDIA_VIDEO];
  414. } else {
  415. ast_log(AST_LOG_WARNING, "Unknown media type field '%s' for 'rtp' information\n", field);
  416. return -1;
  417. }
  418. if (!media || !media->rtp) {
  419. ast_log(AST_LOG_WARNING, "Channel %s has no %s media/RTP session\n",
  420. ast_channel_name(chan), S_OR(field, "audio"));
  421. return -1;
  422. }
  423. if (!strcmp(type, "src")) {
  424. ast_rtp_instance_get_local_address(media->rtp, &addr);
  425. ast_copy_string(buf, ast_sockaddr_stringify(&addr), buflen);
  426. } else if (!strcmp(type, "dest")) {
  427. ast_rtp_instance_get_remote_address(media->rtp, &addr);
  428. ast_copy_string(buf, ast_sockaddr_stringify(&addr), buflen);
  429. } else if (!strcmp(type, "direct")) {
  430. ast_copy_string(buf, ast_sockaddr_stringify(&media->direct_media_addr), buflen);
  431. } else if (!strcmp(type, "secure")) {
  432. snprintf(buf, buflen, "%d", media->srtp ? 1 : 0);
  433. } else if (!strcmp(type, "hold")) {
  434. snprintf(buf, buflen, "%d", media->remotely_held ? 1 : 0);
  435. } else {
  436. ast_log(AST_LOG_WARNING, "Unknown type field '%s' specified for 'rtp' information\n", type);
  437. return -1;
  438. }
  439. return 0;
  440. }
  441. /*!
  442. * \internal \brief Handle reading RTCP information
  443. */
  444. static int channel_read_rtcp(struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
  445. {
  446. struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
  447. struct chan_pjsip_pvt *pvt;
  448. struct ast_sip_session_media *media = NULL;
  449. if (!channel) {
  450. ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
  451. return -1;
  452. }
  453. pvt = channel->pvt;
  454. if (!pvt) {
  455. ast_log(AST_LOG_WARNING, "Channel %s has no chan_pjsip pvt!\n", ast_channel_name(chan));
  456. return -1;
  457. }
  458. if (ast_strlen_zero(type)) {
  459. ast_log(AST_LOG_WARNING, "You must supply a type field for 'rtcp' information\n");
  460. return -1;
  461. }
  462. if (ast_strlen_zero(field) || !strcmp(field, "audio")) {
  463. media = pvt->media[SIP_MEDIA_AUDIO];
  464. } else if (!strcmp(field, "video")) {
  465. media = pvt->media[SIP_MEDIA_VIDEO];
  466. } else {
  467. ast_log(AST_LOG_WARNING, "Unknown media type field '%s' for 'rtcp' information\n", field);
  468. return -1;
  469. }
  470. if (!media || !media->rtp) {
  471. ast_log(AST_LOG_WARNING, "Channel %s has no %s media/RTP session\n",
  472. ast_channel_name(chan), S_OR(field, "audio"));
  473. return -1;
  474. }
  475. if (!strncasecmp(type, "all", 3)) {
  476. enum ast_rtp_instance_stat_field stat_field = AST_RTP_INSTANCE_STAT_FIELD_QUALITY;
  477. if (!strcasecmp(type, "all_jitter")) {
  478. stat_field = AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER;
  479. } else if (!strcasecmp(type, "all_rtt")) {
  480. stat_field = AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT;
  481. } else if (!strcasecmp(type, "all_loss")) {
  482. stat_field = AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS;
  483. }
  484. if (!ast_rtp_instance_get_quality(media->rtp, stat_field, buf, buflen)) {
  485. ast_log(AST_LOG_WARNING, "Unable to retrieve 'rtcp' statistics for %s\n", ast_channel_name(chan));
  486. return -1;
  487. }
  488. } else {
  489. struct ast_rtp_instance_stats stats;
  490. int i;
  491. struct {
  492. const char *name;
  493. enum { INT, DBL } type;
  494. union {
  495. unsigned int *i4;
  496. double *d8;
  497. };
  498. } lookup[] = {
  499. { "txcount", INT, { .i4 = &stats.txcount, }, },
  500. { "rxcount", INT, { .i4 = &stats.rxcount, }, },
  501. { "txjitter", DBL, { .d8 = &stats.txjitter, }, },
  502. { "rxjitter", DBL, { .d8 = &stats.rxjitter, }, },
  503. { "remote_maxjitter", DBL, { .d8 = &stats.remote_maxjitter, }, },
  504. { "remote_minjitter", DBL, { .d8 = &stats.remote_minjitter, }, },
  505. { "remote_normdevjitter", DBL, { .d8 = &stats.remote_normdevjitter, }, },
  506. { "remote_stdevjitter", DBL, { .d8 = &stats.remote_stdevjitter, }, },
  507. { "local_maxjitter", DBL, { .d8 = &stats.local_maxjitter, }, },
  508. { "local_minjitter", DBL, { .d8 = &stats.local_minjitter, }, },
  509. { "local_normdevjitter", DBL, { .d8 = &stats.local_normdevjitter, }, },
  510. { "local_stdevjitter", DBL, { .d8 = &stats.local_stdevjitter, }, },
  511. { "txploss", INT, { .i4 = &stats.txploss, }, },
  512. { "rxploss", INT, { .i4 = &stats.rxploss, }, },
  513. { "remote_maxrxploss", DBL, { .d8 = &stats.remote_maxrxploss, }, },
  514. { "remote_minrxploss", DBL, { .d8 = &stats.remote_minrxploss, }, },
  515. { "remote_normdevrxploss", DBL, { .d8 = &stats.remote_normdevrxploss, }, },
  516. { "remote_stdevrxploss", DBL, { .d8 = &stats.remote_stdevrxploss, }, },
  517. { "local_maxrxploss", DBL, { .d8 = &stats.local_maxrxploss, }, },
  518. { "local_minrxploss", DBL, { .d8 = &stats.local_minrxploss, }, },
  519. { "local_normdevrxploss", DBL, { .d8 = &stats.local_normdevrxploss, }, },
  520. { "local_stdevrxploss", DBL, { .d8 = &stats.local_stdevrxploss, }, },
  521. { "rtt", DBL, { .d8 = &stats.rtt, }, },
  522. { "maxrtt", DBL, { .d8 = &stats.maxrtt, }, },
  523. { "minrtt", DBL, { .d8 = &stats.minrtt, }, },
  524. { "normdevrtt", DBL, { .d8 = &stats.normdevrtt, }, },
  525. { "stdevrtt", DBL, { .d8 = &stats.stdevrtt, }, },
  526. { "local_ssrc", INT, { .i4 = &stats.local_ssrc, }, },
  527. { "remote_ssrc", INT, { .i4 = &stats.remote_ssrc, }, },
  528. { NULL, },
  529. };
  530. if (ast_rtp_instance_get_stats(media->rtp, &stats, AST_RTP_INSTANCE_STAT_ALL)) {
  531. ast_log(AST_LOG_WARNING, "Unable to retrieve 'rtcp' statistics for %s\n", ast_channel_name(chan));
  532. return -1;
  533. }
  534. for (i = 0; !ast_strlen_zero(lookup[i].name); i++) {
  535. if (!strcasecmp(type, lookup[i].name)) {
  536. if (lookup[i].type == INT) {
  537. snprintf(buf, buflen, "%u", *lookup[i].i4);
  538. } else {
  539. snprintf(buf, buflen, "%f", *lookup[i].d8);
  540. }
  541. return 0;
  542. }
  543. }
  544. ast_log(AST_LOG_WARNING, "Unrecognized argument '%s' for 'rtcp' information\n", type);
  545. return -1;
  546. }
  547. return 0;
  548. }
  549. /*!
  550. * \internal \brief Handle reading signalling information
  551. */
  552. static int channel_read_pjsip(struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
  553. {
  554. struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
  555. char *buf_copy;
  556. pjsip_dialog *dlg;
  557. if (!channel) {
  558. ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
  559. return -1;
  560. }
  561. dlg = channel->session->inv_session->dlg;
  562. if (ast_strlen_zero(type)) {
  563. ast_log(LOG_WARNING, "You must supply a type field for 'pjsip' information\n");
  564. return -1;
  565. } else if (!strcmp(type, "secure")) {
  566. #ifdef HAVE_PJSIP_GET_DEST_INFO
  567. pjsip_host_info dest;
  568. pj_pool_t *pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "secure-check", 128, 128);
  569. pjsip_get_dest_info(dlg->target, NULL, pool, &dest);
  570. snprintf(buf, buflen, "%d", dest.flag & PJSIP_TRANSPORT_SECURE ? 1 : 0);
  571. pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
  572. #else
  573. ast_log(LOG_WARNING, "Asterisk has been built against a version of pjproject which does not have the required functionality to support the 'secure' argument. Please upgrade to version 2.3 or later.\n");
  574. return -1;
  575. #endif
  576. } else if (!strcmp(type, "target_uri")) {
  577. pjsip_uri_print(PJSIP_URI_IN_REQ_URI, dlg->target, buf, buflen);
  578. buf_copy = ast_strdupa(buf);
  579. ast_escape_quoted(buf_copy, buf, buflen);
  580. } else if (!strcmp(type, "local_uri")) {
  581. pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, dlg->local.info->uri, buf, buflen);
  582. buf_copy = ast_strdupa(buf);
  583. ast_escape_quoted(buf_copy, buf, buflen);
  584. } else if (!strcmp(type, "remote_uri")) {
  585. pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, dlg->remote.info->uri, buf, buflen);
  586. buf_copy = ast_strdupa(buf);
  587. ast_escape_quoted(buf_copy, buf, buflen);
  588. } else if (!strcmp(type, "t38state")) {
  589. ast_copy_string(buf, t38state_to_string[channel->session->t38state], buflen);
  590. } else if (!strcmp(type, "local_addr")) {
  591. RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
  592. struct transport_info_data *transport_data;
  593. datastore = ast_sip_session_get_datastore(channel->session, "transport_info");
  594. if (!datastore) {
  595. ast_log(AST_LOG_WARNING, "No transport information for channel %s\n", ast_channel_name(chan));
  596. return -1;
  597. }
  598. transport_data = datastore->data;
  599. if (pj_sockaddr_has_addr(&transport_data->local_addr)) {
  600. pj_sockaddr_print(&transport_data->local_addr, buf, buflen, 3);
  601. }
  602. } else if (!strcmp(type, "remote_addr")) {
  603. RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
  604. struct transport_info_data *transport_data;
  605. datastore = ast_sip_session_get_datastore(channel->session, "transport_info");
  606. if (!datastore) {
  607. ast_log(AST_LOG_WARNING, "No transport information for channel %s\n", ast_channel_name(chan));
  608. return -1;
  609. }
  610. transport_data = datastore->data;
  611. if (pj_sockaddr_has_addr(&transport_data->remote_addr)) {
  612. pj_sockaddr_print(&transport_data->remote_addr, buf, buflen, 3);
  613. }
  614. } else {
  615. ast_log(AST_LOG_WARNING, "Unrecognized argument '%s' for 'pjsip' information\n", type);
  616. return -1;
  617. }
  618. return 0;
  619. }
  620. /*! \brief Struct used to push function arguments to task processor */
  621. struct pjsip_func_args {
  622. struct ast_channel *chan;
  623. const char *param;
  624. const char *type;
  625. const char *field;
  626. char *buf;
  627. size_t len;
  628. int ret;
  629. };
  630. /*! \internal \brief Taskprocessor callback that handles the read on a PJSIP thread */
  631. static int read_pjsip(void *data)
  632. {
  633. struct pjsip_func_args *func_args = data;
  634. if (!strcmp(func_args->param, "rtp")) {
  635. func_args->ret = channel_read_rtp(func_args->chan, func_args->type,
  636. func_args->field, func_args->buf,
  637. func_args->len);
  638. } else if (!strcmp(func_args->param, "rtcp")) {
  639. func_args->ret = channel_read_rtcp(func_args->chan, func_args->type,
  640. func_args->field, func_args->buf,
  641. func_args->len);
  642. } else if (!strcmp(func_args->param, "endpoint")) {
  643. struct ast_sip_channel_pvt *pvt = ast_channel_tech_pvt(func_args->chan);
  644. if (!pvt) {
  645. ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(func_args->chan));
  646. return -1;
  647. }
  648. if (!pvt->session || !pvt->session->endpoint) {
  649. ast_log(AST_LOG_WARNING, "Channel %s has no endpoint!\n", ast_channel_name(func_args->chan));
  650. return -1;
  651. }
  652. snprintf(func_args->buf, func_args->len, "%s", ast_sorcery_object_get_id(pvt->session->endpoint));
  653. } else if (!strcmp(func_args->param, "contact")) {
  654. struct ast_sip_channel_pvt *pvt = ast_channel_tech_pvt(func_args->chan);
  655. if (!pvt) {
  656. ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(func_args->chan));
  657. return -1;
  658. }
  659. if (!pvt->session || !pvt->session->contact) {
  660. return 0;
  661. }
  662. snprintf(func_args->buf, func_args->len, "%s", ast_sorcery_object_get_id(pvt->session->contact));
  663. } else if (!strcmp(func_args->param, "aor")) {
  664. struct ast_sip_channel_pvt *pvt = ast_channel_tech_pvt(func_args->chan);
  665. if (!pvt) {
  666. ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(func_args->chan));
  667. return -1;
  668. }
  669. if (!pvt->session || !pvt->session->aor) {
  670. return 0;
  671. }
  672. snprintf(func_args->buf, func_args->len, "%s", ast_sorcery_object_get_id(pvt->session->aor));
  673. } else if (!strcmp(func_args->param, "pjsip")) {
  674. func_args->ret = channel_read_pjsip(func_args->chan, func_args->type,
  675. func_args->field, func_args->buf,
  676. func_args->len);
  677. } else {
  678. func_args->ret = -1;
  679. }
  680. return 0;
  681. }
  682. int pjsip_acf_channel_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
  683. {
  684. struct pjsip_func_args func_args = { 0, };
  685. struct ast_sip_channel_pvt *channel;
  686. char *parse = ast_strdupa(data);
  687. AST_DECLARE_APP_ARGS(args,
  688. AST_APP_ARG(param);
  689. AST_APP_ARG(type);
  690. AST_APP_ARG(field);
  691. );
  692. if (!chan) {
  693. ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
  694. return -1;
  695. }
  696. channel = ast_channel_tech_pvt(chan);
  697. /* Check for zero arguments */
  698. if (ast_strlen_zero(parse)) {
  699. ast_log(LOG_ERROR, "Cannot call %s without arguments\n", cmd);
  700. return -1;
  701. }
  702. AST_STANDARD_APP_ARGS(args, parse);
  703. /* Sanity check */
  704. if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
  705. ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
  706. return 0;
  707. }
  708. if (!channel) {
  709. ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
  710. return -1;
  711. }
  712. memset(buf, 0, len);
  713. func_args.chan = chan;
  714. func_args.param = args.param;
  715. func_args.type = args.type;
  716. func_args.field = args.field;
  717. func_args.buf = buf;
  718. func_args.len = len;
  719. if (ast_sip_push_task_synchronous(channel->session->serializer, read_pjsip, &func_args)) {
  720. ast_log(LOG_WARNING, "Unable to read properties of channel %s: failed to push task\n", ast_channel_name(chan));
  721. return -1;
  722. }
  723. return func_args.ret;
  724. }
  725. int pjsip_acf_dial_contacts_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
  726. {
  727. RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
  728. RAII_VAR(struct ast_str *, dial, NULL, ast_free_ptr);
  729. const char *aor_name;
  730. char *rest;
  731. AST_DECLARE_APP_ARGS(args,
  732. AST_APP_ARG(endpoint_name);
  733. AST_APP_ARG(aor_name);
  734. AST_APP_ARG(request_user);
  735. );
  736. AST_STANDARD_APP_ARGS(args, data);
  737. if (ast_strlen_zero(args.endpoint_name)) {
  738. ast_log(LOG_WARNING, "An endpoint name must be specified when using the '%s' dialplan function\n", cmd);
  739. return -1;
  740. } else if (!(endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", args.endpoint_name))) {
  741. ast_log(LOG_WARNING, "Specified endpoint '%s' was not found\n", args.endpoint_name);
  742. return -1;
  743. }
  744. aor_name = S_OR(args.aor_name, endpoint->aors);
  745. if (ast_strlen_zero(aor_name)) {
  746. ast_log(LOG_WARNING, "No AOR has been provided and no AORs are configured on endpoint '%s'\n", args.endpoint_name);
  747. return -1;
  748. } else if (!(dial = ast_str_create(len))) {
  749. ast_log(LOG_WARNING, "Could not get enough buffer space for dialing contacts\n");
  750. return -1;
  751. } else if (!(rest = ast_strdupa(aor_name))) {
  752. ast_log(LOG_WARNING, "Could not duplicate provided AORs\n");
  753. return -1;
  754. }
  755. while ((aor_name = strsep(&rest, ","))) {
  756. RAII_VAR(struct ast_sip_aor *, aor, ast_sip_location_retrieve_aor(aor_name), ao2_cleanup);
  757. RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
  758. struct ao2_iterator it_contacts;
  759. struct ast_sip_contact *contact;
  760. if (!aor) {
  761. /* If the AOR provided is not found skip it, there may be more */
  762. continue;
  763. } else if (!(contacts = ast_sip_location_retrieve_aor_contacts(aor))) {
  764. /* No contacts are available, skip it as well */
  765. continue;
  766. } else if (!ao2_container_count(contacts)) {
  767. /* We were given a container but no contacts are in it... */
  768. continue;
  769. }
  770. it_contacts = ao2_iterator_init(contacts, 0);
  771. for (; (contact = ao2_iterator_next(&it_contacts)); ao2_ref(contact, -1)) {
  772. ast_str_append(&dial, -1, "PJSIP/");
  773. if (!ast_strlen_zero(args.request_user)) {
  774. ast_str_append(&dial, -1, "%s@", args.request_user);
  775. }
  776. ast_str_append(&dial, -1, "%s/%s&", args.endpoint_name, contact->uri);
  777. }
  778. ao2_iterator_destroy(&it_contacts);
  779. }
  780. /* Trim the '&' at the end off */
  781. ast_str_truncate(dial, ast_str_strlen(dial) - 1);
  782. ast_copy_string(buf, ast_str_buffer(dial), len);
  783. return 0;
  784. }
  785. static int media_offer_read_av(struct ast_sip_session *session, char *buf,
  786. size_t len, enum ast_media_type media_type)
  787. {
  788. int i, size = 0;
  789. for (i = 0; i < ast_format_cap_count(session->req_caps); i++) {
  790. struct ast_format *fmt = ast_format_cap_get_format(session->req_caps, i);
  791. if (ast_format_get_type(fmt) != media_type) {
  792. ao2_ref(fmt, -1);
  793. continue;
  794. }
  795. /* add one since we'll include a comma */
  796. size = strlen(ast_format_get_name(fmt)) + 1;
  797. if (len < size) {
  798. ao2_ref(fmt, -1);
  799. break;
  800. }
  801. len -= size;
  802. /* no reason to use strncat here since we have already ensured buf has
  803. enough space, so strcat can be safely used */
  804. strcat(buf, ast_format_get_name(fmt));
  805. strcat(buf, ",");
  806. ao2_ref(fmt, -1);
  807. }
  808. if (size) {
  809. /* remove the extra comma */
  810. buf[strlen(buf) - 1] = '\0';
  811. }
  812. return 0;
  813. }
  814. struct media_offer_data {
  815. struct ast_sip_session *session;
  816. enum ast_media_type media_type;
  817. const char *value;
  818. };
  819. static int media_offer_write_av(void *obj)
  820. {
  821. struct media_offer_data *data = obj;
  822. ast_format_cap_remove_by_type(data->session->req_caps, data->media_type);
  823. ast_format_cap_update_by_allow_disallow(data->session->req_caps, data->value, 1);
  824. return 0;
  825. }
  826. int pjsip_acf_media_offer_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
  827. {
  828. struct ast_sip_channel_pvt *channel;
  829. if (!chan) {
  830. ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
  831. return -1;
  832. }
  833. if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
  834. ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
  835. return -1;
  836. }
  837. channel = ast_channel_tech_pvt(chan);
  838. if (!strcmp(data, "audio")) {
  839. return media_offer_read_av(channel->session, buf, len, AST_MEDIA_TYPE_AUDIO);
  840. } else if (!strcmp(data, "video")) {
  841. return media_offer_read_av(channel->session, buf, len, AST_MEDIA_TYPE_VIDEO);
  842. }
  843. return 0;
  844. }
  845. int pjsip_acf_media_offer_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
  846. {
  847. struct ast_sip_channel_pvt *channel;
  848. struct media_offer_data mdata = {
  849. .value = value
  850. };
  851. if (!chan) {
  852. ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
  853. return -1;
  854. }
  855. if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
  856. ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
  857. return -1;
  858. }
  859. channel = ast_channel_tech_pvt(chan);
  860. mdata.session = channel->session;
  861. if (!strcmp(data, "audio")) {
  862. mdata.media_type = AST_MEDIA_TYPE_AUDIO;
  863. } else if (!strcmp(data, "video")) {
  864. mdata.media_type = AST_MEDIA_TYPE_VIDEO;
  865. }
  866. return ast_sip_push_task_synchronous(channel->session->serializer, media_offer_write_av, &mdata);
  867. }