Codename Pineapple

Home page | Mailing list | Docs

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

Asterisk developer's documentation :: Codename Pineapple


sip3_transmit.c File Reference


Detailed Description

Various SIP message transmit functions 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_transmit.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/rtp.h"
#include "asterisk/udptl.h"
#include "asterisk/acl.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/app.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/devicestate.h"
#include "asterisk/linkedlists.h"
#include "asterisk/stringfields.h"
#include "asterisk/monitor.h"
#include "asterisk/localtime.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/compiler.h"
#include "sip3.h"
#include "sip3funcs.h"

Include dependency graph for sip3_transmit.c:

Go to the source code of this file.

Functions

GNURK int __transmit_response (struct sip_dialog *p, const char *msg, struct sip_request *req, enum xmittype reliable)
 Base transmit response function.
static int add_vidupdate (struct sip_request *req)
 add XML encoded media control with update
GNURK void transmit_fake_auth_response (struct sip_dialog *p, struct sip_request *req, int reliable)
 Send a fake 401 Unauthorized response when the administrator wants to hide the names of local users/peers from fishers.
GNURK int transmit_info_with_digit (struct sip_dialog *p, const char digit, unsigned int duration)
 Send SIP INFO dtmf message, see Cisco documentation on cisco.com.
GNURK int transmit_info_with_vidupdate (struct sip_dialog *p)
 Send SIP INFO with video update request.
GNURK int transmit_invite (struct sip_dialog *dialog, int sipmethod, int sdp, int init)
 Build REFER/INVITE/OPTIONS message and transmit it.
GNURK int transmit_message_with_text (struct sip_dialog *p, const char *text)
 Transmit text with SIP MESSAGE method.
GNURK int transmit_notify_with_mwi (struct sip_dialog *p, int newmsgs, int oldmsgs, char *vmexten)
 Notify user of messages waiting in voicemail.
GNURK int transmit_refer (struct sip_dialog *p, const char *dest)
 Transmit SIP REFER message (initiated by the transfer() dialplan application.
GNURK int transmit_reinvite_with_sdp (struct sip_dialog *p, int t38type)
 Transmit reinvite with SDP.
GNURK int transmit_request (struct sip_dialog *p, int sipmethod, int seqno, enum xmittype reliable, int newbranch)
 Transmit generic SIP request.
GNURK int transmit_request_with_auth (struct sip_dialog *dialog, int sipmethod, int seqno, enum xmittype reliable, int newbranch)
 Transmit SIP request, auth added.
GNURK int transmit_response (struct sip_dialog *p, const char *msg, struct sip_request *req)
 Transmit response, no retransmits.
GNURK int transmit_response_reliable (struct sip_dialog *p, const char *msg, struct sip_request *req)
 Transmit response, Make sure you get an ACK This is only used for responses to INVITEs, where we need to make sure we get an ACK.
GNURK int transmit_response_with_attachment (enum responseattach attach, struct sip_dialog *p, const char *msg, struct sip_request *req, enum xmittype reliable)
 Transmit responses with various attachments.
GNURK int transmit_response_with_auth (struct sip_dialog *p, const char *msg, struct sip_request *req, const char *randdata, enum xmittype reliable, const char *header, int stale)
 Respond with authorization request.
GNURK int transmit_response_with_unsupported (struct sip_dialog *p, const char *msg, struct sip_request *req, const char *unsupported)
 Transmit response, no retransmits.
GNURK int transmit_sip_request (struct sip_dialog *p, struct sip_request *req)
 Transmit SIP request unreliably (only used in sip_notify subsystem).


Function Documentation

GNURK int __transmit_response struct sip_dialog p,
const char *  msg,
struct sip_request req,
enum xmittype  reliable
 

Base transmit response function.

sip3_transmit.c

Definition at line 113 of file sip3_transmit.c.

References add_header(), add_header_contentLength(), ast_cause2str(), ast_log(), sip_request::data_size, get_header(), ast_channel::hangupcause, LOG_DEBUG, LOG_WARNING, sip_dialog::method, sip_dialog::owner, respprep(), send_response(), sip_request::seqno, SIP_INVITE, SIP_MAX_PACKET, sipnet, siprequest_alloc(), siprequest_free(), and XMIT_UNRELIABLE.

00114 {
00115    struct sip_request *resp;
00116    int seqno = 0;
00117    int res;
00118 
00119 
00120    if (reliable && (sscanf(get_header(req, "CSeq"), "%d ", &seqno) != 1)) {
00121       ast_log(LOG_WARNING, "Unable to determine sequence number from '%s'\n", get_header(req, "CSeq"));
00122       return -1;
00123    }
00124 
00125    resp = siprequest_alloc(SIP_MAX_PACKET, &sipnet);
00126    ast_log(LOG_DEBUG, "   :::: Response data size: %d\n", (int) resp->data_size);
00127    resp->seqno = seqno;
00128    respprep(resp, p, msg, req);
00129    add_header_contentLength(resp, 0);
00130    /* If we are cancelling an incoming invite for some reason, add information
00131       about the reason why we are doing this in clear text */
00132    if (p->method == SIP_INVITE && msg[0] != '1' && p->owner && p->owner->hangupcause) {
00133       char buf[10];
00134 
00135       add_header(resp, "X-Asterisk-HangupCause", ast_cause2str(p->owner->hangupcause));
00136       snprintf(buf, sizeof(buf), "%d", p->owner->hangupcause);
00137       add_header(resp, "X-Asterisk-HangupCauseCode", buf);
00138    }
00139    res =  send_response(p, resp, reliable);
00140    if (reliable == XMIT_UNRELIABLE)
00141       siprequest_free(resp);
00142    return res;
00143 }

static int add_vidupdate struct sip_request req  )  [static]
 

