Asterisk - The Open Source Telephony Project  GIT-master-a1fa8df
res_pjsip_messaging.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  * Kevin Harwell <kharwell@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*** MODULEINFO
20  <depend>pjproject</depend>
21  <depend>res_pjsip</depend>
22  <depend>res_pjsip_session</depend>
23  <support_level>core</support_level>
24  ***/
25 
26 /*** DOCUMENTATION
27  <info name="MessageDestinationInfo" language="en_US" tech="PJSIP">
28  <para>The <literal>destination</literal> parameter is used to construct
29  the Request URI for an outgoing message. It can be in one of the following
30  formats, all prefixed with the <literal>pjsip:</literal> message tech.</para>
31  <para>
32  </para>
33  <enumlist>
34  <enum name="endpoint">
35  <para>Request URI comes from the endpoint's default aor and contact.</para>
36  </enum>
37  <enum name="endpoint/aor">
38  <para>Request URI comes from the specific aor/contact.</para>
39  </enum>
40  <enum name="endpoint@domain">
41  <para>Request URI from the endpoint's default aor and contact. The domain is discarded.</para>
42  </enum>
43  </enumlist>
44  <para>
45  </para>
46  <para>These all use the endpoint to send the message with the specified URI:</para>
47  <para>
48  </para>
49  <enumlist>
50  <enum name="endpoint/&lt;sip[s]:host&gt;>"/>
51  <enum name="endpoint/&lt;sip[s]:user@host&gt;"/>
52  <enum name="endpoint/&quot;display name&quot; &lt;sip[s]:host&gt;"/>
53  <enum name="endpoint/&quot;display name&quot; &lt;sip[s]:user@host&gt;"/>
54  <enum name="endpoint/sip[s]:host"/>
55  <enum name="endpoint/sip[s]:user@host"/>
56  <enum name="endpoint/host"/>
57  <enum name="endpoint/user@host"/>
58  </enumlist>
59  <para>
60  </para>
61  <para>These all use the default endpoint to send the message with the specified URI:</para>
62  <para>
63  </para>
64  <enumlist>
65  <enum name="&lt;sip[s]:host&gt;"/>
66  <enum name="&lt;sip[s]:user@host&gt;"/>
67  <enum name="&quot;display name&quot; &lt;sip[s]:host&gt;"/>
68  <enum name="&quot;display name&quot; &lt;sip[s]:user@host&gt;"/>
69  <enum name="sip[s]:host"/>
70  <enum name="sip[s]:user@host"/>
71  </enumlist>
72  <para>
73  </para>
74  <para>These use the default endpoint to send the message with the specified host:</para>
75  <para>
76  </para>
77  <enumlist>
78  <enum name="host"/>
79  <enum name="user@host"/>
80  </enumlist>
81  <para>
82  </para>
83  <para>This form is similar to a dialstring:</para>
84  <para>
85  </para>
86  <enumlist>
87  <enum name="PJSIP/user@endpoint"/>
88  </enumlist>
89  <para>
90  </para>
91  <para>You still need to prefix the destination with
92  the <literal>pjsip:</literal> message technology prefix. For example:
93  <literal>pjsip:PJSIP/8005551212@myprovider</literal>.
94  The endpoint contact's URI will have the <literal>user</literal> inserted
95  into it and will become the Request URI. If the contact URI already has
96  a user specified, it will be replaced.
97  </para>
98  <para>
99  </para>
100  </info>
101  <info name="MessageFromInfo" language="en_US" tech="PJSIP">
102  <para>The <literal>from</literal> parameter is used to specity the <literal>From:</literal>
103  header in the outgoing SIP MESSAGE. It will override the value specified in
104  MESSAGE(from) which itself will override any <literal>from</literal> value from
105  an incoming SIP MESSAGE.
106  </para>
107  <para>
108  </para>
109  </info>
110  <info name="MessageToInfo" language="en_US" tech="PJSIP">
111  <para>The <literal>to</literal> parameter is used to specity the <literal>To:</literal>
112  header in the outgoing SIP MESSAGE. It will override the value specified in
113  MESSAGE(to) which itself will override any <literal>to</literal> value from
114  an incoming SIP MESSAGE.
115  </para>
116  <para>
117  </para>
118  </info>
119  ***/
120 #include "asterisk.h"
121 
122 #include <pjsip.h>
123 #include <pjsip_ua.h>
124 
125 #include "asterisk/message.h"
126 #include "asterisk/module.h"
127 #include "asterisk/pbx.h"
128 #include "asterisk/res_pjsip.h"
130 #include "asterisk/taskprocessor.h"
131 #include "asterisk/test.h"
132 #include "asterisk/uri.h"
133 
134 const pjsip_method pjsip_message_method = {PJSIP_OTHER_METHOD, {"MESSAGE", 7} };
135 
136 #define MAX_HDR_SIZE 512
137 #define MAX_BODY_SIZE 1024
138 #define MAX_USER_SIZE 128
139 
141 
142 /*!
143  * \internal
144  * \brief Checks to make sure the request has the correct content type.
145  *
146  * \details This module supports the following media types: "text/plain".
147  * Return unsupported otherwise.
148  *
149  * \param rdata The SIP request
150  */
151 static enum pjsip_status_code check_content_type(const pjsip_rx_data *rdata)
152 {
153  int res;
154  if (rdata->msg_info.msg->body && rdata->msg_info.msg->body->len) {
156  &rdata->msg_info.msg->body->content_type, "text", "plain");
157  } else {
158  res = rdata->msg_info.ctype &&
160  &rdata->msg_info.ctype->media, "text", "plain");
161  }
162 
163  return res ? PJSIP_SC_OK : PJSIP_SC_UNSUPPORTED_MEDIA_TYPE;
164 }
165 
166 /*!
167  * \internal
168  * \brief Checks to make sure the request has the correct content type.
169  *
170  * \details This module supports the following media types: "text/\*", "application/\*".
171  * Return unsupported otherwise.
172  *
173  * \param rdata The SIP request
174  */
175 static enum pjsip_status_code check_content_type_in_dialog(const pjsip_rx_data *rdata)
176 {
177  int res = PJSIP_SC_UNSUPPORTED_MEDIA_TYPE;
178  static const pj_str_t text = { "text", 4};
179  static const pj_str_t application = { "application", 11};
180 
181  if (!(rdata->msg_info.msg->body && rdata->msg_info.msg->body->len > 0)) {
182  return res;
183  }
184 
185  /* We'll accept any text/ or application/ content type */
186  if (pj_stricmp(&rdata->msg_info.msg->body->content_type.type, &text) == 0
187  || pj_stricmp(&rdata->msg_info.msg->body->content_type.type, &application) == 0) {
188  res = PJSIP_SC_OK;
189  } else if (rdata->msg_info.ctype
190  && (pj_stricmp(&rdata->msg_info.ctype->media.type, &text) == 0
191  || pj_stricmp(&rdata->msg_info.ctype->media.type, &application) == 0)) {
192  res = PJSIP_SC_OK;
193  }
194 
195  return res;
196 }
197 
198 /*!
199  * \brief Find a contact and insert a "user@" into its URI.
200  *
201  * \param to Original destination (for error messages only)
202  * \param endpoint_name Endpoint name (for error messages only)
203  * \param aors Command separated list of AORs
204  * \param user The user to insert in the contact URI
205  * \param uri Pointer to buffer in which to return the URI
206  *
207  * \return 0 Success
208  * \return -1 Fail
209  *
210  * \note If the contact URI found for the endpoint already has a user in
211  * its URI, it will be replaced.
212  */
213 static int insert_user_in_contact_uri(const char *to, const char *endpoint_name, const char *aors,
214  const char *user, char **uri)
215 {
216  char *scheme = NULL;
217  char *contact_uri = NULL;
218  char *after_scheme = NULL;
219  char *host;
220  struct ast_sip_contact *contact = NULL;
221 
222 
224  if (!contact) {
225  /*
226  * We're getting the contact using the same method as
227  * ast_sip_create_request() so if there's no contact
228  * we can never send this message.
229  */
230  ast_log(LOG_WARNING, "Dest: '%s' MSG SEND FAIL: Couldn't find contact for endpoint '%s'\n",
231  to, endpoint_name);
232  return -1;
233  }
234 
235  contact_uri = ast_strdupa(contact->uri);
236  ao2_cleanup(contact);
237 
238  ast_debug(3, "Dest: '%s' User: '%s' Endpoint: '%s' ContactURI: '%s'\n", to, user, endpoint_name, contact_uri);
239 
240  /*
241  * Contact URIs must have a scheme so we must insert the user between it and the host.
242  */
243  scheme = contact_uri;
244  after_scheme = strchr(contact_uri, ':');
245  if (!after_scheme) {
246  /* A contact URI without a scheme? Something's wrong. Bail */
247  ast_log(LOG_WARNING, "Dest: '%s' MSG SEND FAIL: There was no scheme in the contact URI '%s'\n",
248  to, contact_uri);
249  return -1;
250  }
251  /*
252  * Terminate the scheme.
253  */
254  *after_scheme = '\0';
255  after_scheme++;
256 
257  /*
258  * If the contact_uri already has a user, the host starts after the '@', otherwise
259  * the host is at after_scheme.
260  *
261  * We're going to ignore the existing user.
262  */
263  host = strchr(after_scheme, '@');
264  if (host) {
265  host++;
266  } else {
267  host = after_scheme;
268  }
269 
270  *uri = ast_malloc(strlen(scheme) + strlen(user) + strlen(host) + 3 /* One for the ':', '@' and terminating NULL */);
271  sprintf(*uri, "%s:%s@%s", scheme, user, host); /* Safe */
272 
273  return 0;
274 }
275 
276 /*!
277  * \internal
278  * \brief Get endpoint and URI when the destination is only a single token
279  *
280  * "to" could be one of the following:
281  * endpoint_name
282  * hostname
283  *
284  * \param to Destination specified in MessageSend
285  * \param uri Pointer to URI variable. Must be freed by caller
286  * \return endpoint
287  */
288 static struct ast_sip_endpoint *handle_single_token(const char *to, char *destination, char **uri) {
289  char *endpoint_name = NULL;
290  struct ast_sip_endpoint *endpoint = NULL;
291  struct ast_sip_contact *contact = NULL;
292 
293  /*
294  * If "to" is just one token, it could be an endpoint name
295  * or a hostname without a scheme.
296  */
297 
298  endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", destination);
299  if (!endpoint) {
300  /*
301  * We can only assume it's a hostname.
302  */
303  char *temp_uri = ast_malloc(strlen(destination) + strlen("sip:") + 1);
304  sprintf(temp_uri, "sip:%s", destination);
305  *uri = temp_uri;
307  ast_debug(3, "Dest: '%s' Didn't find endpoint so adding scheme and using URI '%s' with default endpoint\n",
308  to, *uri);
309  return endpoint;
310  }
311 
312  /*
313  * It's an endpoint
314  */
315 
316  endpoint_name = destination;
318  if (!contact) {
319  /*
320  * We're getting the contact using the same method as
321  * ast_sip_create_request() so if there's no contact
322  * we can never send this message.
323  */
324  ast_log(LOG_WARNING, "Dest: '%s' MSG SEND FAIL: Found endpoint '%s' but didn't find an aor/contact for it\n",
325  to, endpoint_name);
326  ao2_cleanup(endpoint);
327  *uri = NULL;
328  return NULL;
329  }
330 
331  *uri = ast_strdup(contact->uri);
332  ast_debug(3, "Dest: '%s' Found endpoint '%s' and found contact with URI '%s'\n",
333  to, endpoint_name, *uri);
334  ao2_cleanup(contact);
335  return endpoint;
336 
337 }
338 
339 /*!
340  * \internal
341  * \brief Get endpoint and URI when the destination contained a '/'
342  *
343  * "to" could be one of the following:
344  * endpoint/aor
345  * endpoint/<sip[s]:host>
346  * endpoint/<sip[s]:user@host>
347  * endpoint/"Bob" <sip[s]:host>
348  * endpoint/"Bob" <sip[s]:user@host>
349  * endpoint/sip[s]:host
350  * endpoint/sip[s]:user@host
351  * endpoint/host
352  * endpoint/user@host
353  *
354  * \param to Destination specified in MessageSend
355  * \param uri Pointer to URI variable. Must be freed by caller
356  * \return endpoint
357  */
358 static struct ast_sip_endpoint *handle_slash(const char *to, char *destination, char **uri,
359  char *slash, char *atsign, char *scheme)
360 {
361  char *endpoint_name = NULL;
362  struct ast_sip_endpoint *endpoint = NULL;
363  struct ast_sip_contact *contact = NULL;
364  char *user = NULL;
365  char *afterslash = slash + 1;
366  struct ast_sip_aor *aor;
367 
368  if (ast_begins_with(destination, "PJSIP/")) {
369  ast_debug(3, "Dest: '%s' Dialplan format'\n", to);
370  /*
371  * This has to be the form PJSIP/user@endpoint
372  */
373  if (!atsign || strchr(afterslash, '/')) {
374  /*
375  * If there's no "user@" or there's a slash somewhere after
376  * "PJSIP/" then we go no further.
377  */
378  *uri = NULL;
380  "Dest: '%s' MSG SEND FAIL: Destinations beginning with 'PJSIP/' must be in the form of 'PJSIP/user@endpoint'\n",
381  to);
382  return NULL;
383  }
384  *atsign = '\0';
385  user = afterslash;
386  endpoint_name = atsign + 1;
387  ast_debug(3, "Dest: '%s' User: '%s' Endpoint: '%s'\n", to, user, endpoint_name);
388  } else {
389  /*
390  * Either...
391  * endpoint/aor
392  * endpoint/uri
393  */
394  *slash = '\0';
395  endpoint_name = destination;
396  ast_debug(3, "Dest: '%s' Endpoint: '%s'\n", to, endpoint_name);
397  }
398 
399  endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", endpoint_name);
400  if (!endpoint) {
401  *uri = NULL;
402  ast_log(LOG_WARNING, "Dest: '%s' MSG SEND FAIL: Didn't find endpoint with name '%s'\n",
403  to, endpoint_name);
404  return NULL;
405  }
406 
407  if (scheme) {
408  /*
409  * If we found a scheme, then everything after the slash MUST be a URI.
410  * We don't need to do any further modification.
411  */
412  *uri = ast_strdup(afterslash);
413  ast_debug(3, "Dest: '%s' Found endpoint '%s' and found URI '%s' after '/'\n",
414  to, endpoint_name, *uri);
415  return endpoint;
416  }
417 
418  if (user) {
419  /*
420  * This has to be the form PJSIP/user@endpoint
421  */
422  int rc;
423 
424  /*
425  * Set the return URI to be the endpoint's contact URI with the user
426  * portion set to the user that was specified before the endpoint name.
427  */
428  rc = insert_user_in_contact_uri(to, endpoint_name, endpoint->aors, user, uri);
429  if (rc != 0) {
430  /*
431  * insert_user_in_contact_uri prints the warning message.
432  */
433  ao2_cleanup(endpoint);
434  endpoint = NULL;
435  *uri = NULL;
436  }
437  ast_debug(3, "Dest: '%s' User: '%s' Endpoint: '%s' URI: '%s'\n", to, user,
438  endpoint_name, *uri);
439 
440  return endpoint;
441  }
442 
443  /*
444  * We're now left with two possibilities...
445  * endpoint/aor
446  * endpoint/uri-without-scheme
447  */
448  aor = ast_sip_location_retrieve_aor(afterslash);
449  if (!aor) {
450  /*
451  * It's probably a URI without a scheme but we don't have a way to tell
452  * for sure. We're going to assume it is and prepend it with a scheme.
453  */
454  *uri = ast_malloc(strlen(afterslash) + strlen("sip:") + 1);
455  sprintf(*uri, "sip:%s", afterslash);
456  ast_debug(3, "Dest: '%s' Found endpoint '%s' but didn't find aor after '/' so using URI '%s'\n",
457  to, endpoint_name, *uri);
458  return endpoint;
459  }
460 
461  /*
462  * Only one possibility left... There was an aor name after the slash.
463  */
464  ast_debug(3, "Dest: '%s' Found endpoint '%s' and found aor '%s' after '/'\n",
465  to, endpoint_name, ast_sorcery_object_get_id(aor));
466 
468  if (!contact) {
469  /*
470  * An aor without a contact is useless and since
471  * ast_sip_create_message() won't be able to find one
472  * either, we just need to bail.
473  */
474  ast_log(LOG_WARNING, "Dest: '%s' MSG SEND FAIL: Found endpoint '%s' but didn't find contact for aor '%s'\n",
475  to, endpoint_name, ast_sorcery_object_get_id(aor));
476  ao2_cleanup(aor);
477  ao2_cleanup(endpoint);
478  *uri = NULL;
479  return NULL;
480  }
481 
482  *uri = ast_strdup(contact->uri);
483  ast_debug(3, "Dest: '%s' Found endpoint '%s' and found contact with URI '%s' for aor '%s'\n",
484  to, endpoint_name, *uri, ast_sorcery_object_get_id(aor));
485  ao2_cleanup(contact);
486  ao2_cleanup(aor);
487 
488  return endpoint;
489 }
490 
491 /*!
492  * \internal
493  * \brief Get endpoint and URI when the destination contained a '@' but no '/' or scheme
494  *
495  * "to" could be one of the following:
496  * <sip[s]:user@host>
497  * "Bob" <sip[s]:user@host>
498  * sip[s]:user@host
499  * user@host
500  *
501  * \param to Destination specified in MessageSend
502  * \param uri Pointer to URI variable. Must be freed by caller
503  * \return endpoint
504  */
505 static struct ast_sip_endpoint *handle_atsign(const char *to, char *destination, char **uri,
506  char *slash, char *atsign, char *scheme)
507 {
508  char *endpoint_name = NULL;
509  struct ast_sip_endpoint *endpoint = NULL;
510  struct ast_sip_contact *contact = NULL;
511  char *afterat = atsign + 1;
512 
513  *atsign = '\0';
514  endpoint_name = destination;
515 
516  /* Apprently there may be ';<user_options>' after the endpoint name ??? */
518  endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", endpoint_name);
519  if (!endpoint) {
520  /*
521  * It's probably a uri with a user but without a scheme but we don't have a way to tell.
522  * We're going to assume it is and prepend it with a scheme.
523  */
524  *uri = ast_malloc(strlen(to) + strlen("sip:") + 1);
525  sprintf(*uri, "sip:%s", to);
527  ast_debug(3, "Dest: '%s' Didn't find endpoint before the '@' so using URI '%s' with default endpoint\n",
528  to, *uri);
529  return endpoint;
530  }
531 
532  /*
533  * OK, it's an endpoint and a domain (which we ignore)
534  */
536  if (!contact) {
537  /*
538  * We're getting the contact using the same method as
539  * ast_sip_create_request() so if there's no contact
540  * we can never send this message.
541  */
542  ao2_cleanup(endpoint);
543  endpoint = NULL;
544  *uri = NULL;
545  ast_log(LOG_WARNING, "Dest: '%s' MSG SEND FAIL: Found endpoint '%s' but didn't find contact\n",
546  to, endpoint_name);
547  return NULL;
548  }
549 
550  *uri = ast_strdup(contact->uri);
551  ao2_cleanup(contact);
552  ast_debug(3, "Dest: '%s' Found endpoint '%s' and found contact with URI '%s' (discarding domain %s)\n",
553  to, endpoint_name, *uri, afterat);
554 
555  return endpoint;
556 }
557 
558 /*!
559  * \internal
560  * \brief Retrieves an endpoint and URI from the "to" string.
561  *
562  * This URI is used as the Request URI.
563  *
564  * Expects the given 'to' to be in one of the following formats:
565  * Why we allow so many is a mystery.
566  *
567  * Basic:
568  * endpoint - We'll get URI from the default aor/contact
569  * endpoint/aor - We'll get the URI from the specific aor/contact
570  * endpoint@domain - We toss the domain part and just use the endpoint
571  *
572  * These all use the endpoint and specified URI:
573  * endpoint/<sip[s]:host>
574  * endpoint/<sip[s]:user@host>
575  * endpoint/"Bob" <sip[s]:host>
576  * endpoint/"Bob" <sip[s]:user@host>
577  * endpoint/sip[s]:host
578  * endpoint/sip[s]:user@host
579  * endpoint/host
580  * endpoint/user@host
581  *
582  * These all use the default endpoint and specified URI:
583  * <sip[s]:host>
584  * <sip[s]:user@host>
585  * "Bob" <sip[s]:host>
586  * "Bob" <sip[s]:user@host>
587  * sip[s]:host
588  * sip[s]:user@host
589  *
590  * These use the default endpoint and specified host:
591  * host
592  * user@host
593  *
594  * This form is similar to a dialstring:
595  * PJSIP/user@endpoint
596  * In this case, the user will be added to the endpoint contact's URI.
597  * If the contact URI already has a user, it will be replaced.
598  *
599  * The ones that have the sip[s] scheme are the easiest to parse.
600  * The rest all have some issue.
601  *
602  * endpoint vs host : We have to test for endpoint first
603  * endpoint/aor vs endpoint/host : We have to test for aor first
604  * What if there's an aor with the same
605  * name as the host?
606  * endpoint@domain vs user@host : We have to test for endpoint first.
607  * What if there's an endpoint with the
608  * same name as the user?
609  *
610  * \param to 'To' field with possible endpoint
611  * \param uri Pointer to a char* which will be set to the URI.
612  * Must be ast_free'd by the caller.
613  *
614  * \note The logic below could probably be condensed but then it wouldn't be
615  * as clear.
616  */
617 static struct ast_sip_endpoint *get_outbound_endpoint(const char *to, char **uri)
618 {
619  char *destination;
620  char *slash = NULL;
621  char *atsign = NULL;
622  char *scheme = NULL;
623  struct ast_sip_endpoint *endpoint = NULL;
624 
625  destination = ast_strdupa(to);
626  slash = strchr(destination, '/');
627  atsign = strchr(destination, '@');
628  scheme = S_OR(strstr(destination, "sip:"), strstr(destination, "sips:"));
629 
630  if (!slash && !atsign && !scheme) {
631  /*
632  * If there's only a single token, it can be either...
633  * endpoint
634  * host
635  */
636  return handle_single_token(to, destination, uri);
637  }
638 
639  if (slash) {
640  /*
641  * If there's a '/', then the form must be one of the following...
642  * PJSIP/user@endpoint
643  * endpoint/aor
644  * endpoint/uri
645  */
646  return handle_slash(to, destination, uri, slash, atsign, scheme);
647  }
648 
649  if (!endpoint && atsign && !scheme) {
650  /*
651  * If there's an '@' but no scheme then it's either following an endpoint name
652  * and being followed by a domain name (which we discard).
653  * OR is's a user@host uri without a scheme. It's probably the latter but because
654  * endpoint@domain looks just like user@host, we'll test for endpoint first.
655  */
656  return handle_atsign(to, destination, uri, slash, atsign, scheme);
657  }
658 
659  /*
660  * If all else fails, we assume it's a URI or just a hostname.
661  */
662  if (scheme) {
663  *uri = ast_strdup(destination);
664  ast_debug(3, "Dest: '%s' Didn't find an endpoint but did find a scheme so using URI '%s' with default endpoint\n",
665  to, *uri);
666  } else {
667  *uri = ast_malloc(strlen(destination) + strlen("sip:") + 1);
668  sprintf(*uri, "sip:%s", destination);
669  ast_debug(3, "Dest: '%s' Didn't find an endpoint and didn't find scheme so adding scheme and using URI '%s' with default endpoint\n",
670  to, *uri);
671  }
673 
674  return endpoint;
675 }
676 
677 /*!
678  * \internal
679  * \brief Replace the To URI in the tdata with the supplied one
680  *
681  * \param tdata the outbound message data structure
682  * \param to URI to replace the To URI with
683  *
684  * \return 0: success, -1: failure
685  */
686 static int update_to_uri(pjsip_tx_data *tdata, char *to)
687 {
688  pjsip_name_addr *parsed_name_addr;
689  pjsip_sip_uri *sip_uri;
690  pjsip_name_addr *tdata_name_addr;
691  pjsip_sip_uri *tdata_sip_uri;
692  char *buf = NULL;
693 #define DEBUG_BUF_SIZE 256
694 
695  parsed_name_addr = (pjsip_name_addr *) pjsip_parse_uri(tdata->pool, to, strlen(to),
696  PJSIP_PARSE_URI_AS_NAMEADDR);
697 
698  if (!parsed_name_addr || (!PJSIP_URI_SCHEME_IS_SIP(parsed_name_addr->uri)
699  && !PJSIP_URI_SCHEME_IS_SIPS(parsed_name_addr->uri))) {
700  ast_log(LOG_WARNING, "To address '%s' is not a valid SIP/SIPS URI\n", to);
701  return -1;
702  }
703 
704  sip_uri = pjsip_uri_get_uri(parsed_name_addr->uri);
705  if (DEBUG_ATLEAST(3)) {
706  buf = ast_alloca(DEBUG_BUF_SIZE);
707  pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, sip_uri, buf, DEBUG_BUF_SIZE);
708  ast_debug(3, "Parsed To: %.*s %s\n", (int)parsed_name_addr->display.slen,
709  parsed_name_addr->display.ptr, buf);
710  }
711 
712  tdata_name_addr = (pjsip_name_addr *) PJSIP_MSG_TO_HDR(tdata->msg)->uri;
713  if (!tdata_name_addr || (!PJSIP_URI_SCHEME_IS_SIP(tdata_name_addr->uri)
714  && !PJSIP_URI_SCHEME_IS_SIPS(tdata_name_addr->uri))) {
715  /* Highly unlikely but we have to check */
716  ast_log(LOG_WARNING, "tdata To address '%s' is not a valid SIP/SIPS URI\n", to);
717  return -1;
718  }
719 
720  tdata_sip_uri = pjsip_uri_get_uri(tdata_name_addr->uri);
721  if (DEBUG_ATLEAST(3)) {
722  buf[0] = '\0';
723  pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, buf, DEBUG_BUF_SIZE);
724  ast_debug(3, "Original tdata To: %.*s %s\n", (int)tdata_name_addr->display.slen,
725  tdata_name_addr->display.ptr, buf);
726  }
727 
728  /* Replace the uri */
729  pjsip_sip_uri_assign(tdata->pool, tdata_sip_uri, sip_uri);
730  /* The display name isn't part of the URI so we need to replace it separately */
731  pj_strdup(tdata->pool, &tdata_name_addr->display, &parsed_name_addr->display);
732 
733  if (DEBUG_ATLEAST(3)) {
734  buf[0] = '\0';
735  pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, buf, 256);
736  ast_debug(3, "New tdata To: %.*s %s\n", (int)tdata_name_addr->display.slen,
737  tdata_name_addr->display.ptr, buf);
738  }
739 
740  return 0;
741 #undef DEBUG_BUF_SIZE
742 }
743 
744 /*!
745  * \internal
746  * \brief Update the display name in the To uri in the tdata with the one from the supplied uri
747  *
748  * \param tdata the outbound message data structure
749  * \param to uri containing the display name to replace in the the To uri
750  *
751  * \return 0: success, -1: failure
752  */
753 static int update_to_display_name(pjsip_tx_data *tdata, char *to)
754 {
755  pjsip_name_addr *parsed_name_addr;
756 
757  parsed_name_addr = (pjsip_name_addr *) pjsip_parse_uri(tdata->pool, to, strlen(to),
758  PJSIP_PARSE_URI_AS_NAMEADDR);
759 
760  if (parsed_name_addr) {
761  if (pj_strlen(&parsed_name_addr->display)) {
762  pjsip_name_addr *name_addr =
763  (pjsip_name_addr *) PJSIP_MSG_TO_HDR(tdata->msg)->uri;
764 
765  pj_strdup(tdata->pool, &name_addr->display, &parsed_name_addr->display);
766 
767  }
768  return 0;
769  }
770 
771  return -1;
772 }
773 
774 /*!
775  * \internal
776  * \brief Overwrite fields in the outbound 'From' header
777  *
778  * The outbound 'From' header is created/added in ast_sip_create_request with
779  * default data. If available that data may be info specified in the 'from_user'
780  * and 'from_domain' options found on the endpoint. That information will be
781  * overwritten with data in the given 'from' parameter.
782  *
783  * \param tdata the outbound message data structure
784  * \param from info to copy into the header
785  *
786  * \return 0: success, -1: failure
787  */
788 static int update_from(pjsip_tx_data *tdata, char *from)
789 {
790  pjsip_name_addr *name_addr;
791  pjsip_sip_uri *uri;
792  pjsip_name_addr *parsed_name_addr;
793 
794  if (ast_strlen_zero(from)) {
795  return 0;
796  }
797 
798  name_addr = (pjsip_name_addr *) PJSIP_MSG_FROM_HDR(tdata->msg)->uri;
799  uri = pjsip_uri_get_uri(name_addr);
800 
801  parsed_name_addr = (pjsip_name_addr *) pjsip_parse_uri(tdata->pool, from,
802  strlen(from), PJSIP_PARSE_URI_AS_NAMEADDR);
803  if (parsed_name_addr) {
804  pjsip_sip_uri *parsed_uri;
805 
806  if (!PJSIP_URI_SCHEME_IS_SIP(parsed_name_addr->uri)
807  && !PJSIP_URI_SCHEME_IS_SIPS(parsed_name_addr->uri)) {
808  ast_log(LOG_WARNING, "From address '%s' is not a valid SIP/SIPS URI\n", from);
809  return -1;
810  }
811 
812  parsed_uri = pjsip_uri_get_uri(parsed_name_addr->uri);
813 
814  if (pj_strlen(&parsed_name_addr->display)) {
815  pj_strdup(tdata->pool, &name_addr->display, &parsed_name_addr->display);
816  }
817 
818  /* Unlike the To header, we only want to replace the user, host and port */
819  pj_strdup(tdata->pool, &uri->user, &parsed_uri->user);
820  pj_strdup(tdata->pool, &uri->host, &parsed_uri->host);
821  uri->port = parsed_uri->port;
822 
823  return 0;
824  } else {
825  /* assume it is 'user[@domain]' format */
826  char *domain = strchr(from, '@');
827 
828  if (domain) {
829  pj_str_t pj_from;
830 
831  pj_strset3(&pj_from, from, domain);
832  pj_strdup(tdata->pool, &uri->user, &pj_from);
833 
834  pj_strdup2(tdata->pool, &uri->host, domain + 1);
835  } else {
836  pj_strdup2(tdata->pool, &uri->user, from);
837  }
838 
839  return 0;
840  }
841 
842  return -1;
843 }
844 
845 /*!
846  * \internal
847  * \brief Checks if the given msg var name should be blocked.
848  *
849  * \details Some headers are not allowed to be overriden by the user.
850  * Determine if the given var header name from the user is blocked for
851  * an outgoing MESSAGE.
852  *
853  * \param name name of header to see if it is blocked.
854  *
855  * \retval TRUE if the given header is blocked.
856  */
857 static int is_msg_var_blocked(const char *name)
858 {
859  int i;
860 
861  /* Don't block the Max-Forwards header because the user can override it */
862  static const char *hdr[] = {
863  "To",
864  "From",
865  "Via",
866  "Route",
867  "Contact",
868  "Call-ID",
869  "CSeq",
870  "Allow",
871  "Content-Length",
872  "Content-Type",
873  "Request-URI",
874  };
875 
876  for (i = 0; i < ARRAY_LEN(hdr); ++i) {
877  if (!strcasecmp(name, hdr[i])) {
878  /* Block addition of this header. */
879  return 1;
880  }
881  }
882  return 0;
883 }
884 
885 /*!
886  * \internal
887  * \brief Copies any other msg vars over to the request headers.
888  *
889  * \param msg The msg structure to copy headers from
890  * \param tdata The SIP transmission data
891  */
892 static enum pjsip_status_code vars_to_headers(const struct ast_msg *msg, pjsip_tx_data *tdata)
893 {
894  const char *name;
895  const char *value;
896  int max_forwards;
897  struct ast_msg_var_iterator *iter;
898 
899  for (iter = ast_msg_var_iterator_init(msg);
900  ast_msg_var_iterator_next(msg, iter, &name, &value);
902  if (!strcasecmp(name, "Max-Forwards")) {
903  /* Decrement Max-Forwards for SIP loop prevention. */
904  if (sscanf(value, "%30d", &max_forwards) != 1 || --max_forwards == 0) {
906  ast_log(LOG_NOTICE, "MESSAGE(Max-Forwards) reached zero. MESSAGE not sent.\n");
907  return -1;
908  }
909  sprintf((char *) value, "%d", max_forwards);
910  ast_sip_add_header(tdata, name, value);
911  } else if (!is_msg_var_blocked(name)) {
912  ast_sip_add_header(tdata, name, value);
913  }
914  }
916 
917  return PJSIP_SC_OK;
918 }
919 
920 /*!
921  * \internal
922  * \brief Copies any other request header data over to ast_msg structure.
923  *
924  * \param rdata The SIP request
925  * \param msg The msg structure to copy headers into
926  */
927 static int headers_to_vars(const pjsip_rx_data *rdata, struct ast_msg *msg)
928 {
929  char *c;
930  char name[MAX_HDR_SIZE];
931  char buf[MAX_HDR_SIZE];
932  int res = 0;
933  pjsip_hdr *h = rdata->msg_info.msg->hdr.next;
934  pjsip_hdr *end= &rdata->msg_info.msg->hdr;
935 
936  while (h != end) {
937  if ((res = pjsip_hdr_print_on(h, buf, sizeof(buf)-1)) > 0) {
938  buf[res] = '\0';
939  if ((c = strchr(buf, ':'))) {
940  ast_copy_string(buf, ast_skip_blanks(c + 1), sizeof(buf));
941  }
942 
943  ast_copy_pj_str(name, &h->name, sizeof(name));
944  if ((res = ast_msg_set_var(msg, name, buf)) != 0) {
945  break;
946  }
947  }
948  h = h->next;
949  }
950  return 0;
951 }
952 
953 /*!
954  * \internal
955  * \brief Prints the message body into the given char buffer.
956  *
957  * \details Copies body content from the received data into the given
958  * character buffer removing any extra carriage return/line feeds.
959  *
960  * \param rdata The SIP request
961  * \param buf Buffer to fill
962  * \param len The length of the buffer
963  */
964 static int print_body(pjsip_rx_data *rdata, char *buf, int len)
965 {
966  int res;
967 
968  if (!rdata->msg_info.msg->body || !rdata->msg_info.msg->body->len) {
969  return 0;
970  }
971 
972  if ((res = rdata->msg_info.msg->body->print_body(
973  rdata->msg_info.msg->body, buf, len)) < 0) {
974  return res;
975  }
976 
977  /* remove any trailing carriage return/line feeds */
978  while (res > 0 && ((buf[--res] == '\r') || (buf[res] == '\n')));
979 
980  buf[++res] = '\0';
981 
982  return res;
983 }
984 
985 /*!
986  * \internal
987  * \brief Converts a 'sip:' uri to a 'pjsip:' so it can be found by
988  * the message tech.
989  *
990  * \param buf uri to insert 'pjsip' into
991  * \param size length of the uri in buf
992  * \param capacity total size of buf
993  */
994 static char *sip_to_pjsip(char *buf, int size, int capacity)
995 {
996  int count;
997  const char *scheme;
998  char *res = buf;
999 
1000  /* remove any wrapping brackets */
1001  if (*buf == '<') {
1002  ++buf;
1003  --size;
1004  }
1005 
1006  scheme = strncmp(buf, "sip", 3) ? "pjsip:" : "pj";
1007  count = strlen(scheme);
1008  if (count + size >= capacity) {
1009  ast_log(LOG_WARNING, "Unable to handle MESSAGE- incoming uri "
1010  "too large for given buffer\n");
1011  return NULL;
1012  }
1013 
1014  memmove(res + count, buf, size);
1015  memcpy(res, scheme, count);
1016 
1017  buf += size - 1;
1018  if (*buf == '>') {
1019  *buf = '\0';
1020  }
1021 
1022  return res;
1023 }
1024 
1025 /*!
1026  * \internal
1027  * \brief Converts a pjsip_rx_data structure to an ast_msg structure.
1028  *
1029  * \details Attempts to fill in as much information as possible into the given
1030  * msg structure copied from the given request data.
1031  *
1032  * \param rdata The SIP request
1033  * \param msg The asterisk message structure to fill in.
1034  */
1035 static enum pjsip_status_code rx_data_to_ast_msg(pjsip_rx_data *rdata, struct ast_msg *msg)
1036 {
1037  RAII_VAR(struct ast_sip_endpoint *, endpt, NULL, ao2_cleanup);
1038  pjsip_uri *ruri = rdata->msg_info.msg->line.req.uri;
1039  pjsip_sip_uri *sip_ruri;
1040  pjsip_name_addr *name_addr;
1041  char buf[MAX_BODY_SIZE];
1042  const char *field;
1043  const char *context;
1044  char exten[AST_MAX_EXTENSION];
1045  int res = 0;
1046  int size;
1047 
1048  if (!PJSIP_URI_SCHEME_IS_SIP(ruri) && !PJSIP_URI_SCHEME_IS_SIPS(ruri)) {
1049  return PJSIP_SC_UNSUPPORTED_URI_SCHEME;
1050  }
1051 
1052  sip_ruri = pjsip_uri_get_uri(ruri);
1053  ast_copy_pj_str(exten, &sip_ruri->user, AST_MAX_EXTENSION);
1054 
1055  /*
1056  * We may want to match in the dialplan without any user
1057  * options getting in the way.
1058  */
1060 
1061  endpt = ast_pjsip_rdata_get_endpoint(rdata);
1062  ast_assert(endpt != NULL);
1063 
1064  context = S_OR(endpt->message_context, endpt->context);
1065  res |= ast_msg_set_context(msg, "%s", context);
1066  res |= ast_msg_set_exten(msg, "%s", exten);
1067 
1068  /* to header */
1069  name_addr = (pjsip_name_addr *)rdata->msg_info.to->uri;
1070  size = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, name_addr, buf, sizeof(buf) - 1);
1071  if (size <= 0) {
1072  return PJSIP_SC_INTERNAL_SERVER_ERROR;
1073  }
1074  buf[size] = '\0';
1075  res |= ast_msg_set_to(msg, "%s", sip_to_pjsip(buf, ++size, sizeof(buf) - 1));
1076 
1077  /* from header */
1078  name_addr = (pjsip_name_addr *)rdata->msg_info.from->uri;
1079  size = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, name_addr, buf, sizeof(buf) - 1);
1080  if (size <= 0) {
1081  return PJSIP_SC_INTERNAL_SERVER_ERROR;
1082  }
1083  buf[size] = '\0';
1084  res |= ast_msg_set_from(msg, "%s", buf);
1085 
1086  field = pj_sockaddr_print(&rdata->pkt_info.src_addr, buf, sizeof(buf) - 1, 3);
1087  res |= ast_msg_set_var(msg, "PJSIP_RECVADDR", field);
1088 
1089  switch (rdata->tp_info.transport->key.type) {
1090  case PJSIP_TRANSPORT_UDP:
1091  case PJSIP_TRANSPORT_UDP6:
1092  field = "udp";
1093  break;
1094  case PJSIP_TRANSPORT_TCP:
1095  case PJSIP_TRANSPORT_TCP6:
1096  field = "tcp";
1097  break;
1098  case PJSIP_TRANSPORT_TLS:
1099  case PJSIP_TRANSPORT_TLS6:
1100  field = "tls";
1101  break;
1102  default:
1103  field = rdata->tp_info.transport->type_name;
1104  }
1105  ast_msg_set_var(msg, "PJSIP_TRANSPORT", field);
1106 
1107  if (print_body(rdata, buf, sizeof(buf) - 1) > 0) {
1108  res |= ast_msg_set_body(msg, "%s", buf);
1109  }
1110 
1111  /* endpoint name */
1112  res |= ast_msg_set_tech(msg, "%s", "PJSIP");
1113  res |= ast_msg_set_endpoint(msg, "%s", ast_sorcery_object_get_id(endpt));
1114  if (endpt->id.self.name.valid) {
1115  res |= ast_msg_set_var(msg, "PJSIP_ENDPOINT", endpt->id.self.name.str);
1116  }
1117 
1118  res |= headers_to_vars(rdata, msg);
1119 
1120  return !res ? PJSIP_SC_OK : PJSIP_SC_INTERNAL_SERVER_ERROR;
1121 }
1122 
1123 struct msg_data {
1124  struct ast_msg *msg;
1126  char *from;
1127 };
1128 
1129 static void msg_data_destroy(void *obj)
1130 {
1131  struct msg_data *mdata = obj;
1132 
1133  ast_free(mdata->from);
1134  ast_free(mdata->destination);
1135 
1136  ast_msg_destroy(mdata->msg);
1137 }
1138 
1139 static struct msg_data *msg_data_create(const struct ast_msg *msg, const char *destination, const char *from)
1140 {
1141  char *uri_params;
1142  struct msg_data *mdata = ao2_alloc(sizeof(*mdata), msg_data_destroy);
1143 
1144  if (!mdata) {
1145  return NULL;
1146  }
1147 
1148  /* typecast to suppress const warning */
1149  mdata->msg = ast_msg_ref((struct ast_msg *) msg);
1150 
1151  /* To starts with 'pjsip:' which needs to be removed. */
1152  if (!(destination = strchr(destination, ':'))) {
1153  ao2_ref(mdata, -1);
1154  return NULL;
1155  }
1156  ++destination;/* Now skip the ':' */
1157 
1158  mdata->destination = ast_strdup(destination);
1159  mdata->from = ast_strdup(from);
1160 
1161  /*
1162  * Sometimes from URI can contain URI parameters, so remove them.
1163  *
1164  * sip:user;user-options@domain;uri-parameters
1165  */
1166  uri_params = strchr(mdata->from, '@');
1167  if (uri_params && (uri_params = strchr(mdata->from, ';'))) {
1168  *uri_params = '\0';
1169  }
1170  return mdata;
1171 }
1172 
1173 static void update_content_type(pjsip_tx_data *tdata, struct ast_msg *msg, struct ast_sip_body *body)
1174 {
1175  static const pj_str_t CONTENT_TYPE = { "Content-Type", sizeof("Content-Type") - 1 };
1176 
1177  const char *content_type = ast_msg_get_var(msg, pj_strbuf(&CONTENT_TYPE));
1178  if (content_type) {
1179  pj_str_t type, subtype;
1180  pjsip_ctype_hdr *parsed;
1181 
1182  /* Let pjsip do the parsing for us */
1183  parsed = pjsip_parse_hdr(tdata->pool, &CONTENT_TYPE,
1184  ast_strdupa(content_type), strlen(content_type),
1185  NULL);
1186 
1187  if (!parsed) {
1188  ast_log(LOG_WARNING, "Failed to parse '%s' as a content type. Using text/plain\n",
1189  content_type);
1190  return;
1191  }
1192 
1193  /* We need to turn type and subtype into zero-terminated strings */
1194  pj_strdup_with_null(tdata->pool, &type, &parsed->media.type);
1195  pj_strdup_with_null(tdata->pool, &subtype, &parsed->media.subtype);
1196 
1197  body->type = pj_strbuf(&type);
1198  body->subtype = pj_strbuf(&subtype);
1199  }
1200 }
1201 
1202 /*!
1203  * \internal
1204  * \brief Send a MESSAGE
1205  *
1206  * \param mdata The outbound message data structure
1207  *
1208  * \return 0: success, -1: failure
1209  *
1210  * mdata contains the To and From specified in the call to the MessageSend
1211  * dialplan app. It also contains the ast_msg object that contains the
1212  * message body and may contain the To and From from the channel datastore,
1213  * usually set with the MESSAGE or MESSAGE_DATA dialplan functions but
1214  * could also come from an incoming sip MESSAGE.
1215  *
1216  * The mdata->to is always used as the basis for the Request URI
1217  * while the mdata->msg->to is used for the To header. If
1218  * mdata->msg->to isn't available, mdata->to is used for the To header.
1219  *
1220  */
1221 static int msg_send(void *data)
1222 {
1223  struct msg_data *mdata = data; /* The caller holds a reference */
1224 
1225  struct ast_sip_body body = {
1226  .type = "text",
1227  .subtype = "plain",
1228  .body_text = ast_msg_get_body(mdata->msg)
1229  };
1230 
1231  pjsip_tx_data *tdata;
1232  RAII_VAR(char *, uri, NULL, ast_free);
1233  RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
1234 
1235  ast_debug(3, "mdata From: %s msg From: %s mdata Destination: %s msg To: %s\n",
1236  mdata->from, ast_msg_get_from(mdata->msg), mdata->destination, ast_msg_get_to(mdata->msg));
1237 
1238  endpoint = get_outbound_endpoint(mdata->destination, &uri);
1239  if (!endpoint) {
1241  "PJSIP MESSAGE - Could not find endpoint '%s' and no default outbound endpoint configured\n",
1242  mdata->destination);
1243 
1244  ast_test_suite_event_notify("MSG_ENDPOINT_URI_FAIL",
1245  "MdataFrom: %s\r\n"
1246  "MsgFrom: %s\r\n"
1247  "MdataDestination: %s\r\n"
1248  "MsgTo: %s\r\n",
1249  mdata->from,
1250  ast_msg_get_from(mdata->msg),
1251  mdata->destination,
1252  ast_msg_get_to(mdata->msg));
1253 
1254  return -1;
1255  }
1256 
1257  ast_debug(3, "Request URI: %s\n", uri);
1258 
1259  if (ast_sip_create_request("MESSAGE", NULL, endpoint, uri, NULL, &tdata)) {
1260  ast_log(LOG_WARNING, "PJSIP MESSAGE - Could not create request\n");
1261  return -1;
1262  }
1263 
1264  /* If there was a To in the actual message, */
1265  if (!ast_strlen_zero(ast_msg_get_to(mdata->msg))) {
1266  char *msg_to = ast_strdupa(ast_msg_get_to(mdata->msg));
1267 
1268  /*
1269  * It's possible that the message To was copied from
1270  * an incoming MESSAGE in which case it'll have the
1271  * pjsip: tech prepended to it. We need to remove it.
1272  */
1273  if (ast_begins_with(msg_to, "pjsip:")) {
1274  msg_to += 6;
1275  }
1276  update_to_uri(tdata, msg_to);
1277  } else {
1278  /*
1279  * If there was no To in the message, it's still possible
1280  * that there is a display name in the mdata To. If so,
1281  * we'll copy the URI display name to the tdata To.
1282  */
1283  update_to_display_name(tdata, uri);
1284  }
1285 
1286  if (!ast_strlen_zero(mdata->from)) {
1287  update_from(tdata, mdata->from);
1288  } else if (!ast_strlen_zero(ast_msg_get_from(mdata->msg))) {
1289  update_from(tdata, (char *)ast_msg_get_from(mdata->msg));
1290  }
1291 
1292 #ifdef TEST_FRAMEWORK
1293  {
1294  pjsip_name_addr *tdata_name_addr;
1295  pjsip_sip_uri *tdata_sip_uri;
1296  char touri[128];
1297  char fromuri[128];
1298 
1299  tdata_name_addr = (pjsip_name_addr *) PJSIP_MSG_TO_HDR(tdata->msg)->uri;
1300  tdata_sip_uri = pjsip_uri_get_uri(tdata_name_addr->uri);
1301  pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, touri, sizeof(touri));
1302  tdata_name_addr = (pjsip_name_addr *) PJSIP_MSG_FROM_HDR(tdata->msg)->uri;
1303  tdata_sip_uri = pjsip_uri_get_uri(tdata_name_addr->uri);
1304  pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, fromuri, sizeof(fromuri));
1305 
1306  ast_test_suite_event_notify("MSG_FROMTO_URI",
1307  "MdataFrom: %s\r\n"
1308  "MsgFrom: %s\r\n"
1309  "MdataDestination: %s\r\n"
1310  "MsgTo: %s\r\n"
1311  "Endpoint: %s\r\n"
1312  "RequestURI: %s\r\n"
1313  "ToURI: %s\r\n"
1314  "FromURI: %s\r\n",
1315  mdata->from,
1316  ast_msg_get_from(mdata->msg),
1317  mdata->destination,
1318  ast_msg_get_to(mdata->msg),
1319  ast_sorcery_object_get_id(endpoint),
1320  uri,
1321  touri,
1322  fromuri
1323  );
1324  }
1325 #endif
1326 
1327  update_content_type(tdata, mdata->msg, &body);
1328 
1329  if (ast_sip_add_body(tdata, &body)) {
1330  pjsip_tx_data_dec_ref(tdata);
1331  ast_log(LOG_ERROR, "PJSIP MESSAGE - Could not add body to request\n");
1332  return -1;
1333  }
1334 
1335  /*
1336  * This copies any headers set with MESSAGE_DATA() to the
1337  * tdata.
1338  */
1339  vars_to_headers(mdata->msg, tdata);
1340 
1341  ast_debug(1, "Sending message to '%s' (via endpoint %s) from '%s'\n",
1342  uri, ast_sorcery_object_get_id(endpoint), mdata->from);
1343 
1344  if (ast_sip_send_request(tdata, NULL, endpoint, NULL, NULL)) {
1345  ast_log(LOG_ERROR, "PJSIP MESSAGE - Could not send request\n");
1346  return -1;
1347  }
1348 
1349  return 0;
1350 }
1351 
1352 static int sip_msg_send(const struct ast_msg *msg, const char *destination, const char *from)
1353 {
1354  struct msg_data *mdata;
1355  int res;
1356 
1357  if (ast_strlen_zero(destination)) {
1358  ast_log(LOG_ERROR, "SIP MESSAGE - a 'To' URI must be specified\n");
1359  return -1;
1360  }
1361 
1362  mdata = msg_data_create(msg, destination, from);
1363  if (!mdata) {
1364  return -1;
1365  }
1366 
1367  res = ast_sip_push_task_wait_serializer(message_serializer, msg_send, mdata);
1368  ao2_ref(mdata, -1);
1369 
1370  return res;
1371 }
1372 
1373 static const struct ast_msg_tech msg_tech = {
1374  .name = "pjsip",
1375  .msg_send = sip_msg_send,
1376 };
1377 
1378 static pj_status_t send_response(pjsip_rx_data *rdata, enum pjsip_status_code code,
1379  pjsip_dialog *dlg, pjsip_transaction *tsx)
1380 {
1381  pjsip_tx_data *tdata;
1382  pj_status_t status;
1383 
1384  status = ast_sip_create_response(rdata, code, NULL, &tdata);
1385  if (status != PJ_SUCCESS) {
1386  ast_log(LOG_ERROR, "Unable to create response (%d)\n", status);
1387  return status;
1388  }
1389 
1390  if (dlg && tsx) {
1391  status = pjsip_dlg_send_response(dlg, tsx, tdata);
1392  } else {
1393  struct ast_sip_endpoint *endpoint;
1394 
1395  endpoint = ast_pjsip_rdata_get_endpoint(rdata);
1396  status = ast_sip_send_stateful_response(rdata, tdata, endpoint);
1397  ao2_cleanup(endpoint);
1398  }
1399 
1400  if (status != PJ_SUCCESS) {
1401  ast_log(LOG_ERROR, "Unable to send response (%d)\n", status);
1402  }
1403 
1404  return status;
1405 }
1406 
1407 static pj_bool_t module_on_rx_request(pjsip_rx_data *rdata)
1408 {
1409  enum pjsip_status_code code;
1410  struct ast_msg *msg;
1411 
1412  /* if not a MESSAGE, don't handle */
1413  if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_message_method)) {
1414  return PJ_FALSE;
1415  }
1416 
1417  code = check_content_type(rdata);
1418  if (code != PJSIP_SC_OK) {
1419  send_response(rdata, code, NULL, NULL);
1420  return PJ_TRUE;
1421  }
1422 
1423  msg = ast_msg_alloc();
1424  if (!msg) {
1425  send_response(rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, NULL, NULL);
1426  return PJ_TRUE;
1427  }
1428 
1429  code = rx_data_to_ast_msg(rdata, msg);
1430  if (code != PJSIP_SC_OK) {
1431  send_response(rdata, code, NULL, NULL);
1432  ast_msg_destroy(msg);
1433  return PJ_TRUE;
1434  }
1435 
1436  if (!ast_msg_has_destination(msg)) {
1437  ast_debug(1, "MESSAGE request received, but no handler wanted it\n");
1438  send_response(rdata, PJSIP_SC_NOT_FOUND, NULL, NULL);
1439  ast_msg_destroy(msg);
1440  return PJ_TRUE;
1441  }
1442 
1443  /* Send it to the messaging core.
1444  *
1445  * If we are unable to send a response, the most likely reason is that we
1446  * are handling a retransmission of an incoming MESSAGE and were unable to
1447  * create a transaction due to a duplicate key. If we are unable to send
1448  * a response, we should not queue the message to the dialplan
1449  */
1450  if (!send_response(rdata, PJSIP_SC_ACCEPTED, NULL, NULL)) {
1451  ast_msg_queue(msg);
1452  }
1453 
1454  return PJ_TRUE;
1455 }
1456 
1457 static int incoming_in_dialog_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
1458 {
1459  enum pjsip_status_code code;
1460  int rc;
1461  pjsip_dialog *dlg = session->inv_session->dlg;
1462  pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
1463  struct ast_msg_data *msg;
1464  struct ast_party_caller *caller;
1465  pjsip_name_addr *name_addr;
1466  size_t from_len;
1467  size_t to_len;
1468  struct ast_msg_data_attribute attrs[4];
1469  int pos = 0;
1470  int body_pos;
1471 
1472  if (!session->channel) {
1473  send_response(rdata, PJSIP_SC_NOT_FOUND, dlg, tsx);
1474  return 0;
1475  }
1476 
1477  code = check_content_type_in_dialog(rdata);
1478  if (code != PJSIP_SC_OK) {
1479  send_response(rdata, code, dlg, tsx);
1480  return 0;
1481  }
1482 
1483  caller = ast_channel_caller(session->channel);
1484 
1485  name_addr = (pjsip_name_addr *) rdata->msg_info.from->uri;
1486  from_len = pj_strlen(&name_addr->display);
1487  if (from_len) {
1488  attrs[pos].type = AST_MSG_DATA_ATTR_FROM;
1489  from_len++;
1490  attrs[pos].value = ast_alloca(from_len);
1491  ast_copy_pj_str(attrs[pos].value, &name_addr->display, from_len);
1492  pos++;
1493  } else if (caller->id.name.valid && !ast_strlen_zero(caller->id.name.str)) {
1494  attrs[pos].type = AST_MSG_DATA_ATTR_FROM;
1495  attrs[pos].value = caller->id.name.str;
1496  pos++;
1497  }
1498 
1499  name_addr = (pjsip_name_addr *) rdata->msg_info.to->uri;
1500  to_len = pj_strlen(&name_addr->display);
1501  if (to_len) {
1502  attrs[pos].type = AST_MSG_DATA_ATTR_TO;
1503  to_len++;
1504  attrs[pos].value = ast_alloca(to_len);
1505  ast_copy_pj_str(attrs[pos].value, &name_addr->display, to_len);
1506  pos++;
1507  }
1508 
1509  attrs[pos].type = AST_MSG_DATA_ATTR_CONTENT_TYPE;
1510  attrs[pos].value = ast_alloca(rdata->msg_info.msg->body->content_type.type.slen
1511  + rdata->msg_info.msg->body->content_type.subtype.slen + 2);
1512  sprintf(attrs[pos].value, "%.*s/%.*s",
1513  (int)rdata->msg_info.msg->body->content_type.type.slen,
1514  rdata->msg_info.msg->body->content_type.type.ptr,
1515  (int)rdata->msg_info.msg->body->content_type.subtype.slen,
1516  rdata->msg_info.msg->body->content_type.subtype.ptr);
1517  pos++;
1518 
1519  body_pos = pos;
1520  attrs[pos].type = AST_MSG_DATA_ATTR_BODY;
1521  attrs[pos].value = ast_malloc(rdata->msg_info.msg->body->len + 1);
1522  if (!attrs[pos].value) {
1523  send_response(rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, dlg, tsx);
1524  return 0;
1525  }
1526  ast_copy_string(attrs[pos].value, rdata->msg_info.msg->body->data, rdata->msg_info.msg->body->len + 1);
1527  pos++;
1528 
1530  if (!msg) {
1531  ast_free(attrs[body_pos].value);
1532  send_response(rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, dlg, tsx);
1533  return 0;
1534  }
1535 
1536  ast_debug(1, "Received in-dialog MESSAGE from '%s:%s': %s %s\n",
1538  ast_channel_name(session->channel),
1541 
1542  rc = ast_msg_data_queue_frame(session->channel, msg);
1543  ast_free(attrs[body_pos].value);
1544  ast_free(msg);
1545  if (rc != 0) {
1546  send_response(rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, dlg, tsx);
1547  } else {
1548  send_response(rdata, PJSIP_SC_ACCEPTED, dlg, tsx);
1549  }
1550 
1551  return 0;
1552 }
1553 
1555  .method = "MESSAGE",
1556  .incoming_request = incoming_in_dialog_request
1557 };
1558 
1559 static pjsip_module messaging_module = {
1560  .name = {"Messaging Module", 16},
1561  .id = -1,
1562  .priority = PJSIP_MOD_PRIORITY_APPLICATION,
1563  .on_rx_request = module_on_rx_request,
1564 };
1565 
1566 static int load_module(void)
1567 {
1568  if (ast_sip_register_service(&messaging_module) != PJ_SUCCESS) {
1569  return AST_MODULE_LOAD_DECLINE;
1570  }
1571 
1572  if (pjsip_endpt_add_capability(ast_sip_get_pjsip_endpoint(),
1573  NULL, PJSIP_H_ALLOW, NULL, 1,
1574  &pjsip_message_method.name) != PJ_SUCCESS) {
1575 
1577  return AST_MODULE_LOAD_DECLINE;
1578  }
1579 
1580  if (ast_msg_tech_register(&msg_tech)) {
1582  return AST_MODULE_LOAD_DECLINE;
1583  }
1584 
1585  message_serializer = ast_sip_create_serializer("pjsip/messaging");
1586  if (!message_serializer) {
1588  ast_msg_tech_unregister(&msg_tech);
1589  return AST_MODULE_LOAD_DECLINE;
1590  }
1591 
1592  ast_sip_session_register_supplement(&messaging_supplement);
1593  return AST_MODULE_LOAD_SUCCESS;
1594 }
1595 
1596 static int unload_module(void)
1597 {
1598  ast_sip_session_unregister_supplement(&messaging_supplement);
1599  ast_msg_tech_unregister(&msg_tech);
1601  ast_taskprocessor_unreference(message_serializer);
1602  return 0;
1603 }
1604 
1605 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Messaging Support",
1606  .support_level = AST_MODULE_SUPPORT_CORE,
1607  .load = load_module,
1608  .unload = unload_module,
1609  .load_pri = AST_MODPRI_APP_DEPEND,
1610  .requires = "res_pjsip,res_pjsip_session",
1611 );
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
static const char type[]
Definition: chan_ooh323.c:109
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:122
#define AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(str)
Truncate the URI user field options string if enabled.
Definition: res_pjsip.h:3036
int ast_msg_set_tech(struct ast_msg *msg, const char *fmt,...)
Set the technology associated with this message.
Definition: message.c:509
static const char name[]
Definition: format_mp3.c:68
Asterisk main include file. File version handling, generic pbx functions.
A SIP address of record.
Definition: res_pjsip.h:361
const char * ast_msg_get_var(struct ast_msg *msg, const char *name)
Get the specified variable on the message.
Definition: message.c:620
static int insert_user_in_contact_uri(const char *to, const char *endpoint_name, const char *aors, const char *user, char **uri)
Find a contact and insert a "user@" into its URI.
struct ao2_iterator iter
Definition: message.c:640
static int update_to_display_name(pjsip_tx_data *tdata, char *to)
static enum pjsip_status_code rx_data_to_ast_msg(pjsip_rx_data *rdata, struct ast_msg *msg)
enum ast_msg_data_attribute_type type
Definition: message.h:463
int ast_msg_set_context(struct ast_msg *msg, const char *fmt,...)
Set the dialplan context for this message.
Definition: message.c:487
int ast_msg_set_body(struct ast_msg *msg, const char *fmt,...)
Set the &#39;body&#39; text of a message (in UTF-8)
Definition: message.c:476
const pjsip_method pjsip_message_method
struct ast_party_name name
Subscriber name.
Definition: channel.h:341
#define MAX_BODY_SIZE
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
#define MAX_HDR_SIZE
struct ast_msg * ast_msg_alloc(void)
Allocate a message.
Definition: message.c:418
int ast_msg_var_iterator_next(const struct ast_msg *msg, struct ast_msg_var_iterator *iter, const char **name, const char **value)
Get the next variable name and value that is set for sending outbound.
Definition: message.c:689
static enum pjsip_status_code check_content_type(const pjsip_rx_data *rdata)
Test Framework API.
const char *const name
Name of this message technology.
Definition: message.h:61
Structure used to transport a message through the frame core.
Definition: message.c:1406
char * str
Subscriber name (Malloced)
Definition: channel.h:265
int ast_msg_tech_register(const struct ast_msg_tech *tech)
Register a message technology.
Definition: message.c:1569
#define ast_assert(a)
Definition: utils.h:710
struct ast_msg_data * ast_msg_data_alloc(enum ast_msg_data_source_type source, struct ast_msg_data_attribute attributes[], size_t count)
Allocates an ast_msg_data structure.
Definition: message.c:1418
static struct test_val c
char * text
Definition: app_queue.c:1514
static const struct ast_msg_tech msg_tech
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
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:5240
struct ast_sip_endpoint * ast_sip_default_outbound_endpoint(void)
Retrieve the default outbound endpoint.
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.
Definition: pjsip_session.c:63
#define NULL
Definition: resample.c:96
Domain data structure.
Definition: sip.h:888
char * end
Definition: eagi_proxy.c:73
Out-of-call text message support.
int value
Definition: syslog.c:37
struct ast_msg * msg
struct pjsip_inv_session * inv_session
const char * ast_msg_get_body(const struct ast_msg *msg)
Get the body of a message.
Definition: message.c:531
A structure describing a SIP session.
void ast_msg_var_iterator_destroy(struct ast_msg_var_iterator *iter)
Destroy a message variable iterator.
Definition: message.c:706
static char * sip_to_pjsip(char *buf, int size, int capacity)
static int load_module(void)
int ast_sip_send_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint, void *token, void(*callback)(void *token, pjsip_event *e))
General purpose method for sending a SIP request.
Definition: res_pjsip.c:5034
int ast_msg_set_to(struct ast_msg *msg, const char *fmt,...)
Set the &#39;to&#39; URI of a message.
Definition: message.c:454
int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message.
Definition: res_pjsip.c:5063
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_msg_get_to(const struct ast_msg *msg)
Retrieve the destination of this message.
Definition: message.c:541
static int unload_module(void)
struct ast_sip_endpoint * ast_pjsip_rdata_get_endpoint(pjsip_rx_data *rdata)
Get the looked-up endpoint on an out-of dialog request or response.
static struct ast_taskprocessor * message_serializer
int ast_sip_create_response(const pjsip_rx_data *rdata, int st_code, struct ast_sip_contact *contact, pjsip_tx_data **p_tdata)
General purpose method for creating a SIP response.
Definition: res_pjsip.c:5448
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.h:313
struct ast_party_id id
Caller party ID.
Definition: channel.h:421
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
static enum pjsip_status_code vars_to_headers(const struct ast_msg *msg, pjsip_tx_data *tdata)
static void update_content_type(pjsip_tx_data *tdata, struct ast_msg *msg, struct ast_sip_body *body)
int ast_sip_add_body(pjsip_tx_data *tdata, const struct ast_sip_body *body)
Add a body to an outbound SIP message.
Definition: res_pjsip.c:5091
#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:911
const char * type
Definition: res_pjsip.h:2029
static struct ast_mansession session
void ast_msg_var_unref_current(struct ast_msg_var_iterator *iter)
Unref a message var from inside an iterator loop.
Definition: message.c:700
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
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:5218
#define AST_MAX_EXTENSION
Definition: channel.h:135
Caller Party information.
Definition: channel.h:419
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void msg_data_destroy(void *obj)
int ast_sip_send_stateful_response(pjsip_rx_data *rdata, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
Send a stateful response to an out of dialog request.
Definition: res_pjsip.c:5420
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static pjsip_module messaging_module
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
struct ast_channel * channel
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
int ast_msg_set_var(struct ast_msg *msg, const char *name, const char *value)
Set a variable on the message going to the dialplan.
Definition: message.c:615
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition: res_pjsip.c:3315
#define ARRAY_LEN(a)
Definition: utils.h:639
Core PBX routines and definitions.
struct ast_sip_contact * ast_sip_location_retrieve_contact_from_aor_list(const char *aor_list)
Retrieve the first bound contact from a list of AORs.
Definition: location.c:304
static struct ast_sip_endpoint * handle_slash(const char *to, char *destination, char **uri, char *slash, char *atsign, char *scheme)
int ast_sip_is_content_type(pjsip_media_type *content_type, char *type, char *subtype)
Checks if the given content type matches type/subtype.
Definition: res_pjsip.c:5259
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:196
struct ast_sip_aor * ast_sip_location_retrieve_aor(const char *aor_name)
Retrieve a named AOR.
Definition: location.c:147
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
int ast_msg_queue(struct ast_msg *msg)
Queue a message for routing through the dialplan.
Definition: message.c:958
struct ast_msg * ast_msg_ref(struct ast_msg *msg)
Bump a msg&#39;s ref count.
Definition: message.c:442
int ast_msg_data_queue_frame(struct ast_channel *channel, struct ast_msg_data *msg)
Queue an AST_FRAME_TEXT_DATA frame containing an ast_msg_data structure.
Definition: message.c:1548
static int headers_to_vars(const pjsip_rx_data *rdata, struct ast_msg *msg)
#define LOG_ERROR
Definition: logger.h:285
static int print_body(pjsip_rx_data *rdata, char *buf, int len)
int ast_msg_tech_unregister(const struct ast_msg_tech *tech)
Unregister a message technology.
Definition: message.c:1610
const char * ast_msg_get_from(const struct ast_msg *msg)
Retrieve the source of this message.
Definition: message.c:536
Channel datastore data for max forwards.
Definition: max_forwards.c:29
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
const char * ast_msg_data_get_attribute(struct ast_msg_data *msg, enum ast_msg_data_attribute_type attribute_type)
Get attribute from ast_msg_data.
Definition: message.c:1533
Contact associated with an address of record.
Definition: res_pjsip.h:281
const char * subtype
Definition: res_pjsip.h:2031
static int update_from(pjsip_tx_data *tdata, char *from)
A message technology.
Definition: message.h:52
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
Definition: res_pjsip.c:5133
static enum pjsip_status_code check_content_type_in_dialog(const pjsip_rx_data *rdata)
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:157
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define LOG_NOTICE
Definition: logger.h:263
static struct ast_sip_endpoint * get_outbound_endpoint(const char *to, char **uri)
struct ast_sip_contact * ast_sip_location_retrieve_first_aor_contact(const struct ast_sip_aor *aor)
Retrieve the first bound contact for an AOR.
Definition: location.c:194
#define ast_free(a)
Definition: astmm.h:182
static int update_to_uri(pjsip_tx_data *tdata, char *to)
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
An API for managing task processing threads that can be shared across modules.
int ast_msg_set_exten(struct ast_msg *msg, const char *fmt,...)
Set the dialplan extension for this message.
Definition: message.c:498
static int sip_msg_send(const struct ast_msg *msg, const char *destination, const char *from)
structure to hold users read from users.conf
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
int ast_msg_set_from(struct ast_msg *msg, const char *fmt,...)
Set the &#39;from&#39; URI of a message.
Definition: message.c:465
A supplement to SIP message processing.
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
static int msg_send(void *data)
A ast_taskprocessor structure is a singleton by name.
Definition: taskprocessor.c:69
int ast_msg_set_endpoint(struct ast_msg *msg, const char *fmt,...)
Set the technology&#39;s endpoint associated with this message.
Definition: message.c:520
static int incoming_in_dialog_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
int ast_msg_has_destination(const struct ast_msg *msg)
Determine if a particular message has a destination via some handler.
Definition: message.c:937
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
const char * ast_channel_name(const struct ast_channel *chan)
void ast_sip_unregister_service(pjsip_module *module)
Definition: res_pjsip.c:3331
static pj_status_t send_response(pjsip_rx_data *rdata, enum pjsip_status_code code, pjsip_dialog *dlg, pjsip_transaction *tsx)
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Definition: strings.h:94
static struct ast_sip_session_supplement messaging_supplement
#define DEBUG_BUF_SIZE
static struct msg_data * msg_data_create(const struct ast_msg *msg, const char *destination, const char *from)
A message.
Definition: message.c:233
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:280
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:120
struct ast_msg * ast_msg_destroy(struct ast_msg *msg)
Destroy an ast_msg.
Definition: message.c:448
const ast_string_field aors
Definition: res_pjsip.h:821
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
#define DEBUG_ATLEAST(level)
Definition: logger.h:433
const ast_string_field uri
Definition: res_pjsip.h:303
Asterisk module definitions.
SIP body description.
Definition: res_pjsip.h:2027
static struct ast_sip_endpoint * handle_atsign(const char *to, char *destination, char **uri, char *slash, char *atsign, char *scheme)
static int is_msg_var_blocked(const char *name)
static struct ast_sip_endpoint * handle_single_token(const char *to, char *destination, char **uri)
jack_status_t status
Definition: app_jack.c:146
const ast_string_field value
Definition: message.c:224
int ast_sip_create_request(const char *method, struct pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint, const char *uri, struct ast_sip_contact *contact, pjsip_tx_data **tdata)
General purpose method for creating a SIP request.
Definition: res_pjsip.c:4490
#define ast_sip_session_register_supplement(supplement)
static pj_bool_t module_on_rx_request(pjsip_rx_data *rdata)
struct ast_msg_var_iterator * ast_msg_var_iterator_init(const struct ast_msg *msg)
Create a new message variable iterator.
Definition: message.c:644