Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions | Variables
res_pjsip_messaging.c File Reference
#include "asterisk.h"
#include <pjsip.h>
#include <pjsip_ua.h>
#include "asterisk/message.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_session.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/test.h"
#include "asterisk/uri.h"
Include dependency graph for res_pjsip_messaging.c:

Go to the source code of this file.

Data Structures

struct  msg_data
 

Macros

#define DEBUG_BUF_SIZE   256
 
#define MAX_BODY_SIZE   1024
 
#define MAX_HDR_SIZE   512
 
#define MAX_USER_SIZE   128
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static enum pjsip_status_code check_content_type (const pjsip_rx_data *rdata)
 
static enum pjsip_status_code check_content_type_in_dialog (const pjsip_rx_data *rdata)
 
static struct ast_sip_endpointget_outbound_endpoint (const char *to, char **uri)
 
static struct ast_sip_endpointhandle_atsign (const char *to, char *destination, char **uri, char *slash, char *atsign, char *scheme)
 
static struct ast_sip_endpointhandle_single_token (const char *to, char *destination, char **uri)
 
static struct ast_sip_endpointhandle_slash (const char *to, char *destination, char **uri, char *slash, char *atsign, char *scheme)
 
static int headers_to_vars (const pjsip_rx_data *rdata, struct ast_msg *msg)
 
static int incoming_in_dialog_request (struct ast_sip_session *session, struct pjsip_rx_data *rdata)
 
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. More...
 
static int is_msg_var_blocked (const char *name)
 
static int load_module (void)
 
static pj_bool_t module_on_rx_request (pjsip_rx_data *rdata)
 
static struct msg_datamsg_data_create (const struct ast_msg *msg, const char *destination, const char *from)
 
static void msg_data_destroy (void *obj)
 
static int msg_send (void *data)
 
static int print_body (pjsip_rx_data *rdata, char *buf, int len)
 
static enum pjsip_status_code rx_data_to_ast_msg (pjsip_rx_data *rdata, struct ast_msg *msg)
 
static pj_status_t send_response (pjsip_rx_data *rdata, enum pjsip_status_code code, pjsip_dialog *dlg, pjsip_transaction *tsx)
 
static int sip_msg_send (const struct ast_msg *msg, const char *destination, const char *from)
 
static char * sip_to_pjsip (char *buf, int size, int capacity)
 
static int unload_module (void)
 
static void update_content_type (pjsip_tx_data *tdata, struct ast_msg *msg, struct ast_sip_body *body)
 
static int update_from (pjsip_tx_data *tdata, char *from)
 
static int update_to_display_name (pjsip_tx_data *tdata, char *to)
 
static int update_to_uri (pjsip_tx_data *tdata, char *to)
 
static enum pjsip_status_code vars_to_headers (const struct ast_msg *msg, pjsip_tx_data *tdata)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Messaging Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip,res_pjsip_session", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_taskprocessormessage_serializer
 
static pjsip_module messaging_module
 
static struct ast_sip_session_supplement messaging_supplement
 
static const struct ast_msg_tech msg_tech
 
const pjsip_method pjsip_message_method = {PJSIP_OTHER_METHOD, {"MESSAGE", 7} }
 

Macro Definition Documentation

◆ DEBUG_BUF_SIZE

#define DEBUG_BUF_SIZE   256

Referenced by update_to_uri().

◆ MAX_BODY_SIZE

#define MAX_BODY_SIZE   1024

Definition at line 137 of file res_pjsip_messaging.c.

Referenced by rx_data_to_ast_msg().

◆ MAX_HDR_SIZE

#define MAX_HDR_SIZE   512

Definition at line 136 of file res_pjsip_messaging.c.

Referenced by headers_to_vars().

◆ MAX_USER_SIZE

#define MAX_USER_SIZE   128

Definition at line 138 of file res_pjsip_messaging.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1611 of file res_pjsip_messaging.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1611 of file res_pjsip_messaging.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 1611 of file res_pjsip_messaging.c.

◆ check_content_type()

static enum pjsip_status_code check_content_type ( const pjsip_rx_data *  rdata)
static