add XML encoded media control with update

Note:
XML: The only way to turn 0 bits of information into a few hundred. (markster)

Definition at line 94 of file sip3_transmit.c.

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

00095 {
00096    const char *xml_is_a_huge_waste_of_space =
00097       "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n"
00098       " <media_control>\r\n"
00099       "  <vc_primitive>\r\n"
00100       "   <to_encoder>\r\n"
00101       "    <picture_fast_update>\r\n"
00102       "    </picture_fast_update>\r\n"
00103       "   </to_encoder>\r\n"
00104       "  </vc_primitive>\r\n"
00105       " </media_control>\r\n";
00106    add_header(req, "Content-Type", "application/media_control+xml");
00107    add_header_contentLength(req, strlen(xml_is_a_huge_waste_of_space));
00108    add_line(req, xml_is_a_huge_waste_of_space);
00109    return 0;
00110 }

GNURK void transmit_fake_auth_response struct sip_dialog p,
struct sip_request req,
int  reliable
 

Send a fake 401 Unauthorized response when the administrator wants to hide the names of local users/peers from fishers.

Definition at line 623 of file sip3_transmit.c.

References ast_random(), ast_string_field_build, and transmit_response_with_auth().

00624 {
00625    ast_string_field_build(p, randdata, "%08lx", ast_random()); /* Create nonce for challenge */
00626    transmit_response_with_auth(p, "401 Unauthorized", req, p->randdata, reliable, "WWW-Authenticate", 0);
00627 }

GNURK int transmit_info_with_digit struct sip_dialog p,
const char  digit,
unsigned int  duration
 

Send SIP INFO dtmf message, see Cisco documentation on cisco.com.

Definition at line 540 of file sip3_transmit.c.

References add_digit(), reqprep(), send_request(), SIP_INFO, SIP_MAX_PACKET, sipnet, siprequest_alloc(), TRUE, and XMIT_RELIABLE.

00541 {
00542    struct sip_request *req;
00543 
00544    req = siprequest_alloc(SIP_MAX_PACKET, &sipnet);
00545    reqprep(req, p, SIP_INFO, 0, TRUE);
00546    add_digit(req, digit, duration);
00547    return send_request(p, req, XMIT_RELIABLE);
00548 }

GNURK int transmit_info_with_vidupdate struct sip_dialog p  ) 
 

Send SIP INFO with video update request.

Definition at line 551 of file sip3_transmit.c.

References add_vidupdate(), reqprep(), send_request(), SIP_INFO, SIP_MAX_PACKET, sipnet, siprequest_alloc(), TRUE, and XMIT_RELIABLE.

00552 {
00553    struct sip_request *req;
00554    req = siprequest_alloc(SIP_MAX_PACKET, &sipnet);
00555 
00556    reqprep(req, p, SIP_INFO, 0, TRUE);
00557    add_vidupdate(req);
00558    return send_request(p, req, XMIT_RELIABLE);
00559 }

GNURK int transmit_invite struct sip_dialog dialog,
int  sipmethod,
int  sdp,
int  init
 

