Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:00:56 2007

Asterisk developer's documentation :: Codename Pineapple


sip3_compose.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2007, Digium, Inc.
00005  * and Edvina AB, Sollentuna, Sweden (chan_sip3 changes/additions)
00006  *
00007  * Mark Spencer <markster@digium.com>
00008  *
00009  * See http://www.asterisk.org for more information about
00010  * the Asterisk project. Please do not directly contact
00011  * any of the maintainers of this project for assistance;
00012  * the project provides a web site, mailing lists and IRC
00013  * channels for your use.
00014  *
00015  * This program is free software, distributed under the terms of
00016  * the GNU General Public License Version 2. See the LICENSE file
00017  * at the top of the source tree.
00018  */
00019 
00020 /*!
00021  * \file
00022  * \brief Various SIP functions for composing SIP packets
00023  * Version 3 of chan_sip
00024  *
00025  * \author Mark Spencer <markster@digium.com>
00026  * \author Olle E. Johansson <oej@edvina.net> (all the chan_sip3 changes)
00027  *
00028  * See Also:
00029  * \arg \ref AstCREDITS
00030  *
00031  */
00032 
00033 #include "asterisk.h"
00034 
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 53128 $")
00036 
00037 #include <stdio.h>
00038 #include <ctype.h>
00039 #include <string.h>
00040 #include <unistd.h>
00041 #include <sys/socket.h>
00042 #include <sys/ioctl.h>
00043 #include <net/if.h>
00044 #include <errno.h>
00045 #include <stdlib.h>
00046 #include <fcntl.h>
00047 #include <netdb.h>
00048 #include <signal.h>
00049 #include <sys/signal.h>
00050 #include <netinet/in.h>
00051 #include <netinet/in_systm.h>
00052 #include <arpa/inet.h>
00053 #include <netinet/ip.h>
00054 #include <regex.h>
00055 
00056 #include "asterisk/lock.h"
00057 #include "asterisk/channel.h"
00058 #include "asterisk/config.h"
00059 #include "asterisk/logger.h"
00060 #include "asterisk/module.h"
00061 #include "asterisk/pbx.h"
00062 #include "asterisk/options.h"
00063 #include "asterisk/sched.h"
00064 #include "asterisk/io.h"
00065 #include "asterisk/acl.h"
00066 #include "asterisk/callerid.h"
00067 #include "asterisk/cli.h"
00068 #include "asterisk/app.h"
00069 #include "asterisk/manager.h"
00070 #include "asterisk/musiconhold.h"
00071 #include "asterisk/dsp.h"
00072 #include "asterisk/features.h"
00073 #include "asterisk/srv.h"
00074 #include "asterisk/astdb.h"
00075 #include "asterisk/causes.h"
00076 #include "asterisk/utils.h"
00077 #include "asterisk/file.h"
00078 #include "asterisk/astobj.h"
00079 #include "asterisk/dnsmgr.h"
00080 #include "asterisk/linkedlists.h"
00081 #include "asterisk/stringfields.h"
00082 #include "asterisk/monitor.h"
00083 #include "asterisk/localtime.h"
00084 #include "asterisk/compiler.h"
00085 #include "sip3.h"
00086 #include "sip3funcs.h"
00087 
00088 /*! \brief Add header to SIP message */
00089 GNURK int add_header(struct sip_request *req, const char *var, const char *value)
00090 {
00091    int maxlen = req->data_size - 4 - req->len; /* 4 bytes are for two \r\n ? */
00092 
00093    if (req->headers == SIP_MAX_HEADERS) {
00094       ast_log(LOG_WARNING, "Out of SIP header space\n");
00095       return -1;
00096    }
00097 
00098    if (req->lines) {
00099       ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
00100       return -1;
00101    }
00102 
00103    if (maxlen <= 0) {
00104       ast_log(LOG_WARNING, "Out of space, can't add anymore (%s:%s)\n", var, value);
00105       if (option_debug > 2)
00106          ast_log(LOG_DEBUG, "    ==== Req->len %d, req->data size %d Maxlen %d\n", req->len, (int) req->data_size, maxlen);
00107       return -1;
00108    }
00109 
00110    req->header[req->headers] = req->data + req->len;
00111 
00112    if (global.compactheaders)
00113       var = find_alias(var, var);
00114 
00115    snprintf(req->header[req->headers], maxlen, "%s: %s\r\n", var, value);
00116    req->len += strlen(req->header[req->headers]);
00117    req->headers++;
00118    if (req->headers < SIP_MAX_HEADERS)
00119       req->headers++;
00120    else
00121       ast_log(LOG_WARNING, "Out of SIP header space... Will generate broken SIP message\n");
00122 
00123    return 0;   
00124 }
00125 
00126 
00127 /*! \brief add a blank line if no body */
00128 GNURK void add_blank(struct sip_request *req)
00129 {
00130    if (!req->lines) {
00131       /* Add extra empty return. add_header() reserves 4 bytes so cannot be truncated */
00132       snprintf(req->data + req->len, req->data_size - req->len, "\r\n");
00133       req->len += strlen(req->data + req->len);
00134    }
00135 }
00136 
00137 /*! \brief Initialize SIP response, based on SIP request */
00138 GNURK int init_resp(struct sip_request *resp, const char *msg)
00139 {
00140    /* Initialize a response */
00141    resp->method = SIP_RESPONSE;
00142    resp->header[0] = resp->data;
00143    snprintf(resp->header[0], resp->data_size, "SIP/2.0 %s\r\n", msg);
00144    resp->len = strlen(resp->header[0]);
00145    resp->headers++;
00146    return 0;
00147 }
00148 
00149 /*! \brief Initialize SIP request */
00150 GNURK int init_req(struct sip_request *req, int sipmethod, const char *recip)
00151 {
00152    /* Initialize a request */
00153         req->method = sipmethod;
00154    if (option_debug > 3)
00155       ast_log(LOG_DEBUG,"!!!!!! Size of request data in init_req: %d\n", (int) req->data_size);
00156    req->header[0] = req->data;
00157    snprintf(req->header[0], req->data_size, "%s %s SIP/2.0\r\n", sip_method2txt(sipmethod), recip);
00158    req->len = strlen(req->header[0]);
00159    req->headers++;
00160    return 0;
00161 }
00162 
00163 /*! \brief Build SIP Call-ID value for a non-REGISTER transaction */
00164 void build_callid_pvt(struct sip_dialog *pvt)
00165 {
00166    char buf[33];
00167 
00168    const char *host = S_OR(pvt->fromdomain, ast_inet_ntoa(pvt->ourip));
00169    
00170    ast_string_field_build(pvt, callid, "%s@%s", generate_random_string(buf, sizeof(buf)), host);
00171 
00172 }
00173 
00174 /*! \brief Append date to SIP message */
00175 void append_date(struct sip_request *req)
00176 {
00177    char tmpdat[256];
00178    struct tm tm;
00179    time_t t = time(NULL);
00180 
00181    gmtime_r(&t, &tm);
00182    strftime(tmpdat, sizeof(tmpdat), "%a, %d %b %Y %T GMT", &tm);
00183    add_header(req, "Date", tmpdat);
00184 }
00185 
00186 /*! \brief Append Max-Forwards header to request */
00187 void append_maxforwards(struct sip_request *req)
00188 {
00189    char buf[4];
00190    snprintf(buf, sizeof(buf), "%d", global.maxforwards);
00191    add_header(req, "Max-Forwards", buf);
00192 }
00193 
00194 /*! \brief Add text body to SIP message */
00195 int add_text(struct sip_request *req, const char *text)
00196 {
00197    /* XXX Convert \n's to \r\n's XXX */
00198    add_header(req, "Content-Type", "text/plain");
00199    add_header_contentLength(req, strlen(text));
00200    add_line(req, text);
00201    return 0;
00202 }
00203 
00204 /*! \brief Add DTMF INFO tone to sip message */
00205 int add_digit(struct sip_request *req, char digit, unsigned int duration)
00206 {
00207    char tmp[256];
00208 
00209    snprintf(tmp, sizeof(tmp), "Signal=%c\r\nDuration=%u\r\n", digit, duration);
00210    add_header(req, "Content-Type", "application/dtmf-relay");
00211    add_header_contentLength(req, strlen(tmp));
00212    add_line(req, tmp);
00213    return 0;
00214 }
00215 
00216 /*! \brief Build contact header - the contact header we send out */
00217 void build_contact(struct sip_dialog *p)
00218 {
00219    /* Construct Contact: header */
00220    if (sipnet_ourport(&sipnet) != STANDARD_SIP_PORT)  /* Needs to be 5060, according to the RFC */
00221       ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip), sipnet_ourport(&sipnet));
00222    else
00223       ast_string_field_build(p, our_contact, "<sip:%s%s%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip));
00224 }
00225 
00226 
00227 /*! \brief Build the Remote Party-ID & From using callingpres options */
00228 void build_rpid(struct sip_dialog *p)
00229 {
00230    int send_pres_tags = TRUE;
00231    const char *privacy=NULL;
00232    const char *screen=NULL;
00233    char buf[256];
00234    const char *clid = global.default_callerid;
00235    const char *clin = NULL;
00236    const char *fromdomain;
00237 
00238    if (!ast_strlen_zero(p->rpid) || !ast_strlen_zero(p->rpid_from))  
00239       return;
00240 
00241    if (p->owner && p->owner->cid.cid_num)
00242       clid = p->owner->cid.cid_num;
00243    if (p->owner && p->owner->cid.cid_name)
00244       clin = p->owner->cid.cid_name;
00245    if (ast_strlen_zero(clin))
00246       clin = clid;
00247 
00248    switch (p->callingpres) {
00249    case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
00250       privacy = "off";
00251       screen = "no";
00252       break;
00253    case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
00254       privacy = "off";
00255       screen = "pass";
00256       break;
00257    case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
00258       privacy = "off";
00259       screen = "fail";
00260       break;
00261    case AST_PRES_ALLOWED_NETWORK_NUMBER:
00262       privacy = "off";
00263       screen = "yes";
00264       break;
00265    case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
00266       privacy = "full";
00267       screen = "no";
00268       break;
00269    case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
00270       privacy = "full";
00271       screen = "pass";
00272       break;
00273    case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
00274       privacy = "full";
00275       screen = "fail";
00276       break;
00277    case AST_PRES_PROHIB_NETWORK_NUMBER:
00278       privacy = "full";
00279       screen = "pass";
00280       break;
00281    case AST_PRES_NUMBER_NOT_AVAILABLE:
00282       send_pres_tags = FALSE;
00283       break;
00284    default:
00285       ast_log(LOG_WARNING, "Unsupported callingpres (%d)\n", p->callingpres);
00286       if ((p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED)
00287          privacy = "full";
00288       else
00289          privacy = "off";
00290       screen = "no";
00291       break;
00292    }
00293    
00294    fromdomain = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip));
00295 
00296    snprintf(buf, sizeof(buf), "\"%s\" <sip:%s@%s>", clin, clid, fromdomain);
00297    if (send_pres_tags)
00298       snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ";privacy=%s;screen=%s", privacy, screen);
00299    ast_string_field_set(p, rpid, buf);
00300 
00301    ast_string_field_build(p, rpid_from, "\"%s\" <sip:%s@%s>;tag=%s", clin,
00302                 S_OR(p->fromuser, clid),
00303                 fromdomain, p->tag);
00304 }
00305 
00306 /*! \brief Prepare SIP response packet */
00307 int respprep(struct sip_request *resp, struct sip_dialog *dialog, const char *msg, struct sip_request *req)
00308 {
00309    char newto[256];
00310    const char *ot;
00311 
00312    init_resp(resp, msg);
00313    copy_via_headers(dialog, resp, req, "Via");
00314    if (msg[0] == '2')
00315       copy_all_header(resp, req, "Record-Route");
00316    add_header(resp, "From", req->from);
00317    ot = req->to;
00318       
00319    if (!strcasestr(ot, "tag=") && strncmp(msg, "100", 3)) {
00320       /* Add the proper tag if we don't have it already.  If they have specified
00321          their tag, use it.  Otherwise, use our own tag */
00322       if (!ast_strlen_zero(dialog->theirtag) && ast_test_flag(&dialog->flags[0], SIP_OUTGOING))
00323          snprintf(newto, sizeof(newto), "%s;tag=%s", ot, dialog->theirtag);
00324       else if (dialog->tag && !ast_test_flag(&dialog->flags[0], SIP_OUTGOING))
00325          snprintf(newto, sizeof(newto), "%s;tag=%s", ot, dialog->tag);
00326       else
00327          ast_copy_string(newto, ot, sizeof(newto));
00328       ot = newto;
00329    }
00330    add_header(resp, "To", ot);
00331    add_header(resp, "Call-ID", dialog->callid);
00332    add_header(resp, "CSeq", req->cseqheader);
00333    add_header(resp, "User-Agent", global.useragent);
00334    add_header(resp, "Allow", ALLOWED_METHODS);
00335    add_header(resp, "Supported", SUPPORTED_EXTENSIONS);
00336    resp->seqno = req->seqno;
00337 
00338    /* We need to add Contact on 200 responses on registrations,
00339       invites and subscriptions. 
00340       INVITE, SUBSCRIBE, OPT och REGISTER responses and requests
00341    */
00342    if (msg[0] == '2' && (dialog->method == SIP_SUBSCRIBE || dialog->method == SIP_REGISTER)) {
00343       /* For successful registration responses, we also need expiry and
00344          contact info */
00345       char tmp[256];
00346 
00347       snprintf(tmp, sizeof(tmp), "%d", dialog->expiry);
00348       add_header(resp, "Expires", tmp);
00349       if (dialog->expiry) {   /* Only add contact if we have an expiry time */
00350          char contact[256];
00351          snprintf(contact, sizeof(contact), "%s;expires=%d", dialog->our_contact, dialog->expiry);
00352          add_header(resp, "Contact", contact);  /* Not when we unregister */
00353       }
00354    } else if (dialog->our_contact[0] && (req->method == SIP_INVITE || req->method == SIP_OPTIONS)) {
00355       if  (msg[0] != '4' && msg[0] != '1')
00356          add_header(resp, "Contact", dialog->our_contact);
00357    }
00358    return 0;
00359 }
00360 
00361 /*! \brief Add 'Content-Length' header to SIP message */
00362 int add_header_contentLength(struct sip_request *req, int len)
00363 {
00364    char clen[10];
00365 
00366    snprintf(clen, sizeof(clen), "%d", len);
00367    return add_header(req, "Content-Length", clen);
00368 }
00369 
00370 /*! \brief Add route header into request per learned route */
00371 void add_route(struct sip_request *req, struct sip_route *route)
00372 {
00373    char r[BUFSIZ*2], *p;
00374    int n, rem = sizeof(r);
00375 
00376    if (!route)
00377       return;
00378 
00379    p = r;
00380    for (;route ; route = route->next) {
00381       n = strlen(route->hop);
00382       if (rem < n+3) /* we need room for ",<route>" */
00383          break;
00384       if (p != r) {  /* add a separator after fist route */
00385          *p++ = ',';
00386          --rem;
00387       }
00388       *p++ = '<';
00389       ast_copy_string(p, route->hop, rem); /* cannot fail */
00390       p += n;
00391       *p++ = '>';
00392       rem -= (n+2);
00393    }
00394    *p = '\0';
00395    add_header(req, "Route", r);
00396 }
00397 
00398 /*! \brief Add content (not header) to SIP message */
00399 int add_line(struct sip_request *req, const char *line)
00400 {
00401    if (req->lines == SIP_MAX_LINES)  {
00402       ast_log(LOG_WARNING, "Out of SIP line space\n");
00403       return -1;
00404    }
00405    if (!req->lines) {
00406       /* Add extra empty return */
00407       snprintf(req->data + req->len, req->data_size - req->len, "\r\n");
00408       req->len += strlen(req->data + req->len);
00409    }
00410    if (req->len >= req->data_size - 4) {
00411       ast_log(LOG_WARNING, "Out of space, can't add anymore: Len %d Data %dd\n", req->len, (int) req->data_size);
00412       return -1;
00413    }
00414    req->line[req->lines] = req->data + req->len;
00415    snprintf(req->line[req->lines], req->data_size - req->len, "%s", line);
00416    req->len += strlen(req->line[req->lines]);
00417    req->lines++;
00418    return 0;   
00419 }
00420 
00421 /*! \brief Set destination from SIP URI */
00422 static void set_destination(struct sip_dialog *p, char *uri)
00423 {
00424    char *h, *maddr, hostname[256];
00425    int port, hn;
00426    struct hostent *hp;
00427    struct ast_hostent ahp;
00428    int debug=sip_debug_test_pvt(p);
00429 
00430    /* Parse uri to h (host) and port - uri is already just the part inside the <> */
00431    /* general form we are expecting is sip[s]:username[:password]@host[:port][;...] */
00432 
00433    if (debug)
00434       ast_verbose("set_destination: Parsing <%s> for address/port to send to\n", uri);
00435 
00436    /* Find and parse hostname */
00437    h = strchr(uri, '@');
00438    if (h)
00439       ++h;
00440    else {
00441       h = uri;
00442       if (strncmp(h, "sip:", 4) == 0)
00443          h += 4;
00444       else if (strncmp(h, "sips:", 5) == 0)
00445          h += 5;
00446    }
00447    hn = strcspn(h, ":;>") + 1;
00448    if (hn > sizeof(hostname)) 
00449       hn = sizeof(hostname);
00450    ast_copy_string(hostname, h, hn);
00451    /* XXX bug here if string has been trimmed to sizeof(hostname) */
00452    h += hn - 1;
00453 
00454    /* Is "port" present? if not default to STANDARD_SIP_PORT */
00455    if (*h == ':') {
00456       /* Parse port */
00457       ++h;
00458       port = strtol(h, &h, 10);
00459    }
00460    else
00461       port = STANDARD_SIP_PORT;
00462 
00463    /* Got the hostname:port - but maybe there's a "maddr=" to override address? */
00464    maddr = strstr(h, "maddr=");
00465    if (maddr) {
00466       maddr += 6;
00467       hn = strspn(maddr, "0123456789.") + 1;
00468       if (hn > sizeof(hostname))
00469          hn = sizeof(hostname);
00470       ast_copy_string(hostname, maddr, hn);
00471    }
00472    
00473    hp = ast_gethostbyname(hostname, &ahp);
00474    if (hp == NULL)  {
00475       ast_log(LOG_WARNING, "Can't find address for host '%s'\n", hostname);
00476       return;
00477    }
00478    p->sa.sin_family = AF_INET;
00479    memcpy(&p->sa.sin_addr, hp->h_addr, sizeof(p->sa.sin_addr));
00480    p->sa.sin_port = htons(port);
00481    if (debug)
00482       ast_verbose("set_destination: set destination to %s, port %d\n", ast_inet_ntoa(p->sa.sin_addr), port);
00483 }
00484 
00485 /*! \brief Initiate new SIP request to peer/user */
00486 void initreqprep(struct sip_request *req, struct sip_dialog *p, int sipmethod)
00487 {
00488    char invite_buf[256] = "";
00489    char *invite = invite_buf;
00490    size_t invite_max = sizeof(invite_buf);
00491    char from[256];
00492    char to[256];
00493    char tmp[BUFSIZ/2];
00494    char tmp2[BUFSIZ/2];
00495    const char *l = NULL, *n = NULL;
00496    const char *urioptions = "";
00497 
00498    if (ast_test_flag(&p->flags[0], SIP_USEREQPHONE)) {
00499       const char *s = p->username;  /* being a string field, cannot be NULL */
00500 
00501       /* Test p->username against allowed characters in AST_DIGIT_ANY
00502          If it matches the allowed characters list, then sipuser = ";user=phone"
00503          If not, then sipuser = ""
00504       */
00505       /* + is allowed in first position in a tel: uri */
00506       if (*s == '+')
00507          s++;
00508       for (; *s; s++) {
00509          if (!strchr(AST_DIGIT_ANYNUM, *s) )
00510             break;
00511       }
00512       /* If we have only digits, add ;user=phone to the uri */
00513       if (*s)
00514          urioptions = ";user=phone";
00515    }
00516 
00517 
00518    snprintf(p->lastmsg, sizeof(p->lastmsg), "Init: %s", sip_method2txt(sipmethod));
00519 
00520    if (p->owner) {
00521       l = p->owner->cid.cid_num;
00522       n = p->owner->cid.cid_name;
00523    }
00524    /* if we are not sending RPID and user wants his callerid restricted */
00525    if (!ast_test_flag(&p->flags[0], SIP_SENDRPID) &&
00526        ((p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED)) {
00527       l = CALLERID_UNKNOWN;
00528       n = l;
00529    }
00530    if (ast_strlen_zero(l))
00531       l = global.default_callerid;
00532    if (ast_strlen_zero(n))
00533       n = l;
00534    /* Allow user to be overridden */
00535    if (!ast_strlen_zero(p->fromuser))
00536       l = p->fromuser;
00537    else /* Save for any further attempts */
00538       ast_string_field_set(p, fromuser, l);
00539 
00540    /* Allow user to be overridden */
00541    if (!ast_strlen_zero(p->fromname))
00542       n = p->fromname;
00543    else /* Save for any further attempts */
00544       ast_string_field_set(p, fromname, n);
00545 
00546    ast_uri_encode(n, tmp, sizeof(tmp), 0);
00547    n = tmp;
00548    ast_uri_encode(l, tmp2, sizeof(tmp2), 0);
00549    l = tmp2;
00550 
00551    if ((sipnet_ourport(&sipnet) != STANDARD_SIP_PORT) && ast_strlen_zero(p->fromdomain))  /* Needs to be 5060 */
00552       snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=%s", n, l, S_OR(p->fromdomain, ast_inet_ntoa(p->ourip)), sipnet_ourport(&sipnet), p->tag);
00553    else
00554       snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=%s", n, l, S_OR(p->fromdomain, ast_inet_ntoa(p->ourip)), p->tag);
00555 
00556    /* If we're calling a registered SIP peer, use the fullcontact to dial to the peer */
00557    if (!ast_strlen_zero(p->fullcontact)) {
00558       /* If we have full contact, trust it */
00559       ast_build_string(&invite, &invite_max, "%s", p->fullcontact);
00560    } else {
00561       /* Otherwise, use the defaultuser while waiting for registration */
00562       ast_build_string(&invite, &invite_max, "sip:");
00563       if (!ast_strlen_zero(p->defaultuser)) {
00564          n = p->defaultuser;
00565          ast_uri_encode(n, tmp, sizeof(tmp), 0);
00566          n = tmp;
00567          ast_build_string(&invite, &invite_max, "%s@", n);
00568       }
00569       ast_build_string(&invite, &invite_max, "%s", p->tohost);
00570       if (ntohs(p->sa.sin_port) != STANDARD_SIP_PORT)    /* Needs to be 5060 */
00571          ast_build_string(&invite, &invite_max, ":%d", ntohs(p->sa.sin_port));
00572       ast_build_string(&invite, &invite_max, "%s", urioptions);
00573    }
00574 
00575    /* If custom URI options have been provided, append them */
00576    if (p->inviteoptions && p->inviteoptions->uri_options)
00577       ast_build_string(&invite, &invite_max, ";%s", p->inviteoptions->uri_options);
00578    
00579    ast_string_field_set(p, uri, invite_buf);
00580 
00581    if (!ast_strlen_zero(p->todnid)) {
00582       if (!strchr(p->todnid, '@')) {
00583          /* We have no domain in the dnid */
00584          snprintf(to, sizeof(to), "<sip:%s@%s>%s%s", p->todnid, p->tohost, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag);
00585       } else {
00586          snprintf(to, sizeof(to), "<sip:%s>%s%s", p->todnid, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag);
00587       }
00588    } else {
00589       if (sipmethod == SIP_NOTIFY && !ast_strlen_zero(p->theirtag)) { 
00590          /* If this is a NOTIFY, use the From: tag in the subscribe (RFC 3265) */
00591          snprintf(to, sizeof(to), "<sip:%s>;tag=%s", p->uri, p->theirtag);
00592       } else if (p->inviteoptions && p->inviteoptions->vxml_url) {
00593          /* If there is a VXML URL append it to the SIP URL */
00594          snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->inviteoptions->vxml_url);
00595       } else 
00596          snprintf(to, sizeof(to), "<%s>", p->uri);
00597    }
00598    
00599    init_req(req, sipmethod, p->uri);
00600    snprintf(tmp, sizeof(tmp), "%d %s", ++p->ocseq, sip_method2txt(sipmethod));
00601 
00602    add_header(req, "Via", p->via);
00603    append_maxforwards(req);
00604    /* SLD: FIXME?: do Route: here too?  I think not cos this is the first request.
00605     * OTOH, then we won't have anything in p->route anyway */
00606    /* Build Remote Party-ID and From */
00607    if (ast_test_flag(&p->flags[0], SIP_SENDRPID) && (sipmethod == SIP_INVITE)) {
00608       build_rpid(p);
00609       add_header(req, "From", p->rpid_from);
00610    } else 
00611       add_header(req, "From", from);
00612    add_header(req, "To", to);
00613    ast_string_field_set(p, exten, l);
00614    build_contact(p);
00615    add_header(req, "Contact", p->our_contact);
00616    add_header(req, "Call-ID", p->callid);
00617    add_header(req, "CSeq", tmp);
00618    add_header(req, "User-Agent", global.useragent);
00619    if (!ast_strlen_zero(p->rpid))
00620       add_header(req, "Remote-Party-ID", p->rpid);
00621 }
00622 
00623 
00624 /*! \brief Initialize a SIP request message (not the initial one in a dialog) */
00625 int reqprep(struct sip_request *req, struct sip_dialog *p, int sipmethod, int seqno, int newbranch)
00626 {
00627    struct sip_request *orig = p->initreq;
00628    char stripped[80];
00629    char tmp[80];
00630    char newto[256];
00631    const char *c;
00632    const char *ot, *of;
00633    int is_strict = FALSE;     /*!< Strict routing flag */
00634 
00635    snprintf(p->lastmsg, sizeof(p->lastmsg), "Tx: %s", sip_method2txt(sipmethod));
00636    
00637    if (!seqno) {
00638       p->ocseq++;
00639       seqno = p->ocseq;
00640    }
00641    req->seqno = seqno;
00642    
00643    build_via(p, newbranch);
00644 
00645    /* Check for strict or loose router */
00646    if (p->route && !ast_strlen_zero(p->route->hop) && strstr(p->route->hop,";lr") == NULL) {
00647       is_strict = TRUE;
00648       if (sipdebug)
00649          ast_log(LOG_DEBUG, "Strict routing enforced for session %s\n", p->callid);
00650    }
00651    if (!ast_test_flag(p->initreq, SIP_PKT_PARSED)) {
00652       if (!ast_test_flag(p->initreq, SIP_PKT_CONNECTED))
00653          parse_request(p->initreq);
00654       else 
00655          ast_log(LOG_WARNING, "Can't parse initial record. This request will look weird. Call ID %s\n", p->callid);
00656    }
00657 
00658    if (sipmethod == SIP_CANCEL)
00659       c = p->initreq->rlPart2;   /* Use original URI */
00660    else if (sipmethod == SIP_ACK) {
00661       /* Use URI from Contact: in 200 OK (if INVITE) 
00662       (we only have the contacturi on INVITEs) */
00663       if (!ast_strlen_zero(p->okcontacturi))
00664          c = is_strict ? p->route->hop : p->okcontacturi;
00665       else
00666          c = p->initreq->rlPart2;
00667    } else if (!ast_strlen_zero(p->okcontacturi)) 
00668       c = is_strict ? p->route->hop : p->okcontacturi; /* Use for BYE or REINVITE */
00669    else if (!ast_strlen_zero(p->uri)) 
00670       c = p->uri;
00671    else {
00672       char *n;
00673       /* We have no URI, use To: or From:  header as URI (depending on direction) */
00674       ast_copy_string(stripped, get_header(orig, (ast_test_flag(&p->flags[0], SIP_OUTGOING)) ? "To" : "From"),
00675             sizeof(stripped));
00676       n = get_in_brackets(stripped);
00677       c = strsep(&n, ";"); /* trim ; and beyond */
00678    }  
00679    init_req(req, sipmethod, c);
00680 
00681    snprintf(tmp, sizeof(tmp), "%d %s", seqno, sip_method2txt(sipmethod));
00682 
00683    add_header(req, "Via", p->via);
00684    if (p->route) {
00685       set_destination(p, p->route->hop);
00686       add_route(req, is_strict ? p->route->next : p->route);
00687    }
00688    append_maxforwards(req);
00689 
00690    ot = get_header(orig, "To");
00691    of = get_header(orig, "From");
00692 
00693    /* Add tag *unless* this is a CANCEL, in which case we need to send it exactly
00694       as our original request, including tag (or presumably lack thereof) */
00695    if (!strcasestr(ot, "tag=") && sipmethod != SIP_CANCEL) {
00696       /* Add the proper tag if we don't have it already.  If they have specified
00697          their tag, use it.  Otherwise, use our own tag */
00698       if (ast_test_flag(&p->flags[0], SIP_OUTGOING) && !ast_strlen_zero(p->theirtag))
00699          snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->theirtag);
00700       else if (!ast_test_flag(&p->flags[0], SIP_OUTGOING))
00701          snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->tag);
00702       else
00703          snprintf(newto, sizeof(newto), "%s", ot);
00704       ot = newto;
00705    }
00706 
00707    if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
00708       add_header(req, "From", of);
00709       add_header(req, "To", ot);
00710    } else {
00711       add_header(req, "From", ot);
00712       add_header(req, "To", of);
00713    }
00714    add_header(req, "Contact", p->our_contact);
00715    copy_header(req, orig, "Call-ID");
00716    add_header(req, "CSeq", tmp);
00717 
00718    add_header(req, "User-Agent", global.useragent);
00719 
00720    if (!ast_strlen_zero(p->rpid))
00721       add_header(req, "Remote-Party-ID", p->rpid);
00722 
00723    return 0;
00724 }
00725 
00726 
00727 

Asterisk is a trademark for Digium, inc.. | Edvina.net | Asterisk.org | This documentation was generated with Doxygen