Asterisk - The Open Source Telephony Project GIT-master-8b8a8c1
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 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 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 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_to_display_name (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 = AST_BUILDOPT_SUM, .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

◆ MAX_BODY_SIZE

#define MAX_BODY_SIZE   1024

Definition at line 137 of file res_pjsip_messaging.c.

◆ MAX_HDR_SIZE

#define MAX_HDR_SIZE   512

Definition at line 136 of file res_pjsip_messaging.c.

◆ 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 1021 of file res_pjsip_messaging.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1021 of file res_pjsip_messaging.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 1021 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.

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:2248

References ast_sip_is_content_type().

Referenced by module_on_rx_request().

◆ 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.

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:1809

References text.

Referenced by incoming_in_dialog_request().

◆ headers_to_vars()

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

Definition at line 310 of file res_pjsip_messaging.c.

311{
312 char *c;
313 char name[MAX_HDR_SIZE];
314 char buf[MAX_HDR_SIZE];
315 int res = 0;
316 pjsip_hdr *h = rdata->msg_info.msg->hdr.next;
317 pjsip_hdr *end= &rdata->msg_info.msg->hdr;
318
319 while (h != end) {
320 if ((res = pjsip_hdr_print_on(h, buf, sizeof(buf)-1)) > 0) {
321 buf[res] = '\0';
322 if ((c = strchr(buf, ':'))) {
323 ast_copy_string(buf, ast_skip_blanks(c + 1), sizeof(buf));
324 }
325
326 ast_copy_pj_str(name, &h->name, sizeof(name));
327 if ((res = ast_msg_set_var(msg, name, buf)) != 0) {
328 break;
329 }
330 }
331 h = h->next;
332 }
333 return 0;
334}
char * end
Definition: eagi_proxy.c:73
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static const char name[]
Definition: format_mp3.c:68
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: main/message.c:641
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:2201
#define MAX_HDR_SIZE
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
static struct test_val 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().

◆ incoming_in_dialog_request()

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

Definition at line 867 of file res_pjsip_messaging.c.

868{
869 enum pjsip_status_code code;
870 int rc;
871 pjsip_dialog *dlg = session->inv_session->dlg;
872 pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
873 struct ast_msg_data *msg;
874 struct ast_party_caller *caller;
875 pjsip_name_addr *name_addr;
876 size_t from_len;
877 size_t to_len;
878 struct ast_msg_data_attribute attrs[4];
879 int pos = 0;
880 int body_pos;
881
882 if (!session->channel) {
883 send_response(rdata, PJSIP_SC_NOT_FOUND, dlg, tsx);
884 return 0;
885 }
886
887 code = check_content_type_in_dialog(rdata);
888 if (code != PJSIP_SC_OK) {
889 send_response(rdata, code, dlg, tsx);
890 return 0;
891 }
892
893 caller = ast_channel_caller(session->channel);
894
895 name_addr = (pjsip_name_addr *) rdata->msg_info.from->uri;
896 from_len = pj_strlen(&name_addr->display);
897 if (from_len) {
898 attrs[pos].type = AST_MSG_DATA_ATTR_FROM;
899 from_len++;
900 attrs[pos].value = ast_alloca(from_len);
901 ast_copy_pj_str(attrs[pos].value, &name_addr->display, from_len);
902 pos++;
903 } else if (caller->id.name.valid && !ast_strlen_zero(caller->id.name.str)) {
904 attrs[pos].type = AST_MSG_DATA_ATTR_FROM;
905 attrs[pos].value = caller->id.name.str;
906 pos++;
907 }
908
909 name_addr = (pjsip_name_addr *) rdata->msg_info.to->uri;
910 to_len = pj_strlen(&name_addr->display);
911 if (to_len) {
912 attrs[pos].type = AST_MSG_DATA_ATTR_TO;
913 to_len++;
914 attrs[pos].value = ast_alloca(to_len);
915 ast_copy_pj_str(attrs[pos].value, &name_addr->display, to_len);
916 pos++;
917 }
918
919 attrs[pos].type = AST_MSG_DATA_ATTR_CONTENT_TYPE;
920 attrs[pos].value = ast_alloca(rdata->msg_info.msg->body->content_type.type.slen
921 + rdata->msg_info.msg->body->content_type.subtype.slen + 2);
922 sprintf(attrs[pos].value, "%.*s/%.*s",
923 (int)rdata->msg_info.msg->body->content_type.type.slen,
924 rdata->msg_info.msg->body->content_type.type.ptr,
925 (int)rdata->msg_info.msg->body->content_type.subtype.slen,
926 rdata->msg_info.msg->body->content_type.subtype.ptr);
927 pos++;
928
929 body_pos = pos;
930 attrs[pos].type = AST_MSG_DATA_ATTR_BODY;
931 attrs[pos].value = ast_malloc(rdata->msg_info.msg->body->len + 1);
932 if (!attrs[pos].value) {
933 send_response(rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, dlg, tsx);
934 return 0;
935 }
936 ast_copy_string(attrs[pos].value, rdata->msg_info.msg->body->data, rdata->msg_info.msg->body->len + 1);
937 pos++;
938
940 if (!msg) {
941 ast_free(attrs[body_pos].value);
942 send_response(rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, dlg, tsx);
943 return 0;
944 }
945
946 ast_debug(1, "Received in-dialog MESSAGE from '%s:%s': %s %s\n",
948 ast_channel_name(session->channel),
951
952 rc = ast_msg_data_queue_frame(session->channel, msg);
953 ast_free(attrs[body_pos].value);
954 ast_free(msg);
955 if (rc != 0) {
956 send_response(rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, dlg, tsx);
957 } else {
958 send_response(rdata, PJSIP_SC_ACCEPTED, dlg, tsx);
959 }
960
961 return 0;
962}
static struct ast_mansession session
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_free(a)
Definition: astmm.h:180
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
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.
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.
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.
@ AST_MSG_DATA_ATTR_BODY
Definition: message.h:458
@ AST_MSG_DATA_ATTR_TO
Definition: message.h:455
@ AST_MSG_DATA_ATTR_FROM
Definition: message.h:456
@ AST_MSG_DATA_ATTR_CONTENT_TYPE
Definition: message.h:457
@ AST_MSG_DATA_SOURCE_TYPE_IN_DIALOG
Definition: message.h:449
#define ast_debug(level,...)
Log a DEBUG message.
static enum pjsip_status_code check_content_type_in_dialog(const pjsip_rx_data *rdata)
static pj_status_t send_response(pjsip_rx_data *rdata, enum pjsip_status_code code, pjsip_dialog *dlg, pjsip_transaction *tsx)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Structure used to transport a message through the frame core.
Caller Party information.
Definition: channel.h:420
struct ast_party_id id
Caller party ID.
Definition: channel.h:422
struct ast_party_name name
Subscriber name.
Definition: channel.h:342
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:281
char * str
Subscriber name (Malloced)
Definition: channel.h:266
int value
Definition: syslog.c:37

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(), check_content_type_in_dialog(), ast_party_caller::id, ast_party_id::name, send_response(), session, ast_party_name::str, ast_msg_data_attribute::type, ast_party_name::valid, ast_msg_data_attribute::value, and value.

◆ is_msg_var_blocked()

static int is_msg_var_blocked ( const char *  name)
static

Definition at line 240 of file res_pjsip_messaging.c.

241{
242 int i;
243
244 /* Don't block the Max-Forwards header because the user can override it */
245 static const char *hdr[] = {
246 "To",
247 "From",
248 "Via",
249 "Route",
250 "Contact",
251 "Call-ID",
252 "CSeq",
253 "Allow",
254 "Content-Length",
255 "Content-Type",
256 "Request-URI",
257 };
258
259 for (i = 0; i < ARRAY_LEN(hdr); ++i) {
260 if (!strcasecmp(name, hdr[i])) {
261 /* Block addition of this header. */
262 return 1;
263 }
264 }
265 return 0;
266}
#define ARRAY_LEN(a)
Definition: utils.h:666

References ARRAY_LEN, and name.

Referenced by vars_to_headers().

◆ load_module()

static int load_module ( void  )
static

Definition at line 976 of file res_pjsip_messaging.c.

977{
978 if (ast_sip_register_service(&messaging_module) != PJ_SUCCESS) {
980 }
981
982 if (pjsip_endpt_add_capability(ast_sip_get_pjsip_endpoint(),
983 NULL, PJSIP_H_ALLOW, NULL, 1,
984 &pjsip_message_method.name) != PJ_SUCCESS) {
985
988 }
989
993 }
994
996 if (!message_serializer) {
1000 }
1001
1004}
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
Definition: res_pjsip.c:2094
int ast_msg_tech_unregister(const struct ast_msg_tech *tech)
Unregister a message technology.
int ast_msg_tech_register(const struct ast_msg_tech *tech)
Register a message technology.
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
void ast_sip_unregister_service(pjsip_module *module)
Definition: res_pjsip.c:133
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition: res_pjsip.c:117
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:520
static struct ast_sip_session_supplement messaging_supplement
static pjsip_module messaging_module
static struct ast_taskprocessor * message_serializer
static const struct ast_msg_tech msg_tech
const pjsip_method pjsip_message_method
#define ast_sip_session_register_supplement(supplement)
#define NULL
Definition: resample.c:96

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(), message_serializer, messaging_module, messaging_supplement, msg_tech, NULL, and pjsip_message_method.

◆ module_on_rx_request()

static pj_bool_t module_on_rx_request ( pjsip_rx_data *  rdata)
static

Definition at line 817 of file res_pjsip_messaging.c.

818{
819 enum pjsip_status_code code;
820 struct ast_msg *msg;
821
822 /* if not a MESSAGE, don't handle */
823 if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_message_method)) {
824 return PJ_FALSE;
825 }
826
827 code = check_content_type(rdata);
828 if (code != PJSIP_SC_OK) {
829 send_response(rdata, code, NULL, NULL);
830 return PJ_TRUE;
831 }
832
833 msg = ast_msg_alloc();
834 if (!msg) {
835 send_response(rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, NULL, NULL);
836 return PJ_TRUE;
837 }
838
839 code = rx_data_to_ast_msg(rdata, msg);
840 if (code != PJSIP_SC_OK) {
841 send_response(rdata, code, NULL, NULL);
842 ast_msg_destroy(msg);
843 return PJ_TRUE;
844 }
845
846 if (!ast_msg_has_destination(msg)) {
847 ast_debug(1, "MESSAGE request received, but no handler wanted it\n");
848 send_response(rdata, PJSIP_SC_NOT_FOUND, NULL, NULL);
849 ast_msg_destroy(msg);
850 return PJ_TRUE;
851 }
852
853 /* Send it to the messaging core.
854 *
855 * If we are unable to send a response, the most likely reason is that we
856 * are handling a retransmission of an incoming MESSAGE and were unable to
857 * create a transaction due to a duplicate key. If we are unable to send
858 * a response, we should not queue the message to the dialplan
859 */
860 if (!send_response(rdata, PJSIP_SC_ACCEPTED, NULL, NULL)) {
861 ast_msg_queue(msg);
862 }
863
864 return PJ_TRUE;
865}
struct ast_msg * ast_msg_destroy(struct ast_msg *msg)
Destroy an ast_msg.
Definition: main/message.c:474
int ast_msg_has_destination(const struct ast_msg *msg)
Determine if a particular message has a destination via some handler.
Definition: main/message.c:963
struct ast_msg * ast_msg_alloc(void)
Allocate a message.
Definition: main/message.c:444
int ast_msg_queue(struct ast_msg *msg)
Queue a message for routing through the dialplan.
Definition: main/message.c:984
static enum pjsip_status_code check_content_type(const pjsip_rx_data *rdata)
static enum pjsip_status_code rx_data_to_ast_msg(pjsip_rx_data *rdata, struct ast_msg *msg)
A message.
Definition: main/message.c:259

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