Definition at line 151 of file res_pjsip_messaging.c.

References ast_sip_is_content_type().

Referenced by module_on_rx_request().

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 }
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

◆ check_content_type_in_dialog()

static enum pjsip_status_code check_content_type_in_dialog ( const pjsip_rx_data *  rdata)
static

Definition at line 175 of file res_pjsip_messaging.c.

References text.

Referenced by incoming_in_dialog_request().

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 }
char * text
Definition: app_queue.c:1508

◆ get_outbound_endpoint()

static struct ast_sip_endpoint* get_outbound_endpoint ( const char *  to,
char **  uri 
)
static

Definition at line 617 of file res_pjsip_messaging.c.

References ast_debug, ast_malloc, ast_sip_default_outbound_endpoint(), ast_strdup, ast_strdupa, handle_atsign(), handle_single_token(), handle_slash(), NULL, and S_OR.

Referenced by msg_send().

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 }
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
struct ast_sip_endpoint * ast_sip_default_outbound_endpoint(void)
Retrieve the default outbound endpoint.
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
static struct ast_sip_endpoint * handle_slash(const char *to, char *destination, char **uri, char *slash, char *atsign, char *scheme)
#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
static struct ast_sip_endpoint * handle_atsign(const char *to, char *destination, char **uri, char *slash, char *atsign, char *scheme)
static struct ast_sip_endpoint * handle_single_token(const char *to, char *destination, char **uri)

◆ handle_atsign()

static struct ast_sip_endpoint* handle_atsign ( const char *  to,
char *  destination,
char **  uri,
char *  slash,
char *  atsign,
char *  scheme 
)
static

Definition at line 505 of file res_pjsip_messaging.c.

References ao2_cleanup, ast_sip_endpoint::aors, ast_debug, ast_log, ast_malloc, ast_sip_default_outbound_endpoint(), ast_sip_get_sorcery(), ast_sip_location_retrieve_contact_from_aor_list(), AST_SIP_USER_OPTIONS_TRUNCATE_CHECK, ast_sorcery_retrieve_by_id(), ast_strdup, ast_sip_contact::endpoint, LOG_WARNING, NULL, and ast_sip_contact::uri.

Referenced by get_outbound_endpoint().

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 }
#define AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(str)
Truncate the URI user field options string if enabled.
Definition: res_pjsip.h:3036
#define LOG_WARNING
Definition: logger.h:274
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
struct ast_sip_endpoint * ast_sip_default_outbound_endpoint(void)
Retrieve the default outbound endpoint.
#define NULL
Definition: resample.c:96
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
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.h:313
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
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
Contact associated with an address of record.
Definition: res_pjsip.h:281
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
const ast_string_field aors
Definition: res_pjsip.h:821
const ast_string_field uri
Definition: res_pjsip.h:303

◆ handle_single_token()

static struct ast_sip_endpoint* handle_single_token ( const char *  to,
char *  destination,
char **  uri 
)
static

Definition at line 288 of file res_pjsip_messaging.c.

References ao2_cleanup, ast_sip_endpoint::aors, ast_debug, ast_log, ast_malloc, ast_sip_default_outbound_endpoint(), ast_sip_get_sorcery(), ast_sip_location_retrieve_contact_from_aor_list(), ast_sorcery_retrieve_by_id(), ast_strdup, ast_sip_contact::endpoint, LOG_WARNING, NULL, and ast_sip_contact::uri.

Referenced by get_outbound_endpoint().