Build REFER/INVITE/OPTIONS message and transmit it.

Definition at line 295 of file sip3_transmit.c.

References add_header(), add_header_contentLength(), add_sdp(), add_t38_sdp(), ALLOWED_METHODS, append_date(), AST_LIST_TRAVERSE, ast_log(), ast_strdupa, ast_strlen_zero(), ast_udptl_offered_from_local(), ast_var_name(), ast_var_value(), build_via(), sip_request::dialog, initialize_initreq(), initreqprep(), LOG_DEBUG, LOG_WARNING, sip_request::method, option_debug, reqprep(), send_request(), SIP_MAX_PACKET, SIP_REFER, sipdebug, sipnet, siprequest_alloc(), siprequest_free(), SUPPORTED_EXTENSIONS, T38_LOCAL_DIRECT, TRUE, ast_channel::varshead, XMIT_CRITICAL, and XMIT_RELIABLE.

00296 {
00297    struct sip_request *req;
00298    int res;
00299    
00300    req = siprequest_alloc(SIP_MAX_PACKET, &sipnet);
00301    req->method = sipmethod;
00302    if (init)
00303       /* Bump branch even on initial requests */
00304       build_via(dialog, TRUE);
00305 
00306    if (init == 2) /* open a new dialog */
00307       initreqprep(req, dialog, sipmethod);
00308    else
00309       reqprep(req, dialog, sipmethod, 0, TRUE);
00310       
00311    if (dialog->inviteoptions && dialog->inviteoptions->auth)
00312       add_header(req, dialog->inviteoptions->authheader, dialog->inviteoptions->auth);
00313    append_date(req);
00314    if (sipmethod == SIP_REFER && dialog->refer) { /* Call transfer */
00315       char buf[BUFSIZ];
00316       if (!ast_strlen_zero(dialog->refer->refer_to))
00317          add_header(req, "Refer-To", dialog->refer->refer_to);
00318       if (!ast_strlen_zero(dialog->refer->referred_by)) {
00319          sprintf(buf, "%s <%s>", dialog->refer->referred_by_name, dialog->refer->referred_by);
00320          add_header(req, "Referred-By", buf);
00321       }
00322    }
00323 
00324    if (dialog->inviteoptions && !ast_strlen_zero(dialog->inviteoptions->replaces)) {
00325       /* This new INVITE is part of an attended transfer. Make sure that the
00326          other end knows and replace the current call with this new call */
00327       add_header(req, "Replaces", dialog->inviteoptions->replaces);
00328       add_header(req, "Require", "replaces");
00329    }
00330 
00331    add_header(req, "Allow", ALLOWED_METHODS);
00332    add_header(req, "Supported", SUPPORTED_EXTENSIONS);
00333    if (dialog->inviteoptions && dialog->inviteoptions->addsipheaders) {
00334       struct ast_channel *ast;
00335       struct varshead *headp = NULL;
00336       const struct ast_var_t *current;
00337 
00338       ast = dialog->owner; /* The owner channel */
00339       if (ast) {
00340          char *headdup;
00341          headp = &ast->varshead;
00342          if (!headp)
00343             ast_log(LOG_WARNING,"No varshead for the channel...ooops!\n");
00344          else {
00345             AST_LIST_TRAVERSE(headp, current, entries) {  
00346                /* SIPADDHEADER: Add SIP header to outgoing call */
00347                if (!strncasecmp(ast_var_name(current), "SIPADDHEADER", strlen("SIPADDHEADER"))) {
00348                   char *content, *end;
00349                   const char *header = ast_var_value(current);
00350 
00351                   headdup = ast_strdupa(header);
00352                   /* Strip of the starting " (if it's there) */
00353                   if (*headdup == '"')
00354                      headdup++;
00355                   if ((content = strchr(headdup, ':'))) {
00356                      *content++ = '\0';
00357                      content = ast_skip_blanks(content); /* Skip white space */
00358                      /* Strip the ending " (if it's there) */
00359                      end = content + strlen(content) -1; 
00360                      if (*end == '"')
00361                         *end = '\0';
00362                   
00363                      add_header(req, headdup, content);
00364                      if (sipdebug)
00365                         ast_log(LOG_DEBUG, "Adding SIP Header \"%s\" with content :%s: \n", headdup, content);
00366                   }
00367                }
00368             }
00369          }
00370       }
00371    }
00372    if (sdp) {
00373       if (dialog->udptl && dialog->t38.state == T38_LOCAL_DIRECT) {
00374          ast_udptl_offered_from_local(dialog->udptl, 1);
00375          if (option_debug)
00376             ast_log(LOG_DEBUG, "T38 is in state %d on channel %s\n", dialog->t38.state, dialog->owner ? dialog->owner->name : "<none>");
00377          add_t38_sdp(req, dialog);
00378       } else if (dialog->rtp) 
00379          add_sdp(req, dialog);
00380    } else {
00381       add_header_contentLength(req, 0);
00382    }
00383 
00384    if (!dialog->initreq)
00385       initialize_initreq(dialog, req);
00386    dialog->lastinvite = dialog->ocseq;
00387    res = send_request(dialog, req, init ? XMIT_CRITICAL : XMIT_RELIABLE);
00388 
00389    if (!init)
00390       siprequest_free(req);
00391 
00392    return res;
00393 }