◆ 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 559 of file res_pjsip_messaging.c.

560{
561 struct msg_data *mdata = ao2_alloc(sizeof(*mdata), msg_data_destroy);
562
563 if (!mdata) {
564 return NULL;
565 }
566
567 /* typecast to suppress const warning */
568 mdata->msg = ast_msg_ref((struct ast_msg *) msg);
569
570 /* To starts with 'pjsip:' which needs to be removed. */
571 if (!(destination = strchr(destination, ':'))) {
572 ao2_ref(mdata, -1);
573 return NULL;
574 }
575 ++destination;/* Now skip the ':' */
576
578 mdata->from = ast_strdup(from);
579
580 return mdata;
581}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
struct ast_msg * ast_msg_ref(struct ast_msg *msg)
Bump a msg's ref count.
Definition: main/message.c:468
static void msg_data_destroy(void *obj)
struct ast_msg * msg

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().

◆ msg_data_destroy()

static void msg_data_destroy ( void *  obj)
static

Definition at line 549 of file res_pjsip_messaging.c.

550{
551 struct msg_data *mdata = obj;
552
553 ast_free(mdata->from);
554 ast_free(mdata->destination);
555
556 ast_msg_destroy(mdata->msg);
557}

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

Referenced by msg_data_create().

◆ msg_send()

