Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:51 2007

Asterisk developer's documentation :: Codename Pineapple


sip3_compose.c File Reference


Detailed Description

Various SIP functions for composing SIP packets Version 3 of chan_sip.

Author:
Mark Spencer <markster@digium.com>

Olle E. Johansson <oej@edvina.net> (all the chan_sip3 changes)

See Also:

Definition in file sip3_compose.c.

#include "asterisk.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <regex.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/manager.h"
#include "asterisk/musiconhold.h"
#include "asterisk/dsp.h"
#include "asterisk/features.h"
#include "asterisk/srv.h"
#include "asterisk/astdb.h"
#include "asterisk/causes.h"
#include "asterisk/utils.h"
#include "asterisk/file.h"
#include "asterisk/astobj.h"
#include "asterisk/dnsmgr.h"
#include "asterisk/linkedlists.h"
#include "asterisk/stringfields.h"
#include "asterisk/monitor.h"
#include "asterisk/localtime.h"
#include "asterisk/compiler.h"
#include "sip3.h"
#include "sip3funcs.h"

Include dependency graph for sip3_compose.c:

Go to the source code of this file.

Functions

GNURK void add_blank (struct sip_request *req)
 add a blank line if no body
int add_digit (struct sip_request *req, char digit, unsigned int duration)
 Add DTMF INFO tone to sip message.
GNURK int add_header (struct sip_request *req, const char *var, const char *value)
 Add header to SIP message.
int add_header_contentLength (struct sip_request *req, int len)
 Add 'Content-Length' header to SIP message.
int add_line (struct sip_request *req, const char *line)
 Add content (not header) to SIP message.
void add_route (struct sip_request *req, struct sip_route *route)
 Add route header into request per learned route.
int add_text (struct sip_request *req, const char *text)
 Add text body to SIP message.
void append_date (struct sip_request *req)
 Append date to SIP message.
void append_maxforwards (struct sip_request *req)
 Append Max-Forwards header to request.
void build_callid_pvt (struct sip_dialog *pvt)
 Build SIP Call-ID value for a non-REGISTER transaction.
void build_contact (struct sip_dialog *p)
 Build contact header - the contact header we send out.
void build_rpid (struct sip_dialog *p)
 Build the Remote Party-ID & From using callingpres options.
GNURK int init_req (struct sip_request *req, int sipmethod, const char *recip)
 Initialize SIP request.
GNURK int init_resp (struct sip_request *resp, const char *msg)
 Initialize SIP response, based on SIP request.
void initreqprep (struct sip_request *req, struct sip_dialog *p, int sipmethod)
 Initiate new SIP request to peer/user.
int reqprep (struct sip_request *req, struct sip_dialog *p, int sipmethod, int seqno, int newbranch)
 Initialize a SIP request message (not the initial one in a dialog).
int respprep (struct sip_request *resp, struct sip_dialog *dialog, const char *msg, struct sip_request *req)
 Prepare SIP response packet.
static void set_destination (struct sip_dialog *p, char *uri)
 Set destination from SIP URI.


Function Documentation

GNURK void add_blank struct sip_request req  ) 
 

add a blank line if no body

Definition at line 128 of file sip3_compose.c.

References sip_request::data, sip_request::data_size, sip_request::len, and sip_request::lines.

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 }

int add_digit struct sip_request req,
char  digit,
unsigned int  duration
 

Add DTMF INFO tone to sip message.

Definition at line 205 of file sip3_compose.c.

References add_header(), add_header_contentLength(), and add_line().

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 }

GNURK int add_header struct sip_request req,
const char *  var,
const char *  value
 

Add header to SIP message.

sip3_compose.c : Composing new SIP messages

Definition at line 89 of file sip3_compose.c.

References ast_log(), sip_globals::compactheaders, sip_request::data, sip_request::data_size, find_alias(), global, sip_request::header, sip_request::headers, sip_request::len, sip_request::lines, LOG_DEBUG, LOG_WARNING, option_debug, and SIP_MAX_HEADERS.

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 }

int add_header_contentLength struct sip_request req,
int  len
 

Add 'Content-Length' header to SIP message.

Definition at line 362 of file sip3_compose.c.

References add_header().

00363 {
00364    char clen[10];
00365 
00366    snprintf(clen, sizeof(clen), "%d", len);
00367    return add_header(req, "Content-Length", clen);
00368 }

int add_line struct sip_request req,
const char *  line
 

Add content (not header) to SIP message.

Definition at line 399 of file sip3_compose.c.

References ast_log(), sip_request::data, sip_request::data_size, sip_request::len, sip_request::line, sip_request::lines, LOG_WARNING, and SIP_MAX_LINES.

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 }

void add_route struct sip_request req,
struct sip_route route
 

Add route header into request per learned route.

Definition at line 371 of file sip3_compose.c.

References sip_route::hop, and sip_route::next.

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 }

int add_text struct sip_request req,
const char *  text
 

Add text body to SIP message.

Definition at line 195 of file sip3_compose.c.

References add_header(), add_header_contentLength(), and add_line().

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 }

void append_date struct sip_request req  ) 
 

Append date to SIP message.

