Asterisk - The Open Source Telephony Project  GIT-master-a24979a
pjsip/dialplan_functions.c
Go to the documentation of this file.
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>When read, returns the codecs offered based upon the media choice.</para>
63  <para>When written, sets the codecs to offer when an outbound dial attempt is made,
64  or when a session refresh is sent using <replaceable>PJSIP_SEND_SESSION_REFRESH</replaceable>.
65  </para>
66  </description>
67  <see-also>
68  <ref type="function">PJSIP_SEND_SESSION_REFRESH</ref>
69  </see-also>
70 </function>
71 <function name="PJSIP_DTMF_MODE" language="en_US">
72  <since>
73  <version>13.18.0</version>
74  <version>14.7.0</version>
75  <version>15.1.0</version>
76  <version>16.0.0</version>
77  </since>
78  <synopsis>
79  Get or change the DTMF mode for a SIP call.
80  </synopsis>
81  <syntax>
82  </syntax>
83  <description>
84  <para>When read, returns the current DTMF mode</para>
85  <para>When written, sets the current DTMF mode</para>
86  <para>This function uses the same DTMF mode naming as the dtmf_mode configuration option</para>
87  </description>
88 </function>
89 <function name="PJSIP_MOH_PASSTHROUGH" language="en_US">
90  <synopsis>
91  Get or change the on-hold behavior for a SIP call.
92  </synopsis>
93  <syntax>
94  </syntax>
95  <description>
96  <para>When read, returns the current moh passthrough mode</para>
97  <para>When written, sets the current moh passthrough mode</para>
98  <para>If <replaceable>yes</replaceable>, on-hold re-INVITEs are sent. If <replaceable>no</replaceable>, music on hold is generated.</para>
99  <para>This function can be used to override the moh_passthrough configuration option</para>
100  </description>
101 </function>
102 <function name="PJSIP_SEND_SESSION_REFRESH" language="en_US">
103  <since>
104  <version>13.12.0</version>
105  <version>14.1.0</version>
106  <version>15.0.0</version>
107  </since>
108  <synopsis>
109  W/O: Initiate a session refresh via an UPDATE or re-INVITE on an established media session
110  </synopsis>
111  <syntax>
112  <parameter name="update_type" required="false">
113  <para>The type of update to send. Default is <literal>invite</literal>.</para>
114  <enumlist>
115  <enum name="invite">
116  <para>Send the session refresh as a re-INVITE.</para>
117  </enum>
118  <enum name="update">
119  <para>Send the session refresh as an UPDATE.</para>
120  </enum>
121  </enumlist>
122  </parameter>
123  </syntax>
124  <description>
125  <para>This function will cause the PJSIP stack to immediately refresh
126  the media session for the channel. This will be done using either a
127  re-INVITE (default) or an UPDATE request.
128  </para>
129  <para>This is most useful when combined with the <replaceable>PJSIP_MEDIA_OFFER</replaceable>
130  dialplan function, as it allows the formats in use on a channel to be
131  re-negotiated after call setup.</para>
132  <warning>
133  <para>The formats the endpoint supports are <emphasis>not</emphasis>
134  checked or enforced by this function. Using this function to offer
135  formats not supported by the endpoint <emphasis>may</emphasis> result
136  in a loss of media.</para>
137  </warning>
138  <example title="Re-negotiate format to g722">
139  ; Within some existing extension on an answered channel
140  same => n,Set(PJSIP_MEDIA_OFFER(audio)=!all,g722)
141  same => n,Set(PJSIP_SEND_SESSION_REFRESH()=invite)
142  </example>
143  </description>
144  <see-also>
145  <ref type="function">PJSIP_MEDIA_OFFER</ref>
146  </see-also>
147 </function>
148 <function name="PJSIP_PARSE_URI" language="en_US">
149  <since>
150  <version>13.24.0</version>
151  <version>16.1.0</version>
152  <version>17.0.0</version>
153  </since>
154  <synopsis>
155  Parse an uri and return a type part of the URI.
156  </synopsis>
157  <syntax>
158  <parameter name="uri" required="true">
159  <para>URI to parse</para>
160  </parameter>
161  <parameter name="type" required="true">
162  <para>The <literal>type</literal> parameter specifies which URI part to read</para>
163  <enumlist>
164  <enum name="display">
165  <para>Display name.</para>
166  </enum>
167  <enum name="scheme">
168  <para>URI scheme.</para>
169  </enum>
170  <enum name="user">
171  <para>User part.</para>
172  </enum>
173  <enum name="passwd">
174  <para>Password part.</para>
175  </enum>
176  <enum name="host">
177  <para>Host part.</para>
178  </enum>
179  <enum name="port">
180  <para>Port number, or zero.</para>
181  </enum>
182  <enum name="user_param">
183  <para>User parameter.</para>
184  </enum>
185  <enum name="method_param">
186  <para>Method parameter.</para>
187  </enum>
188  <enum name="transport_param">
189  <para>Transport parameter.</para>
190  </enum>
191  <enum name="ttl_param">
192  <para>TTL param, or -1.</para>
193  </enum>
194  <enum name="lr_param">
195  <para>Loose routing param, or zero.</para>
196  </enum>
197  <enum name="maddr_param">
198  <para>Maddr param.</para>
199  </enum>
200  </enumlist>
201  </parameter>
202  </syntax>
203  <description>
204  <para>Parse an URI and return a specified part of the URI.</para>
205  </description>
206 </function>
207 <info name="CHANNEL" language="en_US" tech="PJSIP">
208  <enumlist>
209  <enum name="rtp">
210  <para>R/O Retrieve media related information.</para>
211  <parameter name="type" required="true">
212  <para>When <replaceable>rtp</replaceable> is specified, the
213  <literal>type</literal> parameter must be provided. It specifies
214  which RTP parameter to read.</para>
215  <enumlist>
216  <enum name="src">
217  <para>Retrieve the local address for RTP.</para>
218  </enum>
219  <enum name="dest">
220  <para>Retrieve the remote address for RTP.</para>
221  </enum>
222  <enum name="direct">
223  <para>If direct media is enabled, this address is the remote address
224  used for RTP.</para>
225  </enum>
226  <enum name="secure">
227  <para>Whether or not the media stream is encrypted.</para>
228  <enumlist>
229  <enum name="0">
230  <para>The media stream is not encrypted.</para>
231  </enum>
232  <enum name="1">
233  <para>The media stream is encrypted.</para>
234  </enum>
235  </enumlist>
236  </enum>
237  <enum name="hold">
238  <para>Whether or not the media stream is currently restricted
239  due to a call hold.</para>
240  <enumlist>
241  <enum name="0">
242  <para>The media stream is not held.</para>
243  </enum>
244  <enum name="1">
245  <para>The media stream is held.</para>
246  </enum>
247  </enumlist>
248  </enum>
249  </enumlist>
250  </parameter>
251  <parameter name="media_type" required="false">
252  <para>When <replaceable>rtp</replaceable> is specified, the
253  <literal>media_type</literal> parameter may be provided. It specifies
254  which media stream the chosen RTP parameter should be retrieved
255  from.</para>
256  <enumlist>
257  <enum name="audio">
258  <para>Retrieve information from the audio media stream.</para>
259  <note><para>If not specified, <literal>audio</literal> is used
260  by default.</para></note>
261  </enum>
262  <enum name="video">
263  <para>Retrieve information from the video media stream.</para>
264  </enum>
265  </enumlist>
266  </parameter>
267  </enum>
268  <enum name="rtcp">
269  <para>R/O Retrieve RTCP statistics.</para>
270  <parameter name="statistic" required="true">
271  <para>When <replaceable>rtcp</replaceable> is specified, the
272  <literal>statistic</literal> parameter must be provided. It specifies
273  which RTCP statistic parameter to read.</para>
274  <enumlist>
275  <enum name="all">
276  <para>Retrieve a summary of all RTCP statistics.</para>
277  <para>The following data items are returned in a semi-colon
278  delineated list:</para>
279  <enumlist>
280  <enum name="ssrc">
281  <para>Our Synchronization Source identifier</para>
282  </enum>
283  <enum name="themssrc">
284  <para>Their Synchronization Source identifier</para>
285  </enum>
286  <enum name="lp">
287  <para>Our lost packet count</para>
288  </enum>
289  <enum name="rxjitter">
290  <para>Received packet jitter</para>
291  </enum>
292  <enum name="rxcount">
293  <para>Received packet count</para>
294  </enum>
295  <enum name="txjitter">
296  <para>Transmitted packet jitter</para>
297  </enum>
298  <enum name="txcount">
299  <para>Transmitted packet count</para>
300  </enum>
301  <enum name="rlp">
302  <para>Remote lost packet count</para>
303  </enum>
304  <enum name="rtt">
305  <para>Round trip time</para>
306  </enum>
307  </enumlist>
308  </enum>
309  <enum name="all_jitter">
310  <para>Retrieve a summary of all RTCP Jitter statistics.</para>
311  <para>The following data items are returned in a semi-colon
312  delineated list:</para>
313  <enumlist>
314  <enum name="minrxjitter">
315  <para>Our minimum jitter</para>
316  </enum>
317  <enum name="maxrxjitter">
318  <para>Our max jitter</para>
319  </enum>
320  <enum name="avgrxjitter">
321  <para>Our average jitter</para>
322  </enum>
323  <enum name="stdevrxjitter">
324  <para>Our jitter standard deviation</para>
325  </enum>
326  <enum name="reported_minjitter">
327  <para>Their minimum jitter</para>
328  </enum>
329  <enum name="reported_maxjitter">
330  <para>Their max jitter</para>
331  </enum>
332  <enum name="reported_avgjitter">
333  <para>Their average jitter</para>
334  </enum>
335  <enum name="reported_stdevjitter">
336  <para>Their jitter standard deviation</para>
337  </enum>
338  </enumlist>
339  </enum>
340  <enum name="all_loss">
341  <para>Retrieve a summary of all RTCP packet loss statistics.</para>
342  <para>The following data items are returned in a semi-colon
343  delineated list:</para>
344  <enumlist>
345  <enum name="minrxlost">
346  <para>Our minimum lost packets</para>
347  </enum>
348  <enum name="maxrxlost">
349  <para>Our max lost packets</para>
350  </enum>
351  <enum name="avgrxlost">
352  <para>Our average lost packets</para>
353  </enum>
354  <enum name="stdevrxlost">
355  <para>Our lost packets standard deviation</para>
356  </enum>
357  <enum name="reported_minlost">
358  <para>Their minimum lost packets</para>
359  </enum>
360  <enum name="reported_maxlost">
361  <para>Their max lost packets</para>
362  </enum>
363  <enum name="reported_avglost">
364  <para>Their average lost packets</para>
365  </enum>
366  <enum name="reported_stdevlost">
367  <para>Their lost packets standard deviation</para>
368  </enum>
369  </enumlist>
370  </enum>
371  <enum name="all_rtt">
372  <para>Retrieve a summary of all RTCP round trip time information.</para>
373  <para>The following data items are returned in a semi-colon
374  delineated list:</para>
375  <enumlist>
376  <enum name="minrtt">
377  <para>Minimum round trip time</para>
378  </enum>
379  <enum name="maxrtt">
380  <para>Maximum round trip time</para>
381  </enum>
382  <enum name="avgrtt">
383  <para>Average round trip time</para>
384  </enum>
385  <enum name="stdevrtt">
386  <para>Standard deviation round trip time</para>
387  </enum>
388  </enumlist>
389  </enum>
390  <enum name="txcount"><para>Transmitted packet count</para></enum>
391  <enum name="rxcount"><para>Received packet count</para></enum>
392  <enum name="txjitter"><para>Transmitted packet jitter</para></enum>
393  <enum name="rxjitter"><para>Received packet jitter</para></enum>
394  <enum name="remote_maxjitter"><para>Their max jitter</para></enum>
395  <enum name="remote_minjitter"><para>Their minimum jitter</para></enum>
396  <enum name="remote_normdevjitter"><para>Their average jitter</para></enum>
397  <enum name="remote_stdevjitter"><para>Their jitter standard deviation</para></enum>
398  <enum name="local_maxjitter"><para>Our max jitter</para></enum>
399  <enum name="local_minjitter"><para>Our minimum jitter</para></enum>
400  <enum name="local_normdevjitter"><para>Our average jitter</para></enum>
401  <enum name="local_stdevjitter"><para>Our jitter standard deviation</para></enum>
402  <enum name="txploss"><para>Transmitted packet loss</para></enum>
403  <enum name="rxploss"><para>Received packet loss</para></enum>
404  <enum name="remote_maxrxploss"><para>Their max lost packets</para></enum>
405  <enum name="remote_minrxploss"><para>Their minimum lost packets</para></enum>
406  <enum name="remote_normdevrxploss"><para>Their average lost packets</para></enum>
407  <enum name="remote_stdevrxploss"><para>Their lost packets standard deviation</para></enum>
408  <enum name="local_maxrxploss"><para>Our max lost packets</para></enum>
409  <enum name="local_minrxploss"><para>Our minimum lost packets</para></enum>
410  <enum name="local_normdevrxploss"><para>Our average lost packets</para></enum>
411  <enum name="local_stdevrxploss"><para>Our lost packets standard deviation</para></enum>
412  <enum name="rtt"><para>Round trip time</para></enum>
413  <enum name="maxrtt"><para>Maximum round trip time</para></enum>
414  <enum name="minrtt"><para>Minimum round trip time</para></enum>
415  <enum name="normdevrtt"><para>Average round trip time</para></enum>
416  <enum name="stdevrtt"><para>Standard deviation round trip time</para></enum>
417  <enum name="local_ssrc"><para>Our Synchronization Source identifier</para></enum>
418  <enum name="remote_ssrc"><para>Their Synchronization Source identifier</para></enum>
419  </enumlist>
420  </parameter>
421  <parameter name="media_type" required="false">
422  <para>When <replaceable>rtcp</replaceable> is specified, the
423  <literal>media_type</literal> parameter may be provided. It specifies
424  which media stream the chosen RTCP parameter should be retrieved
425  from.</para>
426  <enumlist>
427  <enum name="audio">
428  <para>Retrieve information from the audio media stream.</para>
429  <note><para>If not specified, <literal>audio</literal> is used
430  by default.</para></note>
431  </enum>
432  <enum name="video">
433  <para>Retrieve information from the video media stream.</para>
434  </enum>
435  </enumlist>
436  </parameter>
437  </enum>
438  <enum name="endpoint">
439  <para>R/O The name of the endpoint associated with this channel.
440  Use the <replaceable>PJSIP_ENDPOINT</replaceable> function to obtain
441  further endpoint related information.</para>
442  </enum>
443  <enum name="contact">
444  <para>R/O The name of the contact associated with this channel.
445  Use the <replaceable>PJSIP_CONTACT</replaceable> function to obtain
446  further contact related information. Note this may not be present and if so
447  is only available on outgoing legs.</para>
448  </enum>
449  <enum name="aor">
450  <para>R/O The name of the AOR associated with this channel.
451  Use the <replaceable>PJSIP_AOR</replaceable> function to obtain
452  further AOR related information. Note this may not be present and if so
453  is only available on outgoing legs.</para>
454  </enum>
455  <enum name="pjsip">
456  <para>R/O Obtain information about the current PJSIP channel and its
457  session.</para>
458  <parameter name="type" required="true">
459  <para>When <replaceable>pjsip</replaceable> is specified, the
460  <literal>type</literal> parameter must be provided. It specifies
461  which signalling parameter to read.</para>
462  <enumlist>
463  <enum name="call-id">
464  <para>The SIP call-id.</para>
465  </enum>
466  <enum name="secure">
467  <para>Whether or not the signalling uses a secure transport.</para>
468  <enumlist>
469  <enum name="0"><para>The signalling uses a non-secure transport.</para></enum>
470  <enum name="1"><para>The signalling uses a secure transport.</para></enum>
471  </enumlist>
472  </enum>
473  <enum name="target_uri">
474  <para>The contact URI where requests are sent.</para>
475  </enum>
476  <enum name="local_uri">
477  <para>The local URI.</para>
478  </enum>
479  <enum name="local_tag">
480  <para>Tag in From header</para>
481  </enum>
482  <enum name="remote_uri">
483  <para>The remote URI.</para>
484  </enum>
485  <enum name="remote_tag">
486  <para>Tag in To header</para>
487  </enum>
488  <enum name="request_uri">
489  <para>The request URI of the incoming <literal>INVITE</literal>
490  associated with the creation of this channel.</para>
491  </enum>
492  <enum name="t38state">
493  <para>The current state of any T.38 fax on this channel.</para>
494  <enumlist>
495  <enum name="DISABLED"><para>T.38 faxing is disabled on this channel.</para></enum>
496  <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>
497  <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>
498  <enum name="ENABLED"><para>A T.38 fax session has been enabled.</para></enum>
499  <enum name="REJECTED"><para>A T.38 fax session was attempted but was rejected.</para></enum>
500  </enumlist>
501  </enum>
502  <enum name="local_addr">
503  <para>On inbound calls, the full IP address and port number that
504  the <literal>INVITE</literal> request was received on. On outbound
505  calls, the full IP address and port number that the <literal>INVITE</literal>
506  request was transmitted from.</para>
507  </enum>
508  <enum name="remote_addr">
509  <para>On inbound calls, the full IP address and port number that
510  the <literal>INVITE</literal> request was received from. On outbound
511  calls, the full IP address and port number that the <literal>INVITE</literal>
512  request was transmitted to.</para>
513  </enum>
514  </enumlist>
515  </parameter>
516  </enum>
517  </enumlist>
518 </info>
519 <info name="CHANNEL_EXAMPLES" language="en_US" tech="PJSIP">
520  <example title="PJSIP specific CHANNEL examples">
521  ; Log the current Call-ID
522  same => n,Log(NOTICE, ${CHANNEL(pjsip,call-id)})
523 
524  ; Log the destination address of the audio stream
525  same => n,Log(NOTICE, ${CHANNEL(rtp,dest)})
526 
527  ; Store the round-trip time associated with a
528  ; video stream in the CDR field video-rtt
529  same => n,Set(CDR(video-rtt)=${CHANNEL(rtcp,rtt,video)})
530  </example>
531 </info>
532 ***/
533 
534 #include "asterisk.h"
535 
536 #include <pjsip.h>
537 #include <pjlib.h>
538 #include <pjsip_ua.h>
539 
540 #include "asterisk/astobj2.h"
541 #include "asterisk/module.h"
542 #include "asterisk/acl.h"
543 #include "asterisk/app.h"
544 #include "asterisk/channel.h"
545 #include "asterisk/stream.h"
546 #include "asterisk/format.h"
547 #include "asterisk/dsp.h"
548 #include "asterisk/pbx.h"
549 #include "asterisk/res_pjsip.h"
551 #include "include/chan_pjsip.h"
552 #include "include/dialplan_functions.h"
553 
554 /*!
555  * \brief String representations of the T.38 state enum
556  */
557 static const char *t38state_to_string[T38_MAX_ENUM] = {
558  [T38_DISABLED] = "DISABLED",
559  [T38_LOCAL_REINVITE] = "LOCAL_REINVITE",
560  [T38_PEER_REINVITE] = "REMOTE_REINVITE",
561  [T38_ENABLED] = "ENABLED",
562  [T38_REJECTED] = "REJECTED",
563 };
564 
565 /*!
566  * \internal \brief Handle reading RTP information
567  */
568 static int channel_read_rtp(struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
569 {
570  struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
571  struct ast_sip_session *session;
572  struct ast_sip_session_media *media;
573  struct ast_sockaddr addr;
574 
575  if (!channel) {
576  ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
577  return -1;
578  }
579 
580  session = channel->session;
581  if (!session) {
582  ast_log(AST_LOG_WARNING, "Channel %s has no session!\n", ast_channel_name(chan));
583  return -1;
584  }
585 
586  if (ast_strlen_zero(type)) {
587  ast_log(AST_LOG_WARNING, "You must supply a type field for 'rtp' information\n");
588  return -1;
589  }
590 
591  if (ast_strlen_zero(field) || !strcmp(field, "audio")) {
592  media = session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO];
593  } else if (!strcmp(field, "video")) {
594  media = session->active_media_state->default_session[AST_MEDIA_TYPE_VIDEO];
595  } else {
596  ast_log(AST_LOG_WARNING, "Unknown media type field '%s' for 'rtp' information\n", field);
597  return -1;
598  }
599 
600  if (!media || !media->rtp) {
601  ast_log(AST_LOG_WARNING, "Channel %s has no %s media/RTP session\n",
602  ast_channel_name(chan), S_OR(field, "audio"));
603  return -1;
604  }
605 
606  if (!strcmp(type, "src")) {
608  ast_copy_string(buf, ast_sockaddr_stringify(&addr), buflen);
609  } else if (!strcmp(type, "dest")) {
611  ast_copy_string(buf, ast_sockaddr_stringify(&addr), buflen);
612  } else if (!strcmp(type, "direct")) {
614  } else if (!strcmp(type, "secure")) {
615  if (media->srtp) {
616  struct ast_sdp_srtp *srtp = media->srtp;
618  snprintf(buf, buflen, "%d", flag ? 1 : 0);
619  } else {
620  snprintf(buf, buflen, "%d", 0);
621  }
622  } else if (!strcmp(type, "hold")) {
623  snprintf(buf, buflen, "%d", media->remotely_held ? 1 : 0);
624  } else {
625  ast_log(AST_LOG_WARNING, "Unknown type field '%s' specified for 'rtp' information\n", type);
626  return -1;
627  }
628 
629  return 0;
630 }
631 
632 /*!
633  * \internal \brief Handle reading RTCP information
634  */
635 static int channel_read_rtcp(struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
636 {
637  struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
638  struct ast_sip_session *session;
639  struct ast_sip_session_media *media;
640 
641  if (!channel) {
642  ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
643  return -1;
644  }
645 
646  session = channel->session;
647  if (!session) {
648  ast_log(AST_LOG_WARNING, "Channel %s has no session!\n", ast_channel_name(chan));
649  return -1;
650  }
651 
652  if (ast_strlen_zero(type)) {
653  ast_log(AST_LOG_WARNING, "You must supply a type field for 'rtcp' information\n");
654  return -1;
655  }
656 
657  if (ast_strlen_zero(field) || !strcmp(field, "audio")) {
658  media = session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO];
659  } else if (!strcmp(field, "video")) {
660  media = session->active_media_state->default_session[AST_MEDIA_TYPE_VIDEO];
661  } else {
662  ast_log(AST_LOG_WARNING, "Unknown media type field '%s' for 'rtcp' information\n", field);
663  return -1;
664  }
665 
666  if (!media || !media->rtp) {
667  ast_log(AST_LOG_WARNING, "Channel %s has no %s media/RTP session\n",
668  ast_channel_name(chan), S_OR(field, "audio"));
669  return -1;
670  }
671 
672  if (!strncasecmp(type, "all", 3)) {
674 
675  if (!strcasecmp(type, "all_jitter")) {
677  } else if (!strcasecmp(type, "all_rtt")) {
679  } else if (!strcasecmp(type, "all_loss")) {
681  }
682 
683  if (!ast_rtp_instance_get_quality(media->rtp, stat_field, buf, buflen)) {
684  ast_log(AST_LOG_WARNING, "Unable to retrieve 'rtcp' statistics for %s\n", ast_channel_name(chan));
685  return -1;
686  }
687  } else {
688  struct ast_rtp_instance_stats stats;
689  int i;
690  struct {
691  const char *name;
692  enum { INT, DBL } type;
693  union {
694  unsigned int *i4;
695  double *d8;
696  };
697  } lookup[] = {
698  { "txcount", INT, { .i4 = &stats.txcount, }, },
699  { "rxcount", INT, { .i4 = &stats.rxcount, }, },
700  { "txjitter", DBL, { .d8 = &stats.txjitter, }, },
701  { "rxjitter", DBL, { .d8 = &stats.rxjitter, }, },
702  { "remote_maxjitter", DBL, { .d8 = &stats.remote_maxjitter, }, },
703  { "remote_minjitter", DBL, { .d8 = &stats.remote_minjitter, }, },
704  { "remote_normdevjitter", DBL, { .d8 = &stats.remote_normdevjitter, }, },
705  { "remote_stdevjitter", DBL, { .d8 = &stats.remote_stdevjitter, }, },
706  { "local_maxjitter", DBL, { .d8 = &stats.local_maxjitter, }, },
707  { "local_minjitter", DBL, { .d8 = &stats.local_minjitter, }, },
708  { "local_normdevjitter", DBL, { .d8 = &stats.local_normdevjitter, }, },
709  { "local_stdevjitter", DBL, { .d8 = &stats.local_stdevjitter, }, },
710  { "txploss", INT, { .i4 = &stats.txploss, }, },
711  { "rxploss", INT, { .i4 = &stats.rxploss, }, },
712  { "remote_maxrxploss", DBL, { .d8 = &stats.remote_maxrxploss, }, },
713  { "remote_minrxploss", DBL, { .d8 = &stats.remote_minrxploss, }, },
714  { "remote_normdevrxploss", DBL, { .d8 = &stats.remote_normdevrxploss, }, },
715  { "remote_stdevrxploss", DBL, { .d8 = &stats.remote_stdevrxploss, }, },
716  { "local_maxrxploss", DBL, { .d8 = &stats.local_maxrxploss, }, },
717  { "local_minrxploss", DBL, { .d8 = &stats.local_minrxploss, }, },
718  { "local_normdevrxploss", DBL, { .d8 = &stats.local_normdevrxploss, }, },
719  { "local_stdevrxploss", DBL, { .d8 = &stats.local_stdevrxploss, }, },
720  { "rtt", DBL, { .d8 = &stats.rtt, }, },
721  { "maxrtt", DBL, { .d8 = &stats.maxrtt, }, },
722  { "minrtt", DBL, { .d8 = &stats.minrtt, }, },
723  { "normdevrtt", DBL, { .d8 = &stats.normdevrtt, }, },
724  { "stdevrtt", DBL, { .d8 = &stats.stdevrtt, }, },
725  { "local_ssrc", INT, { .i4 = &stats.local_ssrc, }, },
726  { "remote_ssrc", INT, { .i4 = &stats.remote_ssrc, }, },
727  { NULL, },
728  };
729 
731  ast_log(AST_LOG_WARNING, "Unable to retrieve 'rtcp' statistics for %s\n", ast_channel_name(chan));
732  return -1;
733  }
734 
735  for (i = 0; !ast_strlen_zero(lookup[i].name); i++) {
736  if (!strcasecmp(type, lookup[i].name)) {
737  if (lookup[i].type == INT) {
738  snprintf(buf, buflen, "%u", *lookup[i].i4);
739  } else {
740  snprintf(buf, buflen, "%f", *lookup[i].d8);
741  }
742  return 0;
743  }
744  }
745  ast_log(AST_LOG_WARNING, "Unrecognized argument '%s' for 'rtcp' information\n", type);
746  return -1;
747  }
748 
749  return 0;
750 }
751 
752 static int print_escaped_uri(struct ast_channel *chan, const char *type,
753  pjsip_uri_context_e context, const void *uri, char *buf, size_t size)
754 {
755  int res;
756  char *buf_copy;
757 
758  res = pjsip_uri_print(context, uri, buf, size);
759  if (res < 0) {
760  ast_log(LOG_ERROR, "Channel %s: Unescaped %s too long for %d byte buffer\n",
761  ast_channel_name(chan), type, (int) size);
762 
763  /* Empty buffer that likely is not terminated. */
764  buf[0] = '\0';
765  return -1;
766  }
767 
768  buf_copy = ast_strdupa(buf);
769  ast_escape_quoted(buf_copy, buf, size);
770  return 0;
771 }
772 
773 /*!
774  * \internal \brief Handle reading signalling information
775  */
776 static int channel_read_pjsip(struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
777 {
778  struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
779  char *buf_copy;
780  pjsip_dialog *dlg;
781  int res = 0;
782 
783  if (!channel) {
784  ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
785  return -1;
786  }
787 
788  dlg = channel->session->inv_session->dlg;
789 
790  if (ast_strlen_zero(type)) {
791  ast_log(LOG_WARNING, "You must supply a type field for 'pjsip' information\n");
792  return -1;
793  } else if (!strcmp(type, "call-id")) {
794  snprintf(buf, buflen, "%.*s", (int) pj_strlen(&dlg->call_id->id), pj_strbuf(&dlg->call_id->id));
795  } else if (!strcmp(type, "secure")) {
796 #ifdef HAVE_PJSIP_GET_DEST_INFO
797  pjsip_host_info dest;
798  pj_pool_t *pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "secure-check", 128, 128);
799  pjsip_get_dest_info(dlg->target, NULL, pool, &dest);
800  snprintf(buf, buflen, "%d", dest.flag & PJSIP_TRANSPORT_SECURE ? 1 : 0);
801  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
802 #else
803  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");
804  return -1;
805 #endif
806  } else if (!strcmp(type, "target_uri")) {
807  res = print_escaped_uri(chan, type, PJSIP_URI_IN_REQ_URI, dlg->target, buf,
808  buflen);
809  } else if (!strcmp(type, "local_uri")) {
810  res = print_escaped_uri(chan, type, PJSIP_URI_IN_FROMTO_HDR, dlg->local.info->uri,
811  buf, buflen);
812  } else if (!strcmp(type, "local_tag")) {
813  ast_copy_pj_str(buf, &dlg->local.info->tag, buflen);
814  buf_copy = ast_strdupa(buf);
815  ast_escape_quoted(buf_copy, buf, buflen);
816  } else if (!strcmp(type, "remote_uri")) {
817  res = print_escaped_uri(chan, type, PJSIP_URI_IN_FROMTO_HDR,
818  dlg->remote.info->uri, buf, buflen);
819  } else if (!strcmp(type, "remote_tag")) {
820  ast_copy_pj_str(buf, &dlg->remote.info->tag, buflen);
821  buf_copy = ast_strdupa(buf);
822  ast_escape_quoted(buf_copy, buf, buflen);
823  } else if (!strcmp(type, "request_uri")) {
824  if (channel->session->request_uri) {
825  res = print_escaped_uri(chan, type, PJSIP_URI_IN_REQ_URI,
826  channel->session->request_uri, buf, buflen);
827  }
828  } else if (!strcmp(type, "t38state")) {
830  } else if (!strcmp(type, "local_addr")) {
831  RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
832  struct transport_info_data *transport_data;
833 
834  datastore = ast_sip_session_get_datastore(channel->session, "transport_info");
835  if (!datastore) {
836  ast_log(AST_LOG_WARNING, "No transport information for channel %s\n", ast_channel_name(chan));
837  return -1;
838  }
839  transport_data = datastore->data;
840 
841  if (pj_sockaddr_has_addr(&transport_data->local_addr)) {
842  pj_sockaddr_print(&transport_data->local_addr, buf, buflen, 3);
843  }
844  } else if (!strcmp(type, "remote_addr")) {
845  RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
846  struct transport_info_data *transport_data;
847 
848  datastore = ast_sip_session_get_datastore(channel->session, "transport_info");
849  if (!datastore) {
850  ast_log(AST_LOG_WARNING, "No transport information for channel %s\n", ast_channel_name(chan));
851  return -1;
852  }
853  transport_data = datastore->data;
854 
855  if (pj_sockaddr_has_addr(&transport_data->remote_addr)) {
856  pj_sockaddr_print(&transport_data->remote_addr, buf, buflen, 3);
857  }
858  } else {
859  ast_log(AST_LOG_WARNING, "Unrecognized argument '%s' for 'pjsip' information\n", type);
860  return -1;
861  }
862 
863  return res;
864 }
865 
866 /*! \brief Struct used to push function arguments to task processor */
869  const char *param;
870  const char *type;
871  const char *field;
872  char *buf;
873  size_t len;
874  int ret;
875 };
876 
877 /*! \internal \brief Taskprocessor callback that handles the read on a PJSIP thread */
878 static int read_pjsip(void *data)
879 {
880  struct pjsip_func_args *func_args = data;
881 
882  if (!strcmp(func_args->param, "rtp")) {
883  if (!func_args->session->channel) {
884  func_args->ret = -1;
885  return 0;
886  }
887  func_args->ret = channel_read_rtp(func_args->session->channel, func_args->type,
888  func_args->field, func_args->buf,
889  func_args->len);
890  } else if (!strcmp(func_args->param, "rtcp")) {
891  if (!func_args->session->channel) {
892  func_args->ret = -1;
893  return 0;
894  }
895  func_args->ret = channel_read_rtcp(func_args->session->channel, func_args->type,
896  func_args->field, func_args->buf,
897  func_args->len);
898  } else if (!strcmp(func_args->param, "endpoint")) {
899  if (!func_args->session->endpoint) {
900  ast_log(AST_LOG_WARNING, "Channel %s has no endpoint!\n", func_args->session->channel ?
901  ast_channel_name(func_args->session->channel) : "<unknown>");
902  func_args->ret = -1;
903  return 0;
904  }
905  snprintf(func_args->buf, func_args->len, "%s", ast_sorcery_object_get_id(func_args->session->endpoint));
906  } else if (!strcmp(func_args->param, "contact")) {
907  if (!func_args->session->contact) {
908  return 0;
909  }
910  snprintf(func_args->buf, func_args->len, "%s", ast_sorcery_object_get_id(func_args->session->contact));
911  } else if (!strcmp(func_args->param, "aor")) {
912  if (!func_args->session->aor) {
913  return 0;
914  }
915  snprintf(func_args->buf, func_args->len, "%s", ast_sorcery_object_get_id(func_args->session->aor));
916  } else if (!strcmp(func_args->param, "pjsip")) {
917  if (!func_args->session->channel) {
918  func_args->ret = -1;
919  return 0;
920  }
921  func_args->ret = channel_read_pjsip(func_args->session->channel, func_args->type,
922  func_args->field, func_args->buf,
923  func_args->len);
924  } else {
925  func_args->ret = -1;
926  }
927 
928  return 0;
929 }
930 
931 
932 int pjsip_acf_channel_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
933 {
934  struct pjsip_func_args func_args = { 0, };
935  struct ast_sip_channel_pvt *channel;
936  char *parse = ast_strdupa(data);
937 
939  AST_APP_ARG(param);
940  AST_APP_ARG(type);
941  AST_APP_ARG(field);
942  );
943 
944  if (!chan) {
945  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
946  return -1;
947  }
948 
949  /* Check for zero arguments */
950  if (ast_strlen_zero(parse)) {
951  ast_log(LOG_ERROR, "Cannot call %s without arguments\n", cmd);
952  return -1;
953  }
954 
956 
957  ast_channel_lock(chan);
958 
959  /* Sanity check */
960  if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
961  ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
962  ast_channel_unlock(chan);
963  return 0;
964  }
965 
966  channel = ast_channel_tech_pvt(chan);
967  if (!channel) {
968  ast_log(LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
969  ast_channel_unlock(chan);
970  return -1;
971  }
972 
973  if (!channel->session) {
974  ast_log(LOG_WARNING, "Channel %s has no session\n", ast_channel_name(chan));
975  ast_channel_unlock(chan);
976  return -1;
977  }
978 
979  func_args.session = ao2_bump(channel->session);
980  ast_channel_unlock(chan);
981 
982  memset(buf, 0, len);
983 
984  func_args.param = args.param;
985  func_args.type = args.type;
986  func_args.field = args.field;
987  func_args.buf = buf;
988  func_args.len = len;
989  if (ast_sip_push_task_wait_serializer(func_args.session->serializer, read_pjsip, &func_args)) {
990  ast_log(LOG_WARNING, "Unable to read properties of channel %s: failed to push task\n", ast_channel_name(chan));
991  ao2_ref(func_args.session, -1);
992  return -1;
993  }
994  ao2_ref(func_args.session, -1);
995 
996  return func_args.ret;
997 }
998 
999 int pjsip_acf_dial_contacts_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
1000 {
1001  RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
1002  RAII_VAR(struct ast_str *, dial, NULL, ast_free_ptr);
1003  const char *aor_name;
1004  char *rest;
1005 
1007  AST_APP_ARG(endpoint_name);
1008  AST_APP_ARG(aor_name);
1009  AST_APP_ARG(request_user);
1010  );
1011 
1012  AST_STANDARD_APP_ARGS(args, data);
1013 
1014  if (ast_strlen_zero(args.endpoint_name)) {
1015  ast_log(LOG_WARNING, "An endpoint name must be specified when using the '%s' dialplan function\n", cmd);
1016  return -1;
1017  } else if (!(endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", args.endpoint_name))) {
1018  ast_log(LOG_WARNING, "Specified endpoint '%s' was not found\n", args.endpoint_name);
1019  return -1;
1020  }
1021 
1022  aor_name = S_OR(args.aor_name, endpoint->aors);
1023 
1024  if (ast_strlen_zero(aor_name)) {
1025  ast_log(LOG_WARNING, "No AOR has been provided and no AORs are configured on endpoint '%s'\n", args.endpoint_name);
1026  return -1;
1027  } else if (!(dial = ast_str_create(len))) {
1028  ast_log(LOG_WARNING, "Could not get enough buffer space for dialing contacts\n");
1029  return -1;
1030  } else if (!(rest = ast_strdupa(aor_name))) {
1031  ast_log(LOG_WARNING, "Could not duplicate provided AORs\n");
1032  return -1;
1033  }
1034 
1035  while ((aor_name = ast_strip(strsep(&rest, ",")))) {
1037  RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
1038  struct ao2_iterator it_contacts;
1039  struct ast_sip_contact *contact;
1040 
1041  if (!aor) {
1042  /* If the AOR provided is not found skip it, there may be more */
1043  continue;
1045  /* No contacts are available, skip it as well */
1046  continue;
1047  } else if (!ao2_container_count(contacts)) {
1048  /* We were given a container but no contacts are in it... */
1049  continue;
1050  }
1051 
1052  it_contacts = ao2_iterator_init(contacts, 0);
1053  for (; (contact = ao2_iterator_next(&it_contacts)); ao2_ref(contact, -1)) {
1054  ast_str_append(&dial, -1, "PJSIP/");
1055 
1056  if (!ast_strlen_zero(args.request_user)) {
1057  ast_str_append(&dial, -1, "%s@", args.request_user);
1058  }
1059  ast_str_append(&dial, -1, "%s/%s&", args.endpoint_name, contact->uri);
1060  }
1061  ao2_iterator_destroy(&it_contacts);
1062  }
1063 
1064  /* Trim the '&' at the end off */
1065  ast_str_truncate(dial, ast_str_strlen(dial) - 1);
1066 
1068 
1069  return 0;
1070 }
1071 
1072 /*! \brief Session refresh state information */
1074  /*! \brief Created proposed media state */
1076 };
1077 
1078 /*! \brief Destructor for session refresh information */
1079 static void session_refresh_state_destroy(void *obj)
1080 {
1081  struct session_refresh_state *state = obj;
1082 
1084  ast_free(obj);
1085 }
1086 
1087 /*! \brief Datastore for attaching session refresh state information */
1088 static const struct ast_datastore_info session_refresh_datastore = {
1089  .type = "pjsip_session_refresh",
1090  .destroy = session_refresh_state_destroy,
1091 };
1092 
1093 /*! \brief Helper function which retrieves or allocates a session refresh state information datastore */
1095 {
1096  RAII_VAR(struct ast_datastore *, datastore, ast_sip_session_get_datastore(session, "pjsip_session_refresh"), ao2_cleanup);
1097  struct session_refresh_state *state;
1098 
1099  /* While the datastore refcount is decremented this is operating in the serializer so it will remain valid regardless */
1100  if (datastore) {
1101  return datastore->data;
1102  }
1103 
1104  if (!(datastore = ast_sip_session_alloc_datastore(&session_refresh_datastore, "pjsip_session_refresh"))
1105  || !(datastore->data = ast_calloc(1, sizeof(struct session_refresh_state)))
1106  || ast_sip_session_add_datastore(session, datastore)) {
1107  return NULL;
1108  }
1109 
1110  state = datastore->data;
1111  state->media_state = ast_sip_session_media_state_alloc();
1112  if (!state->media_state) {
1113  ast_sip_session_remove_datastore(session, "pjsip_session_refresh");
1114  return NULL;
1115  }
1116  state->media_state->topology = ast_stream_topology_clone(session->endpoint->media.topology);
1117  if (!state->media_state->topology) {
1118  ast_sip_session_remove_datastore(session, "pjsip_session_refresh");
1119  return NULL;
1120  }
1121 
1122  datastore->data = state;
1123 
1124  return state;
1125 }
1126 
1127 /*! \brief Struct used to push PJSIP_PARSE_URI function arguments to task processor */
1129  const char *uri;
1130  const char *type;
1131  char *buf;
1132  size_t buflen;
1133  int ret;
1134 };
1135 
1136 /*! \internal \brief Taskprocessor callback that handles the PJSIP_PARSE_URI on a PJSIP thread */
1137 static int parse_uri_cb(void *data)
1138 {
1139  struct parse_uri_args *args = data;
1140  pj_pool_t *pool;
1141  pjsip_name_addr *uri;
1142  pjsip_sip_uri *sip_uri;
1143  pj_str_t tmp;
1144 
1145  args->ret = 0;
1146 
1147  pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "ParseUri", 128, 128);
1148  if (!pool) {
1149  ast_log(LOG_ERROR, "Failed to allocate ParseUri endpoint pool.\n");
1150  args->ret = -1;
1151  return 0;
1152  }
1153 
1154  pj_strdup2_with_null(pool, &tmp, args->uri);
1155  uri = (pjsip_name_addr *)pjsip_parse_uri(pool, tmp.ptr, tmp.slen, PJSIP_PARSE_URI_AS_NAMEADDR);
1156  if (!uri || (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
1157  ast_log(LOG_WARNING, "Failed to parse URI '%s'\n", args->uri);
1158  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1159  args->ret = -1;
1160  return 0;
1161  }
1162 
1163  if (!strcmp(args->type, "scheme")) {
1164  ast_copy_pj_str(args->buf, pjsip_uri_get_scheme(uri), args->buflen);
1165  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1166  return 0;
1167  } else if (!strcmp(args->type, "display")) {
1168  ast_copy_pj_str(args->buf, &uri->display, args->buflen);
1169  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1170  return 0;
1171  }
1172 
1173  sip_uri = pjsip_uri_get_uri(uri);
1174  if (!sip_uri) {
1175  ast_log(LOG_ERROR, "Failed to get an URI object for '%s'\n", args->uri);
1176  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1177  args->ret = -1;
1178  return 0;
1179  }
1180 
1181  if (!strcmp(args->type, "user")) {
1182  ast_copy_pj_str(args->buf, &sip_uri->user, args->buflen);
1183  } else if (!strcmp(args->type, "passwd")) {
1184  ast_copy_pj_str(args->buf, &sip_uri->passwd, args->buflen);
1185  } else if (!strcmp(args->type, "host")) {
1186  ast_copy_pj_str(args->buf, &sip_uri->host, args->buflen);
1187  } else if (!strcmp(args->type, "port")) {
1188  snprintf(args->buf, args->buflen, "%d", sip_uri->port);
1189  } else if (!strcmp(args->type, "user_param")) {
1190  ast_copy_pj_str(args->buf, &sip_uri->user_param, args->buflen);
1191  } else if (!strcmp(args->type, "method_param")) {
1192  ast_copy_pj_str(args->buf, &sip_uri->method_param, args->buflen);
1193  } else if (!strcmp(args->type, "transport_param")) {
1194  ast_copy_pj_str(args->buf, &sip_uri->transport_param, args->buflen);
1195  } else if (!strcmp(args->type, "ttl_param")) {
1196  snprintf(args->buf, args->buflen, "%d", sip_uri->ttl_param);
1197  } else if (!strcmp(args->type, "lr_param")) {
1198  snprintf(args->buf, args->buflen, "%d", sip_uri->lr_param);
1199  } else if (!strcmp(args->type, "maddr_param")) {
1200  ast_copy_pj_str(args->buf, &sip_uri->maddr_param, args->buflen);
1201  } else {
1202  ast_log(AST_LOG_WARNING, "Unknown type part '%s' specified\n", args->type);
1203  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1204  args->ret = -1;
1205  return 0;
1206  }
1207 
1208  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1209 
1210  return 0;
1211 }
1212 
1213 int pjsip_acf_parse_uri_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
1214 {
1215  struct parse_uri_args func_args = { 0, };
1216 
1218  AST_APP_ARG(uri_str);
1219  AST_APP_ARG(type);
1220  );
1221 
1222  AST_STANDARD_APP_ARGS(args, data);
1223 
1224  if (ast_strlen_zero(args.uri_str)) {
1225  ast_log(LOG_WARNING, "An URI must be specified when using the '%s' dialplan function\n", cmd);
1226  return -1;
1227  }
1228 
1229  if (ast_strlen_zero(args.type)) {
1230  ast_log(LOG_WARNING, "A type part of the URI must be specified when using the '%s' dialplan function\n", cmd);
1231  return -1;
1232  }
1233 
1234  memset(buf, 0, buflen);
1235 
1236  func_args.uri = args.uri_str;
1237  func_args.type = args.type;
1238  func_args.buf = buf;
1239  func_args.buflen = buflen;
1241  ast_log(LOG_WARNING, "Unable to parse URI: failed to push task\n");
1242  return -1;
1243  }
1244 
1245  return func_args.ret;
1246 }
1247 
1249  size_t len, enum ast_media_type media_type)
1250 {
1251  struct ast_stream_topology *topology;
1252  int idx;
1253  struct ast_stream *stream = NULL;
1254  const struct ast_format_cap *caps;
1255  size_t accum = 0;
1256 
1257  if (session->inv_session->dlg->state == PJSIP_DIALOG_STATE_ESTABLISHED) {
1258  struct session_refresh_state *state;
1259 
1260  /* As we've already answered we need to store our media state until we are ready to send it */
1262  if (!state) {
1263  return -1;
1264  }
1265  topology = state->media_state->topology;
1266  } else {
1267  /* The session is not yet up so we are initially answering or offering */
1268  if (!session->pending_media_state->topology) {
1269  session->pending_media_state->topology = ast_stream_topology_clone(session->endpoint->media.topology);
1270  if (!session->pending_media_state->topology) {
1271  return -1;
1272  }
1273  }
1274  topology = session->pending_media_state->topology;
1275  }
1276 
1277  /* Find the first suitable stream */
1278  for (idx = 0; idx < ast_stream_topology_get_count(topology); ++idx) {
1279  stream = ast_stream_topology_get_stream(topology, idx);
1280 
1281  if (ast_stream_get_type(stream) != media_type ||
1283  stream = NULL;
1284  continue;
1285  }
1286 
1287  break;
1288  }
1289 
1290  /* If no suitable stream then exit early */
1291  if (!stream) {
1292  buf[0] = '\0';
1293  return 0;
1294  }
1295 
1296  caps = ast_stream_get_formats(stream);
1297 
1298  /* Note: buf is not terminated while the string is being built. */
1299  for (idx = 0; idx < ast_format_cap_count(caps); ++idx) {
1300  struct ast_format *fmt;
1301  size_t size;
1302 
1303  fmt = ast_format_cap_get_format(caps, idx);
1304 
1305  /* Add one for a comma or terminator */
1306  size = strlen(ast_format_get_name(fmt)) + 1;
1307  if (len < size) {
1308  ao2_ref(fmt, -1);
1309  break;
1310  }
1311 
1312  /* Append the format name */
1313  strcpy(buf + accum, ast_format_get_name(fmt));/* Safe */
1314  ao2_ref(fmt, -1);
1315 
1316  accum += size;
1317  len -= size;
1318 
1319  /* The last comma on the built string will be set to the terminator. */
1320  buf[accum - 1] = ',';
1321  }
1322 
1323  /* Remove the trailing comma or terminate an empty buffer. */
1324  buf[accum ? accum - 1 : 0] = '\0';
1325  return 0;
1326 }
1327 
1331  const char *value;
1332 };
1333 
1334 static int media_offer_write_av(void *obj)
1335 {
1336  struct media_offer_data *data = obj;
1337  struct ast_stream_topology *topology;
1338  struct ast_stream *stream;
1339  struct ast_format_cap *caps;
1340 
1341  if (data->session->inv_session->dlg->state == PJSIP_DIALOG_STATE_ESTABLISHED) {
1342  struct session_refresh_state *state;
1343 
1344  /* As we've already answered we need to store our media state until we are ready to send it */
1346  if (!state) {
1347  return -1;
1348  }
1349  topology = state->media_state->topology;
1350  } else {
1351  /* The session is not yet up so we are initially answering or offering */
1352  if (!data->session->pending_media_state->topology) {
1354  if (!data->session->pending_media_state->topology) {
1355  return -1;
1356  }
1357  }
1358  topology = data->session->pending_media_state->topology;
1359  }
1360 
1361  /* XXX This method won't work when it comes time to do multistream support. The proper way to do this
1362  * will either be to
1363  * a) Alter all media streams of a particular type.
1364  * b) Change the dialplan function to be able to specify which stream to alter and alter only that
1365  * one stream
1366  */
1367  stream = ast_stream_topology_get_first_stream_by_type(topology, data->media_type);
1368  if (!stream) {
1369  return 0;
1370  }
1371 
1373  if (!caps) {
1374  return -1;
1375  }
1376 
1381  ast_stream_set_formats(stream, caps);
1382  ast_stream_set_metadata(stream, "pjsip_session_refresh", "force");
1383  ao2_ref(caps, -1);
1384 
1385  return 0;
1386 }
1387 
1388 int pjsip_acf_media_offer_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
1389 {
1390  struct ast_sip_channel_pvt *channel;
1391 
1392  if (!chan) {
1393  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1394  return -1;
1395  }
1396 
1397  if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1398  ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
1399  return -1;
1400  }
1401 
1402  channel = ast_channel_tech_pvt(chan);
1403 
1404  if (!strcmp(data, "audio")) {
1406  } else if (!strcmp(data, "video")) {
1408  } else {
1409  /* Ensure that the buffer is empty */
1410  buf[0] = '\0';
1411  }
1412 
1413  return 0;
1414 }
1415 
1416 int pjsip_acf_media_offer_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
1417 {
1418  struct ast_sip_channel_pvt *channel;
1419  struct media_offer_data mdata = {
1420  .value = value
1421  };
1422 
1423  if (!chan) {
1424  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1425  return -1;
1426  }
1427 
1428  if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1429  ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
1430  return -1;
1431  }
1432 
1433  channel = ast_channel_tech_pvt(chan);
1434  mdata.session = channel->session;
1435 
1436  if (!strcmp(data, "audio")) {
1438  } else if (!strcmp(data, "video")) {
1440  }
1441 
1443 }
1444 
1445 int pjsip_acf_dtmf_mode_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
1446 {
1447  struct ast_sip_channel_pvt *channel;
1448 
1449  if (!chan) {
1450  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1451  return -1;
1452  }
1453 
1454  ast_channel_lock(chan);
1455  if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1456  ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
1457  ast_channel_unlock(chan);
1458  return -1;
1459  }
1460 
1461  channel = ast_channel_tech_pvt(chan);
1462 
1463  if (ast_sip_dtmf_to_str(channel->session->dtmf, buf, len) < 0) {
1464  ast_log(LOG_WARNING, "Unknown DTMF mode %d on PJSIP channel %s\n", channel->session->dtmf, ast_channel_name(chan));
1465  ast_channel_unlock(chan);
1466  return -1;
1467  }
1468 
1469  ast_channel_unlock(chan);
1470  return 0;
1471 }
1472 
1473 int pjsip_acf_moh_passthrough_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
1474 {
1475  struct ast_sip_channel_pvt *channel;
1476 
1477  if (!chan) {
1478  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1479  return -1;
1480  }
1481 
1482  if (len < 3) {
1483  ast_log(LOG_WARNING, "%s: buffer too small\n", cmd);
1484  return -1;
1485  }
1486 
1487  ast_channel_lock(chan);
1488  if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1489  ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
1490  ast_channel_unlock(chan);
1491  return -1;
1492  }
1493 
1494  channel = ast_channel_tech_pvt(chan);
1495  strncpy(buf, AST_YESNO(channel->session->moh_passthrough), len);
1496 
1497  ast_channel_unlock(chan);
1498  return 0;
1499 }
1500 
1504 };
1505 
1506 static int sip_session_response_cb(struct ast_sip_session *session, pjsip_rx_data *rdata)
1507 {
1508  struct ast_format *fmt;
1509 
1510  if (!session->channel) {
1511  /* Egads! */
1512  return 0;
1513  }
1514 
1516  if (!fmt) {
1517  /* No format? That's weird. */
1518  return 0;
1519  }
1520  ast_channel_set_writeformat(session->channel, fmt);
1521  ast_channel_set_rawwriteformat(session->channel, fmt);
1522  ast_channel_set_readformat(session->channel, fmt);
1523  ast_channel_set_rawreadformat(session->channel, fmt);
1524  ao2_ref(fmt, -1);
1525 
1526  return 0;
1527 }
1528 
1529 static int dtmf_mode_refresh_cb(void *obj)
1530 {
1531  struct refresh_data *data = obj;
1532 
1533  if (data->session->inv_session->state == PJSIP_INV_STATE_CONFIRMED) {
1534  ast_debug(3, "Changing DTMF mode on channel %s after OFFER/ANSWER completion. Sending session refresh\n", ast_channel_name(data->session->channel));
1535 
1537  sip_session_response_cb, data->method, 1, NULL);
1538  } else if (data->session->inv_session->state == PJSIP_INV_STATE_INCOMING) {
1539  ast_debug(3, "Changing DTMF mode on channel %s during OFFER/ANSWER exchange. Updating SDP answer\n", ast_channel_name(data->session->channel));
1541  }
1542 
1543  return 0;
1544 }
1545 
1546 int pjsip_acf_dtmf_mode_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
1547 {
1548  struct ast_sip_channel_pvt *channel;
1549  struct ast_sip_session_media *media;
1550  int dsp_features = 0;
1551  int dtmf = -1;
1552  struct refresh_data rdata = {
1554  };
1555 
1556  if (!chan) {
1557  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1558  return -1;
1559  }
1560 
1561  ast_channel_lock(chan);
1562  if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1563  ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
1564  ast_channel_unlock(chan);
1565  return -1;
1566  }
1567 
1568  channel = ast_channel_tech_pvt(chan);
1569  rdata.session = channel->session;
1570 
1571  dtmf = ast_sip_str_to_dtmf(value);
1572 
1573  if (dtmf == -1) {
1574  ast_log(LOG_WARNING, "Cannot set DTMF mode to '%s' on channel '%s' as value is invalid.\n", value,
1575  ast_channel_name(chan));
1576  ast_channel_unlock(chan);
1577  return -1;
1578  }
1579 
1580  if (channel->session->dtmf == dtmf) {
1581  /* DTMF mode unchanged, nothing to do! */
1582  ast_channel_unlock(chan);
1583  return 0;
1584  }
1585 
1586  channel->session->dtmf = dtmf;
1587 
1589 
1590  if (media && media->rtp) {
1591  if (channel->session->dtmf == AST_SIP_DTMF_RFC_4733) {
1594  } else if (channel->session->dtmf == AST_SIP_DTMF_INFO) {
1597  } else if (channel->session->dtmf == AST_SIP_DTMF_INBAND) {
1600  } else if (channel->session->dtmf == AST_SIP_DTMF_NONE) {
1603  } else if (channel->session->dtmf == AST_SIP_DTMF_AUTO) {
1605  /* no RFC4733 negotiated, enable inband */
1607  }
1608  } else if (channel->session->dtmf == AST_SIP_DTMF_AUTO_INFO) {
1611  /* if inband, switch to INFO */
1613  }
1614  }
1615  }
1616 
1617  if (channel->session->dsp) {
1618  dsp_features = ast_dsp_get_features(channel->session->dsp);
1619  }
1620  if (channel->session->dtmf == AST_SIP_DTMF_INBAND ||
1621  channel->session->dtmf == AST_SIP_DTMF_AUTO) {
1622  dsp_features |= DSP_FEATURE_DIGIT_DETECT;
1623  } else {
1624  dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
1625  }
1626  if (dsp_features) {
1627  if (!channel->session->dsp) {
1628  if (!(channel->session->dsp = ast_dsp_new())) {
1629  ast_channel_unlock(chan);
1630  return 0;
1631  }
1632  }
1633  ast_dsp_set_features(channel->session->dsp, dsp_features);
1634  } else if (channel->session->dsp) {
1635  ast_dsp_free(channel->session->dsp);
1636  channel->session->dsp = NULL;
1637  }
1638 
1639  ast_channel_unlock(chan);
1640 
1642 }
1643 
1644 int pjsip_acf_moh_passthrough_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
1645 {
1646  struct ast_sip_channel_pvt *channel;
1647 
1648  if (!chan) {
1649  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1650  return -1;
1651  }
1652 
1653  ast_channel_lock(chan);
1654  if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1655  ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
1656  ast_channel_unlock(chan);
1657  return -1;
1658  }
1659 
1660  channel = ast_channel_tech_pvt(chan);
1661  channel->session->moh_passthrough = ast_true(value);
1662 
1663  ast_channel_unlock(chan);
1664 
1665  return 0;
1666 }
1667 
1668 static int refresh_write_cb(void *obj)
1669 {
1670  struct refresh_data *data = obj;
1671  struct session_refresh_state *state;
1672 
1674  if (!state) {
1675  return -1;
1676  }
1677 
1679  sip_session_response_cb, data->method, 1, state->media_state);
1680 
1681  state->media_state = NULL;
1682  ast_sip_session_remove_datastore(data->session, "pjsip_session_refresh");
1683 
1684  return 0;
1685 }
1686 
1687 int pjsip_acf_session_refresh_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
1688 {
1689  struct ast_sip_channel_pvt *channel;
1690  struct refresh_data rdata = {
1692  };
1693 
1694  if (!chan) {
1695  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1696  return -1;
1697  }
1698 
1699  if (ast_channel_state(chan) != AST_STATE_UP) {
1700  ast_log(LOG_WARNING, "'%s' not allowed on unanswered channel '%s'.\n", cmd, ast_channel_name(chan));
1701  return -1;
1702  }
1703 
1704  if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1705  ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
1706  return -1;
1707  }
1708 
1709  channel = ast_channel_tech_pvt(chan);
1710  rdata.session = channel->session;
1711 
1712  if (!strcmp(value, "invite")) {
1714  } else if (!strcmp(value, "update")) {
1716  }
1717 
1719 }
Access Control of various sorts.
Asterisk main include file. File version handling, generic pbx functions.
static struct ast_mansession session
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1739
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static int tmp()
Definition: bt_open.c:389
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:120
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1844
static const char type[]
Definition: chan_ooh323.c:109
#define T38_ENABLED
Definition: chan_ooh323.c:102
#define T38_DISABLED
Definition: chan_ooh323.c:101
PJSIP Channel Driver shared data structures.
enum sip_cc_notify_state state
Definition: chan_sip.c:966
General Asterisk PBX channel definitions.
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2922
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
const char * ast_channel_name(const struct ast_channel *chan)
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
#define ast_channel_unlock(chan)
Definition: channel.h:2923
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
ast_media_type
Types of media.
Definition: codec.h:30
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
@ AST_MEDIA_TYPE_UNKNOWN
Definition: codec.h:31
@ AST_MEDIA_TYPE_VIDEO
Definition: codec.h:33
Convenient Signal Processing routines.
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1773
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1748
#define DSP_FEATURE_DIGIT_DETECT
Definition: dsp.h:28
int ast_dsp_get_features(struct ast_dsp *dsp)
Get features.
Definition: dsp.c:1767
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1758
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
long int flag
Definition: f2c.h:83
Media Format API.
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
int ast_format_cap_update_by_allow_disallow(struct ast_format_cap *cap, const char *list, int allowing)
Parse an "allow" or "deny" list and modify a format capabilities structure accordingly.
Definition: format_cap.c:320
void ast_format_cap_remove_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Remove all formats matching a specific format type.
Definition: format_cap.c:523
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type)
Append the formats of provided type in src to dst.
Definition: format_cap.c:269
struct ast_format * ast_format_cap_get_best_by_type(const struct ast_format_cap *cap, enum ast_media_type type)
Get the most preferred format for a particular media type.
Definition: format_cap.c:417
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition: format_cap.c:395
static const char name[]
Definition: format_mp3.c:68
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ast_sip_push_task_wait_serializer(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to the serializer and wait for it to complete.
Definition: res_pjsip.c:2013
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
char * strsep(char **str, const char *delims)
#define AST_LOG_WARNING
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_WARNING
Asterisk module definitions.
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
Core PBX routines and definitions.
static char * func_args(char *function)
return a pointer to the arguments of the function, and terminates the function name with '\0'
int pjsip_acf_moh_passthrough_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
PJSIP_MOH_PASSTHROUGH function read callback.
int pjsip_acf_media_offer_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
PJSIP_MEDIA_OFFER function read callback.
int pjsip_acf_media_offer_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
PJSIP_MEDIA_OFFER function write callback.
static int read_pjsip(void *data)
static int refresh_write_cb(void *obj)
int pjsip_acf_dtmf_mode_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
PJSIP_DTMF_MODE function write callback.
int pjsip_acf_session_refresh_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
PJSIP_SEND_SESSION_REFRESH function write callback.
static int media_offer_read_av(struct ast_sip_session *session, char *buf, size_t len, enum ast_media_type media_type)
static int media_offer_write_av(void *obj)
static int sip_session_response_cb(struct ast_sip_session *session, pjsip_rx_data *rdata)
static int channel_read_rtp(struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
static void session_refresh_state_destroy(void *obj)
Destructor for session refresh information.
static int print_escaped_uri(struct ast_channel *chan, const char *type, pjsip_uri_context_e context, const void *uri, char *buf, size_t size)
static const char * t38state_to_string[T38_MAX_ENUM]
String representations of the T.38 state enum.
int pjsip_acf_moh_passthrough_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
PJSIP_MOH_PASSTHROUGH function write callback.
static int dtmf_mode_refresh_cb(void *obj)
static struct session_refresh_state * session_refresh_state_get_or_alloc(struct ast_sip_session *session)
Helper function which retrieves or allocates a session refresh state information datastore.
int pjsip_acf_channel_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
CHANNEL function read callback.
static int channel_read_pjsip(struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
int pjsip_acf_dtmf_mode_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
PJSIP_DTMF_MODE function read callback.
int pjsip_acf_dial_contacts_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
PJSIP_DIAL_CONTACTS function read callback.
static const struct ast_datastore_info session_refresh_datastore
Datastore for attaching session refresh state information.
int pjsip_acf_parse_uri_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
PJSIP_PARSE_URI function read callback.
static int channel_read_rtcp(struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
static int parse_uri_cb(void *data)
struct ast_sip_aor * ast_sip_location_retrieve_aor(const char *aor_name)
Retrieve a named AOR.
Definition: location.c:147
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
int ast_sip_dtmf_to_str(const enum ast_sip_dtmf_mode dtmf, char *buf, size_t buf_len)
Convert the DTMF mode enum value into a string.
Definition: res_pjsip.c:2307
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:513
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition: res_pjsip.c:2035
@ AST_SIP_CONTACT_FILTER_REACHABLE
Return only reachable or unknown contacts.
Definition: res_pjsip.h:1089
struct ao2_container * ast_sip_location_retrieve_aor_contacts_filtered(const struct ast_sip_aor *aor, unsigned int flags)
Retrieve all contacts currently available for an AOR and filter based on flags.
Definition: location.c:252
@ AST_SIP_DTMF_NONE
Definition: res_pjsip.h:429
@ AST_SIP_DTMF_AUTO_INFO
Definition: res_pjsip.h:440
@ AST_SIP_DTMF_AUTO
Definition: res_pjsip.h:438
@ AST_SIP_DTMF_INBAND
Definition: res_pjsip.h:434
@ AST_SIP_DTMF_INFO
Definition: res_pjsip.h:436
@ AST_SIP_DTMF_RFC_4733
Definition: res_pjsip.h:432
int ast_sip_str_to_dtmf(const char *dtmf_mode)
Convert the DTMF mode name into an enum.
Definition: res_pjsip.c:2336
ast_sip_session_refresh_method
Definition: res_pjsip.h:505
@ AST_SIP_SESSION_REFRESH_METHOD_UPDATE
Definition: res_pjsip.h:509
@ AST_SIP_SESSION_REFRESH_METHOD_INVITE
Definition: res_pjsip.h:507
struct ast_sip_session_media_state * ast_sip_session_media_state_alloc(void)
Allocate a session media state structure.
struct ast_datastore * ast_sip_session_get_datastore(struct ast_sip_session *session, const char *name)
Retrieve a session datastore.
int ast_sip_session_regenerate_answer(struct ast_sip_session *session, ast_sip_session_sdp_creation_cb on_sdp_creation)
Regenerate SDP Answer.
struct ast_datastore * ast_sip_session_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
Alternative for ast_datastore_alloc()
@ T38_MAX_ENUM
int ast_sip_session_add_datastore(struct ast_sip_session *session, struct ast_datastore *datastore)
Add a datastore to a SIP session.
void ast_sip_session_remove_datastore(struct ast_sip_session *session, const char *name)
Remove a session datastore from the session.
void ast_sip_session_media_state_free(struct ast_sip_session_media_state *media_state)
Free a session media state structure.
int ast_sip_session_refresh(struct ast_sip_session *session, ast_sip_session_request_creation_cb on_request_creation, ast_sip_session_sdp_creation_cb on_sdp_creation, ast_sip_session_response_cb on_response, enum ast_sip_session_refresh_method method, int generate_new_sdp, struct ast_sip_session_media_state *media_state)
Send a reinvite or UPDATE on a session.
#define NULL
Definition: resample.c:96
enum ast_rtp_dtmf_mode ast_rtp_instance_dtmf_mode_get(struct ast_rtp_instance *instance)
Get the DTMF mode of an RTP instance.
Definition: rtp_engine.c:2129
@ AST_RTP_DTMF_MODE_RFC2833
Definition: rtp_engine.h:152
@ AST_RTP_DTMF_MODE_INBAND
Definition: rtp_engine.h:154
@ AST_RTP_DTMF_MODE_NONE
Definition: rtp_engine.h:150
int ast_rtp_instance_dtmf_mode_set(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode)
Set the DTMF mode that should be used.
Definition: rtp_engine.c:2115
ast_rtp_instance_stat_field
Definition: rtp_engine.h:168
@ AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS
Definition: rtp_engine.h:174
@ AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT
Definition: rtp_engine.h:176
@ AST_RTP_INSTANCE_STAT_FIELD_QUALITY
Definition: rtp_engine.h:170
@ AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER
Definition: rtp_engine.h:172
@ AST_RTP_INSTANCE_STAT_ALL
Definition: rtp_engine.h:182
#define ast_rtp_instance_get_remote_address(instance, address)
Get the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1192
void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
Set the value of an RTP instance property.
Definition: rtp_engine.c:705
void ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the local address that we are expecting RTP on.
Definition: rtp_engine.c:643
int ast_rtp_instance_get_stats(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
Retrieve statistics about an RTP instance.
Definition: rtp_engine.c:2438
@ AST_RTP_PROPERTY_DTMF
Definition: rtp_engine.h:117
char * ast_rtp_instance_get_quality(struct ast_rtp_instance *instance, enum ast_rtp_instance_stat_field field, char *buf, size_t size)
Retrieve quality statistics about an RTP instance.
Definition: rtp_engine.c:2452
#define AST_SRTP_CRYPTO_OFFER_OK
Definition: sdp_srtp.h:45
media_type
Media types generate different "dummy answers" for not accepting the offer of a media stream....
Definition: sip.h:486
@ T38_PEER_REINVITE
Definition: sip.h:665
@ T38_LOCAL_REINVITE
Definition: sip.h:664
@ T38_REJECTED
Definition: sip.h:667
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
Media Stream API.
struct ast_stream_topology * ast_stream_topology_clone(const struct ast_stream_topology *topology)
Create a deep clone of an existing stream topology.
Definition: stream.c:667
struct ast_stream * ast_stream_topology_get_first_stream_by_type(const struct ast_stream_topology *topology, enum ast_media_type type)
Gets the first active stream of a specific type from the topology.
Definition: stream.c:964
int ast_stream_set_metadata(struct ast_stream *stream, const char *m_key, const char *value)
Set a stream metadata value.
Definition: stream.c:460
@ AST_STREAM_STATE_REMOVED
Set when the stream has been removed/declined.
Definition: stream.h:78
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps)
Set the current negotiated formats of a stream.
Definition: stream.c:365
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
const struct ast_format_cap * ast_stream_get_formats(const struct ast_stream *stream)
Get the current negotiated formats of a stream.
Definition: stream.c:330
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
Definition: strings.h:764
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1117
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:739
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: main/utils.c:2097
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:640
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:711
#define AST_YESNO(x)
return Yes or No depending on the argument.
Definition: strings.h:143
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:406
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Main Channel structure associated with a channel.
Structure for a data store type.
Definition: datastore.h:31
const char * type
Definition: datastore.h:32
Structure for a data store object.
Definition: datastore.h:64
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Definition of a media format.
Definition: format.c:43
unsigned int remote_ssrc
Definition: rtp_engine.h:424
unsigned int rxcount
Definition: rtp_engine.h:370
unsigned int local_ssrc
Definition: rtp_engine.h:422
unsigned int rxploss
Definition: rtp_engine.h:394
unsigned int txcount
Definition: rtp_engine.h:368
unsigned int txploss
Definition: rtp_engine.h:392
structure for secure RTP audio
Definition: sdp_srtp.h:38
A SIP address of record.
Definition: res_pjsip.h:376
A structure which contains a channel implementation and session.
struct ast_sip_session * session
Pointer to session.
Contact associated with an address of record.
Definition: res_pjsip.h:297
const ast_string_field aor
Definition: res_pjsip.h:319
struct ast_stream_topology * topology
Definition: res_pjsip.h:814
An entity with which Asterisk communicates.
Definition: res_pjsip.h:854
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:887
Structure which contains media state information (streams, sessions)
struct ast_stream_topology * topology
The media stream topology.
struct ast_sip_session_media * default_session[AST_MEDIA_TYPE_END]
Default media sessions for each type.
A structure containing SIP session media information.
struct ast_sdp_srtp * srtp
Holds SRTP information.
unsigned int remotely_held
Stream is on hold by remote side.
struct ast_rtp_instance * rtp
RTP instance itself.
struct ast_sockaddr direct_media_addr
Direct media address.
A structure describing a SIP session.
pjsip_uri * request_uri
struct ast_sip_endpoint * endpoint
enum ast_sip_session_t38state t38state
struct ast_channel * channel
unsigned int moh_passthrough
struct ast_sip_session_media_state * active_media_state
struct ast_sip_session_media_state * pending_media_state
struct ast_dsp * dsp
struct pjsip_inv_session * inv_session
enum ast_sip_dtmf_mode dtmf
struct ast_taskprocessor * serializer
Socket address structure.
Definition: netsock2.h:97
Support for dynamic strings.
Definition: strings.h:604
enum ast_media_type media_type
struct ast_sip_session * session
Struct used to push PJSIP_PARSE_URI function arguments to task processor.
Struct used to push function arguments to task processor.
struct ast_sip_session * session
struct ast_sip_session * session
enum ast_sip_session_refresh_method method
Session refresh state information.
struct ast_sip_session_media_state * media_state
Created proposed media state.
Transport information stored in transport_info datastore.
Definition: chan_pjsip.h:30
pj_sockaddr local_addr
Our address that received the request.
Definition: chan_pjsip.h:34
pj_sockaddr remote_addr
The address that sent the request.
Definition: chan_pjsip.h:32
int value
Definition: syslog.c:37
const char * args
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:936
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
Definition: main/utils.c:781