static int msg_send ( void *  data)
static

Definition at line 631 of file res_pjsip_messaging.c.

632{
633 struct msg_data *mdata = data; /* The caller holds a reference */
634
635 struct ast_sip_body body = {
636 .type = "text",
637 .subtype = "plain",
638 .body_text = ast_msg_get_body(mdata->msg)
639 };
640
641 pjsip_tx_data *tdata;
642 RAII_VAR(char *, uri, NULL, ast_free);
643 RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
644
645 ast_debug(3, "mdata From: %s msg From: %s mdata Destination: %s msg To: %s\n",
646 mdata->from, ast_msg_get_from(mdata->msg), mdata->destination, ast_msg_get_to(mdata->msg));
647
648 endpoint = ast_sip_get_endpoint(mdata->destination, 1, &uri);
649 if (!endpoint) {
651 "PJSIP MESSAGE - Could not find endpoint '%s' and no default outbound endpoint configured\n",
652 mdata->destination);
653
654 ast_test_suite_event_notify("MSG_ENDPOINT_URI_FAIL",
655 "MdataFrom: %s\r\n"
656 "MsgFrom: %s\r\n"
657 "MdataDestination: %s\r\n"
658 "MsgTo: %s\r\n",
659 mdata->from,
660 ast_msg_get_from(mdata->msg),
661 mdata->destination,
662 ast_msg_get_to(mdata->msg));
663
664 return -1;
665 }
666
667 ast_debug(3, "Request URI: %s\n", uri);
668
669 if (ast_sip_create_request("MESSAGE", NULL, endpoint, uri, NULL, &tdata)) {
670 ast_log(LOG_WARNING, "PJSIP MESSAGE - Could not create request\n");
671 return -1;
672 }
673
674 /* If there was a To in the actual message, */
675 if (!ast_strlen_zero(ast_msg_get_to(mdata->msg))) {
676 char *msg_to = ast_strdupa(ast_msg_get_to(mdata->msg));
677
678 /*
679 * It's possible that the message To was copied from
680 * an incoming MESSAGE in which case it'll have the
681 * pjsip: tech prepended to it. We need to remove it.
682 */
683 if (ast_begins_with(msg_to, "pjsip:")) {
684 msg_to += 6;
685 }
686 ast_sip_update_to_uri(tdata, msg_to);
687 } else {
688 /*
689 * If there was no To in the message, it's still possible
690 * that there is a display name in the mdata To. If so,
691 * we'll copy the URI display name to the tdata To.
692 */
693 update_to_display_name(tdata, uri);
694 }
695
696 if (!ast_strlen_zero(mdata->from)) {
697 ast_sip_update_from(tdata, mdata->from);
698 } else if (!ast_strlen_zero(ast_msg_get_from(mdata->msg))) {
699 ast_sip_update_from(tdata, (char *)ast_msg_get_from(mdata->msg));
700 }
701
702#ifdef TEST_FRAMEWORK
703 {
704 pjsip_name_addr *tdata_name_addr;
705 pjsip_sip_uri *tdata_sip_uri;
706 char touri[128];
707 char fromuri[128];
708
709 tdata_name_addr = (pjsip_name_addr *) PJSIP_MSG_TO_HDR(tdata->msg)->uri;
710 tdata_sip_uri = pjsip_uri_get_uri(tdata_name_addr->uri);
711 pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, touri, sizeof(touri));
712 tdata_name_addr = (pjsip_name_addr *) PJSIP_MSG_FROM_HDR(tdata->msg)->uri;
713 tdata_sip_uri = pjsip_uri_get_uri(tdata_name_addr->uri);
714 pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, fromuri, sizeof(fromuri));
715
716 ast_test_suite_event_notify("MSG_FROMTO_URI",
717 "MdataFrom: %s\r\n"
718 "MsgFrom: %s\r\n"
719 "MdataDestination: %s\r\n"
720 "MsgTo: %s\r\n"
721 "Endpoint: %s\r\n"
722 "RequestURI: %s\r\n"
723 "ToURI: %s\r\n"
724 "FromURI: %s\r\n",
725 mdata->from,
726 ast_msg_get_from(mdata->msg),
727 mdata->destination,
728 ast_msg_get_to(mdata->msg),
730 uri,
731 touri,
732 fromuri
733 );
734 }
735#endif
736
737 update_content_type(tdata, mdata->msg, &body);
738
739 if (ast_sip_add_body(tdata, &body)) {
740 pjsip_tx_data_dec_ref(tdata);
741 ast_log(LOG_ERROR, "PJSIP MESSAGE - Could not add body to request\n");
742 return -1;
743 }
744
745 /*
746 * This copies any headers set with MESSAGE_DATA() to the
747 * tdata.
748 */
749 vars_to_headers(mdata->msg, tdata);
750
751 ast_debug(1, "Sending message to '%s' (via endpoint %s) from '%s'\n",
752 uri, ast_sorcery_object_get_id(endpoint), mdata->from);
753
754 if (ast_sip_send_request(tdata, NULL, endpoint, NULL, NULL)) {
755 ast_log(LOG_ERROR, "PJSIP MESSAGE - Could not send request\n");
756 return -1;
757 }
758
759 return 0;
760}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define LOG_ERROR
#define LOG_WARNING
const char * ast_msg_get_from(const struct ast_msg *msg)
Retrieve the source of this message.
Definition: main/message.c:562
const char * ast_msg_get_to(const struct ast_msg *msg)
Retrieve the destination of this message.
Definition: main/message.c:567
const char * ast_msg_get_body(const struct ast_msg *msg)
Get the body of a message.
Definition: main/message.c:557
struct ast_sip_endpoint * ast_sip_get_endpoint(const char *to, int get_default_outbound, char **uri)
Retrieves an endpoint and URI from the "to" string.
Definition: res_pjsip.c:3249
int ast_sip_update_from(pjsip_tx_data *tdata, char *from)
Overwrite fields in the outbound 'From' header.
Definition: res_pjsip.c:3383
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:1979
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:2052
int ast_sip_update_to_uri(pjsip_tx_data *tdata, const char *to)
Replace the To URI in the tdata with the supplied one.
Definition: res_pjsip.c:3323
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:1435
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)
static int update_to_display_name(pjsip_tx_data *tdata, char *to)
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2317
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
Definition: strings.h:97
SIP body description.
Definition: res_pjsip.h:2444
const char * type
Definition: res_pjsip.h:2446
An entity with which Asterisk communicates.
Definition: res_pjsip.h:1051
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:189
#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:941

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_get_endpoint(), ast_sip_send_request(), ast_sip_update_from(), ast_sip_update_to_uri(), ast_sorcery_object_get_id(), ast_strdupa, ast_strlen_zero(), ast_test_suite_event_notify, msg_data::destination, msg_data::from, LOG_ERROR, LOG_WARNING, msg_data::msg, NULL, RAII_VAR, ast_sip_body::type, update_content_type(), update_to_display_name(), and vars_to_headers().

