diff options
author | Richard Mudgett <rmudgett@digium.com> | 2012-01-25 17:23:25 +0000 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2012-01-25 17:23:25 +0000 |
commit | cbe57b11cb673a6eabe7cdd4d2b5c8ba81cec216 (patch) | |
tree | 7d61ca0e8d2d07030bcd0f75ee5b2f9b10e11d82 | |
parent | 4bf5e3716e9388e980274c94df7ad696ec63fbcd (diff) |
Fixes for sending SIP MESSAGE outside of calls.
* Fix authenticate MESSAGE losing custom headers added by the MESSAGE_DATA
function in the authorization attempt.
* Pass up better From header contents for SIP to use. Now is in the
"display-name" <URI> format expected by MessageSend. (Note that this is a
behavior change that could concievably affect some people.)
* Block user from adding standard headers that are added automatically.
(To, From,...)
* Allow the user to override the Content-Type header contents sent by
MessageSend.
* Decrement Max-Forwards header if the user transferred it from an
incoming message.
* Expand SIP short header names so the dialplan and other code only has to
deal with the full names.
* Documents what SIP expects in the MessageSend(from) parameter.
(closes issue ASTERISK-18992)
Reported by: Yuri
(closes issue ASTERISK-18917)
Reported by: Shaun Clark
Review: https://reviewboard.asterisk.org/r/1683/
........
Merged revisions 352520 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@352538 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r-- | CHANGES | 6 | ||||
-rw-r--r-- | channels/chan_sip.c | 370 | ||||
-rw-r--r-- | channels/sip/include/sip.h | 12 | ||||
-rw-r--r-- | main/message.c | 13 |
4 files changed, 307 insertions, 94 deletions
@@ -147,6 +147,12 @@ RTP changes mode has successfully exited. These changes are based on how pjmedia handles media sources and source changes. +Text Messaging +-------------- + * MESSAGE(from) for incoming SIP messages now returns "display-name" <uri> + instead of simply the uri. This is the format that MessageSend() can use + in the from parameter for outgoing SIP messages. + ------------------------------------------------------------------------------ --- Functionality changes from Asterisk 1.8 to Asterisk 10 ------------------- ------------------------------------------------------------------------------ diff --git a/channels/chan_sip.c b/channels/chan_sip.c index f987852f6..7db4d74ed 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -1275,8 +1275,7 @@ static int transmit_reinvite_with_sdp(struct sip_pvt *p, int t38version, int old static int transmit_info_with_aoc(struct sip_pvt *p, struct ast_aoc_decoded *decoded); static int transmit_info_with_digit(struct sip_pvt *p, const char digit, unsigned int duration); static int transmit_info_with_vidupdate(struct sip_pvt *p); -static int transmit_message_with_text(struct sip_pvt *p, const char *text, int init, int auth); -static int transmit_message_with_msg(struct sip_pvt *p, const struct ast_msg *msg); +static int transmit_message(struct sip_pvt *p, int init, int auth); static int transmit_refer(struct sip_pvt *p, const char *dest); static int transmit_notify_with_mwi(struct sip_pvt *p, int newmsgs, int oldmsgs, const char *vmexten); static int transmit_notify_with_sipfrag(struct sip_pvt *p, int cseq, char *message, int terminate); @@ -1536,7 +1535,8 @@ static int add_header(struct sip_request *req, const char *var, const char *valu static int add_header_max_forwards(struct sip_pvt *dialog, struct sip_request *req); static int add_content(struct sip_request *req, const char *line); static int finalize_content(struct sip_request *req); -static int add_text(struct sip_request *req, const char *text); +static void destroy_msg_headers(struct sip_pvt *pvt); +static int add_text(struct sip_request *req, struct sip_pvt *p); static int add_digit(struct sip_request *req, char digit, unsigned int duration, int mode); static int add_rpid(struct sip_request *req, struct sip_pvt *p); static int add_vidupdate(struct sip_request *req); @@ -4512,7 +4512,12 @@ static int sip_sendtext(struct ast_channel *ast, const char *text) ast_verbose("Sending text %s on %s\n", text, ast_channel_name(ast)); } - transmit_message_with_text(dialog, text, 0, 0); + /* Setup to send text message */ + sip_pvt_lock(dialog); + destroy_msg_headers(dialog); + ast_string_field_set(dialog, msg_body, text); + transmit_message(dialog, 0, 0); + sip_pvt_unlock(dialog); return 0; } @@ -5605,7 +5610,7 @@ static int sip_call(struct ast_channel *ast, char *dest, int timeout) /* We're replacing a call. */ p->options->replaces = ast_var_value(current); } else if (!strcasecmp(ast_var_name(current), "SIP_MAX_FORWARDS")) { - if (sscanf(ast_var_value(current), "%d", &(p->maxforwards)) != 1) { + if (sscanf(ast_var_value(current), "%30d", &(p->maxforwards)) != 1) { ast_log(LOG_WARNING, "The SIP_MAX_FORWARDS channel variable is not a valid integer."); } } @@ -5863,6 +5868,8 @@ void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist) p->chanvars = NULL; } + destroy_msg_headers(p); + if (p->srtp) { sip_srtp_destroy(p->srtp); p->srtp = NULL; @@ -7340,35 +7347,37 @@ static char *get_body(struct sip_request *req, char *name, char delimiter) return ""; } +/*! \brief Structure for conversion between compressed SIP and "normal" SIP headers */ +struct cfalias { + const char *fullname; + const char *shortname; +}; +static const struct cfalias aliases[] = { + { "Content-Type", "c" }, + { "Content-Encoding", "e" }, + { "From", "f" }, + { "Call-ID", "i" }, + { "Contact", "m" }, + { "Content-Length", "l" }, + { "Subject", "s" }, + { "To", "t" }, + { "Supported", "k" }, + { "Refer-To", "r" }, + { "Referred-By", "b" }, + { "Allow-Events", "u" }, + { "Event", "o" }, + { "Via", "v" }, + { "Accept-Contact", "a" }, + { "Reject-Contact", "j" }, + { "Request-Disposition", "d" }, + { "Session-Expires", "x" }, + { "Identity", "y" }, + { "Identity-Info", "n" }, +}; + /*! \brief Find compressed SIP alias */ static const char *find_alias(const char *name, const char *_default) { - /*! \brief Structure for conversion between compressed SIP and "normal" SIP */ - static const struct cfalias { - char * const fullname; - char * const shortname; - } aliases[] = { - { "Content-Type", "c" }, - { "Content-Encoding", "e" }, - { "From", "f" }, - { "Call-ID", "i" }, - { "Contact", "m" }, - { "Content-Length", "l" }, - { "Subject", "s" }, - { "To", "t" }, - { "Supported", "k" }, - { "Refer-To", "r" }, - { "Referred-By", "b" }, - { "Allow-Events", "u" }, - { "Event", "o" }, - { "Via", "v" }, - { "Accept-Contact", "a" }, - { "Reject-Contact", "j" }, - { "Request-Disposition", "d" }, - { "Session-Expires", "x" }, - { "Identity", "y" }, - { "Identity-Info", "n" }, - }; int x; for (x = 0; x < ARRAY_LEN(aliases); x++) { @@ -7379,6 +7388,22 @@ static const char *find_alias(const char *name, const char *_default) return _default; } +/*! \brief Find full SIP alias */ +static const char *find_full_alias(const char *name, const char *_default) +{ + int x; + + if (strlen(name) == 1) { + /* We have a short header name to convert. */ + for (x = 0; x < ARRAY_LEN(aliases); ++x) { + if (!strcasecmp(aliases[x].shortname, name)) + return aliases[x].fullname; + } + } + + return _default; +} + static const char *__get_header(const struct sip_request *req, const char *name, int *start) { int pass; @@ -10981,12 +11006,80 @@ static int transmit_provisional_response(struct sip_pvt *p, const char *msg, con return res; } +/*! + * \internal + * \brief Destroy all additional MESSAGE headers. + * + * \param pvt SIP private dialog struct. + * + * \return Nothing + */ +static void destroy_msg_headers(struct sip_pvt *pvt) +{ + struct sip_msg_hdr *doomed; + + while ((doomed = AST_LIST_REMOVE_HEAD(&pvt->msg_headers, next))) { + ast_free(doomed); + } +} + +/*! + * \internal + * \brief Add a MESSAGE header to the dialog. + * + * \param pvt SIP private dialog struct. + * \param hdr_name Name of header for MESSAGE. + * \param hdr_value Value of header for MESSAGE. + * + * \return Nothing + */ +static void add_msg_header(struct sip_pvt *pvt, const char *hdr_name, const char *hdr_value) +{ + size_t hdr_len_name; + size_t hdr_len_value; + struct sip_msg_hdr *node; + char *pos; + + hdr_len_name = strlen(hdr_name) + 1; + hdr_len_value = strlen(hdr_value) + 1; + + node = ast_calloc(1, sizeof(*node) + hdr_len_name + hdr_len_value); + if (!node) { + return; + } + pos = node->stuff; + node->name = pos; + strcpy(pos, hdr_name); + pos += hdr_len_name; + node->value = pos; + strcpy(pos, hdr_value); + + AST_LIST_INSERT_TAIL(&pvt->msg_headers, node, next); +} + /*! \brief Add text body to SIP message */ -static int add_text(struct sip_request *req, const char *text) +static int add_text(struct sip_request *req, struct sip_pvt *p) { + const char *content_type = NULL; + struct sip_msg_hdr *node; + + /* Add any additional MESSAGE headers. */ + AST_LIST_TRAVERSE(&p->msg_headers, node, next) { + if (!strcasecmp(node->name, "Content-Type")) { + /* Save content type */ + content_type = node->value; + } else { + add_header(req, node->name, node->value); + } + } + if (ast_strlen_zero(content_type)) { + /* "Content-Type" not set - use default value */ + content_type = "text/plain;charset=UTF-8"; + } + add_header(req, "Content-Type", content_type); + /* XXX Convert \n's to \r\n's XXX */ - add_header(req, "Content-Type", "text/plain;charset=UTF-8"); - add_content(req, text); + add_content(req, p->msg_body); return 0; } @@ -13615,38 +13708,16 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char * return res; } -/*! \brief Transmit text with SIP MESSAGE method based on an ast_msg */ -static int transmit_message_with_msg(struct sip_pvt *p, const struct ast_msg *msg) -{ - struct sip_request req; - struct ast_msg_var_iterator *i; - const char *var, *val; - - build_via(p); - initreqprep(&req, p, SIP_MESSAGE, NULL); - ast_string_field_set(p, msg_body, ast_msg_get_body(msg)); - initialize_initreq(p, &req); - - i = ast_msg_var_iterator_init(msg); - while (ast_msg_var_iterator_next(msg, i, &var, &val)) { - add_header(&req, var, val); - ast_msg_var_unref_current(i); - } - ast_msg_var_iterator_destroy(i); - - add_text(&req, ast_msg_get_body(msg)); - - return send_request(p, &req, XMIT_RELIABLE, p->ocseq); -} - -/*! \brief Transmit text with SIP MESSAGE method */ -static int transmit_message_with_text(struct sip_pvt *p, const char *text, int init, int auth) +/*! + * \brief Transmit with SIP MESSAGE method + * \note The p->msg_headers and p->msg_body are already setup. + */ +static int transmit_message(struct sip_pvt *p, int init, int auth) { struct sip_request req; if (init) { initreqprep(&req, p, SIP_MESSAGE, NULL); - ast_string_field_set(p, msg_body, text); initialize_initreq(p, &req); } else { reqprep(&req, p, SIP_MESSAGE, 0, 1); @@ -13654,7 +13725,7 @@ static int transmit_message_with_text(struct sip_pvt *p, const char *text, int i if (auth) { return transmit_request_with_auth(p, SIP_MESSAGE, p->ocseq, XMIT_RELIABLE, 0); } else { - add_text(&req, text); + add_text(&req, p); return send_request(p, &req, XMIT_RELIABLE, p->ocseq); } } @@ -13874,23 +13945,31 @@ static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int seqn ast_log(LOG_WARNING, "No authentication available for call %s\n", p->callid); } } - /* If we are hanging up and know a cause for that, send it in clear text to make - debugging easier. */ - if (sipmethod == SIP_BYE) { + + switch (sipmethod) { + case SIP_BYE: + { char buf[20]; + /* + * We are hanging up. If we know a cause for that, send it in + * clear text to make debugging easier. + */ if (ast_test_flag(&p->flags[1], SIP_PAGE2_Q850_REASON) && p->hangupcause) { - sprintf(buf, "Q.850;cause=%i", p->hangupcause & 0x7f); + snprintf(buf, sizeof(buf), "Q.850;cause=%d", p->hangupcause & 0x7f); add_header(&resp, "Reason", buf); } add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->hangupcause)); snprintf(buf, sizeof(buf), "%d", p->hangupcause); add_header(&resp, "X-Asterisk-HangupCauseCode", buf); + break; } - - if (sipmethod == SIP_MESSAGE) { - add_text(&resp, p->msg_body); + case SIP_MESSAGE: + add_text(&resp, p); + break; + default: + break; } return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq); @@ -16514,22 +16593,33 @@ static int get_msg_text2(struct ast_str **buf, struct sip_request *req) return res < 0 ? -1 : 0; } -static void set_message_vars_from_req(struct ast_msg *msg, struct sip_request *req) +static int set_message_vars_from_req(struct ast_msg *msg, struct sip_request *req) { size_t x; - char name_buf[1024] = ""; - char val_buf[1024] = ""; + char name_buf[1024]; + char val_buf[1024]; + const char *name; char *c; + int res = 0; for (x = 0; x < req->headers; x++) { const char *header = REQ_OFFSET_TO_STR(req, header[x]); + if ((c = strchr(header, ':'))) { ast_copy_string(name_buf, header, MIN((c - header + 1), sizeof(name_buf))); ast_copy_string(val_buf, ast_skip_blanks(c + 1), sizeof(val_buf)); ast_trim_blanks(name_buf); - ast_msg_set_var(msg, name_buf, val_buf); + + /* Convert header name to full name alias. */ + name = find_full_alias(name_buf, name_buf); + + res = ast_msg_set_var(msg, name, val_buf); + if (res) { + break; + } } } + return res; } AST_THREADSTORAGE(sip_msg_buf); @@ -16546,12 +16636,15 @@ static void receive_message(struct sip_pvt *p, struct sip_request *req, struct a const char *content_type = sip_get_header(req, "Content-Type"); struct ast_msg *msg; int res; - char *from, *to; + char *from; + char *to; + char from_name[50]; if (strncmp(content_type, "text/plain", strlen("text/plain"))) { /* No text/plain attachment */ transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */ - if (!p->owner) + if (!p->owner) { sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); + } return; } @@ -16585,8 +16678,9 @@ static void receive_message(struct sip_pvt *p, struct sip_request *req, struct a ast_str_truncate(buf, len); if (p->owner) { - if (sip_debug_test_pvt(p)) + if (sip_debug_test_pvt(p)) { ast_verbose("SIP Text message received: '%s'\n", ast_str_buffer(buf)); + } memset(&f, 0, sizeof(f)); f.frametype = AST_FRAME_TEXT; f.subclass.integer = 0; @@ -16598,6 +16692,13 @@ static void receive_message(struct sip_pvt *p, struct sip_request *req, struct a return; } + /* + * At this point MESSAGE is outside of a call. + * + * NOTE: p->owner is NULL so no additional check is needed after + * this point. + */ + if (!sip_cfg.accept_outofcall_message) { /* Message outside of a call, we do not support that */ ast_debug(1, "MESSAGE outside of a call administratively disabled.\n"); @@ -16620,7 +16721,7 @@ static void receive_message(struct sip_pvt *p, struct sip_request *req, struct a if (res < 0) { /* Something failed in authentication */ if (res == AUTH_FAKE_AUTH) { ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", sip_get_header(req, "From")); - transmit_fake_auth_response(p, SIP_OPTIONS, req, XMIT_UNRELIABLE); + transmit_fake_auth_response(p, SIP_MESSAGE, req, XMIT_UNRELIABLE); } else { ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From")); transmit_response(p, "403 Forbidden", req); @@ -16665,9 +16766,7 @@ static void receive_message(struct sip_pvt *p, struct sip_request *req, struct a if (!(msg = ast_msg_alloc())) { transmit_response(p, "500 Internal Server Error", req); - if (!p->owner) { - sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); - } + sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); return; } @@ -16675,7 +16774,16 @@ static void receive_message(struct sip_pvt *p, struct sip_request *req, struct a from = ast_strdupa(sip_get_header(req, "From")); res = ast_msg_set_to(msg, "%s", to); - res |= ast_msg_set_from(msg, "%s", get_in_brackets(from)); + + /* Build "display" <uri> for from string. */ + from = (char *) get_calleridname(from, from_name, sizeof(from_name)); + from = get_in_brackets(from); + if (from_name[0]) { + res |= ast_msg_set_from(msg, "\"%s\" <%s>", from_name, from); + } else { + res |= ast_msg_set_from(msg, "<%s>", from); + } + res |= ast_msg_set_body(msg, "%s", ast_str_buffer(buf)); res |= ast_msg_set_context(msg, "%s", p->context); @@ -16684,15 +16792,16 @@ static void receive_message(struct sip_pvt *p, struct sip_request *req, struct a } res |= ast_msg_set_exten(msg, "%s", p->exten); + res |= set_message_vars_from_req(msg, req); if (res) { ast_msg_destroy(msg); + transmit_response(p, "500 Internal Server Error", req); } else { - set_message_vars_from_req(msg, req); ast_msg_queue(msg); + transmit_response(p, "202 Accepted", req); } - transmit_response(p, "202 Accepted", req); sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); } @@ -20339,7 +20448,7 @@ static void cc_handle_publish_error(struct sip_pvt *pvt, const int resp, struct ao2_ref(monitor_instance, -1); return; } - } else if (sscanf(min_expires, "%d", &pvt->expiry) != 1) { + } else if (sscanf(min_expires, "%30d", &pvt->expiry) != 1) { ast_cc_monitor_failed(cc_entry->core_id, monitor_instance->device_name, "Min-Expires has non-numeric value"); ao2_ref(monitor_instance, -1); @@ -21380,7 +21489,7 @@ static int do_message_auth(struct sip_pvt *p, int resp, const char *rest, struct append_history(p, "MessageAuth", "Try: %d", p->authtries); } - transmit_message_with_text(p, p->msg_body, 0, 1); + transmit_message(p, 0, 1); return 0; } @@ -21912,13 +22021,18 @@ static void *sip_park_thread(void *stuff) res = ast_park_call_exten(transferee, transferer, d->park_exten, d->park_context, 0, &ext); + sip_pvt_lock(transferer->tech_pvt); #ifdef WHEN_WE_KNOW_THAT_THE_CLIENT_SUPPORTS_MESSAGE if (res) { - transmit_message_with_text(transferer->tech_pvt, "Unable to park call.\n", 0, 0); + destroy_msg_headers(transferer->tech_pvt); + ast_string_field_set(transferer->tech_pvt, msg_body, "Unable to park call."); + transmit_message(transferer->tech_pvt, 0, 0); } else { /* Then tell the transferer what happened */ - sprintf(buf, "Call parked on extension '%d'", ext); - transmit_message_with_text(transferer->tech_pvt, buf, 0, 0); + destroy_msg_headers(transferer->tech_pvt); + sprintf(buf, "Call parked on extension '%d'.", ext); + ast_string_field_set(transferer->tech_pvt, msg_body, buf); + transmit_message(transferer->tech_pvt, 0, 0); } #endif @@ -21928,12 +22042,14 @@ static void *sip_park_thread(void *stuff) /* Transfer succeeded */ append_history(transferer->tech_pvt, "SIPpark", "Parked call on %d", ext); transmit_notify_with_sipfrag(transferer->tech_pvt, d->seqno, "200 OK", TRUE); + sip_pvt_unlock(transferer->tech_pvt); transferer->hangupcause = AST_CAUSE_NORMAL_CLEARING; ast_hangup(transferer); /* This will cause a BYE */ ast_debug(1, "SIP Call parked on extension '%d'\n", ext); } else { transmit_notify_with_sipfrag(transferer->tech_pvt, d->seqno, "503 Service Unavailable", TRUE); append_history(transferer->tech_pvt, "SIPpark", "Parking failed\n"); + sip_pvt_unlock(transferer->tech_pvt); ast_debug(1, "SIP Call parked failed \n"); /* Do not hangup call */ } @@ -24475,11 +24591,56 @@ static const struct ast_msg_tech sip_msg_tech = { .msg_send = sip_msg_send, }; +/*! + * \internal + * \brief Check if the given header name is blocked. + * + * \details Determine if the given header name from the user is + * blocked for outgoing MESSAGE packets. + * + * \param header_name Name of header to see if it is blocked. + * + * \retval TRUE if the given header is blocked. + */ +static int block_msg_header(const char *header_name) +{ + int idx; + + /* + * Don't block Content-Type or Max-Forwards headers because the + * user can override them. + */ + static const char *hdr[] = { + "To", + "From", + "Via", + "Route", + "Contact", + "Call-ID", + "CSeq", + "Allow", + "Content-Length", + }; + + for (idx = 0; idx < ARRAY_LEN(hdr); ++idx) { + if (!strcasecmp(header_name, hdr[idx])) { + /* Block addition of this header. */ + return 1; + } + } + return 0; +} + static int sip_msg_send(const struct ast_msg *msg, const char *to, const char *from) { struct sip_pvt *pvt; int res; - char *to_uri, *to_host, *to_user; + char *to_uri; + char *to_host; + char *to_user; + const char *var; + const char *val; + struct ast_msg_var_iterator *iter; struct sip_peer *peer_ptr; if (!(pvt = sip_alloc(NULL, NULL, 0, SIP_MESSAGE, NULL))) { @@ -24487,6 +24648,7 @@ static int sip_msg_send(const struct ast_msg *msg, const char *to, const char *f } to_uri = ast_strdupa(to); + to_uri = get_in_brackets(to_uri); parse_uri(to_uri, "sip:,sips:", &to_user, NULL, &to_host, NULL); if (ast_strlen_zero(to_host)) { @@ -24541,7 +24703,33 @@ static int sip_msg_send(const struct ast_msg *msg, const char *to, const char *f /* XXX Does pvt->expiry need to be set? */ - res = transmit_message_with_msg(pvt, msg); + /* Save additional MESSAGE headers in case of authentication request. */ + for (iter = ast_msg_var_iterator_init(msg); + ast_msg_var_iterator_next(msg, iter, &var, &val); + ast_msg_var_unref_current(iter)) { + if (!strcasecmp(var, "Max-Forwards")) { + /* Decrement Max-Forwards for SIP loop prevention. */ + if (sscanf(val, "%30d", &pvt->maxforwards) != 1 || pvt->maxforwards < 1) { + sip_pvt_unlock(pvt); + dialog_unlink_all(pvt); + dialog_unref(pvt, "MESSAGE(Max-Forwards) reached zero."); + ast_log(LOG_NOTICE, + "MESSAGE(Max-Forwards) reached zero. MESSAGE not sent.\n"); + return -1; + } + --pvt->maxforwards; + continue; + } + if (block_msg_header(var)) { + /* Block addition of this header. */ + continue; + } + add_msg_header(pvt, var, val); + } + ast_msg_var_iterator_destroy(iter); + + ast_string_field_set(pvt, msg_body, ast_msg_get_body(msg)); + res = transmit_message(pvt, 1, 0); sip_pvt_unlock(pvt); sip_scheddestroy(pvt, DEFAULT_TRANS_TIMEOUT); @@ -25088,7 +25276,7 @@ static int handle_cc_subscribe(struct sip_pvt *p, struct sip_request *req) int expires = -1; /* Just need it to be non-zero */ if (!ast_strlen_zero(expires_str)) { - sscanf(expires_str, "%d", &expires); + sscanf(expires_str, "%30d", &expires); } if ((param_separator = strchr(uri, ';'))) { diff --git a/channels/sip/include/sip.h b/channels/sip/include/sip.h index ad9e7819f..f370193e8 100644 --- a/channels/sip/include/sip.h +++ b/channels/sip/include/sip.h @@ -966,6 +966,17 @@ struct offered_media { char codecs[128]; }; +/*! Additional headers to send with MESSAGE method packet. */ +struct sip_msg_hdr { + AST_LIST_ENTRY(sip_msg_hdr) next; + /*! Name of header to stick in MESSAGE */ + const char *name; + /*! Value of header to stick in MESSAGE */ + const char *value; + /*! The name and value strings are stuffed here in that order. */ + char stuff[0]; +}; + /*! \brief Structure used for each SIP dialog, ie. a call, a registration, a subscribe. * Created and initialized by sip_alloc(), the descriptor goes into the list of * descriptors (dialoglist). @@ -1134,6 +1145,7 @@ struct sip_pvt { struct sip_history_head *history; /*!< History of this SIP dialog */ size_t history_entries; /*!< Number of entires in the history */ struct ast_variable *chanvars; /*!< Channel variables to set for inbound call */ + AST_LIST_HEAD_NOLOCK(, sip_msg_hdr) msg_headers; /*!< Additional MESSAGE headers to send. */ AST_LIST_HEAD_NOLOCK(request_queue, sip_request) request_queue; /*!< Requests that arrived but could not be processed immediately */ struct sip_invite_param *options; /*!< Options for INVITE */ struct sip_st_dlg *stimer; /*!< SIP Session-Timers */ diff --git a/main/message.c b/main/message.c index 424775100..c4d2c4372 100644 --- a/main/message.c +++ b/main/message.c @@ -88,15 +88,18 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") <para>This function will read from or write a value to a text message. It is used both to read the data out of an incoming message, as well as modify a message that will be sent outbound.</para> - <para>NOTE: If you want to set an outbound message to carry data in the - current message, do Set(MESSAGE_DATA(key)=${MESSAGE_DATA(key)}).</para> + <note> + <para>If you want to set an outbound message to carry data in the + current message, do + Set(MESSAGE_DATA(<replaceable>key</replaceable>)=${MESSAGE_DATA(<replaceable>key</replaceable>)}).</para> + </note> </description> <see-also> <ref type="application">MessageSend</ref> </see-also> </function> <application name="MessageSend" language="en_US"> - <synopsis> + <synopsis> Send a text message. </synopsis> <syntax> @@ -106,6 +109,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") <parameter name="from" required="false"> <para>A From URI for the message if needed for the message technology being used to send this message.</para> + <note> + <para>For SIP the from parameter can be a configured peer name + or in the form of "display-name" <URI>.</para> + </note> </parameter> </syntax> <description> |