GNURK int transmit_message_with_text struct sip_dialog p,
const char *  text
 

Transmit text with SIP MESSAGE method.

Definition at line 444 of file sip3_transmit.c.

References add_text(), len, reqprep(), send_request(), SIP_MAX_PACKET, SIP_MESSAGE, sipnet, siprequest_alloc(), TRUE, and XMIT_RELIABLE.

00445 {
00446    struct sip_request *req;
00447    size_t len = SIP_MAX_PACKET;
00448 
00449    /* If we have a very large text message, allocate enough memory for it 
00450       We're guessing that the max size of headers is 500 bytes here.
00451    */
00452    if (strlen(text) > (len - 500))
00453       len += strlen(text);
00454 
00455    req = siprequest_alloc(len, &sipnet);
00456 
00457    reqprep(req, p, SIP_MESSAGE, 0, TRUE);
00458    add_text(req, text);
00459    return send_request(p, req, XMIT_RELIABLE);
00460 }

GNURK int transmit_notify_with_mwi struct sip_dialog p,
int  newmsgs,
int  oldmsgs,
char *  vmexten
 

Notify user of messages waiting in voicemail.

Note:
- Notification only works for registered peers with mailbox= definitions in sip.conf
  • We use the SIP Event package message-summary MIME type defaults to "application/simple-message-summary";

Definition at line 401 of file sip3_transmit.c.

References add_header(), add_header_contentLength(), add_line(), ast_build_string(), ast_inet_ntoa(), ast_log(), sip_globals::default_notifymime, sip_globals::default_vmexten, sip_dialog::expiry, global, initialize_initreq(), sip_dialog::initreq, initreqprep(), LOG_WARNING, sip_dialog::ourip, S_OR, send_request(), SIP_MAX_PACKET, SIP_NOTIFY, sipnet, siprequest_alloc(), sip_dialog::subscribed, and XMIT_RELIABLE.

00402 {
00403    struct sip_request *req;
00404    char tmp[500];
00405    char *t = tmp;
00406    size_t maxbytes = sizeof(tmp);
00407 
00408    req = siprequest_alloc(SIP_MAX_PACKET, &sipnet);
00409    initreqprep(req, p, SIP_NOTIFY);
00410    add_header(req, "Event", "message-summary");
00411    add_header(req, "Content-Type", global.default_notifymime);
00412 
00413    ast_build_string(&t, &maxbytes, "Messages-Waiting: %s\r\n", newmsgs ? "yes" : "no");
00414    ast_build_string(&t, &maxbytes, "Message-Account: sip:%s@%s\r\n",
00415       S_OR(vmexten, global.default_vmexten), S_OR(p->fromdomain, ast_inet_ntoa(p->ourip)));
00416    ast_build_string(&t, &maxbytes, "Voice-Message: %d/%d (0/0)\r\n", newmsgs, oldmsgs);
00417    if (p->subscribed) {
00418       if (p->expiry)
00419          add_header(req, "Subscription-State", "active");
00420       else  /* Expired */
00421          add_header(req, "Subscription-State", "terminated;reason=timeout");
00422    }
00423 
00424    if (t > tmp + sizeof(tmp))
00425       ast_log(LOG_WARNING, "Buffer overflow detected!!  (Please file a bug report)\n");
00426 
00427    add_header_contentLength(req, strlen(tmp));
00428    add_line(req, tmp);
00429 
00430    if (!p->initreq) 
00431       initialize_initreq(p, req);
00432    return send_request(p, req, XMIT_RELIABLE);
00433 }

