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