Definition at line 175 of file sip3_compose.c.

References add_header().

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 }

void append_maxforwards struct sip_request req  ) 
 

Append Max-Forwards header to request.

Definition at line 187 of file sip3_compose.c.

References add_header(), global, and sip_globals::maxforwards.

Referenced by reqprep(), transmit_refer(), and transmit_register().

00188 {
00189    char buf[4];
00190    snprintf(buf, sizeof(buf), "%d", global.maxforwards);
00191    add_header(req, "Max-Forwards", buf);
00192 }

void build_callid_pvt struct sip_dialog pvt  ) 
 

Build SIP Call-ID value for a non-REGISTER transaction.

Definition at line 164 of file sip3_compose.c.

References ast_inet_ntoa(), ast_string_field_build, generate_random_string(), sip_dialog::ourip, and S_OR.

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 }

void build_contact struct sip_dialog p  ) 
 

Build contact header - the contact header we send out.

Definition at line 217 of file sip3_compose.c.

References ast_inet_ntoa(), ast_string_field_build, ast_strlen_zero(), sipnet, sipnet_ourport(), and STANDARD_SIP_PORT.

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 }

void build_rpid struct sip_dialog p  ) 
 

Build the Remote Party-ID & From using callingpres options.

Definition at line 228 of file sip3_compose.c.

References ast_inet_ntoa(), ast_log(), AST_PRES_ALLOWED, AST_PRES_ALLOWED_NETWORK_NUMBER, AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, AST_PRES_NUMBER_NOT_AVAILABLE, AST_PRES_PROHIB_NETWORK_NUMBER, AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, AST_PRES_RESTRICTION, ast_string_field_build, ast_string_field_set, ast_strlen_zero(), sip_dialog::callingpres, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, sip_globals::default_callerid, FALSE, global, LOG_WARNING, sip_dialog::ourip, sip_dialog::owner, S_OR, sip_dialog::tag, and TRUE.

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 }

GNURK int init_req struct sip_request req,
int  sipmethod,
const char *  recip
 

Initialize SIP request.

Definition at line 150 of file sip3_compose.c.

References ast_log(), sip_request::data, sip_request::data_size, sip_request::header, sip_request::headers, sip_request::len, LOG_DEBUG, sip_request::method, option_debug, and sip_method2txt().

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 }

GNURK int init_resp struct sip_request resp,
const char *  msg
 

Initialize SIP response, based on SIP request.

Definition at line 138 of file sip3_compose.c.

References sip_request::data, sip_request::data_size, sip_request::header, sip_request::headers, sip_request::len, sip_request::method, and SIP_RESPONSE.

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 }

void initreqprep struct sip_request req,
struct sip_dialog p,
int  sipmethod
 

Initiate new SIP request to peer/user.

Definition at line 486 of file sip3_compose.c.

References AST_DIGIT_ANYNUM, ast_test_flag, sip_dialog::flags, s, and SIP_USEREQPHONE.

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 }

int reqprep struct sip_request req,
struct sip_dialog p,
int  sipmethod,
int  seqno,
int  newbranch
 

Initialize a SIP request message (not the initial one in a dialog).

< Strict routing flag

Definition at line 625 of file sip3_compose.c.

References add_header(), add_route(), append_maxforwards(), ast_log(), ast_strlen_zero(), ast_test_flag, build_via(), copy_header(), FALSE, sip_dialog::flags, get_header(), get_in_brackets(), global, sip_route::hop, init_req(), sip_dialog::initreq, sip_dialog::lastmsg, LOG_DEBUG, LOG_WARNING, sip_route::next, sip_dialog::ocseq, parse_request(), sip_request::rlPart2, sip_dialog::route, sip_request::seqno, set_destination(), SIP_ACK, SIP_CANCEL, sip_method2txt(), SIP_OUTGOING, SIP_PKT_CONNECTED, SIP_PKT_PARSED, sipdebug, strcasestr(), strsep(), sip_dialog::tag, TRUE, and sip_globals::useragent.

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 }

int respprep struct sip_request resp,
struct sip_dialog dialog,
const char *  msg,
struct sip_request req
 

Prepare SIP response packet.

Definition at line 307 of file sip3_compose.c.

References add_header(), ALLOWED_METHODS, ast_strlen_zero(), ast_test_flag, copy_all_header(), copy_via_headers(), sip_request::cseqheader, sip_dialog::expiry, sip_dialog::flags, sip_request::from, global, init_resp(), sip_dialog::method, sip_request::method, sip_request::seqno, SIP_INVITE, SIP_OPTIONS, SIP_OUTGOING, SIP_REGISTER, SIP_SUBSCRIBE, strcasestr(), SUPPORTED_EXTENSIONS, sip_dialog::tag, sip_request::to, and sip_globals::useragent.

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 }

static void set_destination struct sip_dialog p,
char *  uri
[static]
 

Set destination from SIP URI.

Definition at line 422 of file sip3_compose.c.

References ahp, ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_verbose(), debug(), hostname, hp, LOG_WARNING, sip_dialog::sa, sip_debug_test_pvt(), and STANDARD_SIP_PORT.

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 }


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