GNURK int transmit_refer struct sip_dialog p,
const char *  dest
 

Transmit SIP REFER message (initiated by the transfer() dialplan application.

Note:
this is currently broken as we have no way of telling the dialplan engine whether a transfer succeeds or fails.
Todo:
Fix the transfer() dialplan function so that a transfer may fail
Todo:
In theory, we should hang around and wait for a reply, before returning to the dial plan here. Don't know really how that would affect the transfer() app or the pbx, but, well, to make this useful we should have a STATUS code on transfer().

Definition at line 467 of file sip3_transmit.c.

References add_header(), ALLOWED_METHODS, append_maxforwards(), ast_log(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, sip_dialog::flags, sip_request::from, get_header(), get_in_brackets(), sip_request::headers, sip_dialog::initreq, LOG_DEBUG, LOG_NOTICE, option_debug, sip_dialog::refer, REFER_SENT, sip_refer::refer_to, sip_refer::referred_by, reqprep(), send_request(), SIP_MAX_PACKET, SIP_OUTGOING, SIP_REFER, sip_refer_allocate(), sipdebug, sipnet, siprequest_alloc(), sip_refer::status, SUPPORTED_EXTENSIONS, sip_dialog::tag, TRUE, and XMIT_RELIABLE.

00468 {
00469    struct sip_request *req;
00470    char from[256];
00471    const char *of;
00472    char *c;
00473    char referto[256];
00474    char *ttag, *ftag;
00475    char *theirtag = ast_strdupa(p->theirtag);
00476 
00477    
00478    req = siprequest_alloc(SIP_MAX_PACKET, &sipnet);
00479    req->headers = 0;
00480 
00481    if (option_debug || sipdebug)
00482       ast_log(LOG_DEBUG, "SIP transfer of %s to %s\n", p->callid, dest);
00483 
00484    /* Are we transfering an inbound or outbound call ? */
00485    if (ast_test_flag(&p->flags[0], SIP_OUTGOING))  {
00486       of = get_header(p->initreq, "To");
00487       ttag = theirtag;
00488       ftag = p->tag;
00489    } else {
00490       of = get_header(p->initreq, "From");
00491       ftag = theirtag;
00492       ttag = p->tag;
00493    }
00494 
00495    ast_copy_string(from, of, sizeof(from));
00496    of = get_in_brackets(from);
00497    ast_string_field_set(p, from, of);
00498    if (strncmp(of, "sip:", 4))
00499       ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n");
00500    else
00501       of += 4;
00502    /* Get just the username part */
00503    if ((c = strchr(dest, '@')))
00504       c = NULL;
00505    else if ((c = strchr(of, '@')))
00506       *c++ = '\0';
00507    if (c) 
00508       snprintf(referto, sizeof(referto), "<sip:%s@%s>", dest, c);
00509    else
00510       snprintf(referto, sizeof(referto), "<sip:%s>", dest);
00511 
00512    /* save in case we get 407 challenge */
00513    sip_refer_allocate(p);
00514    ast_copy_string(p->refer->refer_to, referto, sizeof(p->refer->refer_to));
00515    ast_copy_string(p->refer->referred_by, p->our_contact, sizeof(p->refer->referred_by));
00516    p->refer->status = REFER_SENT;   /* Set refer status */
00517 
00518    reqprep(req, p, SIP_REFER, 0, TRUE);
00519    append_maxforwards(req);
00520 
00521    add_header(req, "Refer-To", referto);
00522    add_header(req, "Allow", ALLOWED_METHODS);
00523    add_header(req, "Supported", SUPPORTED_EXTENSIONS);
00524    if (!ast_strlen_zero(p->our_contact))
00525       add_header(req, "Referred-By", p->our_contact);
00526 
00527    return send_request(p, req, XMIT_RELIABLE);
00528    /* We should propably wait for a NOTIFY here until we ack the transfer */
00529    /* Maybe fork a new thread and wait for a STATUS of REFER_200OK on the refer status before returning to app_transfer */
00530 
00531    /*! \todo In theory, we should hang around and wait for a reply, before
00532    returning to the dial plan here. Don't know really how that would
00533    affect the transfer() app or the pbx, but, well, to make this
00534    useful we should have a STATUS code on transfer().
00535    */
00536 }

GNURK int transmit_reinvite_with_sdp struct sip_dialog p,
int  t38type
 

Transmit reinvite with SDP.

Note:
A re-invite is basically a new INVITE with the same CALL-ID and TAG as the INVITE that opened the SIP dialogue We reinvite so that the audio stream (RTP) go directly between the SIP UAs. SIP Signalling stays with * in the path. IF type == 1, we send T.38 SDP

Definition at line 270 of file sip3_transmit.c.

References add_header(), add_sdp(), add_t38_sdp(), ALLOWED_METHODS, append_history, ast_test_flag, sip_dialog::flags, initialize_initreq(), reqprep(), send_request(), SIP_INVITE, SIP_MAX_PACKET, SIP_NO_HISTORY, SIP_REINVITE_UPDATE, SIP_UPDATE, sipdebug, sipnet, siprequest_alloc(), SUPPORTED_EXTENSIONS, and XMIT_CRITICAL.

00271 {
00272    struct sip_request *req;
00273 
00274    req = siprequest_alloc(SIP_MAX_PACKET, &sipnet);
00275    reqprep(req, p, ast_test_flag(&p->flags[0], SIP_REINVITE_UPDATE) ?  SIP_UPDATE : SIP_INVITE, 0, 1);
00276    
00277    add_header(req, "Allow", ALLOWED_METHODS);
00278    add_header(req, "Supported", SUPPORTED_EXTENSIONS);
00279    if (sipdebug)
00280       add_header(req, "X-asterisk-Info",(t38type ? "SIP re-invite for T38 fax" : "SIP re-invite (External RTP bridge)"));
00281    if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY))
00282       append_history(p, "ReInv", "%s", (t38type ? "Re-invite sent for T38" : "Re-invite sent for external RTP media"));
00283    if (t38type)
00284       add_t38_sdp(req, p);
00285    else
00286       add_sdp(req, p);
00287 
00288    /* Use this as the basis */
00289    initialize_initreq(p, req);
00290    p->lastinvite = p->ocseq;
00291    return send_request(p, req, XMIT_CRITICAL);
00292 }