288  {
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 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
struct ast_sip_endpoint * ast_sip_default_outbound_endpoint(void)
Retrieve the default outbound endpoint.
#define NULL
Definition: resample.c:96
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
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.h:313
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
const ast_string_field endpoint_name
Definition: res_pjsip.h:303
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
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
Contact associated with an address of record.
Definition: res_pjsip.h:281
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
const ast_string_field aors
Definition: res_pjsip.h:821
const ast_string_field uri
Definition: res_pjsip.h:303

◆ handle_slash()

static struct ast_sip_endpoint* handle_slash ( const char *  to,
char *  destination,
char **  uri,
char *  slash,
char *  atsign,
char *  scheme 
)
static

Definition at line 358 of file res_pjsip_messaging.c.

References ao2_cleanup, ast_sip_endpoint::aors, ast_begins_with(), ast_debug, ast_log, ast_malloc, ast_sip_get_sorcery(), ast_sip_location_retrieve_aor(), ast_sip_location_retrieve_first_aor_contact(), ast_sorcery_object_get_id(), ast_sorcery_retrieve_by_id(), ast_strdup, insert_user_in_contact_uri(), LOG_WARNING, NULL, and ast_sip_contact::uri.

Referenced by get_outbound_endpoint().

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 }
A SIP address of record.
Definition: res_pjsip.h:361
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.
#define LOG_WARNING
Definition: logger.h:274
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
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
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
const ast_string_field endpoint_name
Definition: res_pjsip.h:303
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
struct ast_sip_aor * ast_sip_location_retrieve_aor(const char *aor_name)
Retrieve a named AOR.
Definition: location.c:147
Contact associated with an address of record.
Definition: res_pjsip.h:281
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
structure to hold users read from users.conf
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Definition: strings.h:94
const ast_string_field aors
Definition: res_pjsip.h:821
const ast_string_field uri
Definition: res_pjsip.h:303

◆ headers_to_vars()

static int headers_to_vars ( const pjsip_rx_data *  rdata,
struct ast_msg msg 
)
static

Definition at line 927 of file res_pjsip_messaging.c.

References ast_copy_pj_str(), ast_copy_string(), ast_msg_set_var(), ast_skip_blanks(), buf, c, end, MAX_HDR_SIZE, and name.

Referenced by rx_data_to_ast_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 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define MAX_HDR_SIZE
static struct test_val c
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
char * end
Definition: eagi_proxy.c:73
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
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:157
static const char name[]
Definition: cdr_mysql.c:74
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ incoming_in_dialog_request()

static int incoming_in_dialog_request ( struct ast_sip_session session,
struct pjsip_rx_data *  rdata 
)
static

Definition at line 1457 of file res_pjsip_messaging.c.

References ast_alloca, ast_channel_caller(), ast_channel_name(), ast_copy_pj_str(), ast_copy_string(), ast_debug, ast_free, ast_malloc, ast_msg_data_alloc(), AST_MSG_DATA_ATTR_BODY, AST_MSG_DATA_ATTR_CONTENT_TYPE, AST_MSG_DATA_ATTR_FROM, AST_MSG_DATA_ATTR_TO, ast_msg_data_get_attribute(), ast_msg_data_queue_frame(), AST_MSG_DATA_SOURCE_TYPE_IN_DIALOG, ast_strlen_zero, ast_sip_session::channel, check_content_type_in_dialog(), ast_party_caller::id, ast_sip_session::inv_session, msg_data::msg, ast_party_id::name, send_response(), ast_party_name::str, ast_msg_data_attribute::type, ast_party_name::valid, msg_data::value, and ast_msg_data_attribute::value.

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 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
struct ast_party_name name
Subscriber name.
Definition: channel.h:341
Structure used to transport a message through the frame core.
Definition: message.c:1406
char * str
Subscriber name (Malloced)
Definition: channel.h:265
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
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
int value
Definition: syslog.c:37
struct pjsip_inv_session * inv_session
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_party_id id
Caller party ID.
Definition: channel.h:421
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
Caller Party information.
Definition: channel.h:419
struct ast_channel * channel
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
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
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
static enum pjsip_status_code check_content_type_in_dialog(const pjsip_rx_data *rdata)
#define ast_free(a)
Definition: astmm.h:182
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_channel_name(const struct ast_channel *chan)
static pj_status_t send_response(pjsip_rx_data *rdata, enum pjsip_status_code code, pjsip_dialog *dlg, pjsip_transaction *tsx)
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:280

◆ insert_user_in_contact_uri()

static int insert_user_in_contact_uri ( const char *  to,
const char *  endpoint_name,
const char *  aors,
const char *  user,
char **  uri 
)
static