Referenced by sip_msg_send().

◆ print_body()

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

Definition at line 347 of file res_pjsip_messaging.c.

348{
349 int res;
350
351 if (!rdata->msg_info.msg->body || !rdata->msg_info.msg->body->len) {
352 return 0;
353 }
354
355 if ((res = rdata->msg_info.msg->body->print_body(
356 rdata->msg_info.msg->body, buf, len)) < 0) {
357 return res;
358 }
359
360 /* remove any trailing carriage return/line feeds */
361 while (res > 0 && ((buf[--res] == '\r') || (buf[res] == '\n')));
362
363 buf[++res] = '\0';
364
365 return res;
366}
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

References buf, and len().

Referenced by rx_data_to_ast_msg().

◆ 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 418 of file res_pjsip_messaging.c.

419{
420 RAII_VAR(struct ast_sip_endpoint *, endpt, NULL, ao2_cleanup);
421 pjsip_uri *ruri = rdata->msg_info.msg->line.req.uri;
422 pjsip_name_addr *name_addr;
423 pjsip_sip_uri *suri;
424 char *display_name;
425 char buf[MAX_BODY_SIZE];
426 const char *field;
427 const char *context;
428 char exten[AST_MAX_EXTENSION];
429 int res = 0;
430 int size;
431
432 if (!ast_sip_is_allowed_uri(ruri)) {
433 return PJSIP_SC_UNSUPPORTED_URI_SCHEME;
434 }
435
437
438 /*
439 * We may want to match in the dialplan without any user
440 * options getting in the way.
441 */
443
444 endpt = ast_pjsip_rdata_get_endpoint(rdata);
445 ast_assert(endpt != NULL);
446
447 context = S_OR(endpt->message_context, endpt->context);
448 res |= ast_msg_set_context(msg, "%s", context);
449 res |= ast_msg_set_exten(msg, "%s", exten);
450
451 /* to header */
452 name_addr = (pjsip_name_addr *)rdata->msg_info.to->uri;
453 size = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, name_addr, buf, sizeof(buf) - 1);
454 if (size <= 0) {
455 return PJSIP_SC_INTERNAL_SERVER_ERROR;
456 }
457 buf[size] = '\0';
458 res |= ast_msg_set_to(msg, "%s", sip_to_pjsip(buf, ++size, sizeof(buf) - 1));
459
460 /*
461 * We need to sanitize the from header's display name
462 * by replacing any control characters, including NULLs,
463 * with spaces. Since the display name is a pj_str_t, we
464 * can't modify it in place, so we need to copy it to a
465 * temporary buffer first. The good news is that we can't
466 * accidentally run over the end of the buffer, even if
467 * there's a NULL in the middle, because the display name
468 * is a pj_str_t and we know its length.
469 */
470 name_addr = (pjsip_name_addr *)rdata->msg_info.from->uri;
471 suri = pjsip_uri_get_uri((pjsip_uri *)name_addr);
472 if (name_addr->display.slen > 0) {
473 int i = 0;
474 char *temp_name = ast_alloca(name_addr->display.slen + 1);
475 for (i = 0; i < name_addr->display.slen; i++) {
476 if (name_addr->display.ptr[i] < 32) {
477 temp_name[i] = ' ';
478 } else {
479 temp_name[i] = name_addr->display.ptr[i];
480 }
481 }
482 temp_name[name_addr->display.slen] = '\0';
483 /*
484 * We need space for each double quote, the display name,
485 * the trailing space and the NULL terminator.
486 */
487 display_name = ast_alloca(name_addr->display.slen + 5);
488 size = sprintf(display_name, "\"%s\" ", temp_name); /* Safe */
489 } else {
490 display_name = "";
491 }
492
493 /*
494 * In the end, the string should look like...
495 * "display name" <scheme:user@host>
496 * If there's no display name, it and its double quotes
497 * will be suppressed.
498 * Note that the port is not included.
499 */
501 display_name,
502 PJSTR_PRINTF_VAR(*pjsip_uri_get_scheme(suri)),
503 PJSTR_PRINTF_VAR(*ast_sip_pjsip_uri_get_username((pjsip_uri *)name_addr)),
504 PJSTR_PRINTF_VAR(*ast_sip_pjsip_uri_get_hostname((pjsip_uri *)name_addr)));
505
506 field = pj_sockaddr_print(&rdata->pkt_info.src_addr, buf, sizeof(buf) - 1, 3);
507 res |= ast_msg_set_var(msg, "PJSIP_RECVADDR", field);
508
509 switch (rdata->tp_info.transport->key.type) {
510 case PJSIP_TRANSPORT_UDP:
511 case PJSIP_TRANSPORT_UDP6:
512 field = "udp";
513 break;
514 case PJSIP_TRANSPORT_TCP:
515 case PJSIP_TRANSPORT_TCP6:
516 field = "tcp";
517 break;
518 case PJSIP_TRANSPORT_TLS:
519 case PJSIP_TRANSPORT_TLS6:
520 field = "tls";
521 break;
522 default:
523 field = rdata->tp_info.transport->type_name;
524 }
525 ast_msg_set_var(msg, "PJSIP_TRANSPORT", field);
526
527 if (print_body(rdata, buf, sizeof(buf) - 1) > 0) {
528 res |= ast_msg_set_body(msg, "%s", buf);
529 }
530
531 /* endpoint name */
532 res |= ast_msg_set_tech(msg, "%s", "PJSIP");
533 res |= ast_msg_set_endpoint(msg, "%s", ast_sorcery_object_get_id(endpt));
534 if (endpt->id.self.name.valid) {
535 res |= ast_msg_set_var(msg, "PJSIP_ENDPOINT", endpt->id.self.name.str);
536 }
537
538 res |= headers_to_vars(rdata, msg);
539
540 return !res ? PJSIP_SC_OK : PJSIP_SC_INTERNAL_SERVER_ERROR;
541}
#define AST_MAX_EXTENSION
Definition: channel.h:134
int ast_msg_set_from(struct ast_msg *msg, const char *fmt,...)
Set the 'from' URI of a message.
Definition: main/message.c:491
int ast_msg_set_endpoint(struct ast_msg *msg, const char *fmt,...)
Set the technology's endpoint associated with this message.
Definition: main/message.c:546
int ast_msg_set_exten(struct ast_msg *msg, const char *fmt,...)
Set the dialplan extension for this message.
Definition: main/message.c:524
int ast_msg_set_tech(struct ast_msg *msg, const char *fmt,...)
Set the technology associated with this message.
Definition: main/message.c:535
int ast_msg_set_context(struct ast_msg *msg, const char *fmt,...)
Set the dialplan context for this message.
Definition: main/message.c:513
int ast_msg_set_body(struct ast_msg *msg, const char *fmt,...)
Set the 'body' text of a message (in UTF-8)
Definition: main/message.c:502
int ast_msg_set_to(struct ast_msg *msg, const char *fmt,...)
Set the 'to' URI of a message.
Definition: main/message.c:480
const pj_str_t * ast_sip_pjsip_uri_get_username(pjsip_uri *uri)
Get the user portion of the pjsip_uri.
Definition: res_pjsip.c:3477
int ast_sip_is_allowed_uri(pjsip_uri *uri)
Check whether a pjsip_uri is allowed or not.
Definition: res_pjsip.c:3472
#define AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(str)
Truncate the URI user field options string if enabled.
Definition: res_pjsip.h:3504
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.
const pj_str_t * ast_sip_pjsip_uri_get_hostname(pjsip_uri *uri)
Get the host portion of the pjsip_uri.
Definition: res_pjsip.c:3496
#define PJSTR_PRINTF_VAR(_v)
Definition: res_pjsip.h:72
#define PJSTR_PRINTF_SPEC
Definition: res_pjsip.h:71
static int print_body(pjsip_rx_data *rdata, char *buf, int len)
#define MAX_BODY_SIZE
static char * sip_to_pjsip(char *buf, int size, int capacity)
static int headers_to_vars(const pjsip_rx_data *rdata, struct ast_msg *msg)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
#define ast_assert(a)
Definition: utils.h:739

