123 #include <pjsip_ua.h>
128 #include "asterisk/res_pjsip.h"
129 #include "asterisk/res_pjsip_session.h"
132 #include "asterisk/uri.h"
134 const pjsip_method pjsip_message_method = {PJSIP_OTHER_METHOD, {
"MESSAGE", 7} };
136 #define MAX_HDR_SIZE 512
137 #define MAX_BODY_SIZE 1024
138 #define MAX_USER_SIZE 128
151 static enum pjsip_status_code check_content_type(
const pjsip_rx_data *rdata)
154 if (rdata->msg_info.msg->body && rdata->msg_info.msg->body->len) {
155 res = ast_sip_is_content_type(
156 &rdata->msg_info.msg->body->content_type,
"text",
"plain");
158 res = rdata->msg_info.ctype &&
159 ast_sip_is_content_type(
160 &rdata->msg_info.ctype->media,
"text",
"plain");
163 return res ? PJSIP_SC_OK : PJSIP_SC_UNSUPPORTED_MEDIA_TYPE;
175 static enum pjsip_status_code check_content_type_in_dialog(
const pjsip_rx_data *rdata)
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};
181 if (!(rdata->msg_info.msg->body && rdata->msg_info.msg->body->len > 0)) {
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) {
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)) {
207 static int update_to_display_name(pjsip_tx_data *tdata,
char *to)
209 pjsip_name_addr *parsed_name_addr;
211 parsed_name_addr = (pjsip_name_addr *) pjsip_parse_uri(tdata->pool, to, strlen(to),
212 PJSIP_PARSE_URI_AS_NAMEADDR);
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;
219 pj_strdup(tdata->pool, &name_addr->display, &parsed_name_addr->display);
240 static int is_msg_var_blocked(
const char *
name)
245 static const char *hdr[] = {
259 for (i = 0; i < ARRAY_LEN(hdr); ++i) {
260 if (!strcasecmp(name, hdr[i])) {
275 static enum pjsip_status_code vars_to_headers(
const struct ast_msg *msg, pjsip_tx_data *tdata)
285 if (!strcasecmp(name,
"Max-Forwards")) {
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");
292 sprintf((
char *) value,
"%d", max_forwards);
293 ast_sip_add_header(tdata, name, value);
294 }
else if (!is_msg_var_blocked(name)) {
295 ast_sip_add_header(tdata, name, value);
310 static int headers_to_vars(
const pjsip_rx_data *rdata,
struct ast_msg *msg)
313 char name[MAX_HDR_SIZE];
314 char buf[MAX_HDR_SIZE];
316 pjsip_hdr *h = rdata->msg_info.msg->hdr.next;
317 pjsip_hdr *end= &rdata->msg_info.msg->hdr;
320 if ((res = pjsip_hdr_print_on(h, buf,
sizeof(buf)-1)) > 0) {
322 if ((c = strchr(buf,
':'))) {
326 ast_copy_pj_str(name, &h->name,
sizeof(name));
347 static int print_body(pjsip_rx_data *rdata,
char *buf,
int len)
351 if (!rdata->msg_info.msg->body || !rdata->msg_info.msg->body->len) {
355 if ((res = rdata->msg_info.msg->body->print_body(
356 rdata->msg_info.msg->body, buf, len)) < 0) {
361 while (res > 0 && ((buf[--res] ==
'\r') || (buf[res] ==
'\n')));
377 static char *
sip_to_pjsip(
char *buf,
int size,
int capacity)
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");
397 memmove(res + count, buf, size);
398 memcpy(res, scheme, count);
418 static enum pjsip_status_code rx_data_to_ast_msg(pjsip_rx_data *rdata,
struct ast_msg *msg)
421 pjsip_uri *ruri = rdata->msg_info.msg->line.req.uri;
422 pjsip_name_addr *name_addr;
423 char buf[MAX_BODY_SIZE];
430 if (!ast_sip_is_allowed_uri(ruri)) {
431 return PJSIP_SC_UNSUPPORTED_URI_SCHEME;
440 AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten);
442 endpt = ast_pjsip_rdata_get_endpoint(rdata);
443 ast_assert(endpt != NULL);
445 context =
S_OR(endpt->message_context, endpt->context);
450 name_addr = (pjsip_name_addr *)rdata->msg_info.to->uri;
451 size = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, name_addr, buf,
sizeof(buf) - 1);
453 return PJSIP_SC_INTERNAL_SERVER_ERROR;
459 name_addr = (pjsip_name_addr *)rdata->msg_info.from->uri;
460 size = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, name_addr, buf,
sizeof(buf) - 1);
462 return PJSIP_SC_INTERNAL_SERVER_ERROR;
467 field = pj_sockaddr_print(&rdata->pkt_info.src_addr, buf,
sizeof(buf) - 1, 3);
470 switch (rdata->tp_info.transport->key.type) {
471 case PJSIP_TRANSPORT_UDP:
472 case PJSIP_TRANSPORT_UDP6:
475 case PJSIP_TRANSPORT_TCP:
476 case PJSIP_TRANSPORT_TCP6:
479 case PJSIP_TRANSPORT_TLS:
480 case PJSIP_TRANSPORT_TLS6:
484 field = rdata->tp_info.transport->type_name;
488 if (print_body(rdata, buf,
sizeof(buf) - 1) > 0) {
495 if (endpt->id.self.name.valid) {
496 res |=
ast_msg_set_var(msg,
"PJSIP_ENDPOINT", endpt->id.self.name.str);
499 res |= headers_to_vars(rdata, msg);
501 return !res ? PJSIP_SC_OK : PJSIP_SC_INTERNAL_SERVER_ERROR;
510 static void msg_data_destroy(
void *obj)
514 ast_free(mdata->from);
515 ast_free(mdata->destination);
520 static struct msg_data *msg_data_create(
const struct ast_msg *msg,
const char *destination,
const char *from)
523 struct msg_data *mdata = ao2_alloc(
sizeof(*mdata), msg_data_destroy);
533 if (!(destination = strchr(destination,
':'))) {
547 uri_params = strchr(mdata->from,
'@');
548 if (uri_params && (uri_params = strchr(mdata->from,
';'))) {
554 static void update_content_type(pjsip_tx_data *tdata,
struct ast_msg *msg,
struct ast_sip_body *body)
556 static const pj_str_t CONTENT_TYPE = {
"Content-Type",
sizeof(
"Content-Type") - 1 };
558 const char *content_type =
ast_msg_get_var(msg, pj_strbuf(&CONTENT_TYPE));
560 pj_str_t type, subtype;
561 pjsip_ctype_hdr *parsed;
564 parsed = pjsip_parse_hdr(tdata->pool, &CONTENT_TYPE,
569 ast_log(LOG_WARNING,
"Failed to parse '%s' as a content type. Using text/plain\n",
575 pj_strdup_with_null(tdata->pool, &type, &parsed->media.type);
576 pj_strdup_with_null(tdata->pool, &subtype, &parsed->media.subtype);
578 body->
type = pj_strbuf(&type);
579 body->
subtype = pj_strbuf(&subtype);
602 static int msg_send(
void *data)
612 pjsip_tx_data *tdata;
613 RAII_VAR(
char *, uri, NULL, ast_free);
616 ast_debug(3,
"mdata From: %s msg From: %s mdata Destination: %s msg To: %s\n",
619 endpoint = ast_sip_get_endpoint(mdata->destination, 1, &uri);
622 "PJSIP MESSAGE - Could not find endpoint '%s' and no default outbound endpoint configured\n",
628 "MdataDestination: %s\r\n"
640 if (ast_sip_create_request(
"MESSAGE", NULL, endpoint, uri, NULL, &tdata)) {
641 ast_log(LOG_WARNING,
"PJSIP MESSAGE - Could not create request\n");
657 ast_sip_update_to_uri(tdata, msg_to);
664 update_to_display_name(tdata, uri);
667 if (!ast_strlen_zero(mdata->from)) {
668 ast_sip_update_from(tdata, mdata->from);
673 #ifdef TEST_FRAMEWORK
675 pjsip_name_addr *tdata_name_addr;
676 pjsip_sip_uri *tdata_sip_uri;
680 tdata_name_addr = (pjsip_name_addr *) PJSIP_MSG_TO_HDR(tdata->msg)->uri;
681 tdata_sip_uri = pjsip_uri_get_uri(tdata_name_addr->uri);
682 pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, touri,
sizeof(touri));
683 tdata_name_addr = (pjsip_name_addr *) PJSIP_MSG_FROM_HDR(tdata->msg)->uri;
684 tdata_sip_uri = pjsip_uri_get_uri(tdata_name_addr->uri);
685 pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, fromuri,
sizeof(fromuri));
690 "MdataDestination: %s\r\n"
708 update_content_type(tdata, mdata->msg, &body);
710 if (ast_sip_add_body(tdata, &body)) {
711 pjsip_tx_data_dec_ref(tdata);
712 ast_log(LOG_ERROR,
"PJSIP MESSAGE - Could not add body to request\n");
720 vars_to_headers(mdata->msg, tdata);
722 ast_debug(1,
"Sending message to '%s' (via endpoint %s) from '%s'\n",
725 if (ast_sip_send_request(tdata, NULL, endpoint, NULL, NULL)) {
726 ast_log(LOG_ERROR,
"PJSIP MESSAGE - Could not send request\n");
733 static int sip_msg_send(
const struct ast_msg *msg,
const char *destination,
const char *from)
738 if (ast_strlen_zero(destination)) {
739 ast_log(LOG_ERROR,
"SIP MESSAGE - a 'To' URI must be specified\n");
743 mdata = msg_data_create(msg, destination, from);
756 .msg_send = sip_msg_send,
759 static pj_status_t send_response(pjsip_rx_data *rdata,
enum pjsip_status_code code,
760 pjsip_dialog *dlg, pjsip_transaction *tsx)
762 pjsip_tx_data *tdata;
765 status = ast_sip_create_response(rdata, code, NULL, &tdata);
766 if (status != PJ_SUCCESS) {
767 ast_log(LOG_ERROR,
"Unable to create response (%d)\n", status);
772 status = pjsip_dlg_send_response(dlg, tsx, tdata);
776 endpoint = ast_pjsip_rdata_get_endpoint(rdata);
777 status = ast_sip_send_stateful_response(rdata, tdata, endpoint);
778 ao2_cleanup(endpoint);
781 if (status != PJ_SUCCESS) {
782 ast_log(LOG_ERROR,
"Unable to send response (%d)\n", status);
788 static pj_bool_t module_on_rx_request(pjsip_rx_data *rdata)
790 enum pjsip_status_code code;
794 if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_message_method)) {
798 code = check_content_type(rdata);
799 if (code != PJSIP_SC_OK) {
800 send_response(rdata, code, NULL, NULL);
806 send_response(rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, NULL, NULL);
810 code = rx_data_to_ast_msg(rdata, msg);
811 if (code != PJSIP_SC_OK) {
812 send_response(rdata, code, NULL, NULL);
818 ast_debug(1,
"MESSAGE request received, but no handler wanted it\n");
819 send_response(rdata, PJSIP_SC_NOT_FOUND, NULL, NULL);
831 if (!send_response(rdata, PJSIP_SC_ACCEPTED, NULL, NULL)) {
838 static int incoming_in_dialog_request(
struct ast_sip_session *session,
struct pjsip_rx_data *rdata)
840 enum pjsip_status_code code;
843 pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
846 pjsip_name_addr *name_addr;
854 send_response(rdata, PJSIP_SC_NOT_FOUND, dlg, tsx);
858 code = check_content_type_in_dialog(rdata);
859 if (code != PJSIP_SC_OK) {
860 send_response(rdata, code, dlg, tsx);
864 caller = ast_channel_caller(session->
channel);
866 name_addr = (pjsip_name_addr *) rdata->msg_info.from->uri;
867 from_len = pj_strlen(&name_addr->display);
869 attrs[pos].type = AST_MSG_DATA_ATTR_FROM;
872 ast_copy_pj_str(attrs[pos].value, &name_addr->display, from_len);
875 attrs[pos].type = AST_MSG_DATA_ATTR_FROM;
880 name_addr = (pjsip_name_addr *) rdata->msg_info.to->uri;
881 to_len = pj_strlen(&name_addr->display);
883 attrs[pos].type = AST_MSG_DATA_ATTR_TO;
886 ast_copy_pj_str(attrs[pos].value, &name_addr->display, to_len);
890 attrs[pos].type = AST_MSG_DATA_ATTR_CONTENT_TYPE;
891 attrs[pos].value =
ast_alloca(rdata->msg_info.msg->body->content_type.type.slen
892 + rdata->msg_info.msg->body->content_type.subtype.slen + 2);
893 sprintf(attrs[pos].value,
"%.*s/%.*s",
894 (
int)rdata->msg_info.msg->body->content_type.type.slen,
895 rdata->msg_info.msg->body->content_type.type.ptr,
896 (
int)rdata->msg_info.msg->body->content_type.subtype.slen,
897 rdata->msg_info.msg->body->content_type.subtype.ptr);
901 attrs[pos].type = AST_MSG_DATA_ATTR_BODY;
902 attrs[pos].value =
ast_malloc(rdata->msg_info.msg->body->len + 1);
903 if (!attrs[pos].value) {
904 send_response(rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, dlg, tsx);
907 ast_copy_string(attrs[pos].value, rdata->msg_info.msg->body->data, rdata->msg_info.msg->body->len + 1);
912 ast_free(attrs[body_pos].value);
913 send_response(rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, dlg, tsx);
917 ast_debug(1,
"Received in-dialog MESSAGE from '%s:%s': %s %s\n",
919 ast_channel_name(session->
channel),
924 ast_free(attrs[body_pos].value);
927 send_response(rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, dlg, tsx);
929 send_response(rdata, PJSIP_SC_ACCEPTED, dlg, tsx);
937 .incoming_request = incoming_in_dialog_request
940 static pjsip_module messaging_module = {
941 .name = {
"Messaging Module", 16},
943 .priority = PJSIP_MOD_PRIORITY_APPLICATION,
944 .on_rx_request = module_on_rx_request,
947 static int load_module(
void)
949 if (ast_sip_register_service(&messaging_module) != PJ_SUCCESS) {
953 if (pjsip_endpt_add_capability(ast_sip_get_pjsip_endpoint(),
954 NULL, PJSIP_H_ALLOW, NULL, 1,
955 &pjsip_message_method.name) != PJ_SUCCESS) {
957 ast_sip_unregister_service(&messaging_module);
962 ast_sip_unregister_service(&messaging_module);
967 if (!message_serializer) {
968 ast_sip_unregister_service(&messaging_module);
973 ast_sip_session_register_supplement(&messaging_supplement);
977 static int unload_module(
void)
979 ast_sip_session_unregister_supplement(&messaging_supplement);
981 ast_sip_unregister_service(&messaging_module);
986 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,
"PJSIP Messaging Support",
987 .support_level = AST_MODULE_SUPPORT_CORE,
989 .unload = unload_module,
991 .requires =
"res_pjsip,res_pjsip_session",
int ast_msg_set_tech(struct ast_msg *msg, const char *fmt,...)
Set the technology associated with this message.
Asterisk main include file. File version handling, generic pbx functions.
const char * ast_msg_get_var(struct ast_msg *msg, const char *name)
Get the specified variable on the message.
char name[0]
Friendly name of the taskprocessor. Subsystem is appended after the name's NULL terminator.
int ast_msg_set_context(struct ast_msg *msg, const char *fmt,...)
Set the dialplan context for this message.
int ast_msg_set_body(struct ast_msg *msg, const char *fmt,...)
Set the 'body' text of a message (in UTF-8)
struct ast_party_name name
Subscriber name.
struct ast_msg * ast_msg_alloc(void)
Allocate a message.
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.
const char *const name
Name of this message technology.
Structure used to transport a message through the frame core.
char * str
Subscriber name (Malloced)
int ast_msg_tech_register(const struct ast_msg_tech *tech)
Register a message technology.
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.
#define ast_strdup(str)
A wrapper for strdup()
Out-of-call text message support.
struct pjsip_inv_session * inv_session
const char * ast_msg_get_body(const struct ast_msg *msg)
Get the body of a message.
A structure describing a SIP session.
void ast_msg_var_iterator_destroy(struct ast_msg_var_iterator *iter)
Destroy a message variable iterator.
int ast_msg_set_to(struct ast_msg *msg, const char *fmt,...)
Set the 'to' URI of a message.
const char * ast_msg_get_to(const struct ast_msg *msg)
Retrieve the destination of this message.
struct ast_party_id id
Caller party ID.
#define ast_strdupa(s)
duplicate a string in memory from the stack
void ast_msg_var_unref_current(struct ast_msg_var_iterator *iter)
Unref a message var from inside an iterator loop.
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.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define AST_MAX_EXTENSION
Caller Party information.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
struct ast_channel * channel
#define ast_malloc(len)
A wrapper for malloc()
#define ast_debug(level,...)
Log a DEBUG message.
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.
An entity with which Asterisk communicates.
Core PBX routines and definitions.
#define ast_test_suite_event_notify(s, f,...)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
int ast_msg_queue(struct ast_msg *msg)
Queue a message for routing through the dialplan.
struct ast_msg * ast_msg_ref(struct ast_msg *msg)
Bump a msg's ref count.
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.
int ast_msg_tech_unregister(const struct ast_msg_tech *tech)
Unregister a message technology.
const char * ast_msg_get_from(const struct ast_msg *msg)
Retrieve the source of this message.
Channel datastore data for max forwards.
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_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
const ast_string_field from
Module has failed to load, may be in an inconsistent state.
An API for managing task processing threads that can be shared across modules.
int ast_msg_set_exten(struct ast_msg *msg, const char *fmt,...)
Set the dialplan extension for this message.
int ast_msg_set_from(struct ast_msg *msg, const char *fmt,...)
Set the 'from' URI of a message.
A supplement to SIP message processing.
A ast_taskprocessor structure is a singleton by name.
int ast_msg_set_endpoint(struct ast_msg *msg, const char *fmt,...)
Set the technology's endpoint associated with this message.
int ast_msg_has_destination(const struct ast_msg *msg)
Determine if a particular message has a destination via some handler.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
unsigned char valid
TRUE if the name information is valid/present.
struct ast_msg * ast_msg_destroy(struct ast_msg *msg)
Destroy an ast_msg.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
struct ast_msg_var_iterator * ast_msg_var_iterator_init(const struct ast_msg *msg)
Create a new message variable iterator.