Find a contact and insert a "user@" into its URI.

Parameters
toOriginal destination (for error messages only)
endpoint_nameEndpoint name (for error messages only)
aorsCommand separated list of AORs
userThe user to insert in the contact URI
uriPointer to buffer in which to return the URI
Returns
0 Success
-1 Fail
Note
If the contact URI found for the endpoint already has a user in its URI, it will be replaced.

Definition at line 213 of file res_pjsip_messaging.c.

References ao2_cleanup, ast_debug, ast_log, ast_malloc, ast_sip_location_retrieve_contact_from_aor_list(), ast_strdupa, host, LOG_WARNING, NULL, and ast_sip_contact::uri.

Referenced by handle_slash().

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 }
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
const ast_string_field endpoint_name
Definition: res_pjsip.h:303
static char host[256]
Definition: muted.c:77
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
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
Contact associated with an address of record.
Definition: res_pjsip.h:281
structure to hold users read from users.conf
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
const ast_string_field uri
Definition: res_pjsip.h:303

◆ is_msg_var_blocked()

static int is_msg_var_blocked ( const char *  name)
static

Definition at line 857 of file res_pjsip_messaging.c.

References ARRAY_LEN.

Referenced by vars_to_headers().

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 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static const char name[]
Definition: cdr_mysql.c:74

◆ load_module()

static int load_module ( void  )
static

Definition at line 1566 of file res_pjsip_messaging.c.

References AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_msg_tech_register(), ast_msg_tech_unregister(), ast_sip_create_serializer(), ast_sip_get_pjsip_endpoint(), ast_sip_register_service(), ast_sip_session_register_supplement, ast_sip_unregister_service(), messaging_module, NULL, and pjsip_message_method.

Referenced by unload_module().

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 
1582  return AST_MODULE_LOAD_DECLINE;
1583  }
1584 
1585  message_serializer = ast_sip_create_serializer("pjsip/messaging");
1586  if (!message_serializer) {
1589  return AST_MODULE_LOAD_DECLINE;
1590  }
1591 
1593  return AST_MODULE_LOAD_SUCCESS;
1594 }
const pjsip_method pjsip_message_method
int ast_msg_tech_register(const struct ast_msg_tech *tech)
Register a message technology.
Definition: message.c:1569
static const struct ast_msg_tech msg_tech
#define NULL
Definition: resample.c:96
static struct ast_taskprocessor * message_serializer
static pjsip_module messaging_module
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition: res_pjsip.c:3315
int ast_msg_tech_unregister(const struct ast_msg_tech *tech)
Unregister a message technology.
Definition: message.c:1610
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
Definition: res_pjsip.c:5133
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
void ast_sip_unregister_service(pjsip_module *module)
Definition: res_pjsip.c:3331
static struct ast_sip_session_supplement messaging_supplement
#define ast_sip_session_register_supplement(supplement)

◆ module_on_rx_request()

static pj_bool_t module_on_rx_request ( pjsip_rx_data *  rdata)
static

Definition at line 1407 of file res_pjsip_messaging.c.

References ast_debug, ast_msg_alloc(), ast_msg_destroy(), ast_msg_has_destination(), ast_msg_queue(), check_content_type(), msg_data::msg, NULL, pjsip_message_method, rx_data_to_ast_msg(), and send_response().

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 }
static enum pjsip_status_code rx_data_to_ast_msg(pjsip_rx_data *rdata, struct ast_msg *msg)
const pjsip_method pjsip_message_method
struct ast_msg * ast_msg_alloc(void)
Allocate a message.
Definition: message.c:418
static enum pjsip_status_code check_content_type(const pjsip_rx_data *rdata)
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
int ast_msg_queue(struct ast_msg *msg)
Queue a message for routing through the dialplan.
Definition: message.c:958
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
static pj_status_t send_response(pjsip_rx_data *rdata, enum pjsip_status_code code, pjsip_dialog *dlg, pjsip_transaction *tsx)
A message.
Definition: message.c:233
struct ast_msg * ast_msg_destroy(struct ast_msg *msg)
Destroy an ast_msg.
Definition: message.c:448