References ao2_cleanup, ast_alloca, 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_is_allowed_uri(), ast_sip_pjsip_uri_get_hostname(), ast_sip_pjsip_uri_get_username(), AST_SIP_USER_OPTIONS_TRUNCATE_CHECK, ast_sorcery_object_get_id(), buf, voicemailpwcheck::context, headers_to_vars(), MAX_BODY_SIZE, NULL, PJSTR_PRINTF_SPEC, PJSTR_PRINTF_VAR, print_body(), RAII_VAR, S_OR, and sip_to_pjsip().

Referenced by module_on_rx_request().

◆ 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 788 of file res_pjsip_messaging.c.

790{
791 pjsip_tx_data *tdata;
792 pj_status_t status;
793
794 status = ast_sip_create_response(rdata, code, NULL, &tdata);
795 if (status != PJ_SUCCESS) {
796 ast_log(LOG_ERROR, "Unable to create response (%d)\n", status);
797 return status;
798 }
799
800 if (dlg && tsx) {
801 status = pjsip_dlg_send_response(dlg, tsx, tdata);
802 } else {
803 struct ast_sip_endpoint *endpoint;
804
805 endpoint = ast_pjsip_rdata_get_endpoint(rdata);
806 status = ast_sip_send_stateful_response(rdata, tdata, endpoint);
807 ao2_cleanup(endpoint);
808 }
809
810 if (status != PJ_SUCCESS) {
811 ast_log(LOG_ERROR, "Unable to send response (%d)\n", status);
812 }
813
814 return status;
815}
jack_status_t status
Definition: app_jack.c:149
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:2468
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:2424

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().

