![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
sip3_compose.c File Reference
Olle E. Johansson <oej@edvina.net> (all the chan_sip3 changes)
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. | |
|
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||||||||||||||
|
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 }
|
|
||||||||||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|