◆ msg_data_create()

static struct msg_data* msg_data_create ( const struct ast_msg msg,
const char *  destination,
const char *  from 
)
static

Definition at line 1139 of file res_pjsip_messaging.c.

References ao2_alloc, ao2_ref, ast_msg_ref(), ast_strdup, msg_data::destination, msg_data::from, msg_data::msg, msg_data_destroy(), and NULL.

Referenced by sip_msg_send().

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 
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 }
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
struct ast_msg * msg
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void msg_data_destroy(void *obj)
struct ast_msg * ast_msg_ref(struct ast_msg *msg)
Bump a msg&#39;s ref count.
Definition: message.c:442
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
A message.
Definition: message.c:233

◆ msg_data_destroy()

static void msg_data_destroy ( void *  obj)
static

Definition at line 1129 of file res_pjsip_messaging.c.

References ast_free, ast_msg_destroy(), msg_data::destination, msg_data::from, and msg_data::msg.

Referenced by msg_data_create().

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 }
struct ast_msg * msg
#define ast_free(a)
Definition: astmm.h:182
struct ast_msg * ast_msg_destroy(struct ast_msg *msg)
Destroy an ast_msg.
Definition: message.c:448

◆ msg_send()

static int msg_send ( void *  data)
static

Definition at line 1221 of file res_pjsip_messaging.c.

References ao2_cleanup, ast_begins_with(), ast_debug, ast_free, ast_log, ast_msg_get_body(), ast_msg_get_from(), ast_msg_get_to(), ast_sip_add_body(), ast_sip_create_request(), ast_sip_send_request(), ast_sorcery_object_get_id(), ast_strdupa, ast_strlen_zero, ast_test_suite_event_notify, msg_data::destination, msg_data::from, get_outbound_endpoint(), LOG_ERROR, LOG_WARNING, msg_data::msg, NULL, RAII_VAR, ast_sip_body::type, update_content_type(), update_from(), update_to_display_name(), update_to_uri(), and vars_to_headers().

Referenced by sip_msg_send().

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 }
static int update_to_display_name(pjsip_tx_data *tdata, char *to)
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
struct ast_msg * msg
const char * ast_msg_get_body(const struct ast_msg *msg)
Get the body of a message.
Definition: message.c:531
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
#define ast_strlen_zero(foo)
Definition: strings.h:52
const char * ast_msg_get_to(const struct ast_msg *msg)
Retrieve the destination of this message.
Definition: message.c:541
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#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
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:196
#define LOG_ERROR
Definition: logger.h:285
const char * ast_msg_get_from(const struct ast_msg *msg)
Retrieve the source of this message.
Definition: message.c:536
static int update_from(pjsip_tx_data *tdata, char *from)
static struct ast_sip_endpoint * get_outbound_endpoint(const char *to, char **uri)
#define ast_free(a)
Definition: astmm.h:182
static int update_to_uri(pjsip_tx_data *tdata, char *to)
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Definition: strings.h:94
SIP body description.
Definition: res_pjsip.h:2027
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

◆ print_body()

static int print_body ( pjsip_rx_data *  rdata,
char *  buf,
int  len 
)
static

Definition at line 964 of file res_pjsip_messaging.c.

Referenced by rx_data_to_ast_msg().

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 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

◆ rx_data_to_ast_msg()

static enum pjsip_status_code rx_data_to_ast_msg ( pjsip_rx_data *  rdata,
struct ast_msg msg 
)
static

Definition at line 1035 of file res_pjsip_messaging.c.

References ao2_cleanup, ast_assert, ast_copy_pj_str(), AST_MAX_EXTENSION, ast_msg_set_body(), ast_msg_set_context(), ast_msg_set_endpoint(), ast_msg_set_exten(), ast_msg_set_from(), ast_msg_set_tech(), ast_msg_set_to(), ast_msg_set_var(), ast_pjsip_rdata_get_endpoint(), AST_SIP_USER_OPTIONS_TRUNCATE_CHECK, ast_sorcery_object_get_id(), buf, context, exten, headers_to_vars(), MAX_BODY_SIZE, NULL, print_body(), RAII_VAR, S_OR, and sip_to_pjsip().