GNURK int transmit_request struct sip_dialog p,
int  sipmethod,
int  seqno,
enum xmittype  reliable,
int  newbranch
 

Transmit generic SIP request.

Definition at line 562 of file sip3_transmit.c.

References add_header_contentLength(), reqprep(), send_request(), SIP_MAX_PACKET, sipnet, siprequest_alloc(), siprequest_free(), and XMIT_UNRELIABLE.

00563 {
00564    struct sip_request *resp;
00565    int res;
00566 
00567    resp = siprequest_alloc(SIP_MAX_PACKET, &sipnet);
00568 
00569    reqprep(resp, p, sipmethod, seqno, newbranch);
00570    add_header_contentLength(resp, 0);
00571    res = send_request(p, resp, reliable);
00572    if (reliable == XMIT_UNRELIABLE)
00573       siprequest_free(resp);
00574    return res;
00575 }

GNURK int transmit_request_with_auth struct sip_dialog dialog,
int  sipmethod,
int  seqno,
enum xmittype  reliable,
int  newbranch
 

Transmit SIP request, auth added.

Definition at line 578 of file sip3_transmit.c.

References add_header(), add_header_contentLength(), ast_cause2str(), ast_log(), ast_strlen_zero(), auth_headers(), sip_invite_param::auth_type, build_reply_digest(), sip_request::dialog, ast_channel::hangupcause, sip_dialog::inviteoptions, LOG_ERROR, LOG_WARNING, sip_dialog::owner, PROXY_AUTH, reqprep(), send_request(), SIP_BYE, SIP_MAX_PACKET, sipnet, siprequest_alloc(), siprequest_free(), and XMIT_UNRELIABLE.

