136#define MAX_HDR_SIZE 512
137#define MAX_BODY_SIZE 1024
138#define MAX_USER_SIZE 128
154 if (rdata->msg_info.msg->body && rdata->msg_info.msg->body->len) {
156 &rdata->msg_info.msg->body->content_type,
"text",
"plain");
158 res = rdata->msg_info.ctype &&
160 &rdata->msg_info.ctype->media,
"text",
"plain");
163 return res ? PJSIP_SC_OK : PJSIP_SC_UNSUPPORTED_MEDIA_TYPE;
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)) {
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);
245 static const char *hdr[] = {
260 if (!strcasecmp(
name, hdr[i])) {
285 if (!strcasecmp(
name,
"Max-Forwards")) {
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,
':'))) {
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')));
389 scheme = strncmp(
buf,
"sip", 3) ?
"pjsip:" :
"pj";
390 count = strlen(scheme);
391 if (count + size >= capacity) {
393 "too large for given buffer\n");
397 memmove(res + count,
buf, size);
398 memcpy(res, scheme, count);
421 pjsip_uri *ruri = rdata->msg_info.msg->line.req.uri;
422 pjsip_name_addr *name_addr;
431 return PJSIP_SC_UNSUPPORTED_URI_SCHEME;
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;
495 if (endpt->id.self.name.valid) {
496 res |=
ast_msg_set_var(msg,
"PJSIP_ENDPOINT", endpt->id.self.name.str);
501 return !res ? PJSIP_SC_OK : PJSIP_SC_INTERNAL_SERVER_ERROR;
547 uri_params = strchr(mdata->
from,
'@');
548 if (uri_params && (uri_params = strchr(mdata->
from,
';'))) {
556 static const pj_str_t CONTENT_TYPE = {
"Content-Type",
sizeof(
"Content-Type") - 1 };
560 pj_str_t
type, subtype;
561 pjsip_ctype_hdr *parsed;
564 parsed = pjsip_parse_hdr(tdata->pool, &CONTENT_TYPE,
575 pj_strdup_with_null(tdata->pool, &
type, &parsed->media.type);
576 pj_strdup_with_null(tdata->pool, &subtype, &parsed->media.subtype);
579 body->
subtype = pj_strbuf(&subtype);
612 pjsip_tx_data *tdata;
616 ast_debug(3,
"mdata From: %s msg From: %s mdata Destination: %s msg To: %s\n",
622 "PJSIP MESSAGE - Could not find endpoint '%s' and no default outbound endpoint configured\n",
628 "MdataDestination: %s\r\n"
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"
711 pjsip_tx_data_dec_ref(tdata);
722 ast_debug(1,
"Sending message to '%s' (via endpoint %s) from '%s'\n",
759static 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;
766 if (
status != PJ_SUCCESS) {
772 status = pjsip_dlg_send_response(dlg, tsx, tdata);
781 if (
status != PJ_SUCCESS) {
790 enum pjsip_status_code code;
799 if (code != PJSIP_SC_OK) {
811 if (code != PJSIP_SC_OK) {
818 ast_debug(1,
"MESSAGE request received, but no handler wanted it\n");
840 enum pjsip_status_code code;
842 pjsip_dialog *dlg =
session->inv_session->dlg;
843 pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
846 pjsip_name_addr *name_addr;
859 if (code != PJSIP_SC_OK) {
866 name_addr = (pjsip_name_addr *) rdata->msg_info.from->uri;
867 from_len = pj_strlen(&name_addr->display);
880 name_addr = (pjsip_name_addr *) rdata->msg_info.to->uri;
881 to_len = pj_strlen(&name_addr->display);
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);
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);
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",
927 send_response(rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, dlg, tsx);
941 .name = {
"Messaging Module", 16},
943 .priority = PJSIP_MOD_PRIORITY_APPLICATION,
991 .
requires =
"res_pjsip,res_pjsip_session",
Asterisk main include file. File version handling, generic pbx functions.
static struct ast_mansession session
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_strdup(str)
A wrapper for strdup()
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_malloc(len)
A wrapper for malloc()
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_alloc(data_size, destructor_fn)
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
#define AST_MAX_EXTENSION
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
const char * ast_msg_data_get_attribute(struct ast_msg_data *msg, enum ast_msg_data_attribute_type attribute_type)
Get attribute from ast_msg_data.
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_CONTENT_TYPE
@ AST_MSG_DATA_SOURCE_TYPE_IN_DIALOG
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
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 ast_debug(level,...)
Log a DEBUG message.
Out-of-call text message support.
int ast_msg_set_from(struct ast_msg *msg, const char *fmt,...)
Set the 'from' URI of a message.
const char * ast_msg_get_var(struct ast_msg *msg, const char *name)
Get the specified variable on the message.
const char * ast_msg_get_from(const struct ast_msg *msg)
Retrieve the source of this message.
void ast_msg_var_iterator_destroy(struct ast_msg_var_iterator *iter)
Destroy a message variable iterator.
struct ast_msg * ast_msg_destroy(struct ast_msg *msg)
Destroy an ast_msg.
int ast_msg_set_endpoint(struct ast_msg *msg, const char *fmt,...)
Set the technology's endpoint associated with this 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.
int ast_msg_set_exten(struct ast_msg *msg, const char *fmt,...)
Set the dialplan extension for this message.
int ast_msg_set_tech(struct ast_msg *msg, const char *fmt,...)
Set the technology 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.
struct ast_msg * ast_msg_alloc(void)
Allocate a message.
int ast_msg_tech_unregister(const struct ast_msg_tech *tech)
Unregister a message technology.
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.
const char * ast_msg_get_to(const struct ast_msg *msg)
Retrieve the destination of this message.
int ast_msg_tech_register(const struct ast_msg_tech *tech)
Register a message technology.
const char * ast_msg_get_body(const struct ast_msg *msg)
Get the body of a message.
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)
int ast_msg_set_to(struct ast_msg *msg, const char *fmt,...)
Set the 'to' URI of a message.
void ast_msg_var_unref_current(struct ast_msg_var_iterator *iter)
Unref a message var from inside an iterator loop.
struct ast_msg_var_iterator * ast_msg_var_iterator_init(const struct ast_msg *msg)
Create a new message variable iterator.
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.
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Core PBX routines and definitions.
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.
const pj_str_t * ast_sip_pjsip_uri_get_username(pjsip_uri *uri)
Get the user portion of the pjsip_uri.
void ast_sip_unregister_service(pjsip_module *module)
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.
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
int ast_sip_is_allowed_uri(pjsip_uri *uri)
Check whether a pjsip_uri is allowed or not.
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
#define AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(str)
Truncate the URI user field options string if enabled.
int ast_sip_update_from(pjsip_tx_data *tdata, char *from)
Overwrite fields in the outbound 'From' header.
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.
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.
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.
int ast_sip_add_body(pjsip_tx_data *tdata, const struct ast_sip_body *body)
Add a body to an outbound SIP message.
int ast_sip_update_to_uri(pjsip_tx_data *tdata, const char *to)
Replace the To URI in the tdata with the supplied one.
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.
int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message.
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.
int ast_sip_is_content_type(pjsip_media_type *content_type, char *type, char *subtype)
Checks if the given content type matches type/subtype.
static struct ast_sip_session_supplement messaging_supplement
static enum pjsip_status_code vars_to_headers(const struct ast_msg *msg, pjsip_tx_data *tdata)
static pj_bool_t module_on_rx_request(pjsip_rx_data *rdata)
static int incoming_in_dialog_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
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 enum pjsip_status_code rx_data_to_ast_msg(pjsip_rx_data *rdata, struct ast_msg *msg)
static int print_body(pjsip_rx_data *rdata, char *buf, int len)
static void msg_data_destroy(void *obj)
static pjsip_module messaging_module
static int msg_send(void *data)
static void update_content_type(pjsip_tx_data *tdata, struct ast_msg *msg, struct ast_sip_body *body)
static int load_module(void)
static struct msg_data * msg_data_create(const struct ast_msg *msg, const char *destination, const char *from)
static struct ast_taskprocessor * message_serializer
static char * sip_to_pjsip(char *buf, int size, int capacity)
static int unload_module(void)
static const struct ast_msg_tech msg_tech
static int is_msg_var_blocked(const char *name)
const pjsip_method pjsip_message_method
static int headers_to_vars(const 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 update_to_display_name(pjsip_tx_data *tdata, char *to)
static int sip_msg_send(const struct ast_msg *msg, const char *destination, const char *from)
#define ast_sip_session_register_supplement(supplement)
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
enum ast_msg_data_attribute_type type
Structure used to transport a message through the frame core.
const char *const name
Name of this message technology.
Caller Party information.
struct ast_party_id id
Caller party ID.
struct ast_party_name name
Subscriber name.
unsigned char valid
TRUE if the name information is valid/present.
char * str
Subscriber name (Malloced)
An entity with which Asterisk communicates.
A supplement to SIP message processing.
A structure describing a SIP session.
A ast_taskprocessor structure is a singleton by name.
Channel datastore data for max forwards.
An API for managing task processing threads that can be shared across modules.
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
#define ast_test_suite_event_notify(s, f,...)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.