[asterisk-commits] mmichelson: branch group/issue8824 r143333 - /team/group/issue8824/channels/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Sep 16 19:42:45 CDT 2008
Author: mmichelson
Date: Tue Sep 16 19:42:45 2008
New Revision: 143333
URL: http://svn.digium.com/view/asterisk?view=rev&rev=143333
Log:
First batch of changes with regards to chan_sip.c for
implementing redirecting information with the "Diversion" header.
* SIP now handles an indication of AST_CONTROL_REDIRECTING by
sending a "181 Call is being Forwarded" response with a
Diversion: header if redirecting information is changed prior
to the initial INVITE we received getting a final response.
* When we receive a 3XX response on an INVITE, we update the
redirecting-to information for the owner channel based on the
Contact: header present in the 3XX response.
Still left to do in chan_sip:
* Update the redirecting information if we read a Diversion:
header on an incoming INVITE
* Update the redirecting-from information when we receive a
3XX response. This information may come from a Diversion header
or we can use the original RURI of the request which was responded
to if no Diversion header is present. Also, queue an
AST_CONTROL_REDIRECTING frame when we receive a 3XX response.
* Update the add_diversion_header function to also include a
reason based on the value of the owner channel's redirecting.reason
value.
Modified:
team/group/issue8824/channels/chan_sip.c
Modified: team/group/issue8824/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/group/issue8824/channels/chan_sip.c?view=diff&rev=143333&r1=143332&r2=143333
==============================================================================
--- team/group/issue8824/channels/chan_sip.c (original)
+++ team/group/issue8824/channels/chan_sip.c Tue Sep 16 19:42:45 2008
@@ -2123,6 +2123,7 @@
static int get_msg_text(char *buf, int len, struct sip_request *req, int addnewline);
static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout);
static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen);
+static void update_redirecting(struct sip_pvt *p, const void *data, size_t datalen);
/*-- TCP connection handling ---*/
static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_session_instance *ser);
@@ -5481,6 +5482,9 @@
break;
case AST_CONTROL_CONNECTED_LINE:
update_connectedline(p, data, datalen);
+ break;
+ case AST_CONTROL_REDIRECTING:
+ update_redirecting(p, data, datalen);
break;
case -1:
res = -1;
@@ -9052,6 +9056,45 @@
add_header(req, "User-Agent", global_useragent);
}
+/*! \brief Add "Diversion" header to outgoing message
+ *
+ * We need to add a Diversion header if the owner channel of
+ * this dialog has redirecting information associated with it.
+ * XXX Add locking if necessary later.
+ *
+ * \param req The request/response to which we will add the header
+ * \param pvt The sip_pvt which represents the call-leg
+ */
+static void add_diversion_header(struct sip_request *req, struct sip_pvt *pvt)
+{
+ const char *diverting_number;
+ const char *diverting_name;
+ char header_text[256];
+
+ if (!pvt->owner) {
+ return;
+ }
+
+ /* XXX Eventually change this to use pvt->owner->redirecting.from.number */
+ diverting_number = pvt->owner->cid.cid_rdnis;
+ diverting_name = pvt->owner->redirecting.from.name;
+
+ if (ast_strlen_zero(diverting_number)) {
+ return;
+ }
+
+ /* We at least have a number to place in the Diversion header, which is enough */
+ if (ast_strlen_zero(diverting_name)) {
+ snprintf(header_text, sizeof(header_text), "sip:%s@%s", diverting_number, pvt->fromdomain);
+ } else {
+ snprintf(header_text, sizeof(header_text), "\"%s\" <sip:%s@%s>", diverting_name, diverting_number, pvt->fromdomain);
+ }
+
+ /* XXX Need to add a "reason" to the header text as well. */
+
+ add_header(req, "Diversion", header_text);
+}
+
/*! \brief Build REFER/INVITE/OPTIONS message and transmit it
\param init 0 = Prepare request within dialog, 1= prepare request, new branch, 2= prepare new request and new dialog. do_proxy_auth calls this with init!=2
\param p sip_pvt structure
@@ -9163,6 +9206,9 @@
}
if ((sipmethod == SIP_INVITE || sipmethod == SIP_UPDATE) && ast_test_flag(&p->flags[0], SIP_SENDRPID))
add_rpid(&req, p);
+ if (sipmethod == SIP_INVITE) {
+ add_diversion_header(&req, p);
+ }
if (sdp) {
if (p->udptl && (p->t38.state == T38_LOCAL_DIRECT || p->t38.state == T38_LOCAL_REINVITE)) {
ast_udptl_offered_from_local(p->udptl, 1);
@@ -9515,6 +9561,21 @@
" *Variable: <name>=<value> At least one variable pair must be specified.\n"
" ActionID: <id> Action ID for this transaction. Will be returned.\n";
+/*! \brief Send a provisional response indicating that a call was redirected
+ */
+static void update_redirecting(struct sip_pvt *p, const void *data, size_t datalen)
+{
+ struct sip_request resp;
+
+ if (p->owner->_state == AST_STATE_UP || ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
+ return;
+ }
+
+ respprep(&resp, p, "181 Call is being forwarded", &p->initreq);
+ add_diversion_header(&resp, p);
+ send_response(p, &resp, XMIT_UNRELIABLE, 0);
+}
+
/*! \brief Notify peer that the connected line has changed */
static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen)
{
@@ -11225,9 +11286,14 @@
pbx_builtin_setvar_helper(p->owner, "__SIPRDNISDOMAIN", rdomain);
if (sip_debug_test_pvt(p))
- ast_verbose("RDNIS for this call is is %s (reason %s)\n", exten, reason ? reason : "");
+ ast_verbose("RDNIS for this call is %s (reason %s)\n", exten, reason ? reason : "");
ast_string_field_set(p, rdnis, rexten);
+
+ /*XXX Add logic here for updating the redirecting information for the owner channel.
+ * The diversion header which we just parsed will have the from name and number. The "To"
+ * will be taken care of either in the Contact: header or in the RURI
+ */
return 0;
}
@@ -15129,21 +15195,35 @@
/*! \brief Parse 302 Moved temporalily response */
static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req)
{
- char tmp[SIPBUFSIZE];
- char *s, *e, *t, *trans;
+ char contact[SIPBUFSIZE];
+ char *contact_name = NULL;
+ char *contact_number = NULL;
+#if 0
+ char *redirecting_name = NULL;
+ char *redirecting_number = NULL;
+#endif
+ char *separator, *trans;
char *domain;
enum sip_transport transport = SIP_TRANSPORT_UDP;
- ast_copy_string(tmp, get_header(req, "Contact"), sizeof(tmp));
- if ((t = strchr(tmp, ',')))
- *t = '\0';
-
- s = get_in_brackets(tmp);
- if ((trans = strcasestr(s, ";transport="))) do {
+ ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact));
+ if ((separator = strchr(contact, ',')))
+ *separator = '\0';
+
+ /* ooh, a name */
+ if (*contact == '"') {
+ contact_name = contact + 1;
+ if ((separator = strchr(contact_name, '"'))) {
+ *separator++ = '\0';
+ }
+ }
+
+ contact_number = get_in_brackets(contact);
+ if ((trans = strcasestr(contact_number, ";transport="))) {
trans += 11;
- if ((e = strchr(trans, ';')))
- *e = '\0';
+ if ((separator = strchr(trans, ';')))
+ *separator = '\0';
if (!strncasecmp(trans, "tcp", 3))
transport = SIP_TRANSPORT_TCP;
@@ -15151,11 +15231,11 @@
transport = SIP_TRANSPORT_TLS;
else {
if (strncasecmp(trans, "udp", 3))
- ast_debug(1, "received contact with an invalid transport, '%s'\n", s);
+ ast_debug(1, "received contact with an invalid transport, '%s'\n", contact_number);
transport = SIP_TRANSPORT_UDP;
}
- } while(0);
- s = remove_uri_parameters(s);
+ }
+ contact_number = remove_uri_parameters(contact_number);
if (p->socket.ser) {
ao2_ref(p->socket.ser, -1);
@@ -15166,42 +15246,66 @@
p->socket.type = transport;
if (ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) {
- if (!strncasecmp(s, "sip:", 4))
- s += 4;
- else if (!strncasecmp(s, "sips:", 5))
- s += 5;
- e = strchr(s, '/');
- if (e)
- *e = '\0';
- ast_debug(2, "Found promiscuous redirection to 'SIP/::::%s@%s'\n", get_transport(transport), s);
+ if (!strncasecmp(contact_number, "sip:", 4))
+ contact_number += 4;
+ else if (!strncasecmp(contact_number, "sips:", 5))
+ contact_number += 5;
+ separator = strchr(contact_number, '/');
+ if (separator)
+ *separator = '\0';
+ ast_debug(2, "Found promiscuous redirection to 'SIP/::::%s@%s'\n", get_transport(transport), contact_number);
if (p->owner)
- ast_string_field_build(p->owner, call_forward, "SIP/::::%s@%s", get_transport(transport), s);
+ ast_string_field_build(p->owner, call_forward, "SIP/::::%s@%s", get_transport(transport), contact_number);
} else {
- e = strchr(tmp, '@');
- if (e) {
- *e++ = '\0';
- domain = e;
+ separator = strchr(contact, '@');
+ if (separator) {
+ *separator++ = '\0';
+ domain = separator;
} else {
/* No username part */
- domain = tmp;
- }
- e = strchr(tmp, '/'); /* WHEN do we hae a forward slash in the URI? */
- if (e)
- *e = '\0';
-
- if (!strncasecmp(s, "sip:", 4))
- s += 4;
- else if (!strncasecmp(s, "sips:", 5))
- s += 5;
- e = strchr(s, ';'); /* And username ; parameters? */
- if (e)
- *e = '\0';
- ast_debug(2, "Received 302 Redirect to extension '%s' (domain %s)\n", s, domain);
+ domain = contact;
+ }
+ separator = strchr(contact, '/'); /* WHEN do we hae a forward slash in the URI? */
+ if (separator)
+ *separator = '\0';
+
+ if (!strncasecmp(contact_number, "sip:", 4))
+ contact_number += 4;
+ else if (!strncasecmp(contact_number, "sips:", 5))
+ contact_number += 5;
+ separator = strchr(contact_number, ';'); /* And username ; parameters? */
+ if (separator)
+ *separator = '\0';
+ ast_debug(2, "Received 302 Redirect to extension '%s' (domain %s)\n", contact_number, domain);
if (p->owner) {
pbx_builtin_setvar_helper(p->owner, "SIPDOMAIN", domain);
- ast_string_field_set(p->owner, call_forward, s);
- }
- }
+ ast_string_field_set(p->owner, call_forward, contact_number);
+ }
+ }
+
+ /* We've gotten the number for the contact, now get the name */
+
+ if (*contact == '\"') {
+ contact_name = contact + 1;
+ if ((separator = strchr(contact_name, '\"'))) {
+ *separator = '\0';
+ }
+ }
+
+ if (p->owner) {
+ if (p->owner->redirecting.to.number) {
+ ast_free(p->owner->redirecting.to.number);
+ }
+ p->owner->redirecting.to.number = ast_strdup(contact_number);
+ if (p->owner->redirecting.to.name) {
+ ast_free(p->owner->redirecting.to.name);
+ }
+ p->owner->redirecting.to.name = ast_strdup(contact_name);
+ }
+
+ /*XXX Add logic for obtaining redirecting-from information. This may be
+ * in a diversion header or by getting the request's original RURI
+ */
}
/*! \brief Check pending actions on SIP call */
More information about the asterisk-commits
mailing list