00579 {
00580    struct sip_request *resp;
00581    int res;
00582 
00583    resp = siprequest_alloc(SIP_MAX_PACKET, &sipnet);
00584    if (!resp) {
00585       ast_log(LOG_ERROR, "--- Can't allocate SIP request for this transaction! Call ID %s\n", dialog->callid);
00586    }
00587 
00588    reqprep(resp, dialog, sipmethod, seqno, newbranch);
00589    if (!ast_strlen_zero(dialog->realm)) {
00590       char digest[1024];
00591 
00592       memset(digest, 0, sizeof(digest));
00593       if(!build_reply_digest(dialog, sipmethod, digest, sizeof(digest))) {
00594          char *dummy, *response;
00595 
00596          enum sip_auth_type code = dialog->inviteoptions ? dialog->inviteoptions->auth_type : PROXY_AUTH; /* XXX force 407 if unknown */
00597          auth_headers(code, &dummy, &response);
00598          add_header(resp, response, digest);
00599       } else
00600          ast_log(LOG_WARNING, "No authentication available for call %s\n", dialog->callid);
00601    }
00602    /* If we are hanging up and know a cause for that, send it in clear text to make
00603       debugging easier. */
00604    if (sipmethod == SIP_BYE && dialog->owner && dialog->owner->hangupcause)   {
00605       char buf[10];
00606 
00607       add_header(resp, "X-Asterisk-HangupCause", ast_cause2str(dialog->owner->hangupcause));
00608       snprintf(buf, sizeof(buf), "%d", dialog->owner->hangupcause);
00609       add_header(resp, "X-Asterisk-HangupCauseCode", buf);
00610    }
00611 
00612    add_header_contentLength(resp, 0);
00613 
00614    res = send_request(dialog, resp, reliable);
00615    if (reliable == XMIT_UNRELIABLE)
00616       siprequest_free(resp);
00617    return res;
00618 }

GNURK int transmit_response struct sip_dialog p,
const char *  msg,
struct sip_request req
 

Transmit response, no retransmits.

Definition at line 146 of file sip3_transmit.c.

References __transmit_response(), and XMIT_UNRELIABLE.

00147 {
00148    return __transmit_response(p, msg, req, XMIT_UNRELIABLE);
00149 }

GNURK int transmit_response_reliable struct sip_dialog p,
const char *  msg,
struct sip_request req
 

Transmit response, Make sure you get an ACK This is only used for responses to INVITEs, where we need to make sure we get an ACK.

Definition at line 155 of file sip3_transmit.c.

References __transmit_response(), and XMIT_CRITICAL.

00156 {
00157    return __transmit_response(p, msg, req, XMIT_CRITICAL);
00158 }

GNURK int transmit_response_with_attachment enum responseattach  attach,
struct sip_dialog p,
const char *  msg,
struct sip_request req,
enum xmittype  reliable
 

Transmit responses with various attachments.

Definition at line 161 of file sip3_transmit.c.

References add_header(), add_header_contentLength(), add_sdp(), add_t38_sdp(), append_date(), ast_log(), ast_rtp_codec_setpref(), ast_test_flag, ast_udptl_offered_from_local(), sip_dialog::autoframing, expiry, sip_dialog::flags, LOG_DEBUG, LOG_ERROR, option_debug, sip_dialog::prefs, respprep(), sip_dialog::rtp, send_response(), sip_request::seqno, SIP_MAX_PACKET, SIP_OUTGOING, sipnet, siprequest_alloc(), siprequest_free(), try_suggested_sip_codec(), sip_dialog::udptl, WITH_ALLOW, WITH_DATE, WITH_MINEXPIRY, WITH_SDP, WITH_T38_SDP, and XMIT_UNRELIABLE.

Referenced by handle_invite_replaces(), handle_request(), handle_request_invite(), handle_request_options(), handle_request_subscribe(), register_verify(), sip_answer(), sip_handle_t38_reinvite(), sip_indicate(), and write_media_frame().