Referenced by module_on_rx_request().

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 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#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
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
#define MAX_BODY_SIZE
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define ast_assert(a)
Definition: utils.h:695
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
#define NULL
Definition: resample.c:96
static char * sip_to_pjsip(char *buf, int size, int capacity)
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
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.
#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
#define AST_MAX_EXTENSION
Definition: channel.h:135
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
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
static int headers_to_vars(const pjsip_rx_data *rdata, struct ast_msg *msg)
static int print_body(pjsip_rx_data *rdata, char *buf, int len)
int ast_msg_set_exten(struct ast_msg *msg, const char *fmt,...)
Set the dialplan extension for this message.
Definition: message.c:498
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
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
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#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
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ send_response()

static pj_status_t send_response ( pjsip_rx_data *  rdata,
enum pjsip_status_code  code,
pjsip_dialog *  dlg,
pjsip_transaction *  tsx 
)
static

Definition at line 1378 of file res_pjsip_messaging.c.

References ao2_cleanup, ast_log, ast_pjsip_rdata_get_endpoint(), ast_sip_create_response(), ast_sip_send_stateful_response(), LOG_ERROR, NULL, and status.

Referenced by incoming_in_dialog_request(), and module_on_rx_request().

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 }
#define NULL
Definition: resample.c:96
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.
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
#define ast_log
Definition: astobj2.c:42
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
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
#define LOG_ERROR
Definition: logger.h:285
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
jack_status_t status
Definition: app_jack.c:146

◆ sip_msg_send()

static int sip_msg_send ( const struct ast_msg msg,
const char *  destination,
const char *  from 
)
static

Definition at line 1352 of file res_pjsip_messaging.c.

References ao2_ref, ast_log, ast_sip_push_task_wait_serializer(), ast_strlen_zero, LOG_ERROR, msg_data_create(), and msg_send().

1353 {
1354  struct msg_data *mdata;
1355  int res;
1356 
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 
1368  ao2_ref(mdata, -1);
1369 
1370  return res;
1371 }
#define ast_strlen_zero(foo)
Definition: strings.h:52
static struct ast_taskprocessor * message_serializer
#define ast_log
Definition: astobj2.c:42
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 ao2_ref(o, delta)
Definition: astobj2.h:464
#define LOG_ERROR
Definition: logger.h:285
static int msg_send(void *data)
static struct msg_data * msg_data_create(const struct ast_msg *msg, const char *destination, const char *from)

◆ sip_to_pjsip()

static char* sip_to_pjsip ( char *  buf,
int  size,
int  capacity 
)
static

Definition at line 994 of file res_pjsip_messaging.c.

References ast_log, buf, LOG_WARNING, and NULL.

Referenced by rx_data_to_ast_msg().

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 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1596 of file res_pjsip_messaging.c.

References AST_MODFLAG_LOAD_ORDER, AST_MODPRI_APP_DEPEND, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ast_msg_tech_unregister(), ast_sip_session_unregister_supplement(), ast_sip_unregister_service(), ast_taskprocessor_unreference(), ASTERISK_GPL_KEY, load_module(), and messaging_module.

1597 {
1602  return 0;
1603 }
static const struct ast_msg_tech msg_tech
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
static struct ast_taskprocessor * message_serializer
static pjsip_module messaging_module
int ast_msg_tech_unregister(const struct ast_msg_tech *tech)
Unregister a message technology.
Definition: message.c:1610
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
void ast_sip_unregister_service(pjsip_module *module)
Definition: res_pjsip.c:3331
static struct ast_sip_session_supplement messaging_supplement

◆ update_content_type()

static void update_content_type ( pjsip_tx_data *  tdata,
struct ast_msg msg,
struct ast_sip_body body 
)
static

Definition at line 1173 of file res_pjsip_messaging.c.