◆ sip_msg_send()

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

Definition at line 762 of file res_pjsip_messaging.c.

763{
764 struct msg_data *mdata;
765 int res;
766
768 ast_log(LOG_ERROR, "SIP MESSAGE - a 'To' URI must be specified\n");
769 return -1;
770 }
771
773 if (!mdata) {
774 return -1;
775 }
776
778 ao2_ref(mdata, -1);
779
780 return res;
781}
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:2179
static int msg_send(void *data)
static struct msg_data * msg_data_create(const struct ast_msg *msg, const char *destination, const char *from)

References ao2_ref, ast_log, ast_sip_push_task_wait_serializer(), ast_strlen_zero(), msg_data::destination, msg_data::from, LOG_ERROR, message_serializer, msg_data::msg, msg_data_create(), and msg_send().

◆ sip_to_pjsip()

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

Definition at line 377 of file res_pjsip_messaging.c.

378{
379 int count;
380 const char *scheme;
381 char *res = buf;
382
383 /* remove any wrapping brackets */
384 if (*buf == '<') {
385 ++buf;
386 --size;
387 }
388
389 scheme = strncmp(buf, "sip", 3) ? "pjsip:" : "pj";
390 count = strlen(scheme);
391 if (count + size >= capacity) {
392 ast_log(LOG_WARNING, "Unable to handle MESSAGE- incoming uri "
393 "too large for given buffer\n");
394 return NULL;
395 }
396
397 memmove(res + count, buf, size);
398 memcpy(res, scheme, count);
399
400 buf += size - 1;
401 if (*buf == '>') {
402 *buf = '\0';
403 }
404
405 return res;
406}