00163 {
00164    struct sip_request *resp;
00165    char buf[12];
00166    int res;
00167 
00168    resp = siprequest_alloc(SIP_MAX_PACKET, &sipnet);
00169    respprep(resp, p, msg, req);
00170    if (resp->seqno == 0) {
00171       if (req->seqno) {
00172          ast_log(LOG_DEBUG, " ************ Response seqno still zero!!!!!!!!!\n");
00173          resp->seqno = req->seqno;
00174       } else {
00175          ast_log(LOG_DEBUG, " ************ Request seqno still zero!!!!!!!!! Can't set response seqno\n");
00176       }
00177    }
00178    append_date(resp);
00179    switch (attach) {
00180    case WITH_DATE:
00181       add_header_contentLength(resp, 0);
00182       break;
00183    case WITH_MINEXPIRY:
00184       snprintf(buf, sizeof(buf), "%d", expiry.min_expiry);
00185       add_header(resp, "Min-Expires", buf);
00186       break;
00187    case WITH_ALLOW:
00188       add_header(resp, "Accept", "application/sdp");
00189       add_header_contentLength(resp, 0);
00190       break;
00191    case WITH_SDP:
00192       if (p->rtp) {
00193          if (!p->autoframing && !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
00194             if (option_debug)
00195                ast_log(LOG_DEBUG, "Setting framing from config on incoming call\n");
00196             ast_rtp_codec_setpref(p->rtp, &p->prefs);
00197          }
00198          try_suggested_sip_codec(p);   
00199          add_sdp(resp, p);
00200       } else 
00201          ast_log(LOG_ERROR, "Can't add SDP to response, since we have no RTP session allocated. Call-ID %s\n", p->callid);
00202       break;
00203    case WITH_T38_SDP:
00204       if (p->udptl) {
00205          ast_udptl_offered_from_local(p->udptl, 0);
00206          add_t38_sdp(resp, p);
00207       } else 
00208          ast_log(LOG_ERROR, "Can't add T38 SDP to response, since we have no UDPTL session allocated. Call-ID %s\n", p->callid);
00209       break;
00210    }
00211    res =  send_response(p, resp, reliable);
00212    if (reliable == XMIT_UNRELIABLE)
00213       siprequest_free(resp);
00214    return res;
00215 }

GNURK int transmit_response_with_auth struct sip_dialog p,
const char *  msg,
struct sip_request req,
const char *  randdata,
enum xmittype  reliable,
const char *  header,
int  stale
 

Respond with authorization request.

Definition at line 236 of file sip3_transmit.c.

References add_header(), add_header_contentLength(), ast_log(), get_header(), global, LOG_WARNING, sip_globals::realm, respprep(), send_response(), sip_request::seqno, SIP_MAX_PACKET, sipnet, siprequest_alloc(), siprequest_free(), and XMIT_UNRELIABLE.

00237 {
00238    struct sip_request *resp;
00239    char tmp[512];
00240    int seqno = 0;
00241    int res;
00242 
00243 
00244    if (reliable && (sscanf(get_header(req, "CSeq"), "%d ", &seqno) != 1)) {
00245       ast_log(LOG_WARNING, "Unable to determine sequence number from '%s'\n", get_header(req, "CSeq"));
00246       return -1;
00247    }
00248    resp = siprequest_alloc(SIP_MAX_PACKET, &sipnet);
00249 
00250 
00251    /* Stale means that they sent us correct authentication, but 
00252       based it on an old challenge (nonce) */
00253    snprintf(tmp, sizeof(tmp), "Digest algorithm=MD5, realm=\"%s\", nonce=\"%s\"%s", global.realm, randdata, stale ? ", stale=true" : "");
00254    respprep(resp, p, msg, req);
00255    add_header(resp, header, tmp);
00256    add_header_contentLength(resp, 0);
00257    res =  send_response(p, resp, reliable);
00258    if (reliable == XMIT_UNRELIABLE)
00259       siprequest_free(resp);
00260    return res;
00261 }

GNURK int transmit_response_with_unsupported struct sip_dialog p,
const char *  msg,
struct sip_request req,
const char *  unsupported
 

Transmit response, no retransmits.

Definition at line 218 of file sip3_transmit.c.

References add_blank(), add_header(), add_header_contentLength(), append_date(), respprep(), send_response(), SIP_MAX_PACKET, sipnet, siprequest_alloc(), siprequest_free(), and XMIT_UNRELIABLE.

00219 {
00220    struct sip_request *resp;
00221    int res;
00222 
00223    resp = siprequest_alloc(SIP_MAX_PACKET, &sipnet);
00224 
00225    respprep(resp, p, msg, req);
00226    append_date(resp);
00227    add_header(resp, "Unsupported", unsupported);
00228    add_header_contentLength(resp, 0);
00229    add_blank(resp);
00230    res = send_response(p, resp, XMIT_UNRELIABLE);
00231    siprequest_free(resp);
00232    return res;
00233 }

GNURK int transmit_sip_request struct sip_dialog p,
struct sip_request req
 

Transmit SIP request unreliably (only used in sip_notify subsystem).

Definition at line 436 of file sip3_transmit.c.

References initialize_initreq(), sip_dialog::initreq, send_request(), and XMIT_UNRELIABLE.

00437 {
00438    if (!p->initreq)  /* Initialize first request before sending */
00439       initialize_initreq(p, req);
00440    return send_request(p, req, XMIT_UNRELIABLE);
00441 }


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