References ast_log, ast_msg_get_var(), ast_strdupa, LOG_WARNING, NULL, ast_sip_body::subtype, type, and ast_sip_body::type.

Referenced by msg_send().

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 }
static const char type[]
Definition: chan_ooh323.c:109
const char * ast_msg_get_var(struct ast_msg *msg, const char *name)
Get the specified variable on the message.
Definition: message.c:620
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
const char * type
Definition: res_pjsip.h:2029
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char * subtype
Definition: res_pjsip.h:2031

◆ update_from()

static int update_from ( pjsip_tx_data *  tdata,
char *  from 
)
static

Definition at line 788 of file res_pjsip_messaging.c.

References ast_log, ast_strlen_zero, and LOG_WARNING.

Referenced by msg_send().

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 }
#define LOG_WARNING
Definition: logger.h:274
Domain data structure.
Definition: sip.h:888
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42

◆ update_to_display_name()

static int update_to_display_name ( pjsip_tx_data *  tdata,
char *  to 
)
static

Definition at line 753 of file res_pjsip_messaging.c.

Referenced by msg_send().

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 }

◆ update_to_uri()

static int update_to_uri ( pjsip_tx_data *  tdata,
char *  to 
)
static

Definition at line 686 of file res_pjsip_messaging.c.

References ast_alloca, ast_debug, ast_log, buf, DEBUG_ATLEAST, DEBUG_BUF_SIZE, LOG_WARNING, and NULL.

Referenced by msg_send().

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 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
#define DEBUG_BUF_SIZE
#define DEBUG_ATLEAST(level)
Definition: logger.h:441

◆ vars_to_headers()

static enum pjsip_status_code vars_to_headers ( const struct ast_msg msg,
pjsip_tx_data *  tdata 
)
static

Definition at line 892 of file res_pjsip_messaging.c.

References ast_log, ast_msg_var_iterator_destroy(), ast_msg_var_iterator_init(), ast_msg_var_iterator_next(), ast_msg_var_unref_current(), ast_sip_add_header(), is_msg_var_blocked(), ast_msg_var_iterator::iter, LOG_NOTICE, name, and value.

Referenced by msg_send().

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 }
struct ao2_iterator iter
Definition: message.c:640
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
int value
Definition: syslog.c:37
void ast_msg_var_iterator_destroy(struct ast_msg_var_iterator *iter)
Destroy a message variable iterator.
Definition: message.c:706
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
#define ast_log
Definition: astobj2.c:42
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
Channel datastore data for max forwards.
Definition: max_forwards.c:29
#define LOG_NOTICE
Definition: logger.h:263
static const char name[]
Definition: cdr_mysql.c:74
static int is_msg_var_blocked(const char *name)
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

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Messaging Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip,res_pjsip_session", }
static

Definition at line 1611 of file res_pjsip_messaging.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1611 of file res_pjsip_messaging.c.

◆ message_serializer

struct ast_taskprocessor* message_serializer
static

Definition at line 140 of file res_pjsip_messaging.c.

◆ messaging_module

pjsip_module messaging_module
static

Definition at line 1559 of file res_pjsip_messaging.c.

Referenced by load_module(), and unload_module().

◆ messaging_supplement

struct ast_sip_session_supplement messaging_supplement
static
Initial value:
= {
.method = "MESSAGE",
.incoming_request = incoming_in_dialog_request
}
static int incoming_in_dialog_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)

Definition at line 1554 of file res_pjsip_messaging.c.

◆ msg_tech

const struct ast_msg_tech msg_tech
static
Initial value:
= {
.name = "pjsip",
.msg_send = sip_msg_send,
}
static int sip_msg_send(const struct ast_msg *msg, const char *destination, const char *from)

Definition at line 1373 of file res_pjsip_messaging.c.

Referenced by action_messagesend(), ast_msg_send(), and msg_send_exec().

◆ pjsip_message_method

const pjsip_method pjsip_message_method = {PJSIP_OTHER_METHOD, {"MESSAGE", 7} }

Definition at line 134 of file res_pjsip_messaging.c.

Referenced by load_module(), and module_on_rx_request().