References ast_log, buf, LOG_WARNING, and NULL.

Referenced by rx_data_to_ast_msg().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1006 of file res_pjsip_messaging.c.

1007{
1012 return 0;
1013}
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
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.

References ast_msg_tech_unregister(), ast_sip_session_unregister_supplement(), ast_sip_unregister_service(), ast_taskprocessor_unreference(), message_serializer, messaging_module, messaging_supplement, and msg_tech.

◆ 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 583 of file res_pjsip_messaging.c.

584{
585 static const pj_str_t CONTENT_TYPE = { "Content-Type", sizeof("Content-Type") - 1 };
586
587 const char *content_type = ast_msg_get_var(msg, pj_strbuf(&CONTENT_TYPE));
588 if (content_type) {
589 pj_str_t type, subtype;
590 pjsip_ctype_hdr *parsed;
591
592 /* Let pjsip do the parsing for us */
593 parsed = pjsip_parse_hdr(tdata->pool, &CONTENT_TYPE,
594 ast_strdupa(content_type), strlen(content_type),
595 NULL);
596
597 if (!parsed) {
598 ast_log(LOG_WARNING, "Failed to parse '%s' as a content type. Using text/plain\n",
599 content_type);
600 return;
601 }
602
603 /* We need to turn type and subtype into zero-terminated strings */
604 pj_strdup_with_null(tdata->pool, &type, &parsed->media.type);
605 pj_strdup_with_null(tdata->pool, &subtype, &parsed->media.subtype);
606
607 body->type = pj_strbuf(&type);
608 body->subtype = pj_strbuf(&subtype);
609 }
610}
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: main/message.c:646
const char * subtype
Definition: res_pjsip.h:2448

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

Referenced by msg_send().

◆ update_to_display_name()

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

Definition at line 207 of file res_pjsip_messaging.c.

208{
209 pjsip_name_addr *parsed_name_addr;
210
211 parsed_name_addr = (pjsip_name_addr *) pjsip_parse_uri(tdata->pool, to, strlen(to),
212 PJSIP_PARSE_URI_AS_NAMEADDR);
213
214 if (parsed_name_addr) {
215 if (pj_strlen(&parsed_name_addr->display)) {
216 pjsip_name_addr *name_addr =
217 (pjsip_name_addr *) PJSIP_MSG_TO_HDR(tdata->msg)->uri;
218
219 pj_strdup(tdata->pool, &name_addr->display, &parsed_name_addr->display);
220
221 }
222 return 0;
223 }
224
225 return -1;
226}

Referenced by msg_send().

◆ vars_to_headers()

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

Definition at line 275 of file res_pjsip_messaging.c.

276{
277 const char *name;
278 const char *value;
279 int max_forwards;
281
285 if (!strcasecmp(name, "Max-Forwards")) {
286 /* Decrement Max-Forwards for SIP loop prevention. */
287 if (sscanf(value, "%30d", &max_forwards) != 1 || --max_forwards == 0) {
289 ast_log(LOG_NOTICE, "MESSAGE(Max-Forwards) reached zero. MESSAGE not sent.\n");
290 return -1;
291 }
292 sprintf((char *) value, "%d", max_forwards);
294 } else if (!is_msg_var_blocked(name)) {
296 }
297 }
299
300 return PJSIP_SC_OK;
301}
#define LOG_NOTICE
void ast_msg_var_iterator_destroy(struct ast_msg_var_iterator *iter)
Destroy a message variable iterator.
Definition: main/message.c:732
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: main/message.c:715
void ast_msg_var_unref_current(struct ast_msg_var_iterator *iter)
Unref a message var from inside an iterator loop.
Definition: main/message.c:726
struct ast_msg_var_iterator * ast_msg_var_iterator_init(const struct ast_msg *msg)
Create a new message variable iterator.
Definition: main/message.c:670
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:2008
static int is_msg_var_blocked(const char *name)
struct ao2_iterator iter
Definition: main/message.c:666
Channel datastore data for max forwards.
Definition: max_forwards.c:29

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().

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 = AST_BUILDOPT_SUM, .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 1021 of file res_pjsip_messaging.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1021 of file res_pjsip_messaging.c.

◆ message_serializer

struct ast_taskprocessor* message_serializer
static

Definition at line 140 of file res_pjsip_messaging.c.

Referenced by load_module(), sip_msg_send(), and unload_module().

◆ messaging_module

pjsip_module messaging_module
static

Definition at line 969 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 964 of file res_pjsip_messaging.c.

Referenced by load_module(), and unload_module().

◆ 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 783 of file res_pjsip_messaging.c.

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

◆ 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().