Codename Pineapple

Home page | Mailing list | Docs

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

Asterisk developer's documentation :: Codename Pineapple


chan_sip3.c File Reference


Detailed Description

Implementation of Session Initiation Protocol Version 3 of chan_sip.

Author:
Mark Spencer <markster@digium.com>

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

See Also: Implementation of RFC 3261 - without S/MIME, TCP and TLS support Configuration file sip.conf

Todo:
SIP over TCP

SIP over TLS

Better support of forking

VIA branch tag transaction checking

Transaction support

Definition in file chan_sip3.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/translate.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/sip3.h"
#include "sip3/sip3funcs.h"

Include dependency graph for chan_sip3.c:

Go to the source code of this file.

Defines

#define CHAN_SIP3_MAIN
#define GNURK
#define SIPLABEL   sip3

Functions

GNURK int add_t38_sdp (struct sip_request *resp, struct sip_dialog *p)
 Add T.38 Session Description Protocol message.
static int add_vidupdate (struct sip_request *req)
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"Session Initiation Protocol, chan_sip3 version (SIP)",.load=load_module,.unload=unload_module,.reload=reload,)
 AST_MUTEX_DEFINE_STATIC (sip_reload_lock)
 Make sure we don't reload twice at the same time.
GNURK void ast_quiet_chan (struct ast_channel *chan)
 Turn off generator data XXX Does this function belong in the SIP channel?
static int auto_congest (void *nothing)
 Scheduled congestion on a call.
static void build_route (struct sip_dialog *p, struct sip_request *req, int backwards)
 Build route list from Record-Route header.
static int cb_extensionstate (char *context, char *exten, int state, void *data)
 Callback for the devicestate notification (SUBSCRIBE) support subsystem.
static void check_pendings (struct sip_dialog *p)
 Check pending actions on SIP call.
static int check_user (struct sip_dialog *p, struct sip_request *req, int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin)
 Find user If we get a match, this will add a reference pointer to the user object in ASTOBJ, that needs to be unreferenced.
static enum check_auth_result check_user_full (struct sip_dialog *p, struct sip_request *req, int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin, struct sip_device **authpeer)
 Check if matching user or peer is defined Match user on From: user name and peer on IP/port This is used on first invite (not re-invites) and subscribe requests.
static void check_via (struct sip_dialog *p, struct sip_request *req)
 check Via: header for hostname, port and rport request/answer
GNURK int create_addr (struct sip_dialog *dialog, const char *username, char *domain, const char *device)
 create address structure from peer name Or, if peer not found, find it in the global DNS returns TRUE (-1) on failure, FALSE on success
static int create_addr_from_peer (struct sip_dialog *dialog, struct sip_device *device)
 Create address structure from device reference. return -1 on error, 0 on success.
GNURK void do_setnat (struct sip_dialog *dialog, int natflags)
 Set nat mode on the various media streams.
void free_old_route (struct sip_route *route)
 Remove route from route list.
static int func_header_read (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
 Read SIP header (dialplan function).
static int function_sipchaninfo_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 ${SIPCHANINFO()} Dialplan function - reads sip channel data
static int function_sippeer (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 ${SIPPEER()} Dialplan function - reads peer data
static int get_also_info (struct sip_dialog *p, struct sip_request *oreq)
 Call transfer support (old way, deprecated by the IETF)--.
static int get_msg_text (char *buf, int len, struct sip_request *req)
 Get text out of a SIP MESSAGE packet.
GNURK struct sip_dialogget_sip_dialog_byid_locked (const char *callid, const char *totag, const char *fromtag)
 Lock dialog list lock and find matching pvt lock
  • Their tag is fromtag, our tag is to-tag
  • This means that in some transactions, totag needs to be their tag :-) depending upon the direction.

static int handle_invite_replaces (struct sip_dialog *p, struct sip_request *req, int debug, struct sockaddr_in *sin)
 Handle the transfer part of INVITE with a replaces: header, meaning a target pickup or an attended transfer.
GNURK int handle_request (struct sip_dialog *p, struct sip_request *req, struct sockaddr_in *sin, int *recount, int *nounlock)
 Handle incoming SIP requests (methods).
static int handle_request_bye (struct sip_dialog *p, struct sip_request *req)
 Handle incoming BYE request.
static int handle_request_cancel (struct sip_dialog *p, struct sip_request *req)
 Handle incoming CANCEL request.
static void handle_request_info (struct sip_dialog *p, struct sip_request *req)
 Receive SIP INFO Message.
static int handle_request_invite (struct sip_dialog *p, struct sip_request *req, int debug, struct sockaddr_in *sin, int *recount, char *e)
 Handle incoming INVITE request.
static int handle_request_message (struct sip_dialog *p, struct sip_request *req)
 Handle incoming MESSAGE request.
static int handle_request_notify (struct sip_dialog *p, struct sip_request *req, struct sockaddr_in *sin, char *e)
 Handle incoming notifications.
static int handle_request_options (struct sip_dialog *p, struct sip_request *req)
 Handle incoming OPTIONS request.
static int handle_request_register (struct sip_dialog *p, struct sip_request *req, struct sockaddr_in *sin, char *e)
 Handle incoming REGISTER request.
static int handle_request_subscribe (struct sip_dialog *p, struct sip_request *req, struct sockaddr_in *sin, char *e)
 Handle incoming SUBSCRIBE request.
static void handle_response (struct sip_dialog *p, int resp, char *rest, struct sip_request *req)
 Handle SIP response in dialogue.
static void handle_response_answer (struct sip_dialog *dialog, struct sip_request *req, int outgoing, int reinvite)
 Handle a positive response to an INVITE - 200 OK.
static void handle_response_bye (struct sip_dialog *dialog, int resp, char *rest, struct sip_request *req)
static void handle_response_invite (struct sip_dialog *p, int resp, char *rest, struct sip_request *req)
 Handle SIP response to INVITE dialogue.
static void handle_response_message (struct sip_dialog *dialog, int resp, char *rest, struct sip_request *req)
static void handle_response_notify (struct sip_dialog *dialog, int resp, char *rest, struct sip_request *req)
static void handle_response_refer (struct sip_dialog *p, int resp, char *rest, struct sip_request *req)
static void list_route (struct sip_route *route)
 List all routes - mostly for debugging.
static int load_module (void)
 load_module: PBX load module - initialization
static int parse_ok_contact (struct sip_dialog *pvt, struct sip_request *req)
 Save contact header for 200 OK on INVITE.
static enum parse_register_result parse_register_contact (struct sip_dialog *pvt, struct sip_device *peer, struct sip_request *req)
 Parse contact header and save registration (peer registration).
static void receive_message (struct sip_dialog *p, struct sip_request *req)
 Receive SIP MESSAGE method messages.
static enum check_auth_result register_verify (struct sip_dialog *p, struct sockaddr_in *sin, struct sip_request *req, char *uri)
 Verify registration of user
  • Registration is done in several steps, first a REGISTER without auth to get a challenge (nonce) then a second one with auth
  • Registration requests are only matched with peers that are marked as "dynamic".

static int reload (void)
 reload: Part of Asterisk module interface
static int set_address_from_contact (struct sip_dialog *pvt)
 Change the other partys IP address based on given contact.
static int sip_addheader (struct ast_channel *chan, void *data)
 Add a SIP header to an outbound INVITE.
static int sip_answer (struct ast_channel *ast)
 sip_answer: Answer SIP call , send 200 OK on Invite Part of PBX interface
static int sip_call (struct ast_channel *ast, char *dest, int timeout)
 Initiate SIP call from PBX used from the dial() application.
GNURK int sip_debug_test_pvt (struct sip_dialog *p)
 Test PVT for debugging output.
static int sip_devicestate (void *data)
 Part of PBX channel interface.
GNURK int sip_do_reload ()
 Reload module.
static int sip_dtmfmode (struct ast_channel *chan, void *data)
 Set the DTMFmode for an outbound SIP call (application).
GNURK void sip_dump_history (struct sip_dialog *dialog)
 Dump SIP history to debug log file at end of lifespan for SIP dialog.
static int sip_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
 sip_fixup: Fix up a channel: If a channel is consumed, this is called. Basically update any ->owner links :: PBX interface
static int sip_handle_t38_reinvite (struct ast_channel *chan, struct sip_dialog *pvt, int reinvite)
static int sip_hangup (struct ast_channel *ast)
 sip_hangup: Hangup SIP call Part of PBX interface, called from ast_hangup
static int sip_indicate (struct ast_channel *ast, int condition, const void *data, size_t datalen)
 Play indication to user :: PBX interface With SIP a lot of indications is sent as messages, letting the device play the indication - busy signal, congestion etc.
static struct ast_channelsip_new (struct sip_dialog *dialog, int state, const char *title)
 Initiate a call in the SIP channel :: PBX interface.
GNURK int sip_notify (int fd, int argc, char *argv[])
 Cli command to send SIP notify to peer.
GNURK void sip_peer_hold (struct sip_dialog *p, int hold)
 Change onhold state of a peer using a pvt structure.
GNURK int sip_prune_realtime (int fd, int argc, char *argv[])
 Remove temporary realtime objects from memory (CLI).
GNURK int sip_reload (int fd)
 Force reload of module from cli.
int sip_reload_check ()
static struct ast_channelsip_request_call (const char *type, int format, void *data, int *cause)
GNURK int sip_send_mwi_to_peer (struct sip_device *peer)
 Send message waiting indication to alert peer that they've got voicemail.
static int sip_senddigit_begin (struct ast_channel *ast, char digit)
 Start sending DTMF character on SIP channel within one call, we're able to transmit in many methods simultaneously.
static int sip_senddigit_end (struct ast_channel *ast, char digit, unsigned int duration)
 Send DTMF character on SIP channel within one call, we're able to transmit in many methods simultaneously.
static int sip_sendtext (struct ast_channel *ast, const char *text)
 Send SIP MESSAGE text within a call Called from PBX core sendtext() application.
static int sip_sipredirect (struct sip_dialog *p, const char *dest)
 Transfer call before connect with a 302 redirect.
static int sip_transfer (struct ast_channel *ast, const char *dest)
 Transfer SIP call :: PBX interface.
static int sip_write (struct ast_channel *ast, struct ast_frame *frame)
 Send frame to media channel (rtp) :: PBX interface.
static int t38_get_rate (int t38cap)
 Get Max T.38 Transmission rate from T38 capabilities.
static char * terminate_uri (char *uri)
GNURK void try_suggested_sip_codec (struct sip_dialog *p)
 Try setting codec suggested by the SIP_CODEC channel variable.
static int unload_module (void)
GNURK int update_call_counter (struct sip_dialog *fup, int event)
 update_call_counter: Handle call_limit for SIP users Setting a call-limit will cause calls above the limit not to be accepted.
static int write_media_frame (struct ast_channel *ast, struct sip_dialog *p, struct ast_frame *frame, struct ast_rtp *mediartp)

Variables

static char * app_dtmfmode = "SIPDtmfMode"
static char * app_sipaddheader = "SIPAddHeader"
static char * descrip_dtmfmode = "SIPDtmfMode(inband|info|rfc2833): Changes the dtmfmode for a SIP call\n"
static char * descrip_sipaddheader
sip_dialogdialoglist = NULL
expiry_times expiry
 various expiry times for registrations
sip_globals global
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
io_contextio
ast_confignotify_types
sched_contextsched
static struct ast_custom_function sip_header_function
static int sip_reloading = FALSE
static enum channelreloadreason sip_reloadreason
static const struct ast_channel_tech sip_tech
 Definition of this channel for PBX channel registration.
static const struct ast_channel_tech sip_tech_info
 This version of the sip channel tech has no send_digit_begin callback. This is for use with channels using SIP INFO DTMF so that the core knows that the channel doesn't want DTMF BEGIN frames.
static struct ast_custom_function sipchaninfo_function
 Structure to declare a dialplan function: SIPCHANINFO.
channel_counters sipcounters = { 0, 0, 0, 0, 0, 0, 0, 0}
ast_custom_function sippeer_function
 Structure to declare a dialplan function: SIPPEER.
static char * synopsis_dtmfmode = "Change the dtmfmode for a SIP call"
static char * synopsis_sipaddheader = "Add a SIP header to the outbound call"


Define Documentation

#define CHAN_SIP3_MAIN
 

Definition at line 406 of file chan_sip3.c.

#define GNURK
 

Definition at line 410 of file chan_sip3.c.

#define SIPLABEL   sip3
 

Definition at line 473 of file chan_sip3.c.


Function Documentation

GNURK int add_t38_sdp struct sip_request resp,
struct sip_dialog p
 

Add T.38 Session Description Protocol message.

Definition at line 1749 of file chan_sip3.c.

References add_header(), add_header_contentLength(), add_line(), ast_build_string(), ast_inet_ntoa(), ast_log(), ast_udptl_get_local_max_datagram(), ast_udptl_get_us(), t38properties::capability, debug(), t38properties::jointcapability, sip_dialog::lastrtprx, sip_dialog::lastrtptx, len, LOG_DEBUG, LOG_WARNING, sip_dialog::ourip, t38properties::peercapability, s, sip_dialog::sessionid, sip_dialog::sessionversion, sip_debug_test_pvt(), sip_dialog::t38, t38_get_rate(), T38FAX_FILL_BIT_REMOVAL, T38FAX_RATE_MANAGEMENT_LOCAL_TCF, T38FAX_TRANSCODING_JBIG, T38FAX_TRANSCODING_MMR, T38FAX_UDP_EC_NONE, T38FAX_UDP_EC_REDUNDANCY, T38FAX_VERSION, T38FAX_VERSION_0, T38FAX_VERSION_1, sip_dialog::udptl, and sip_dialog::udptlredirip.

01750 {
01751    int len = 0;
01752    int x = 0;
01753    struct sockaddr_in udptlsin;
01754    char v[256] = "";
01755    char s[256] = "";
01756    char o[256] = "";
01757    char c[256] = "";
01758    char t[256] = "";
01759    char m_modem[256];
01760    char a_modem[1024];
01761    char *m_modem_next = m_modem;
01762    size_t m_modem_left = sizeof(m_modem);
01763    char *a_modem_next = a_modem;
01764    size_t a_modem_left = sizeof(a_modem);
01765    struct sockaddr_in udptldest = { 0, };
01766    int debug;
01767    
01768    debug = sip_debug_test_pvt(p);
01769    len = 0;
01770    if (!p->udptl) {
01771       ast_log(LOG_WARNING, "No way to add SDP without an UDPTL structure\n");
01772       return -1;
01773    }
01774    
01775    if (!p->sessionid) {
01776       p->sessionid = getpid();
01777       p->sessionversion = p->sessionid;
01778    } else
01779       p->sessionversion++;
01780    
01781    /* Our T.38 end is */
01782    ast_udptl_get_us(p->udptl, &udptlsin);
01783    
01784    /* Determine T.38 UDPTL destination */
01785    if (p->udptlredirip.sin_addr.s_addr) {
01786       udptldest.sin_port = p->udptlredirip.sin_port;
01787       udptldest.sin_addr = p->udptlredirip.sin_addr;
01788    } else {
01789       udptldest.sin_addr = p->ourip;
01790       udptldest.sin_port = udptlsin.sin_port;
01791    }
01792    
01793    if (debug) 
01794       ast_log(LOG_DEBUG, "T.38 UDPTL is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(udptlsin.sin_port));
01795    
01796    /* We break with the "recommendation" and send our IP, in order that our
01797       peer doesn't have to ast_gethostbyname() us */
01798    
01799    if (debug) {
01800       ast_log(LOG_DEBUG, "Our T38 capability (%d), peer T38 capability (%d), joint capability (%d)\n",
01801          p->t38.capability,
01802          p->t38.peercapability,
01803          p->t38.jointcapability);
01804    }
01805    snprintf(v, sizeof(v), "v=0\r\n");
01806    snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", p->sessionid, p->sessionversion, ast_inet_ntoa(udptldest.sin_addr));
01807    snprintf(s, sizeof(s), "s=session\r\n");
01808    snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(udptldest.sin_addr));
01809    snprintf(t, sizeof(t), "t=0 0\r\n");
01810    ast_build_string(&m_modem_next, &m_modem_left, "m=image %d udptl t38\r\n", ntohs(udptldest.sin_port));
01811    
01812    if ((p->t38.jointcapability & T38FAX_VERSION) == T38FAX_VERSION_0)
01813       ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxVersion:0\r\n");
01814    if ((p->t38.jointcapability & T38FAX_VERSION) == T38FAX_VERSION_1)
01815       ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxVersion:1\r\n");
01816    if ((x = t38_get_rate(p->t38.jointcapability)))
01817       ast_build_string(&a_modem_next, &a_modem_left, "a=T38MaxBitRate:%d\r\n",x);
01818    ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxFillBitRemoval:%d\r\n", (p->t38.jointcapability & T38FAX_FILL_BIT_REMOVAL) ? 1 : 0);
01819    ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxTranscodingMMR:%d\r\n", (p->t38.jointcapability & T38FAX_TRANSCODING_MMR) ? 1 : 0);
01820    ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxTranscodingJBIG:%d\r\n", (p->t38.jointcapability & T38FAX_TRANSCODING_JBIG) ? 1 : 0);
01821    ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxRateManagement:%s\r\n", (p->t38.jointcapability & T38FAX_RATE_MANAGEMENT_LOCAL_TCF) ? "localTCF" : "transferredTCF");
01822    x = ast_udptl_get_local_max_datagram(p->udptl);
01823    ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxMaxBuffer:%d\r\n",x);
01824    ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxMaxDatagram:%d\r\n",x);
01825    if (p->t38.jointcapability != T38FAX_UDP_EC_NONE)
01826       ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxUdpEC:%s\r\n", (p->t38.jointcapability & T38FAX_UDP_EC_REDUNDANCY) ? "t38UDPRedundancy" : "t38UDPFEC");
01827     len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m_modem) + strlen(a_modem);
01828    add_header(resp, "Content-Type", "application/sdp");
01829    add_header_contentLength(resp, len);
01830    add_line(resp, v);
01831    add_line(resp, o);
01832    add_line(resp, s);
01833    add_line(resp, c);
01834    add_line(resp, t);
01835    add_line(resp, m_modem);
01836    add_line(resp, a_modem);
01837    
01838    /* Update lastrtprx when we send our SDP */
01839    p->lastrtprx = p->lastrtptx = time(NULL);
01840    
01841    return 0;
01842 }

static int add_vidupdate struct sip_request req  )  [static]
 

AST_MODULE_INFO ASTERISK_GPL_KEY  ,
AST_MODFLAG_DEFAULT  ,
"Session Initiation   Protocol,
chan_sip3 version(SIP)"  ,
load = load_module,
unload = unload_module,
reload = reload
 

AST_MUTEX_DEFINE_STATIC sip_reload_lock   ) 
 

Make sure we don't reload twice at the same time.

GNURK void ast_quiet_chan struct ast_channel chan  ) 
 

Turn off generator data XXX Does this function belong in the SIP channel?

Definition at line 4034 of file chan_sip3.c.

References ast_channel::_state, ast_deactivate_generator(), AST_STATE_UP, and ast_channel::generatordata.

04035 {
04036    if (chan && chan->_state == AST_STATE_UP) {
04037       if (chan->generatordata)
04038          ast_deactivate_generator(chan);
04039    }
04040 }

static int auto_congest void *  nothing  )  [static]
 

Scheduled congestion on a call.

Definition at line 881 of file chan_sip3.c.

References append_history, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_CONGESTION, ast_log(), ast_queue_control(), dialog_lock(), FALSE, sip_dialog::initid, LOG_NOTICE, sip_dialog::owner, and TRUE.

00882 {
00883    struct sip_dialog *dialog = nothing;
00884 
00885    dialog_lock(dialog, TRUE);
00886    dialog->initid = -1;
00887    if (dialog->owner) {
00888       /* XXX fails on possible deadlock */
00889       if (!ast_channel_trylock(dialog->owner)) {
00890          ast_log(LOG_NOTICE, "Auto-congesting %s\n", dialog->owner->name);
00891          append_history(dialog, "Cong", "Auto-congesting (timer)");
00892          ast_queue_control(dialog->owner, AST_CONTROL_CONGESTION);
00893          ast_channel_unlock(dialog->owner);
00894       }
00895    }
00896    dialog_lock(dialog, FALSE);
00897    return 0;
00898 }

static void build_route struct sip_dialog p,
struct sip_request req,
int  backwards
[static]
 

Build route list from Record-Route header.

Definition at line 2107 of file chan_sip3.c.

References __get_header(), ast_log(), ast_malloc, free_old_route(), sip_route::hop, len, LOG_DEBUG, sip_route::next, option_debug, sip_dialog::route, and sip_dialog::route_persistant.

02108 {
02109    struct sip_route *thishop, *head, *tail;
02110    int start = 0;
02111    int len;
02112    const char *rr, *contact, *c;
02113 
02114    /* Once a persistant route is set, don't fool with it */
02115    if (p->route && p->route_persistant) {
02116       if (option_debug)
02117          ast_log(LOG_DEBUG, "build_route: Retaining previous route: <%s>\n", p->route->hop);
02118       return;
02119    }
02120 
02121    if (p->route) {
02122       free_old_route(p->route);
02123       p->route = NULL;
02124    }
02125    
02126    p->route_persistant = backwards;
02127    
02128    /* Build a tailq, then assign it to p->route when done.
02129     * If backwards, we add entries from the head so they end up
02130     * in reverse order. However, we do need to maintain a correct
02131     * tail pointer because the contact is always at the end.
02132     */
02133    head = NULL;
02134    tail = head;
02135    /* 1st we pass through all the hops in any Record-Route headers */
02136    for (;;) {
02137       /* Each Record-Route header */
02138       rr = __get_header(req, "Record-Route", &start);
02139       if (*rr == '\0')
02140          break;
02141       for (; (rr = strchr(rr, '<')) ; rr += len) { /* Each route entry */
02142          ++rr;
02143          len = strcspn(rr, ">") + 1;
02144          /* Make a struct route */
02145          if ((thishop = ast_malloc(sizeof(*thishop) + len))) {
02146             /* ast_calloc is not needed because all fields are initialized in this block */
02147             ast_copy_string(thishop->hop, rr, len);
02148             if (option_debug > 1)
02149                ast_log(LOG_DEBUG, "build_route: Record-Route hop: <%s>\n", thishop->hop);
02150             /* Link in */
02151             if (backwards) {
02152                /* Link in at head so they end up in reverse order */
02153                thishop->next = head;
02154                head = thishop;
02155                /* If this was the first then it'll be the tail */
02156                if (!tail)
02157                   tail = thishop;
02158             } else {
02159                thishop->next = NULL;
02160                /* Link in at the end */
02161                if (tail)
02162                   tail->next = thishop;
02163                else
02164                   head = thishop;
02165                tail = thishop;
02166             }
02167          }
02168       }
02169    }
02170 
02171    /* Only append the contact if we are dealing with a strict router */
02172    if (!head || (!ast_strlen_zero(head->hop) && strstr(head->hop,";lr") == NULL) ) {
02173       /* 2nd append the Contact: if there is one */
02174       /* Can be multiple Contact headers, comma separated values - we just take the first */
02175       contact = get_header(req, "Contact");
02176       if (!ast_strlen_zero(contact)) {
02177          if (option_debug > 1)
02178             ast_log(LOG_DEBUG, "build_route: Contact hop: %s\n", contact);
02179          /* Look for <: delimited address */
02180          c = strchr(contact, '<');
02181          if (c) {
02182             /* Take to > */
02183             ++c;
02184             len = strcspn(c, ">") + 1;
02185          } else {
02186             /* No <> - just take the lot */
02187             c = contact;
02188             len = strlen(contact) + 1;
02189          }
02190          if ((thishop = ast_malloc(sizeof(*thishop) + len))) {
02191             /* ast_calloc is not needed because all fields are initialized in this block */
02192             ast_copy_string(thishop->hop, c, len);
02193             thishop->next = NULL;
02194             /* Goes at the end */
02195             if (tail)
02196                tail->next = thishop;
02197             else
02198                head = thishop;
02199          }
02200       }
02201    }
02202 
02203    /* Store as new route */
02204    p->route = head;
02205 
02206    /* For debugging dump what we ended up with */
02207    if (sip_debug_test_pvt(p))
02208       list_route(p->route);
02209 }

static int cb_extensionstate char *  context,
char *  exten,
int  state,
void *  data
[static]
 

Callback for the devicestate notification (SUBSCRIBE) support subsystem.

Note:
If you add an "hint" priority to the extension in the dial plan, you will get notifications on device state changes

Definition at line 2234 of file chan_sip3.c.

References append_history, AST_EXTENSION_DEACTIVATED, AST_EXTENSION_REMOVED, ast_extension_state2str(), ast_verbose(), sip_dialog::autokillid, DEFAULT_TRANS_TIMEOUT, FALSE, sip_dialog::laststate, NONE, option_verbose, sip_cancel_destroy(), sip_scheddestroy(), sip_dialog::stateid, sip_dialog::subscribed, transmit_state_notify(), VERBOSE_PREFIX_1, and VERBOSE_PREFIX_2.

02235 {
02236    struct sip_dialog *p = data;
02237 
02238    switch(state) {
02239    case AST_EXTENSION_DEACTIVATED:  /* Retry after a while */
02240    case AST_EXTENSION_REMOVED:   /* Extension is gone */
02241       if (p->autokillid > -1)
02242          sip_cancel_destroy(p);  /* Remove subscription expiry for renewals */
02243       sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);  /* Delete subscription in 32 secs */
02244       ast_verbose(VERBOSE_PREFIX_2 "Extension state: Watcher for hint %s %s. Notify User %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", p->peername);
02245       p->stateid = -1;
02246       p->subscribed = NONE;
02247       append_history(p, "Subscribestatus", "%s", state == AST_EXTENSION_REMOVED ? "HintRemoved" : "Deactivated");
02248       break;
02249    default: /* Tell user */
02250       p->laststate = state;
02251       break;
02252    }
02253    transmit_state_notify(p, state, 1, FALSE);
02254 
02255    if (option_verbose > 1)
02256       ast_verbose(VERBOSE_PREFIX_1 "Extension Changed %s new state %s for Notify User %s\n", exten, ast_extension_state2str(state), p->peername);
02257    return 0;
02258 }

static void check_pendings struct sip_dialog p  )  [static]
 

Check pending actions on SIP call.

Definition at line 3433 of file chan_sip3.c.

References ast_clear_flag, ast_log(), ast_test_flag, DEFAULT_TRANS_TIMEOUT, FALSE, sip_dialog::flags, option_debug, SIP_BYE, SIP_CAN_BYE, SIP_CANCEL, SIP_NEEDREINVITE, SIP_PENDINGBYE, sip_scheddestroy(), transmit_reinvite_with_sdp(), and transmit_request_with_auth().

03434 {
03435    if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
03436       /* if we can't BYE, then this is really a pending CANCEL */
03437       if (!ast_test_flag(&p->flags[0], SIP_CAN_BYE))
03438          transmit_request_with_auth(p, SIP_CANCEL, p->ocseq, 1, 0);
03439          /* Actually don't destroy us yet, wait for the 487 on our original 
03440             INVITE, but do set an autodestruct just in case we never get it. */
03441       else 
03442          transmit_request_with_auth(p, SIP_BYE, 0, 1, 1);
03443       ast_clear_flag(&p->flags[0], SIP_PENDINGBYE);   
03444       sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
03445    } else if (ast_test_flag(&p->flags[0], SIP_NEEDREINVITE)) {
03446       if (option_debug)
03447          ast_log(LOG_DEBUG, "Sending pending reinvite on '%s'\n", p->callid);
03448       /* Didn't get to reinvite yet, so do it now */
03449       transmit_reinvite_with_sdp(p, FALSE);
03450       ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE); 
03451    }
03452 }

static int check_user struct sip_dialog p,
struct sip_request req,
int  sipmethod,
char *  uri,
enum xmittype  reliable,
struct sockaddr_in *  sin
[static]
 

Find user If we get a match, this will add a reference pointer to the user object in ASTOBJ, that needs to be unreferenced.

Definition at line 2868 of file chan_sip3.c.

References check_user_full().

02869 {
02870    return check_user_full(p, req, sipmethod, uri, reliable, sin, NULL);
02871 }

static enum check_auth_result check_user_full struct sip_dialog p,
struct sip_request req,
int  sipmethod,
char *  uri,
enum xmittype  reliable,
struct sockaddr_in *  sin,
struct sip_device **  authpeer
[static]
 

Check if matching user or peer is defined Match user on From: user name and peer on IP/port This is used on first invite (not re-invites) and subscribe requests.

Returns:
0 on success, non-zero on failure

Definition at line 2637 of file chan_sip3.c.

References sip_device_extra::accountcode, accountcode, sip_globals::allowguest, sip_device::allowtransfer, sip_device_extra::amaflags, ast_apply_ha(), ast_copy_flags, ast_inet_ntoa(), ast_is_shrinkable_phonenumber(), ast_log(), ast_rtp_codec_setpref(), ast_rtp_destroy(), AST_RTP_DTMF, ast_set_flag, ast_shrink_phone_number(), ast_strdupa, ast_string_field_free, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_uri_decode(), ast_variable_new(), ast_verbose(), AUTH_SUCCESSFUL, sip_device::autoframing, build_contact(), sip_device::call_limit, sip_device::callgroup, sip_device::callingpres, sip_device::capability, sip_device::chanvars, check_auth(), sip_device_extra::cid_name, cid_name, sip_device_extra::cid_num, cid_num, context, debug(), device_unref(), do_setnat(), exten, sip_device::extra, find_device(), sip_device::flags, get_calleridname(), get_header(), get_in_brackets(), get_rpid_num(), global, sip_device::ha, sip_device::language, language, sip_device::lastms, LOG_NOTICE, sip_device::maxcallbitrate, sip_device::maxms, sip_device_extra::mohinterpret, mohinterpret, sip_device_extra::mohsuggest, mohsuggest, ast_variable::next, sip_registry::peer, sip_device::pickupgroup, sip_device::prefs, sip_device::registry, replace_cid(), SIP_CALL_LIMIT, sip_cancel_destroy(), sip_debug_test_addr(), SIP_DTMF, SIP_DTMF_AUTO, SIP_DTMF_RFC2833, SIP_FLAGS_TO_COPY, SIP_INSECURE_INVITE, SIP_NAT_ROUTE, SIP_PAGE2_FLAGS_TO_COPY, SIP_PAGE2_VIDEOSUPPORT, SIP_PEER, SIP_PKT_IGNORE, SIP_UNKNOWN, SIP_USER, sip_device::sipoptions, and sip_device::type.

02640 {
02641    struct sip_device *device = NULL;
02642    char from[256], *c;
02643    char *of;
02644    char rpid_num[50];
02645    const char *rpid;
02646    enum check_auth_result res = AUTH_SUCCESSFUL;
02647    char *t;
02648    char calleridname[50];
02649    int debug = sip_debug_test_addr(sin);
02650    struct ast_variable *tmpvar = NULL, *v = NULL;
02651    enum objecttype devicematch = SIP_UNKNOWN;
02652    char *uri2 = ast_strdupa(uri);
02653 
02654    /* Terminate URI */
02655    t = uri2;
02656    while (*t && *t > 32 && *t != ';')
02657       t++;
02658    *t = '\0';
02659    ast_copy_string(from, get_header(req, "From"), sizeof(from));  /* XXX bug in original code, overwrote string */
02660    ast_uri_decode(from);
02661    /* XXX here tries to map the username for invite things */
02662    memset(calleridname, 0, sizeof(calleridname));
02663    get_calleridname(from, calleridname, sizeof(calleridname));
02664    if (calleridname[0])
02665       ast_string_field_set(p, cid_name, calleridname);
02666 
02667    rpid = get_header(req, "Remote-Party-ID");
02668    memset(rpid_num, 0, sizeof(rpid_num));
02669    if (!ast_strlen_zero(rpid)) 
02670       p->callingpres = get_rpid_num(rpid, rpid_num, sizeof(rpid_num));
02671 
02672    of = get_in_brackets(from);
02673    if (ast_strlen_zero(p->exten)) {
02674       char *t = uri2;
02675       if (!strncmp(t, "sip:", 4))
02676          t+= 4;
02677       ast_string_field_set(p, exten, t);
02678       t = strchr(p->exten, '@');
02679       if (t)
02680          *t = '\0';
02681       if (ast_strlen_zero(p->our_contact))
02682          build_contact(p);
02683    }
02684    /* save the URI part of the From header */
02685    ast_string_field_set(p, from, of);
02686    if (strncmp(of, "sip:", 4))
02687       ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n");
02688    else
02689       of += 4;
02690    /* Get just the username part */
02691    if ((c = strchr(of, '@'))) {
02692       char *tmp;
02693       *c = '\0';
02694       if ((c = strchr(of, ':')))
02695          *c = '\0';
02696       tmp = ast_strdupa(of);
02697       if (ast_is_shrinkable_phonenumber(tmp))
02698          ast_shrink_phone_number(tmp);
02699       ast_string_field_set(p, cid_num, tmp);
02700    }
02701    if (ast_strlen_zero(of))
02702       return AUTH_SUCCESSFUL;
02703 
02704    if (p->registry && p->registry->peer)  /* We already know this device from registry */
02705       device = p->registry->peer;
02706    else
02707       /* Find device in device list */
02708       device = find_device(of, NULL, 1);
02709    if (device && !ast_apply_ha(device->ha, sin)) {
02710       device_unref(device);
02711       device = NULL;
02712    }
02713    /* Secondly match on IP/port (will in the future only be applied to trunks, not devices */
02714    if (!device) {
02715       /* Look for peer based on the IP address we received data from */
02716       /* If peer is registered from this IP address or have this as a default
02717          IP address, this call is from the peer 
02718       */
02719       device = find_device(NULL, &p->recv, 1);
02720    }
02721    if (device && !ast_apply_ha(device->ha, sin)) {
02722       device_unref(device);
02723       device = NULL;
02724    }
02725    if (device)
02726       devicematch = SIP_PEER;    /* We matched on a peer */
02727    /* No device found */
02728    if (!device) {
02729       if (debug)
02730          ast_verbose("Found no matching peer or user for '%s:%d'\n", ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
02731 
02732       /* do we allow guests? */
02733       if (!global.allowguest)
02734          res = -1;  /* we don't want any guests, authentication will fail */
02735       return res;
02736    }
02737 
02738    /* Ok, we have a device, let's check authentication if needed */
02739    ast_copy_flags(&p->flags[0], &device->flags[0], SIP_FLAGS_TO_COPY);
02740    ast_copy_flags(&p->flags[1], &device->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
02741 
02742    /* Copy SIP extensions profile to peer */
02743    if (p->sipoptions)
02744       device->sipoptions = p->sipoptions;
02745 
02746    /* copy channel vars */
02747    for (v = device->chanvars ; v ; v = v->next) {
02748       if ((tmpvar = ast_variable_new(v->name, v->value))) {
02749          tmpvar->next = p->chanvars; 
02750          p->chanvars = tmpvar;
02751       }
02752    }
02753    p->prefs = device->prefs;
02754    /* Set Frame packetization */
02755    if (p->rtp) {
02756       ast_rtp_codec_setpref(p->rtp, &p->prefs);
02757       p->autoframing = device->autoframing;
02758    }
02759 
02760    replace_cid(p, rpid_num, calleridname);
02761    
02762    do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT_ROUTE));
02763 
02764    if (device->maxms && device->lastms)
02765       p->timer_t1 = device->lastms;
02766    if (ast_test_flag(&device->flags[0], SIP_INSECURE_INVITE)) {
02767       /* Pretend there is no required authentication */
02768       ast_string_field_free(p, peersecret);
02769       ast_string_field_free(p, peermd5secret);
02770    }
02771    /* Now, check auth */
02772    if (!(res = check_auth(p, req, device->name, device->secret, device->md5secret, sipmethod, uri, reliable, ast_test_flag(req, SIP_PKT_IGNORE)))) {
02773       /* We have positive authentication, let's configure this SIP session */
02774       sip_cancel_destroy(p);
02775       ast_copy_flags(&p->flags[0], &device->flags[0], SIP_FLAGS_TO_COPY);
02776       ast_copy_flags(&p->flags[1], &device->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
02777       /* Copy SIP extensions profile from INVITE */
02778       if (p->sipoptions)
02779          device->sipoptions = p->sipoptions;
02780       /* If we have a call limit, set flag */
02781       if (device->call_limit)
02782          ast_set_flag(&p->flags[0], SIP_CALL_LIMIT);
02783       if (!ast_strlen_zero(device->extra.context))
02784          ast_string_field_set(p, context, device->extra.context);
02785       if (!ast_strlen_zero(device->extra.cid_num) && !ast_strlen_zero(p->cid_num)) {
02786          char *tmp = ast_strdupa(device->extra.cid_num);
02787          if (tmp) {
02788             if (ast_is_shrinkable_phonenumber(tmp))
02789                ast_shrink_phone_number(tmp);
02790             ast_string_field_set(p, cid_num, tmp);
02791          } else {
02792             ast_string_field_set(p, cid_num, device->extra.cid_num);
02793          }
02794       }
02795       if (!ast_strlen_zero(device->extra.cid_name) && !ast_strlen_zero(p->cid_num))
02796          ast_string_field_set(p, cid_name, device->extra.cid_name);
02797       ast_string_field_set(p, peersecret, device->secret);
02798       ast_string_field_set(p, peermd5secret, device->md5secret);
02799       ast_string_field_set(p, fullcontact, device->fullcontact);
02800       ast_string_field_set(p, peername, device->name);
02801       ast_string_field_set(p, authname, device->name);
02802       if (!ast_strlen_zero(device->defaultuser)) {
02803          ast_string_field_set(p, peername, device->defaultuser);
02804          /* Use the default username for authentication on outbound calls */
02805          if(!ast_strlen_zero(device->authuser))
02806             ast_string_field_set(p, authname, device->authuser);
02807       }
02808       if (p->t38.peercapability)
02809          p->t38.jointcapability &= p->t38.peercapability;
02810       p->maxcallbitrate = device->maxcallbitrate;
02811       /* If we do not support video, remove video from call structure */
02812       if (!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) && p->vrtp) {
02813          ast_rtp_destroy(p->vrtp);
02814          p->vrtp = NULL;
02815       }
02816       ast_string_field_set(p, subscribecontext, device->extra.subscribecontext);
02817       ast_string_field_set(p, accountcode, device->extra.accountcode);
02818       ast_string_field_set(p, language, device->language);
02819       ast_string_field_set(p, mohsuggest, device->extra.mohsuggest);
02820       ast_string_field_set(p, mohinterpret, device->extra.mohinterpret);
02821       p->allowtransfer = device->allowtransfer;
02822       p->amaflags = device->extra.amaflags;
02823       p->callgroup = device->callgroup;
02824       p->pickupgroup = device->pickupgroup;
02825       p->callingpres = device->callingpres;
02826       p->capability = device->capability;
02827       p->jointcapability = device->capability;
02828       p->prefs = device->prefs;
02829       if (p->peercapability)
02830          p->jointcapability &= p->peercapability;
02831       p->maxcallbitrate = device->maxcallbitrate;
02832       if (!ast_test_flag((&p->flags[1]), SIP_PAGE2_VIDEOSUPPORT) && p->vrtp) {
02833          ast_rtp_destroy(p->vrtp);
02834          p->vrtp = NULL;
02835       }
02836       if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
02837          p->noncodeccapability |= AST_RTP_DTMF;
02838       else
02839          p->noncodeccapability &= ~AST_RTP_DTMF;
02840 
02841       /* copy channel vars */
02842       for (v = device->chanvars ; v ; v = v->next) {
02843          if ((tmpvar = ast_variable_new(v->name, v->value))) {
02844             tmpvar->next = p->chanvars; 
02845             p->chanvars = tmpvar;
02846          }
02847       }  
02848       do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT_ROUTE));
02849       ast_string_field_set(p, peersecret, device->secret);
02850       ast_string_field_set(p, peermd5secret, device->md5secret);
02851       ast_string_field_set(p, subscribecontext, device->extra.subscribecontext);
02852       ast_string_field_set(p, mohinterpret, device->extra.mohinterpret);
02853       ast_string_field_set(p, mohsuggest, device->extra.mohsuggest);
02854       if (device->callingpres)   /* Peer calling pres setting will override RPID */
02855          p->callingpres = device->callingpres;
02856    }
02857    if (device && debug)
02858       ast_verbose("Found %s '%s'\n", device->type & SIP_USER ? "user" : "peer", device->name);
02859 
02860    device_unref(device);
02861 
02862    return res;
02863 }

static void check_via struct sip_dialog p,
struct sip_request req
[static]
 

check Via: header for hostname, port and rport request/answer

Definition at line 2571 of file chan_sip3.c.

References ahp, ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_set_flag, ast_verbose(), sip_dialog::flags, get_header(), hp, LOG_WARNING, sip_dialog::sa, sip_debug_test_pvt(), sip_nat_mode(), SIP_NAT_ROUTE, sip_real_dst(), and STANDARD_SIP_PORT.

02572 {
02573    char via[256];
02574    char *c, *pt;
02575    struct hostent *hp;
02576    struct ast_hostent ahp;
02577 
02578    ast_copy_string(via, get_header(req, "Via"), sizeof(via));
02579    if (strlen(via) == 0)
02580       ast_log(LOG_DEBUG, "Empty VIA string found \n");
02581 
02582    /* Work on the leftmost value of the topmost Via header */
02583    c = strchr(via, ',');
02584    if (c)
02585       *c = '\0';
02586 
02587    /* Check for rport */
02588    c = strstr(via, ";rport");
02589    if (c && (c[6] != '=')) /* rport query, not answer */
02590       ast_set_flag(&p->flags[0], SIP_NAT_ROUTE);
02591 
02592    c = strchr(via, ';');
02593    if (c) 
02594       *c = '\0';
02595 
02596    c = strchr(via, ' ');
02597    if (c) {
02598       *c = '\0';
02599       c = ast_skip_blanks(c+1);
02600       if (strcasecmp(via, "SIP/2.0/UDP")) {
02601          ast_log(LOG_WARNING, "Don't know how to respond via '%s'\n", via);
02602          return;
02603       }
02604       pt = strchr(c, ':');
02605       if (pt)
02606          *pt++ = '\0';  /* remember port pointer */
02607 
02608       /* Set sender's address to the IP address in via for replies */
02609       memset(&p->sa, 0, sizeof(p->sa));
02610       p->sa.sin_family = AF_INET;
02611 
02612       if (!inet_aton(c, &p->sa.sin_addr)) {  /* Check if this is an IP address, not a host name */
02613          /* resolve host name */
02614          hp = ast_gethostbyname(c, &ahp);
02615          if (!hp) {
02616             ast_log(LOG_WARNING, "'%s' is not a valid DNS host name\n", c);
02617             return;
02618          }
02619          memcpy(&p->sa.sin_addr, hp->h_addr, sizeof(p->sa.sin_addr));
02620       }
02621       p->sa.sin_port = htons(pt ? atoi(pt) : STANDARD_SIP_PORT);
02622 
02623       if (sip_debug_test_pvt(p)) {
02624          const struct sockaddr_in *dst = sip_real_dst(p);
02625          
02626          ast_verbose("Sending to %s : %d (%s)\n", ast_inet_ntoa(dst->sin_addr), ntohs(dst->sin_port), sip_nat_mode(p));
02627          ast_verbose("Sender's address %s : %d (%s)\n", ast_inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port), sip_nat_mode(p));
02628       }
02629    }
02630 }

GNURK int create_addr struct sip_dialog dialog,
const char *  username,
char *  domain,
const char *  device
 

create address structure from peer name Or, if peer not found, find it in the global DNS returns TRUE (-1) on failure, FALSE on success

Definition at line 808 of file chan_sip3.c.

References ahp, ast_get_srv(), ast_gethostbyname(), ast_log(), ast_string_field_set, ast_strlen_zero(), ast_verbose(), create_addr_from_peer(), device_unref(), FALSE, find_device(), global, hp, LOG_DEBUG, LOG_WARNING, option_debug, option_verbose, sip_dialog::recv, sip_dialog::sa, sip_globals::srvlookup, STANDARD_SIP_PORT, sip_globals::t1default, sip_dialog::timer_t1, and TRUE.

00809 {
00810    struct hostent *hp;
00811    struct ast_hostent ahp;
00812    struct sip_device *p = NULL;
00813    char *port;
00814    int portno;
00815    char host[MAXHOSTNAMELEN], *hostn;
00816    char peername[256];
00817    char todomain[256];
00818    int srvcheck = TRUE;
00819 
00820 
00821    dialog->sa.sin_family = AF_INET;
00822    dialog->timer_t1 = global.t1default; /* Default SIP retransmission timer T1 (RFC 3261) */
00823    if (!ast_strlen_zero(device)) {
00824       int res;
00825 
00826       p = find_device(device, NULL, 1);
00827 
00828       if (p)  {
00829          res = create_addr_from_peer(dialog, p);
00830          device_unref(p);
00831          return res;
00832       } else {
00833          if (option_verbose > 1)
00834             ast_verbose("Can't find peer %s\n", device);
00835 
00836          return -1;  /* Can't find peer */
00837       }
00838    }
00839 
00840    /* See if we have a port. If we have a given port,
00841       disable SRV lookups */
00842    if (!ast_strlen_zero(domain)) {
00843       ast_copy_string(todomain, domain, sizeof(todomain));
00844       port = strchr(todomain, ':');
00845    }
00846    if (port) {
00847       *port++ = '\0';
00848       srvcheck = FALSE;
00849    }
00850 
00851    hostn = domain;
00852    portno = port ? atoi(port) : STANDARD_SIP_PORT;
00853 
00854    if (global.srvlookup && srvcheck) {
00855       char service[MAXHOSTNAMELEN];
00856       int tportno;
00857       int ret;
00858 
00859       snprintf(service, sizeof(service), "_sip._udp.%s", domain);
00860       ret = ast_get_srv(NULL, host, sizeof(host), &tportno, service);
00861       if (ret > 0) {
00862          hostn = host;
00863          portno = tportno;
00864          if (option_debug > 2)
00865             ast_log(LOG_DEBUG, "Resolved domain %s to host %s in SRV \n", domain, hostn);
00866       }
00867    } 
00868    hp = ast_gethostbyname(hostn, &ahp);
00869    if (!hp) {
00870       ast_log(LOG_WARNING, "No such host: %s\n", peername);
00871       return -2;
00872    }
00873    ast_string_field_set(dialog, tohost, domain);
00874    memcpy(&dialog->sa.sin_addr, hp->h_addr, sizeof(dialog->sa.sin_addr));
00875    dialog->sa.sin_port = htons(portno);
00876    dialog->recv = dialog->sa;
00877    return 0;
00878 }

static int create_addr_from_peer struct sip_dialog r,
struct sip_device peer
[static]
 

Create address structure from device reference. return -1 on error, 0 on success.

Definition at line 692 of file chan_sip3.c.

References sip_device::addr, sip_device::allowtransfer, sip_dialog::allowtransfer, ast_copy_flags, ast_inet_ntoa(), ast_log(), ast_rtp_codec_setpref(), ast_rtp_destroy(), AST_RTP_DTMF, ast_rtp_set_rtpholdtimeout(), ast_rtp_set_rtpkeepalive(), ast_rtp_set_rtptimeout(), ast_rtp_setdtmf(), ast_rtp_setdtmfcompensate(), ast_set_flag, ast_strdupa, ast_string_field_build, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_udptl_destroy(), ast_udptl_get_error_correction_scheme(), sip_device::autoframing, sip_dialog::autoframing, sip_device::call_limit, sip_device::callgroup, sip_dialog::callgroup, t38properties::capability, sip_device::capability, sip_dialog::capability, context, sip_device::defaddr, do_setnat(), sip_device::extra, sip_device::flags, sip_dialog::flags, global, sip_dialog::initreq, t38properties::jointcapability, sip_device::lastms, LOG_DEBUG, sip_device::maxcallbitrate, sip_dialog::maxcallbitrate, sip_device::maxms, sip_device_extra::mohinterpret, mohinterpret, sip_device_extra::mohsuggest, mohsuggest, sip_dialog::noncodeccapability, option_debug, sip_device::pickupgroup, sip_dialog::pickupgroup, sip_device::prefs, sip_dialog::prefs, sip_dialog::recv, sip_dialog::rtp, rtptimers::rtpholdtimeout, rtptimers::rtpkeepalive, rtptimers::rtptimeout, sip_device::rtptimer, sip_dialog::sa, SIP_CALL_LIMIT, SIP_DTMF, SIP_DTMF_AUTO, SIP_DTMF_INFO, SIP_DTMF_RFC2833, SIP_FLAGS_TO_COPY, SIP_NAT, SIP_NAT_ROUTE, SIP_PAGE2_FLAGS_TO_COPY, SIP_PAGE2_RFC2833_COMPENSATE, SIP_PAGE2_T38SUPPORT, SIP_PAGE2_VIDEOSUPPORT, sip_globals::t1min, sip_dialog::t38, sip_globals::t38_capability, T38FAX_RATE_MANAGEMENT_TRANSFERED_TCF, T38FAX_UDP_EC_FEC, T38FAX_UDP_EC_NONE, T38FAX_UDP_EC_REDUNDANCY, sip_dialog::timer_t1, sip_device_extra::tohost, sip_dialog::udptl, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, UDPTL_ERROR_CORRECTION_REDUNDANCY, and sip_dialog::vrtp.

00693 {
00694    if ((device->addr.sin_addr.s_addr || device->defaddr.sin_addr.s_addr) &&
00695        (!device->maxms || ((device->lastms >= 0)  && (device->lastms <= device->maxms)))) {
00696       dialog->sa = (device->addr.sin_addr.s_addr) ? device->addr : device->defaddr;
00697       dialog->recv = dialog->sa;
00698    } else 
00699       return -1;
00700 
00701    ast_copy_flags(&dialog->flags[0], &device->flags[0], SIP_FLAGS_TO_COPY);
00702    ast_copy_flags(&dialog->flags[1], &device->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
00703    dialog->capability = device->capability;
00704    if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) && dialog->vrtp) {
00705       ast_rtp_destroy(dialog->vrtp);
00706       dialog->vrtp = NULL;
00707    }
00708    dialog->prefs = device->prefs;
00709    if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_T38SUPPORT)) {
00710       dialog->t38.capability = global.t38_capability;
00711       if (dialog->udptl) {
00712          if (ast_udptl_get_error_correction_scheme(dialog->udptl) == UDPTL_ERROR_CORRECTION_FEC )
00713             dialog->t38.capability |= T38FAX_UDP_EC_FEC;
00714          else if (ast_udptl_get_error_correction_scheme(dialog->udptl) == UDPTL_ERROR_CORRECTION_REDUNDANCY )
00715             dialog->t38.capability |= T38FAX_UDP_EC_REDUNDANCY;
00716          else if (ast_udptl_get_error_correction_scheme(dialog->udptl) == UDPTL_ERROR_CORRECTION_NONE )
00717             dialog->t38.capability |= T38FAX_UDP_EC_NONE;
00718          dialog->t38.capability |= T38FAX_RATE_MANAGEMENT_TRANSFERED_TCF;
00719          if (option_debug > 1)
00720             ast_log(LOG_DEBUG,"Our T38 capability (%d)\n", dialog->t38.capability);
00721       }
00722       dialog->t38.jointcapability = dialog->t38.capability;
00723    } else if (dialog->udptl) {
00724       ast_udptl_destroy(dialog->udptl);
00725       dialog->udptl = NULL;
00726    }
00727    do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE );
00728 
00729    if (dialog->rtp) {
00730       ast_rtp_setdtmf(dialog->rtp, ast_test_flag(&dialog->flags[0], SIP_DTMF) != SIP_DTMF_INFO);
00731       ast_rtp_setdtmfcompensate(dialog->rtp, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
00732    }
00733    if (dialog->vrtp) {
00734       ast_rtp_setdtmf(dialog->vrtp, 0);
00735       ast_rtp_setdtmfcompensate(dialog->vrtp, 0);
00736    }
00737 
00738    /* Set Frame packetization */
00739    if (dialog->rtp) {
00740       ast_rtp_codec_setpref(dialog->rtp, &dialog->prefs);
00741       dialog->autoframing = device->autoframing;
00742    }
00743 
00744    /* XXX Why use username for all of this? */
00745    //ast_string_field_set(dialog, peername, device->defaultuser);
00746 
00747    ast_string_field_set(dialog, peername, device->name);
00748    /* Authuser is fromuser, and if that not is set, it's the defaultuser, if that's set */
00749    
00750    if (ast_strlen_zero(device->extra.fromuser))
00751       ast_string_field_set(dialog, authname, device->defaultuser);
00752    else
00753       ast_string_field_set(dialog, authname, device->extra.fromuser);
00754    ast_string_field_set(dialog, defaultuser, device->defaultuser);
00755    ast_string_field_set(dialog, peersecret, device->secret);
00756    ast_string_field_set(dialog, peermd5secret, device->md5secret);
00757    ast_string_field_set(dialog, tohost, device->extra.tohost);
00758    ast_string_field_set(dialog, mohinterpret, device->extra.mohinterpret);
00759    ast_string_field_set(dialog, mohsuggest, device->extra.mohsuggest);
00760    ast_string_field_set(dialog, fullcontact, device->fullcontact);
00761    if (!dialog->initreq && !ast_strlen_zero(device->extra.fromdomain)) {
00762       char *tmpcall;
00763       char *c;
00764       tmpcall = ast_strdupa(dialog->callid);
00765       c = strchr(tmpcall, '@');
00766       if (c) {
00767          *c = '\0';
00768          ast_string_field_build(dialog, callid, "%s@%s", tmpcall, device->extra.fromdomain);
00769       }
00770    }
00771    if (ast_strlen_zero(dialog->tohost))
00772       ast_string_field_set(dialog, tohost, ast_inet_ntoa(dialog->sa.sin_addr));
00773    if (!ast_strlen_zero(device->extra.fromdomain))
00774       ast_string_field_set(dialog, fromdomain, device->extra.fromdomain);
00775    if (!ast_strlen_zero(device->extra.fromuser))
00776       ast_string_field_set(dialog, fromuser, device->extra.fromuser);
00777    dialog->callgroup = device->callgroup;
00778    dialog->pickupgroup = device->pickupgroup;
00779    dialog->allowtransfer = device->allowtransfer;
00780    /* Set timer T1 to RTT for this peer (if known by qualify=) */
00781    /* Minimum is settable or default to 100 ms */
00782    if (device->maxms && device->lastms)
00783       dialog->timer_t1 = device->lastms < global.t1min ? global.t1min : device->lastms;
00784    if ((ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
00785        (ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
00786       dialog->noncodeccapability |= AST_RTP_DTMF;
00787    else
00788       dialog->noncodeccapability &= ~AST_RTP_DTMF;
00789    ast_string_field_set(dialog, context, device->extra.context);
00790    ast_rtp_set_rtptimeout(dialog->rtp, device->rtptimer.rtptimeout);
00791    ast_rtp_set_rtpholdtimeout(dialog->rtp, device->rtptimer.rtpholdtimeout);
00792    ast_rtp_set_rtpkeepalive(dialog->rtp, device->rtptimer.rtpkeepalive);
00793    if (dialog->vrtp) {
00794       ast_rtp_set_rtptimeout(dialog->vrtp, device->rtptimer.rtptimeout);
00795       ast_rtp_set_rtpholdtimeout(dialog->vrtp, device->rtptimer.rtpholdtimeout);
00796       ast_rtp_set_rtpkeepalive(dialog->vrtp, device->rtptimer.rtpkeepalive);
00797    }
00798    if (device->call_limit)
00799       ast_set_flag(&dialog->flags[0], SIP_CALL_LIMIT);
00800    dialog->maxcallbitrate = device->maxcallbitrate;
00801    
00802    return 0;
00803 }

GNURK void do_setnat struct sip_dialog dialog,
int  natflags
 

Set nat mode on the various media streams.

Definition at line 668 of file chan_sip3.c.

References ast_log(), ast_rtp_setnat(), ast_udptl_setnat(), LOG_DEBUG, option_debug, sip_dialog::rtp, sip_dialog::udptl, and sip_dialog::vrtp.

00669 {
00670    const char *mode = natflags ? "On" : "Off";
00671 
00672    if (dialog->rtp) {
00673       if (option_debug)
00674          ast_log(LOG_DEBUG, "Setting NAT on RTP to %s\n", mode);
00675       ast_rtp_setnat(dialog->rtp, natflags);
00676    }
00677    if (dialog->vrtp) {
00678       if (option_debug)
00679          ast_log(LOG_DEBUG, "Setting NAT on VRTP to %s\n", mode);
00680       ast_rtp_setnat(dialog->vrtp, natflags);
00681    }
00682    if (dialog->udptl) {
00683       if (option_debug)
00684          ast_log(LOG_DEBUG, "Setting NAT on UDPTL to %s\n", mode);
00685       ast_udptl_setnat(dialog->udptl, natflags);
00686    }
00687 }

void free_old_route struct sip_route route  ) 
 

Remove route from route list.

Definition at line 2084 of file chan_sip3.c.

References free, and sip_route::next.

02085 {
02086    struct sip_route *next;
02087 
02088    while (route) {
02089       next = route->next;
02090       free(route);
02091       route = next;
02092    }
02093 }

static int func_header_read struct ast_channel chan,
const char *  function,
char *  data,
char *  buf,
size_t  len
[static]
 

Read SIP header (dialplan function).

Definition at line 3212 of file chan_sip3.c.

References __get_header(), AST_APP_ARG, ast_channel_lock, ast_channel_unlock, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), sip_request::header, sip_dialog::initreq, LOG_WARNING, sip_tech, sip_tech_info, ast_channel::tech, and ast_channel::tech_pvt.

03213 {
03214    struct sip_dialog *p;
03215    const char *content = NULL;
03216    AST_DECLARE_APP_ARGS(args,
03217       AST_APP_ARG(header);
03218       AST_APP_ARG(number);
03219    );
03220    int i, number, start = 0;
03221 
03222    if (ast_strlen_zero(data)) {
03223       ast_log(LOG_WARNING, "This function requires a header name.\n");
03224       return -1;
03225    }
03226 
03227    ast_channel_lock(chan);
03228    if (chan->tech != &sip_tech && chan->tech != &sip_tech_info) {
03229       ast_log(LOG_WARNING, "This function can only be used on SIP channels.\n");
03230       ast_channel_unlock(chan);
03231       return -1;
03232    }
03233 
03234    AST_STANDARD_APP_ARGS(args, data);
03235    if (!args.number) {
03236       number = 1;
03237    } else {
03238       sscanf(args.number, "%d", &number);
03239       if (number < 1)
03240          number = 1;
03241    }
03242 
03243    p = chan->tech_pvt;
03244 
03245    /* If there is no private structure, this channel is no longer alive */
03246    if (!p) {
03247       ast_channel_unlock(chan);
03248       return -1;
03249    }
03250 
03251    for (i = 0; i < number; i++)
03252       content = __get_header(p->initreq, args.header, &start);
03253 
03254    if (ast_strlen_zero(content)) {
03255       ast_channel_unlock(chan);
03256       return -1;
03257    }
03258 
03259    ast_copy_string(buf, content, len);
03260    ast_channel_unlock(chan);
03261 
03262    return 0;
03263 }

static int function_sipchaninfo_read struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len
[static]
 

${SIPCHANINFO()} Dialplan function - reads sip channel data

Definition at line 3364 of file chan_sip3.c.

References ast_channel_lock, ast_channel_unlock, ast_inet_ntoa(), ast_log(), LOG_WARNING, sip_dialog::recv, sip_dialog::sa, sip_tech, sip_tech_info, t38properties::state, sip_dialog::t38, T38_DISABLED, ast_channel::tech, and ast_channel::tech_pvt.

03365 {
03366    struct sip_dialog *p;
03367 
03368    *buf = 0;
03369    
03370    if (!data) {
03371       ast_log(LOG_WARNING, "This function requires a parameter name.\n");
03372       return -1;
03373    }
03374 
03375    ast_channel_lock(chan);
03376    if (chan->tech != &sip_tech && chan->tech != &sip_tech_info) {
03377       ast_log(LOG_WARNING, "This function can only be used on SIP channels.\n");
03378       ast_channel_unlock(chan);
03379       return -1;
03380    }
03381 
03382    p = chan->tech_pvt;
03383 
03384    /* If there is no private structure, this channel is no longer alive */
03385    if (!p) {
03386       ast_channel_unlock(chan);
03387       return -1;
03388    }
03389 
03390    if (!strcasecmp(data, "peerip")) {
03391       ast_copy_string(buf, p->sa.sin_addr.s_addr ? ast_inet_ntoa(p->sa.sin_addr) : "", len);
03392    } else  if (!strcasecmp(data, "recvip")) {
03393       ast_copy_string(buf, p->recv.sin_addr.s_addr ? ast_inet_ntoa(p->recv.sin_addr) : "", len);
03394    } else  if (!strcasecmp(data, "from")) {
03395       ast_copy_string(buf, p->from, len);
03396    } else  if (!strcasecmp(data, "uri")) {
03397       ast_copy_string(buf, p->uri, len);
03398    } else  if (!strcasecmp(data, "useragent")) {
03399       ast_copy_string(buf, p->useragent, len);
03400    } else  if (!strcasecmp(data, "peername")) {
03401       ast_copy_string(buf, p->peername, len);
03402    } else if (!strcasecmp(data, "t38passthrough")) {
03403       if (p->t38.state == T38_DISABLED)
03404          ast_copy_string(buf, "0", sizeof("0"));
03405       else    /* T38 is offered or enabled in this call */
03406          ast_copy_string(buf, "1", sizeof("1"));
03407    } else {
03408       ast_channel_unlock(chan);
03409       return -1;
03410    }
03411    ast_channel_unlock(chan);
03412 
03413    return 0;
03414 }

static int function_sippeer struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len
[static]
 

${SIPPEER()} Dialplan function - reads peer data

Definition at line 3276 of file chan_sip3.c.

References sip_device_extra::accountcode, sip_device::addr, ast_codec_pref_index(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_test_flag, sip_device::call_limit, sip_device::capability, sip_device_extra::cid_name, sip_device_extra::cid_num, device_status(), device_unref(), sip_device::expire, sip_device::extra, find_device(), sip_device::flags, sip_device::inUse, sip_device::language, sip_device::mailbox, sip_device::prefs, SIP_PAGE2_DYNAMIC, and strsep().

03277 {
03278    struct sip_device *peer;
03279    char *colname;
03280 
03281    if ((colname = strchr(data, '|')))
03282       *colname++ = '\0';
03283    else
03284       colname = "ip";
03285 
03286    if (!(peer = find_device(data, NULL, 1)))
03287       return -1;
03288 
03289    if (!strcasecmp(colname, "ip")) {
03290       ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len);
03291    } else  if (!strcasecmp(colname, "status")) {
03292       device_status(peer, buf, len);
03293    } else  if (!strcasecmp(colname, "language")) {
03294       ast_copy_string(buf, peer->language, len);
03295    } else  if (!strcasecmp(colname, "regexten")) {
03296       ast_copy_string(buf, peer->extra.regexten, len);
03297    } else  if (!strcasecmp(colname, "limit")) {
03298       snprintf(buf, len, "%d", peer->call_limit);
03299    } else  if (!strcasecmp(colname, "curcalls")) {
03300       snprintf(buf, len, "%d", peer->inUse);
03301    } else  if (!strcasecmp(colname, "accountcode")) {
03302       ast_copy_string(buf, peer->extra.accountcode, len);
03303    } else  if (!strcasecmp(colname, "useragent")) {
03304       ast_copy_string(buf, peer->useragent, len);
03305    } else  if (!strcasecmp(colname, "mailbox")) {
03306       ast_copy_string(buf, peer->mailbox.mailbox, len);
03307    } else  if (!strcasecmp(colname, "context")) {
03308       ast_copy_string(buf, peer->extra.context, len);
03309    } else  if (!strcasecmp(colname, "expire")) {
03310       snprintf(buf, len, "%d", peer->expire);
03311    } else  if (!strcasecmp(colname, "dynamic")) {
03312       ast_copy_string(buf, (ast_test_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC) ? "yes" : "no"), len);
03313    } else  if (!strcasecmp(colname, "callerid_name")) {
03314       ast_copy_string(buf, peer->extra.cid_name, len);
03315    } else  if (!strcasecmp(colname, "callerid_num")) {
03316       ast_copy_string(buf, peer->extra.cid_num, len);
03317    } else  if (!strcasecmp(colname, "codecs")) {
03318       ast_getformatname_multiple(buf, len -1, peer->capability);
03319    } else  if (!strncasecmp(colname, "codec[", 6)) {
03320       char *codecnum;
03321       int index = 0, codec = 0;
03322       
03323       codecnum = colname + 6; /* move past the '[' */
03324       codecnum = strsep(&codecnum, "]"); /* trim trailing ']' if any */
03325       index = atoi(codecnum);
03326       if((codec = ast_codec_pref_index(&peer->prefs, index))) {
03327          ast_copy_string(buf, ast_getformatname(codec), len);
03328       }
03329    }
03330 
03331    device_unref(peer);
03332 
03333    return 0;
03334 }

static int get_also_info struct sip_dialog p,
struct sip_request oreq
[static]
 

Call transfer support (old way, deprecated by the IETF)--.

Definition at line 2515 of file chan_sip3.c.

References ast_canmatch_extension(), ast_exists_extension(), ast_log(), ast_string_field_set, ast_strlen_zero(), ast_uri_decode(), ast_verbose(), context, sip_globals::default_context, get_header(), get_in_brackets(), global, sip_dialog::initreq, LOG_WARNING, ast_channel::macrocontext, option_debug, sip_dialog::owner, pbx_builtin_getvar_helper(), sip_dialog::refer, sip_refer::refer_call, sip_refer::refer_contact, sip_refer::refer_to, sip_refer::refer_to_domain, sip_refer::referred_by, S_OR, and sip_debug_test_pvt().

02516 {
02517    char tmp[256] = "", *c, *a;
02518    struct sip_request *req = oreq ? oreq : p->initreq;
02519    struct sip_refer *referdata = p->refer;
02520    const char *transfer_context = NULL;
02521    
02522    ast_copy_string(tmp, get_header(req, "Also"), sizeof(tmp));
02523    c = get_in_brackets(tmp);
02524 
02525    ast_uri_decode(c);
02526    
02527    if (strncmp(c, "sip:", 4)) {
02528       ast_log(LOG_WARNING, "Huh?  Not a SIP header in Also: transfer (%s)?\n", c);
02529       return -1;
02530    }
02531    c += 4;
02532 
02533    if ((a = strchr(c, ';')))  /* Remove arguments */
02534       *a = '\0';
02535 
02536    if ((a = strchr(c, '@'))) {   /* Separate Domain */
02537       *a++ = '\0';
02538       ast_copy_string(referdata->refer_to_domain, a, sizeof(referdata->refer_to_domain));
02539    }
02540    
02541    
02542    if (sip_debug_test_pvt(p))
02543       ast_verbose("Looking for %s in %s\n", c, p->context);
02544 
02545    if (p->owner)  /* Mimic behaviour in res_features.c */
02546       transfer_context = pbx_builtin_getvar_helper(p->owner, "TRANSFER_CONTEXT");
02547 
02548    /* By default, use the context in the channel sending the REFER */
02549    if (ast_strlen_zero(transfer_context)) {
02550       transfer_context = S_OR(p->owner->macrocontext,
02551                S_OR(p->context, global.default_context));
02552    }
02553    if (ast_exists_extension(NULL, transfer_context, c, 1, NULL)) {
02554       /* This is a blind transfer */
02555       if (option_debug)
02556          ast_log(LOG_DEBUG,"SIP Bye-also transfer to Extension %s@%s \n", c, transfer_context);
02557       ast_copy_string(referdata->refer_to, c, sizeof(referdata->refer_to));
02558       ast_copy_string(referdata->referred_by, "", sizeof(referdata->referred_by));
02559       ast_copy_string(referdata->refer_contact, "", sizeof(referdata->refer_contact));
02560       referdata->refer_call = NULL;
02561       /* Set new context */
02562       ast_string_field_set(p, context, transfer_context);
02563       return 0;
02564    } else if (ast_canmatch_extension(NULL, p->context, c, 1, NULL)) {
02565       return 1;
02566    }
02567 
02568    return -1;
02569 }

static int get_msg_text char *  buf,
int  len,
struct sip_request req
[static]
 

Get text out of a SIP MESSAGE packet.

Definition at line 2874 of file chan_sip3.c.

References sip_request::line, and sip_request::lines.

02875 {
02876    int x;
02877    int y;
02878 
02879    buf[0] = '\0';
02880    y = len - strlen(buf) - 5;
02881    if (y < 0)
02882       y = 0;
02883    for (x=0;x<req->lines;x++) {
02884       strncat(buf, req->line[x], y); /* safe */
02885       y -= strlen(req->line[x]) + 1;
02886       if (y < 0)
02887          y = 0;
02888       if (y != 0)
02889          strcat(buf, "\n"); /* safe */
02890    }
02891    return 0;
02892 }

GNURK struct sip_dialog* get_sip_dialog_byid_locked const char *  callid,
const char *  totag,
const char *  fromtag
 

Lock dialog list lock and find matching pvt lock

  • Their tag is fromtag, our tag is to-tag
  • This means that in some transactions, totag needs to be their tag :-) depending upon the direction.

Definition at line 2464 of file chan_sip3.c.

References ast_log(), dialog_lock(), dialoglist, dialoglist_lock(), FALSE, LOG_DEBUG, match(), sip_dialog::next, option_debug, sip_dialog::tag, and TRUE.

Referenced by handle_request_invite(), and local_attended_transfer().

02465 {
02466    struct sip_dialog *sip_dialog_ptr;
02467 
02468    dialoglist_lock();
02469 
02470    if (option_debug > 3 && totag)
02471       ast_log(LOG_DEBUG, "Looking for callid %s (fromtag %s totag %s)\n", callid, fromtag ? fromtag : "<no fromtag>", totag ? totag : "<no totag>");
02472 
02473    /* Search interfaces and find the match */
02474    for (sip_dialog_ptr = dialoglist; sip_dialog_ptr; sip_dialog_ptr = sip_dialog_ptr->next) {
02475       if (!strcmp(sip_dialog_ptr->callid, callid)) {
02476          int match = 1;
02477          char *ourtag = sip_dialog_ptr->tag;
02478 
02479          /* Go ahead and lock it (and its owner) before returning */
02480          dialog_lock(sip_dialog_ptr, TRUE);
02481 
02482          /* Check if tags match. If not, this is not the call we want
02483             (With a forking SIP proxy, several call legs share the
02484             call id, but have different tags)
02485          */
02486          if (strcmp(fromtag, sip_dialog_ptr->theirtag) || strcmp(totag, ourtag))
02487             match = 0;
02488 
02489          if (!match) {
02490             dialog_lock(sip_dialog_ptr, FALSE);
02491             continue;
02492          }
02493 
02494          if (option_debug > 3 && totag)             
02495             ast_log(LOG_DEBUG, "Matched %s call - their tag is %s Our tag is %s\n",
02496                ast_test_flag(&sip_dialog_ptr->flags[0], SIP_OUTGOING) ? "OUTGOING": "INCOMING",
02497                sip_dialog_ptr->theirtag, sip_dialog_ptr->tag);
02498 
02499          /* deadlock avoidance... */
02500          while (sip_dialog_ptr->owner && ast_channel_trylock(sip_dialog_ptr->owner)) {
02501             dialog_lock(sip_dialog_ptr, FALSE);
02502             usleep(1);
02503             dialog_lock(sip_dialog_ptr, TRUE);
02504          }
02505          break;
02506       }
02507    }
02508    dialoglist_unlock();
02509    if (option_debug > 3 && !sip_dialog_ptr)
02510       ast_log(LOG_DEBUG, "Found no match for callid %s to-tag %s from-tag %s\n", callid, totag, fromtag);
02511    return sip_dialog_ptr;
02512 }

static int handle_invite_replaces struct sip_dialog p,
struct sip_request req,
int  debug,
struct sockaddr_in *  sin
[static]
 

Handle the transfer part of INVITE with a replaces: header, meaning a target pickup or an attended transfer.

Definition at line 4198 of file chan_sip3.c.

References ast_channel::_state, append_history, ast_bridged_channel(), AST_CAUSE_SWITCH_CONGESTION, ast_channel_masquerade(), ast_channel_unlock, ast_frfree(), ast_hangup(), ast_log(), ast_quiet_chan(), ast_read(), ast_set_flag, ast_setstate(), ast_state2str(), AST_STATE_DOWN, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_test_flag, DEFAULT_TRANS_TIMEOUT, dialog_lock(), FALSE, sip_pvt::flags, ast_channel::hangupcause, LOG_ERROR, LOG_NOTICE, LOG_WARNING, option_debug, sip_pvt::owner, sip_dialog::owner, sip_dialog::refer, sip_refer::refer_call, SIP_DEFER_BYE_ON_TRANSFER, SIP_PKT_IGNORE, sip_scheddestroy(), ast_channel::tech_pvt, transmit_response(), transmit_response_reliable(), transmit_response_with_attachment(), WITH_SDP, and XMIT_RELIABLE.

04199 {
04200    struct ast_frame *f;
04201    int earlyreplace = 0;
04202    int oneleggedreplace = 0;     /* Call with no bridge, propably IVR or voice message */
04203    struct ast_channel *c = p->owner;   /* Our incoming call */
04204    struct ast_channel *replacecall = p->refer->refer_call->owner; /* The channel we're about to take over */
04205    struct ast_channel *targetcall;     /* The bridge to the take-over target */
04206 
04207    /* Check if we're in ring state */
04208    if (replacecall->_state == AST_STATE_RING)
04209       earlyreplace = 1;
04210 
04211    /* Check if we have a bridge */
04212    if (!(targetcall = ast_bridged_channel(replacecall))) {
04213       /* We have no bridge */
04214       if (!earlyreplace) {
04215          if (option_debug > 1)
04216             ast_log(LOG_DEBUG, " Attended transfer attempted to replace call with no bridge (maybe ringing). Channel %s!\n", replacecall->name);
04217          oneleggedreplace = 1;
04218       }
04219    } 
04220    if (option_debug > 3 && targetcall && targetcall->_state == AST_STATE_RINGING)
04221          ast_log(LOG_DEBUG, "SIP transfer: Target channel is in ringing state\n");
04222 
04223    if (option_debug > 3) {
04224       if (targetcall) 
04225          ast_log(LOG_DEBUG, "SIP transfer: Invite Replace incoming channel should bridge to channel %s while hanging up channel %s\n", targetcall->name, replacecall->name); 
04226       else
04227          ast_log(LOG_DEBUG, "SIP transfer: Invite Replace incoming channel should replace and hang up channel %s (one call leg)\n", replacecall->name); 
04228    }
04229 
04230    if (ast_test_flag(req, SIP_PKT_IGNORE)) {
04231       ast_log(LOG_NOTICE, "Ignoring this INVITE with replaces in a stupid way.\n");
04232       /* We should answer something here. If we are here, the
04233          call we are replacing exists, so an accepted 
04234          can't harm */
04235       transmit_response_with_attachment(WITH_SDP, p, "200 OK", req, XMIT_RELIABLE);
04236       /* Do something more clever here */
04237       ast_channel_unlock(c);
04238       dialog_lock(p->refer->refer_call, FALSE);
04239       return 1;
04240    } 
04241    if (!c) {
04242       /* What to do if no channel ??? */
04243       ast_log(LOG_ERROR, "Unable to create new channel.  Invite/replace failed.\n");
04244       transmit_response_reliable(p, "503 Service Unavailable", req);
04245       append_history(p, "Xfer", "INVITE/Replace Failed. No new channel.");
04246       sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
04247       dialog_lock(p->refer->refer_call, FALSE);
04248       return 1;
04249    }
04250    append_history(p, "Xfer", "INVITE/Replace received");
04251    /* We have three channels to play with
04252       channel c: New incoming call
04253       targetcall: Call from PBX to target
04254       p->refer->refer_call: SIP pvt dialog from transferer to pbx.
04255       replacecall: The owner of the previous
04256       We need to masq C into refer_call to connect to 
04257       targetcall;
04258       If we are talking to internal audio stream, target call is null.
04259    */
04260 
04261    /* Fake call progress */
04262    transmit_response(p, "100 Trying", req);
04263    ast_setstate(c, AST_STATE_RING);
04264 
04265    /* Masquerade the new call into the referred call to connect to target call 
04266       Targetcall is not touched by the masq */
04267 
04268    /* Answer the incoming call and set channel to UP state */
04269    transmit_response_with_attachment(WITH_SDP, p, "200 OK", req, XMIT_RELIABLE);
04270    ast_setstate(c, AST_STATE_UP);
04271    
04272    /* Stop music on hold and other generators */
04273    ast_quiet_chan(replacecall);
04274    ast_quiet_chan(targetcall);
04275    if (option_debug > 3)
04276       ast_log(LOG_DEBUG, "Invite/Replaces: preparing to masquerade %s into %s\n", c->name, replacecall->name);
04277    /* Unlock clone, but not original (replacecall) */
04278    ast_channel_unlock(c);
04279 
04280    /* Unlock dialog */
04281    dialog_lock(p->refer->refer_call, FALSE);
04282 
04283    /* Make sure that the masq does not free our PVT for the old call */
04284    ast_set_flag(&p->refer->refer_call->flags[0], SIP_DEFER_BYE_ON_TRANSFER);  /* Delay hangup */
04285       
04286    /* Prepare the masquerade - if this does not happen, we will be gone */
04287    if(ast_channel_masquerade(replacecall, c))
04288       ast_log(LOG_ERROR, "Failed to masquerade C into Replacecall\n");
04289    else if (option_debug > 3)
04290       ast_log(LOG_DEBUG, "Invite/Replaces: Going to masquerade %s into %s\n", c->name, replacecall->name);
04291 
04292    /* The masquerade will happen as soon as someone reads a frame from the channel */
04293 
04294    /* C should now be in place of replacecall */
04295    /* ast_read needs to lock channel */
04296    ast_channel_unlock(c);
04297    
04298    if (earlyreplace || oneleggedreplace ) {
04299       /* Force the masq to happen */
04300       if ((f = ast_read(replacecall))) {  /* Force the masq to happen */
04301          ast_frfree(f);
04302          f = NULL;
04303          if (option_debug > 3)
04304             ast_log(LOG_DEBUG, "Invite/Replace:  Could successfully read frame from RING channel!\n");
04305       } else {
04306          ast_log(LOG_WARNING, "Invite/Replace:  Could not read frame from RING channel \n");
04307       }
04308       c->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
04309       ast_channel_unlock(replacecall);
04310    } else { /* Bridged call, UP channel */
04311       if ((f = ast_read(replacecall))) {  /* Force the masq to happen */
04312          /* Masq ok */
04313          ast_frfree(f);
04314          f = NULL;
04315          if (option_debug > 2)
04316             ast_log(LOG_DEBUG, "Invite/Replace:  Could successfully read frame from channel! Masq done.\n");
04317       } else {
04318          ast_log(LOG_WARNING, "Invite/Replace:  Could not read frame from channel. Transfer failed\n");
04319       }
04320       ast_channel_unlock(replacecall);
04321    }
04322    dialog_lock(p->refer->refer_call, FALSE);
04323 
04324    ast_setstate(c, AST_STATE_DOWN);
04325    if (option_debug > 3) {
04326       struct ast_channel *test;
04327       ast_log(LOG_DEBUG, "After transfer:----------------------------\n");
04328       ast_log(LOG_DEBUG, " -- C:        %s State %s\n", c->name, ast_state2str(c->_state));
04329       if (replacecall)
04330          ast_log(LOG_DEBUG, " -- replacecall:        %s State %s\n", replacecall->name, ast_state2str(replacecall->_state));
04331       if (p->owner) {
04332          ast_log(LOG_DEBUG, " -- P->owner: %s State %s\n", p->owner->name, ast_state2str(p->owner->_state));
04333          test = ast_bridged_channel(p->owner);
04334          if (test)
04335             ast_log(LOG_DEBUG, " -- Call bridged to P->owner: %s State %s\n", test->name, ast_state2str(test->_state));
04336          else
04337             ast_log(LOG_DEBUG, " -- No call bridged to C->owner \n");
04338       } else 
04339          ast_log(LOG_DEBUG, " -- No channel yet \n");
04340       ast_log(LOG_DEBUG, "End After transfer:----------------------------\n");
04341    }
04342 
04343    ast_channel_unlock(p->owner); /* Unlock new owner */
04344    dialog_lock(p, FALSE);
04345 
04346    /* The call should be down with no ast_channel, so hang it up */
04347    c->tech_pvt = NULL;
04348    ast_hangup(c);
04349    return 0;
04350 }

GNURK int handle_request struct sip_dialog p,
struct sip_request req,
struct sockaddr_in *  sin,
int *  recount,
int *  nounlock
 

Handle incoming SIP requests (methods).

Note:
This is where all incoming requests go first

Definition at line 5263 of file chan_sip3.c.

References __sip_ack(), append_history, ast_inet_ntoa(), ast_log(), ast_set_flag, ast_string_field_set, ast_strlen_zero(), ast_test_flag, check_pendings(), sip_request::cseqheader, debug(), DEFAULT_TRANS_TIMEOUT, DIALOG_STATE_TERMINATED, dialogstatechange(), error(), extract_uri(), FALSE, find_sdp(), sip_dialog::flags, sip_request::from, get_header(), gettag(), handle_request_bye(), handle_request_cancel(), handle_request_info(), handle_request_invite(), handle_request_message(), handle_request_notify(), handle_request_options(), handle_request_refer(), handle_request_register(), handle_request_subscribe(), handle_response(), sip_request::header, sip_dialog::initreq, len, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sip_request::method, option_debug, process_sdp(), sip_request::rlPart1, sip_request::rlPart2, sip_request::seqno, SIP_ACK, SIP_ALREADYGONE, SIP_BYE, SIP_CANCEL, sip_debug_test_pvt(), SIP_INFO, SIP_INVITE, SIP_MESSAGE, sip_method2txt(), SIP_NEEDDESTROY, SIP_NOTIFY, SIP_OPTIONS, SIP_PKT_IGNORE, SIP_PKT_IGNORE_REQ, SIP_PKT_IGNORE_RESP, SIP_PKT_RESPONSE, SIP_PKT_WITH_TOTAG, SIP_REFER, SIP_REGISTER, SIP_RESPONSE, sip_scheddestroy(), SIP_SUBSCRIBE, sip_dialog::tag, transmit_response(), transmit_response_reliable(), transmit_response_with_attachment(), WITH_ALLOW, and XMIT_UNRELIABLE.

05264 {
05265    /* Called with p->lock held, as well as p->owner->lock if appropriate, keeping things
05266       relatively static */
05267    //struct sip_request resp;
05268    const char *cmd;
05269    const char *cseq;
05270    const char *useragent;
05271    int len;
05272    int respid;
05273    int res = 0;
05274    int debug = sip_debug_test_pvt(p);
05275    char *e;
05276    int error = 0;
05277 
05278    /* Clear out potential response */
05279    //memset(&resp, 0, sizeof(resp));
05280 
05281    /* Get Method and Cseq */
05282    cseq = req->cseqheader;
05283    cmd = req->header[0];
05284 
05285    /* Must have Cseq */
05286    if (ast_strlen_zero(cmd) || ast_strlen_zero(cseq)) {
05287       ast_log(LOG_ERROR, "Missing Cseq. Dropping this SIP message, it's incomplete.\n");
05288       error = 1;
05289    } else {
05290       int seqno;
05291       /* Can we do this earlier in parse_request? */
05292       if (!error && sscanf(cseq, "%d%n", &seqno, &len) != 1) {
05293          ast_log(LOG_ERROR, "No seqno in '%s'. Dropping incomplete message.\n", cmd);
05294          error = 1;
05295       }
05296       req->seqno = seqno;
05297    }
05298 
05299    if (error) {
05300       if (!p->initreq)  /* New call */
05301          ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); /* Make sure we destroy this dialog */
05302       return -1;
05303    }
05304 
05305    /* Get the command XXX */
05306 
05307    cmd = req->rlPart1;
05308    e = req->rlPart2;
05309 
05310    /* Save useragent of the client */
05311    useragent = get_header(req, "User-Agent");
05312    if (!ast_strlen_zero(useragent))
05313       ast_string_field_set(p, useragent, useragent);
05314 
05315    /* Find out SIP method for incoming request */
05316    if (req->method == SIP_RESPONSE) {  /* Response to our request */
05317       /* Response to our request -- Do some sanity checks */   
05318       if (!p->initreq) {
05319          if (option_debug)
05320             ast_log(LOG_DEBUG, "That's odd...  Got a response on a call we dont know about. Cseq %d Cmd %s\n", req->seqno, cmd);
05321          ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); 
05322          return 0;
05323       } else if (p->ocseq < req->seqno) {
05324          if (option_debug)
05325             ast_log(LOG_DEBUG, "Ignoring out of order response %d (expecting %d)\n", req->seqno, p->ocseq);
05326          return -1;
05327       } else if (p->ocseq != req->seqno) {
05328          /* ignore means "don't do anything with it" but still have to 
05329             respond appropriately  
05330             In fact, it really means that we have to resend the response
05331             but in this version of chan_sip we haven't got it in memory...
05332          */
05333          ast_set_flag(req, SIP_PKT_IGNORE);
05334          ast_set_flag(req, SIP_PKT_IGNORE_RESP);
05335          append_history(p, "Ignore", "Ignoring this retransmit\n");
05336       }
05337    
05338       e = ast_skip_blanks(e);
05339       if (sscanf(e, "%d %n", &respid, &len) != 1) {
05340          ast_log(LOG_WARNING, "Invalid response: '%s'\n", e);
05341       } else {
05342          /* More SIP ridiculousness, we have to ignore bogus contacts in 100 etc responses */
05343          if ((respid == 200) || ((respid >= 300) && (respid <= 399)))
05344             extract_uri(p, req);
05345          handle_response(p, respid, e + len, req);
05346       }
05347       return 0;
05348    }
05349 
05350    /* New SIP request coming in 
05351       (could be new request in existing SIP dialog as well...) 
05352     */         
05353    
05354    p->method = req->method;   /* Find out which SIP method they are using */
05355    if (option_debug > 3)
05356       ast_log(LOG_DEBUG, "**** Received %s - Command in SIP %s\n", sip_method2txt(p->method), cmd); 
05357 
05358    if (p->icseq && (p->icseq > req->seqno)) {
05359       if (option_debug)
05360          ast_log(LOG_DEBUG, "Ignoring too old SIP packet packet %d (expecting >= %d)\n", req->seqno, p->icseq);
05361       if (req->method != SIP_ACK)
05362          transmit_response(p, "503 Server error", req);  /* We must respond according to RFC 3261 sec 12.2 */
05363       return -1;
05364    } else if (p->icseq &&
05365          p->icseq == req->seqno &&
05366          req->method != SIP_ACK &&
05367          (p->method != SIP_CANCEL || ast_test_flag(&p->flags[0], SIP_ALREADYGONE))) {
05368       /* ignore means "don't do anything with it" but still have to 
05369          respond appropriately.  We do this if we receive a repeat of
05370          the last sequence number  */
05371       ast_set_flag(req, SIP_PKT_IGNORE);
05372       ast_set_flag(req, SIP_PKT_IGNORE_REQ);
05373       if (option_debug > 2)
05374          ast_log(LOG_DEBUG, "Ignoring SIP message because of retransmit (%s Seqno %d, ours %d)\n", sip_method2txt(p->method), p->icseq, req->seqno);
05375    }
05376       
05377    if (req->seqno >= p->icseq)
05378       /* Next should follow monotonically (but not necessarily 
05379          incrementally -- thanks again to the genius authors of SIP --
05380          increasing */
05381       p->icseq = req->seqno;
05382 
05383    /* Find their tag if we haven't got it */
05384    if (ast_strlen_zero(p->theirtag)) {
05385       char tag[128];
05386 
05387       gettag(req->from, tag, sizeof(tag));
05388       ast_string_field_set(p, theirtag, tag);
05389    }
05390    snprintf(p->lastmsg, sizeof(p->lastmsg), "Rx: %s", cmd);
05391 
05392    /* If this is a request packet without a from tag, it's not
05393       correct according to RFC 3261  */
05394    /* Check if this a new request in a new dialog with a totag already attached to it,
05395       RFC 3261 - section 12.2 - and we don't want to mess with recovery  */
05396 
05397    if ((!p->initreq) && ast_test_flag(req, SIP_PKT_WITH_TOTAG)) {
05398       /* If this is a first request and it got a to-tag, it is not for us */
05399       if (!ast_test_flag(req, SIP_PKT_IGNORE) && req->method == SIP_INVITE)
05400          transmit_response_reliable(p, "481 Call/Transaction Does Not Exist", req);
05401       else if (req->method != SIP_ACK)
05402          transmit_response(p, "481 Call/Transaction Does Not Exist", req);
05403       sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
05404       dialogstatechange(p, DIALOG_STATE_TERMINATED);
05405       return res;
05406    }
05407 
05408    /* Handle various incoming SIP methods in requests */
05409    switch (p->method) {
05410    case SIP_OPTIONS:
05411       res = handle_request_options(p, req);
05412       break;
05413    case SIP_INVITE:
05414       res = handle_request_invite(p, req, debug, sin, recount, e);
05415       break;
05416    case SIP_REFER:
05417       res = handle_request_refer(p, req, debug, req->seqno, nounlock);
05418       break;
05419    case SIP_CANCEL:
05420       res = handle_request_cancel(p, req);
05421       break;
05422    case SIP_BYE:
05423       res = handle_request_bye(p, req);
05424       break;
05425    case SIP_MESSAGE:
05426       res = handle_request_message(p, req);
05427       break;
05428    case SIP_SUBSCRIBE:
05429       res = handle_request_subscribe(p, req, sin, e);
05430       break;
05431    case SIP_REGISTER:
05432       res = handle_request_register(p, req, sin, e);
05433       break;
05434    case SIP_INFO:
05435       handle_request_info(p, req);
05436       break;
05437    case SIP_NOTIFY:
05438       res = handle_request_notify(p, req, sin, e);
05439       break;
05440    case SIP_ACK:
05441       /* Make sure we don't ignore this */
05442       /* ACK on 200 OK */
05443       if (req->seqno == p->pendinginvite) {
05444          if (option_debug)
05445             ast_log(LOG_DEBUG, "Got ACK on 200 OK, this call setup is complete - %s Cseq %d\n", p->callid, req->seqno);
05446          p->pendinginvite = 0;
05447          __sip_ack(p, req->seqno, SIP_PKT_RESPONSE, 0, FALSE);
05448          if (find_sdp(req)) {
05449             if (process_sdp(p, req))
05450                return -1;
05451          } 
05452          check_pendings(p);
05453       } else if (option_debug)
05454          ast_log(LOG_DEBUG, "Got ACK that does not match dialog cseq, this is unexpected - %s Cseq %d Pending cseq %d\n", p->callid, req->seqno, p->pendinginvite);
05455       /* Got an ACK that we did not match with active dialog. 
05456          We have given a final response */
05457       if (!p->lastinvite && ast_strlen_zero(p->randdata))
05458          ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); 
05459       break;
05460    default:
05461       transmit_response_with_attachment(WITH_ALLOW, p, "501 Method Not Implemented", req, XMIT_UNRELIABLE);
05462       ast_log(LOG_NOTICE, "Unknown SIP command '%s' from '%s'\n", 
05463          cmd, ast_inet_ntoa(p->sa.sin_addr));
05464       /* If this is some new method, and we don't have a call, destroy it now */
05465       if (!p->initreq)
05466          ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); 
05467       break;
05468    }
05469    return res;
05470 }

static int handle_request_bye struct sip_dialog p,
struct sip_request req
[static]
 

Handle incoming BYE request.

Definition at line 4858 of file chan_sip3.c.

References append_history, ast_async_goto(), ast_bridged_channel(), AST_CONTROL_UNHOLD, ast_inet_ntoa(), ast_log(), ast_queue_control(), ast_queue_hangup(), ast_rtp_get_quality(), ast_set_flag, ast_string_field_set, ast_strlen_zero(), ast_test_flag, check_via(), ast_channel::context, context, sip_globals::default_context, DEFAULT_TRANS_TIMEOUT, sip_dialog::flags, get_also_info(), get_header(), global, sip_dialog::initreq, LOG_NOTICE, LOG_WARNING, option_debug, pbx_builtin_setvar_helper(), sip_dialog::pendinginvite, set_initreq(), SIP_ALREADYGONE, SIP_NO_HISTORY, SIP_OUTGOING, SIP_PKT_IGNORE, sip_scheddestroy(), stop_media_flows(), transmit_response(), and transmit_response_reliable().

04859 {
04860    struct ast_channel *c=NULL;
04861    int res;
04862    struct ast_channel *bridged_to;
04863    char *audioqos = NULL, *videoqos = NULL;
04864    
04865    if (p->pendinginvite && !ast_test_flag(&p->flags[0], SIP_OUTGOING) && !ast_test_flag(req, SIP_PKT_IGNORE))
04866       transmit_response_reliable(p, "487 Request Terminated", p->initreq);
04867 
04868    set_initreq(p, req);
04869    check_via(p, req);
04870    ast_set_flag(&p->flags[0], SIP_ALREADYGONE); 
04871 
04872    if (p->rtp) {
04873       audioqos = ast_rtp_get_quality(p->rtp);
04874       if (p->owner)
04875          pbx_builtin_setvar_helper(p->owner, "RTPAUDIOQOS", audioqos);
04876    }
04877    if (p->vrtp) {
04878       videoqos = ast_rtp_get_quality(p->vrtp);
04879       if (p->owner)
04880          pbx_builtin_setvar_helper(p->owner, "RTPVIDEOQOS", videoqos);
04881    }
04882 
04883    /* Get RTCP quality before end of call */
04884    if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY) || p->owner) {
04885       if (p->rtp)
04886          append_history(p, "RTCPaudio", "Quality:%s", audioqos);
04887       if (p->vrtp)
04888          append_history(p, "RTCPvideo", "Quality:%s", videoqos);
04889    }
04890 
04891    stop_media_flows(p);
04892    if (!ast_strlen_zero(get_header(req, "Also"))) {
04893       ast_log(LOG_NOTICE, "Client '%s' using deprecated BYE/Also transfer method.  Ask vendor to support REFER instead\n",
04894          ast_inet_ntoa(p->recv.sin_addr));
04895       if (ast_strlen_zero(p->context))
04896          ast_string_field_set(p, context, global.default_context);
04897       res = get_also_info(p, req);
04898       if (!res) {
04899          c = p->owner;
04900          if (c) {
04901             bridged_to = ast_bridged_channel(c);
04902             if (bridged_to) {
04903                /* Don't actually hangup here... */
04904                ast_queue_control(c, AST_CONTROL_UNHOLD);
04905                ast_async_goto(bridged_to, p->context, p->refer->refer_to,1);
04906             } else
04907                ast_queue_hangup(p->owner);
04908          }
04909       } else {
04910          ast_log(LOG_WARNING, "Invalid transfer information from '%s'\n", ast_inet_ntoa(p->recv.sin_addr));
04911          if (p->owner)
04912             ast_queue_hangup(p->owner);
04913       }
04914    } else if (p->owner) {
04915       ast_queue_hangup(p->owner);
04916       if (option_debug > 2)
04917          ast_log(LOG_DEBUG, "Received bye, issuing owner hangup\n");
04918    } else {
04919       sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
04920       if (option_debug > 2)
04921          ast_log(LOG_DEBUG, "Received bye, no owner, selfdestruct soon.\n");
04922    }
04923    transmit_response(p, "200 OK", req);
04924 
04925    return 1;
04926 }

static int handle_request_cancel struct sip_dialog p,
struct sip_request req
[static]
 

Handle incoming CANCEL request.

Definition at line 4829 of file chan_sip3.c.

References ast_channel::_state, ast_log(), ast_queue_hangup(), ast_set_flag, AST_STATE_UP, check_via(), DEFAULT_TRANS_TIMEOUT, sip_dialog::flags, sip_dialog::initreq, option_debug, sip_dialog::owner, SIP_ALREADYGONE, sip_scheddestroy(), stop_media_flows(), transmit_response(), and transmit_response_reliable().

04830 {
04831       
04832    check_via(p, req);
04833    ast_set_flag(&p->flags[0], SIP_ALREADYGONE); 
04834    
04835    if (p->owner && p->owner->_state == AST_STATE_UP) {
04836       /* This call is up, cancel is ignored, we need a bye */
04837       transmit_response(p, "200 OK", req);
04838       if (option_debug)
04839          ast_log(LOG_DEBUG, "Got CANCEL on an answered call. Ignoring... \n");
04840       return 0;
04841    }
04842    stop_media_flows(p);
04843    if (p->owner)
04844       ast_queue_hangup(p->owner);
04845    else
04846       sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
04847    if (p->initreq) {
04848       transmit_response_reliable(p, "487 Request Terminated", p->initreq);
04849       transmit_response(p, "200 OK", req);
04850       return 1;
04851    } else {
04852       transmit_response(p, "481 Call Leg Does Not Exist", req);
04853       return 0;
04854    }
04855 }

static void handle_request_info struct sip_dialog p,
struct sip_request req
[static]
 

Receive SIP INFO Message.

Note:
Doesn't read the duration of the DTMF signal

Definition at line 3038 of file chan_sip3.c.

References ast_bridged_channel(), ast_cdr_setuserfield(), AST_CONTROL_FLASH, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_log(), ast_queue_control(), ast_queue_frame(), ast_strlen_zero(), ast_test_flag, ast_verbose(), ast_channel::cdr, DIALOG_STATE_TERMINATED, DIALOG_STATE_TRYING, dialogstatechange(), event, sip_dialog::flags, get_body(), get_header(), ast_frame::len, LOG_WARNING, sip_dialog::owner, SIP_PKT_IGNORE, SIP_USECLIENTCODE, sipdebug, sip_dialog::state, ast_frame::subclass, transmit_final_response(), transmit_response(), and XMIT_UNRELIABLE.

03039 {
03040    char buf[1024];
03041    unsigned int event;
03042    const char *c = get_header(req, "Content-Type");
03043 
03044    if (ast_test_flag(req, SIP_PKT_IGNORE))  {
03045       transmit_response(p, "200 OK", req);
03046       return;
03047    }
03048 
03049    /* All replies to INFO are final */
03050    dialogstatechange(p, DIALOG_STATE_TERMINATED);
03051 
03052    /* Need to check the media/type */
03053    if (!strcasecmp(c, "application/dtmf-relay") ||
03054        !strcasecmp(c, "application/vnd.nortelnetworks.digits")) {
03055       unsigned int duration = 0;
03056 
03057       if (p->state == DIALOG_STATE_TRYING) { /* INFO outside of a dialog */
03058          transmit_final_response(p, "481 Call leg/transaction does not exist", req, XMIT_UNRELIABLE); /* Should return error */
03059          return;
03060       }
03061 
03062       /* Try getting the "signal=" part */
03063       if (ast_strlen_zero(c = get_body(req, "Signal")) && ast_strlen_zero(c = get_body(req, "d"))) {
03064          ast_log(LOG_WARNING, "Unable to retrieve DTMF signal from INFO message from %s\n", p->callid);
03065          transmit_response(p, "200 OK", req); /* Should return error */
03066          return;
03067       } else
03068          ast_copy_string(buf, c, sizeof(buf));
03069 
03070       if (!ast_strlen_zero((c = get_body(req, "Duration"))))
03071          duration = atoi(c);
03072       if (!duration)
03073          duration = 100; /* 100 ms */
03074 
03075    
03076 
03077       if (ast_strlen_zero(buf)) {
03078          /* Nothing there folks, move on. */
03079          transmit_response(p, "200 OK", req);
03080          return;
03081       }
03082       /* We have a DTMF code in the attachment */
03083 
03084       if (buf[0] == '*')
03085          event = 10;
03086       else if (buf[0] == '#')
03087          event = 11;
03088       else if ((buf[0] >= 'A') && (buf[0] <= 'D'))
03089          event = 12 + buf[0] - 'A';
03090       else
03091          event = atoi(buf);
03092       if (event == 16) {
03093          /* send a FLASH event */
03094          struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH, };
03095          ast_queue_frame(p->owner, &f);
03096          if (sipdebug)
03097             ast_verbose("* DTMF-relay event received: FLASH\n");
03098       } else {
03099          /* send a DTMF event */
03100          struct ast_frame f = { AST_FRAME_DTMF, };
03101          if (event < 10) {
03102             f.subclass = '0' + event;
03103          } else if (event < 11) {
03104             f.subclass = '*';
03105          } else if (event < 12) {
03106             f.subclass = '#';
03107          } else if (event < 16) {
03108             f.subclass = 'A' + (event - 12);
03109          }
03110          f.len = duration;
03111          ast_queue_frame(p->owner, &f);
03112          if (sipdebug)
03113             ast_verbose("* DTMF-relay event received: %c\n", f.subclass);
03114       }
03115       transmit_response(p, "200 OK", req);
03116       return;
03117    } else if (!strcasecmp(c, "application/media_control+xml")) {
03118       /* Eh, we'll just assume it's a fast picture update for now */
03119       if (p->owner)
03120          ast_queue_control(p->owner, AST_CONTROL_VIDUPDATE);
03121       transmit_response(p, "200 OK", req);
03122       return;
03123    } else if (!ast_strlen_zero(c = get_header(req, "X-ClientCode"))) {
03124       /* Client code (from SNOM phone) */
03125       if (ast_test_flag(&p->flags[0], SIP_USECLIENTCODE)) {
03126          if (p->owner && p->owner->cdr)
03127             ast_cdr_setuserfield(p->owner, c);
03128          if (p->owner && ast_bridged_channel(p->owner) && ast_bridged_channel(p->owner)->cdr)
03129             ast_cdr_setuserfield(ast_bridged_channel(p->owner), c);
03130          transmit_response(p, "200 OK", req);
03131       } else {
03132          transmit_response(p, "415 Unsupported media type", req);
03133       }
03134       return;
03135    }
03136    /* Other type of INFO message, not really understood by Asterisk */
03137    /* if (get_msg_text(buf, sizeof(buf), req)) { */
03138 
03139    ast_log(LOG_WARNING, "Unable to parse INFO message from %s. Content %s\n", p->callid, buf);
03140    transmit_response(p, "415 Unsupported media type", req);
03141    return;
03142 }

static int handle_request_invite struct sip_dialog p,
struct sip_request req,
int  debug,
struct sockaddr_in *  sin,
int *  recount,
char *  e
[static]
 

Handle incoming INVITE request.

Note:
If the INVITE has a Replaces header, it is part of an attended transfer. If so, we do not go through the dial plan but tries to find the active call and masquerade into it
XXX: we should also check here does the other side supports t38 at all !!! XXX

Definition at line 4359 of file chan_sip3.c.

References ast_channel::_state, append_history, ast_bridged_channel(), AST_CAUSE_CALL_REJECTED, AST_CAUSE_NORMAL_CLEARING, ast_channel_lock, ast_channel_unlock, ast_hangup(), ast_log(), AST_PBX_CALL_LIMIT, AST_PBX_FAILED, ast_pbx_start(), AST_PBX_SUCCESS, ast_pickup_call(), ast_pickup_ext(), ast_rtp_setdtmf(), ast_rtp_setdtmfcompensate(), ast_set_flag, ast_setstate(), AST_STATE_DOWN, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdupa, ast_string_field_free, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_uri_decode(), ast_verbose(), AUTH_CHALLENGE_SENT, AUTH_FAKE_AUTH, sip_dialog::autokillid, build_contact(), build_route(), sip_dialog::capability, check_user(), check_via(), context, DEC_CALL_LIMIT, sip_globals::default_context, DEFAULT_TRANS_TIMEOUT, dialog_lock(), DIALOG_STATE_CONFIRMED, DIALOG_STATE_EARLY, DIALOG_STATE_PROCEEDING, DIALOG_STATE_TERMINATED, dialogstatechange(), error(), exten, extract_uri(), FALSE, find_sdp(), sip_dialog::flags, get_destination(), get_header(), get_rdnis(), get_sip_dialog_byid_locked(), global, handle_invite_replaces(), ast_channel::hangupcause, INC_CALL_LIMIT, sip_dialog::jointcapability, sip_dialog::lastinvite, LOG_NOTICE, LOG_WARNING, make_our_tag(), option_debug, sip_pvt::owner, sip_dialog::owner, parse_ok_contact(), parse_sip_options(), sip_dialog::pendinginvite, process_sdp(), sip_dialog::refer, sip_refer::refer_call, sip_dialog::rtp, S_OR, sip_request::seqno, set_initreq(), SIP_ALREADYGONE, sip_cancel_destroy(), SIP_DTMF, SIP_DTMF_INFO, sip_handle_t38_reinvite(), SIP_INVITE, sip_new(), SIP_NO_HISTORY, SIP_OPT_REPLACES, SIP_OUTGOING, SIP_PAGE2_ALLOWOVERLAP, SIP_PAGE2_RFC2833_COMPENSATE, SIP_PKT_IGNORE, sip_refer_allocate(), sip_scheddestroy(), sip_tech, sip_tech_info, sipdebug, sip_dialog::sipoptions, t38properties::state, strcasestr(), strsep(), sip_dialog::t38, T38_DISABLED, T38_ENABLED, T38_PEER_REINVITE, sip_dialog::tag, ast_channel::tech, ast_channel::tech_pvt, transmit_fake_auth_response(), transmit_final_response(), transmit_response(), transmit_response_reliable(), transmit_response_with_attachment(), transmit_response_with_unsupported(), TRUE, ast_channel_tech::type, sip_dialog::udptl, update_call_counter(), WITH_SDP, WITH_T38_SDP, XMIT_CRITICAL, XMIT_RELIABLE, and XMIT_UNRELIABLE.

04360 {
04361    int res = 1;
04362    int gotdest;
04363    const char *p_replaces;
04364    char *replace_id = NULL;
04365    const char *required;
04366    unsigned int required_profile = 0;
04367    struct ast_channel *c = NULL;    /* New channel */
04368    int error = 0;
04369 
04370    /* Find out what they support */
04371    if (!p->sipoptions) {
04372       const char *supported = get_header(req, "Supported");
04373       if (!ast_strlen_zero(supported))
04374          parse_sip_options(p, supported);
04375    }
04376 
04377    /* Find out what they require */
04378    required = get_header(req, "Require");
04379    if (!ast_strlen_zero(required)) {
04380       required_profile = parse_sip_options(NULL, required);
04381       if (required_profile && required_profile != SIP_OPT_REPLACES) {
04382          /* At this point we only support REPLACES */
04383          transmit_response_with_unsupported(p, "420 Bad extension (unsupported)", req, required);
04384          ast_log(LOG_WARNING,"Received SIP INVITE with unsupported required extension: %s\n", required);
04385          error = 1;
04386       }
04387    }
04388 
04389    /* Check if this is a loop */
04390    if (!error && ast_test_flag(&p->flags[0], SIP_OUTGOING) && p->owner && (p->owner->_state != AST_STATE_UP)) {
04391       /* This is a call to ourself.  Send ourselves an error code and stop
04392          processing immediately, as SIP really has no good mechanism for
04393          being able to call yourself */
04394       /* we need to check the tags and the branch. If they're different, this is
04395            in fact a forked call through a SIP proxy somewhere. */
04396       transmit_final_response(p, "482 Loop Detected", req, XMIT_RELIABLE);
04397       error = 1;
04398    }
04399    
04400    /* Check if we already have a pending invite. If so, then deny this one */
04401    if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->pendinginvite) {
04402       /* We already have a pending invite. Sorry. You are on hold. */
04403       transmit_response(p, "491 Request Pending", req);
04404       
04405       if (option_debug)
04406          ast_log(LOG_DEBUG, "Got INVITE on call where we already have pending INVITE, deferring that - %s\n", p->callid);
04407       /* No destruction here, we have a current dialog */
04408       return 0;
04409    }
04410    if (error) {
04411       dialogstatechange(p, DIALOG_STATE_TERMINATED);
04412       if (!p->lastinvite)
04413          sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
04414       return 0;
04415    }
04416 
04417    p_replaces = get_header(req, "Replaces");
04418 
04419    if (!ast_strlen_zero(p_replaces)) {
04420       /* We have a replaces header */
04421       char *ptr;
04422       char *fromtag = NULL;
04423       char *totag = NULL;
04424       char *start, *to;
04425 
04426       if (p->owner) {
04427          if (option_debug > 2)
04428             ast_log(LOG_DEBUG, "INVITE w Replaces on existing call? Refusing action. [%s]\n", p->callid);
04429          transmit_response(p, "400 Bad request", req);   /* The best way to not not accept the transfer */
04430          /* Do not destroy existing call */
04431          return -1;
04432       }
04433 
04434       if (sipdebug && option_debug > 2)
04435          ast_log(LOG_DEBUG, "INVITE part of call transfer. Replaces [%s]\n", p_replaces);
04436       /* Create a buffer we can manipulate */
04437       replace_id = ast_strdupa(p_replaces);
04438       ast_uri_decode(replace_id);
04439 
04440       if (!p->refer && !sip_refer_allocate(p)) {
04441          append_history(p, "Xfer", "INVITE/Replace Failed. Out of memory.");
04442          transmit_final_response(p, "500 Server Internal Error", req, XMIT_RELIABLE);
04443          return -1;
04444       }
04445 
04446       /*  Todo: (When we find phones that support this)
04447          if the replaces header contains ";early-only"
04448          we can only replace the call in early
04449          stage, not after it's up.
04450 
04451          If it's not in early mode, 486 Busy.
04452       */
04453       
04454       /* Skip leading whitespace */
04455       replace_id = ast_skip_blanks(replace_id);
04456 
04457       start = replace_id;
04458       while ( (ptr = strsep(&start, ";")) ) {
04459          ptr = ast_skip_blanks(ptr); /* XXX maybe unnecessary ? */
04460          if ( (to = strcasestr(ptr, "to-tag=") ) )
04461             totag = to + 7;   /* skip the keyword */
04462          else if ( (to = strcasestr(ptr, "from-tag=") ) ) {
04463             fromtag = to + 9; /* skip the keyword */
04464             fromtag = strsep(&fromtag, "&"); /* trim what ? */
04465          }
04466       }
04467 
04468       if (sipdebug && option_debug > 3) 
04469          ast_log(LOG_DEBUG,"Invite/replaces: Will use Replace-Call-ID : %s Fromtag: %s Totag: %s\n", replace_id, fromtag ? fromtag : "<no from tag>", totag ? totag : "<no to tag>");
04470 
04471 
04472       /* Try to find call that we are replacing 
04473          If we have a Replaces  header, we need to cancel that call if we succeed with this call 
04474       */
04475       if ((p->refer->refer_call = get_sip_dialog_byid_locked(replace_id, totag, fromtag)) == NULL) {
04476          ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existent call id (%s)!\n", replace_id);
04477          transmit_final_response(p, "481 Call leg Does not exit (Replaces)", req, XMIT_RELIABLE);
04478          error = 1;
04479       }
04480 
04481       /* At this point, bot the pvt and the owner of the call to be replaced is locked */
04482 
04483       /* The matched call is the call from the transferer to Asterisk .
04484          We want to bridge the bridged part of the call to the 
04485          incoming invite, thus taking over the refered call */
04486 
04487       if (p->refer->refer_call == p) {
04488          ast_log(LOG_NOTICE, "INVITE with replaces into it's own call id (%s == %s)!\n", replace_id, p->callid);
04489          p->refer->refer_call = NULL;
04490          transmit_final_response(p, "400 Bad request", req, XMIT_RELIABLE);
04491          error = 1;
04492       }
04493 
04494       if (!error && !p->refer->refer_call->owner) {
04495          /* Oops, someting wrong anyway, no owner, no call */
04496          ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existing call id (%s)!\n", replace_id);
04497          /* Check for better return code */
04498          transmit_final_response(p, "481 Call leg Does not exit (Replaces)", req, XMIT_RELIABLE);
04499          error = 1;
04500       }
04501 
04502       if (!error && p->refer->refer_call->owner->_state != AST_STATE_RING && p->refer->refer_call->owner->_state != AST_STATE_UP ) {
04503          ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-ringing or active call id (%s)!\n", replace_id);
04504          transmit_final_response(p, "603 Declined (Replaces)", req, XMIT_RELIABLE);
04505          error = 1;
04506       }
04507 
04508       if (error) {   /* Give up this dialog */
04509          append_history(p, "Xfer", "INVITE/Replace Failed.");
04510          dialog_lock(p, FALSE);
04511          if (p->refer->refer_call) {
04512             dialog_lock(p->refer->refer_call, FALSE);
04513             ast_channel_unlock(p->refer->refer_call->owner);
04514          }
04515          return -1;
04516       }
04517    }
04518 
04519 
04520    /* Check if this is an INVITE that sets up a new dialog or
04521       a re-invite in an existing dialog */
04522 
04523    if (!ast_test_flag(req, SIP_PKT_IGNORE)) {
04524       sip_cancel_destroy(p);
04525       /* This also counts as a pending invite */
04526       p->pendinginvite = req->seqno;
04527       check_via(p, req);
04528 
04529       if (!p->owner) {  /* Not a re-invite */
04530          /* Use this as the basis */
04531          set_initreq(p, req);
04532          if (debug)
04533             ast_verbose("Using INVITE request as basis request - %s\n", p->callid);
04534          append_history(p, "Invite", "New call: %s", p->callid);
04535          parse_ok_contact(p, req);
04536       } else { /* Re-invite on existing call */
04537          /* Handle SDP here if we already have an owner */
04538          if (find_sdp(req)) {
04539             if (process_sdp(p, req)) {
04540                transmit_response(p, "488 Not acceptable here", req);
04541                if (!p->lastinvite)
04542                   sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
04543                return -1;
04544             }
04545          } else {
04546             p->jointcapability = p->capability;
04547             if (option_debug)
04548                ast_log(LOG_DEBUG, "Hm....  No sdp for the moment\n");
04549          }
04550          if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY)) /* This is a response, note what it was for */
04551             append_history(p, "ReInv", "Re-invite received");
04552       }
04553    } else if (debug)
04554       ast_verbose("Ignoring this INVITE request\n");
04555 
04556    
04557    if (!p->lastinvite && !ast_test_flag(req, SIP_PKT_IGNORE) && !p->owner) {
04558       /* This is a new invite */
04559       /* Handle authentication if this is our first invite */
04560       res = check_user(p, req, SIP_INVITE, e, XMIT_RELIABLE, sin);
04561       if (res == AUTH_CHALLENGE_SENT)
04562          return 0; 
04563       if (res < 0) { /* Something failed in authentication */
04564          if (res == AUTH_FAKE_AUTH) {
04565             ast_log(LOG_NOTICE, "Sending fake auth rejection for user %s\n", get_header(req, "From"));
04566             transmit_fake_auth_response(p, req, 1);
04567          } else {
04568             ast_log(LOG_NOTICE, "Failed to authenticate user %s\n", get_header(req, "From"));
04569             transmit_response_reliable(p, "403 Forbidden", req);
04570          }
04571          sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
04572          ast_string_field_free(p, theirtag);
04573          return 0;
04574       }
04575 
04576       /* We have a succesful authentication, process the SDP portion if there is one */
04577       if (find_sdp(req)) {
04578          if (process_sdp(p, req)) {
04579             /* Unacceptable codecs */
04580             transmit_final_response(p, "488 Not acceptable here", req, XMIT_RELIABLE);
04581             if (option_debug)
04582                ast_log(LOG_DEBUG, "No compatible codecs for this SIP call.\n");
04583             return -1;
04584          }
04585       } else { /* No SDP in invite, call control session */
04586          p->jointcapability = p->capability;
04587          if (option_debug > 1)
04588             ast_log(LOG_DEBUG, "No SDP in Invite, third party call control\n");
04589       }
04590 
04591       /* Initialize the context if it hasn't been already */
04592       if (ast_strlen_zero(p->context))
04593          ast_string_field_set(p, context, global.default_context);
04594 
04595 
04596       /* Check number of concurrent calls -vs- incoming limit HERE */
04597       if (option_debug)
04598          ast_log(LOG_DEBUG, "Checking SIP call limits for device %s\n", p->peername);
04599       if ((res = update_call_counter(p, INC_CALL_LIMIT))) {
04600          if (res < 0) {
04601             ast_log(LOG_NOTICE, "Failed to place call for user %s, too many calls\n", p->peername);
04602             transmit_final_response(p, "480 Temporarily Unavailable", req, XMIT_RELIABLE);
04603          }
04604          return 0;
04605       }
04606       gotdest = get_destination(p, NULL); /* Get destination right away */
04607       get_rdnis(p, NULL);        /* Get redirect information */
04608       extract_uri(p, req);       /* Get the Contact URI */
04609       build_contact(p);       /* Build our contact header */
04610       if (p->rtp) {
04611          ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) != SIP_DTMF_INFO);
04612          ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
04613       }
04614 
04615       if (!replace_id && gotdest) { /* No matching extension found */
04616          char *response;
04617          if (gotdest == 1 && ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP))
04618             response = "484 Address Incomplete";
04619          else
04620             response = "404 Not Found";
04621          transmit_final_response(p, response, req, XMIT_RELIABLE);
04622          update_call_counter(p, DEC_CALL_LIMIT);
04623          return 0;
04624       } else {
04625          /* If no extension was specified, use the s one */
04626          /* Basically for calling to IP/Host name only */
04627          if (ast_strlen_zero(p->exten))
04628             ast_string_field_set(p, exten, "s");
04629          /* Initialize our tag */   
04630 
04631          make_our_tag(p->tag, sizeof(p->tag));
04632 
04633          /* First invitation - create the channel */
04634          c = sip_new(p, AST_STATE_DOWN, S_OR(p->peername, NULL));
04635          *recount = 1;
04636 
04637          /* Save Record-Route for any later requests we make on this dialogue */
04638          build_route(p, req, 0);
04639 
04640          if (c) /* Pre-lock the call */
04641             ast_channel_lock(c);
04642       }
04643    } else {
04644       if (option_debug > 1 && sipdebug) {
04645          if (!ast_test_flag(req, SIP_PKT_IGNORE))
04646             ast_log(LOG_DEBUG, "Got a SIP re-invite for call %s\n", p->callid);
04647          else
04648             ast_log(LOG_DEBUG, "Got a SIP re-transmit of INVITE for call %s\n", p->callid);
04649       }
04650       c = p->owner;
04651    }
04652 
04653    if (!ast_test_flag(req, SIP_PKT_IGNORE) && p)
04654       p->lastinvite = req->seqno;
04655 
04656    if (replace_id) {    /* Attended transfer or call pickup - we're the target */
04657       /* Go and take over the target call */
04658       if (sipdebug && option_debug > 3)
04659          ast_log(LOG_DEBUG, "Sending this call to the invite/replcaes handler %s\n", p->callid);
04660       return handle_invite_replaces(p, req, debug, sin);
04661    }
04662 
04663 
04664    if (c) { /* We have a call  -either a new call or an old one (RE-INVITE) */
04665       switch(c->_state) {
04666       case AST_STATE_DOWN:
04667          if (option_debug > 1)
04668             ast_log(LOG_DEBUG, "%s: New call is still down.... Trying... \n", c->name);
04669          transmit_response(p, "100 Trying", req);
04670          ast_setstate(c, AST_STATE_RING);
04671          if (strcmp(p->exten, ast_pickup_ext())) { /* Call to extension -start pbx on this call */
04672             enum ast_pbx_result res;
04673             const char *response = NULL;
04674 
04675             res = ast_pbx_start(c);
04676 
04677             switch(res) {
04678             case AST_PBX_FAILED:
04679                ast_log(LOG_WARNING, "Failed to start PBX :(\n");
04680                response = "503 Unavailable";
04681                break;
04682             case AST_PBX_CALL_LIMIT:
04683                ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
04684                response = "480 Temporarily Unavailable";
04685                break;
04686             case AST_PBX_SUCCESS:
04687                /* nothing to do */
04688                break;
04689             }
04690             if (response)
04691                transmit_final_response(p, response, req, ast_test_flag(req, SIP_PKT_IGNORE) ? XMIT_UNRELIABLE : XMIT_RELIABLE);
04692 
04693             if (res) {
04694                /* Unlock locks so ast_hangup can do its magic */
04695                ast_channel_unlock(c);
04696                dialog_lock(p, FALSE);
04697                ast_hangup(c);
04698                dialog_lock(p, TRUE);
04699                c = NULL;
04700             }
04701          } else { /* Pickup call in call group */
04702             ast_channel_unlock(c);
04703             if (ast_pickup_call(c)) {
04704                ast_log(LOG_NOTICE, "Nothing to pick up for %s\n", p->callid);
04705                transmit_final_response(p, "503 Unavailable", req, ast_test_flag(req, SIP_PKT_IGNORE) ? XMIT_UNRELIABLE : XMIT_RELIABLE);
04706                ast_set_flag(&p->flags[0], SIP_ALREADYGONE); 
04707                /* Unlock locks so ast_hangup can do its magic */
04708                dialog_lock(p, FALSE);
04709                c->hangupcause = AST_CAUSE_CALL_REJECTED;
04710             } else {
04711                dialog_lock(p, FALSE);
04712                ast_setstate(c, AST_STATE_DOWN);
04713                c->hangupcause = AST_CAUSE_NORMAL_CLEARING;
04714             }
04715             ast_hangup(c);
04716             dialog_lock(p, TRUE);
04717             c = NULL;
04718          }
04719          break;
04720       case AST_STATE_RING:
04721          transmit_response(p, "100 Trying", req);
04722          if (!p->owner)
04723             dialogstatechange(p, DIALOG_STATE_PROCEEDING);
04724          break;
04725       case AST_STATE_RINGING:
04726          transmit_response(p, "180 Ringing", req);
04727          if (!p->owner)
04728             dialogstatechange(p, DIALOG_STATE_EARLY);
04729          break;
04730       case AST_STATE_UP:
04731          if (option_debug > 1)
04732             ast_log(LOG_DEBUG, "%s: This call is UP.... \n", c->name);
04733 
04734          if (p->t38.state == T38_PEER_REINVITE) {
04735             struct ast_channel *bridgepeer = NULL;
04736             struct sip_dialog *bridge_dialog = NULL;
04737             
04738             if ((bridgepeer = ast_bridged_channel(p->owner))) {
04739                /* We have a bridge, and this is re-invite to switchover to T38 so we send re-invite with T38 SDP, to other side of bridge*/
04740                /*! XXX: we should also check here does the other side supports t38 at all !!! XXX */
04741                if (!strcasecmp(bridgepeer->tech->type, "SIP")) { /* If we are bridged to SIP channel */
04742                   bridge_dialog = (struct sip_dialog*)bridgepeer->tech_pvt;
04743                   if (bridge_dialog->t38.state == T38_DISABLED) {
04744                      if (bridge_dialog->udptl) { /* If everything is OK with other side's udptl struct */
04745                         /* Send re-invite to the bridged channel */
04746                         sip_handle_t38_reinvite(bridgepeer, p, 1);
04747                      } else { /* Something is wrong with peers udptl struct */
04748                         ast_log(LOG_WARNING, "Strange... The other side of the bridge don't have udptl struct\n");
04749                         dialog_lock(bridge_dialog, TRUE);
04750                         bridge_dialog->t38.state = T38_DISABLED;
04751                         dialog_lock(bridge_dialog, FALSE);
04752                         if (option_debug > 1)
04753                            ast_log(LOG_DEBUG,"T38 state changed to %d on channel %s\n", bridge_dialog->t38.state, bridgepeer->name);
04754                         transmit_final_response(p, "488 Not Acceptable here", req, ast_test_flag(req, SIP_PKT_IGNORE) ? XMIT_UNRELIABLE : XMIT_RELIABLE);
04755                      }
04756                   } else {
04757                      /* The other side is already setup for T.38 most likely so we need to acknowledge this too */
04758                      transmit_response_with_attachment(WITH_T38_SDP, p, "200 OK", req, XMIT_CRITICAL);
04759                      dialogstatechange(p, DIALOG_STATE_CONFIRMED);
04760                      p->t38.state = T38_ENABLED;
04761                      if (option_debug)
04762                         ast_log(LOG_DEBUG, "T38 state changed to %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
04763                   }
04764                } else {
04765                   /* Other side is not a SIP channel */
04766                   transmit_final_response(p, "488 Not Acceptable here", req, ast_test_flag(req, SIP_PKT_IGNORE) ? XMIT_UNRELIABLE : XMIT_RELIABLE);
04767                   p->t38.state = T38_DISABLED;
04768                   if (option_debug > 1)
04769                      ast_log(LOG_DEBUG,"T38 state changed to %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
04770                }
04771             } else {
04772                /* we are not bridged in a call */
04773                transmit_response_with_attachment(WITH_T38_SDP, p, "200 OK", req, XMIT_CRITICAL);
04774                dialogstatechange(p, DIALOG_STATE_CONFIRMED);
04775                p->t38.state = T38_ENABLED;
04776                if (option_debug)
04777                   ast_log(LOG_DEBUG,"T38 state changed to %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
04778             }
04779          } else if (p->t38.state == T38_DISABLED) { /* Channel doesn't have T38 offered or enabled */
04780             int sendok = TRUE;
04781 
04782             /* If we are bridged to a channel that has T38 enabled than this is a case of RTP re-invite after T38 session */
04783             /* so handle it here (re-invite other party to RTP) */
04784             struct ast_channel *bridgepeer = NULL;
04785             struct sip_dialog *bridge_dialog = NULL;
04786             if ((bridgepeer = ast_bridged_channel(p->owner))) {
04787                if (bridgepeer->tech == &sip_tech || bridgepeer->tech == &sip_tech_info) {
04788                   bridge_dialog = (struct sip_dialog*)bridgepeer->tech_pvt;
04789                   /* Does the bridged peer have T38 ? */
04790                   if (bridge_dialog->t38.state == T38_ENABLED) {
04791                      ast_log(LOG_WARNING, "RTP re-invite after T38 session not handled yet !\n");
04792                      /* Insted of this we should somehow re-invite the other side of the bridge to RTP */
04793                      transmit_final_response(p, "488 Not Acceptable here (unsupported)", req, ast_test_flag(req, SIP_PKT_IGNORE) ? XMIT_UNRELIABLE : XMIT_RELIABLE);
04794                      sendok = FALSE;
04795                   } 
04796                   /* No bridged peer with T38 enabled*/
04797                }
04798             } 
04799 
04800             /* This is a normal call and we can accept it - let's rock and roll! */
04801             if (sendok)
04802                transmit_response_with_attachment(WITH_SDP, p, "200 OK", req, XMIT_CRITICAL);
04803             dialogstatechange(p, DIALOG_STATE_CONFIRMED);
04804 
04805          }
04806          break;
04807       default:
04808          ast_log(LOG_WARNING, "Don't know how to handle INVITE in state %d\n", c->_state);
04809          transmit_response(p, "100 Trying", req);
04810          break;
04811       }
04812    } else {
04813       if (p && (p->autokillid == -1)) {
04814          const char *msg;
04815 
04816          if (!p->jointcapability)
04817             msg = "488 Not Acceptable Here (codec error)";
04818          else {
04819             ast_log(LOG_NOTICE, "Unable to create/find SIP channel for this INVITE\n");
04820             msg = "503 Unavailable";
04821          }
04822          transmit_final_response(p, msg, req, ast_test_flag(req, SIP_PKT_IGNORE) ? XMIT_UNRELIABLE : XMIT_RELIABLE);
04823       }
04824    }
04825    return res;
04826 }

static int handle_request_message struct sip_dialog p,
struct sip_request req
[static]
 

Handle incoming MESSAGE request.

Definition at line 4929 of file chan_sip3.c.

References ast_test_flag, ast_verbose(), receive_message(), SIP_PKT_DEBUG, SIP_PKT_IGNORE, transmit_final_response(), and XMIT_UNRELIABLE.

04930 {
04931    if (!ast_test_flag(req, SIP_PKT_IGNORE)) {
04932       if (ast_test_flag(req, SIP_PKT_DEBUG))
04933          ast_verbose("Receiving message!\n");
04934       receive_message(p, req);
04935    } else
04936       transmit_final_response(p, "202 Accepted", req, XMIT_UNRELIABLE);
04937    return 1;
04938 }

static int handle_request_notify struct sip_dialog p,
struct sip_request req,
struct sockaddr_in *  sin,
char *  e
[static]
 

Handle incoming notifications.

Note:
Out of dialog NOTIFY messages are killed in match_or_create_dialog() If implementing VMI support, that needs to change

Definition at line 4046 of file chan_sip3.c.

References ast_log(), DEFAULT_TRANS_TIMEOUT, event, FALSE, get_header(), get_msg_text(), sip_dialog::lastinvite, LOG_NOTICE, LOG_WARNING, option_debug, sip_scheddestroy(), sipdebug, transmit_response(), and TRUE.

04047 {
04048    /* This is mostly a skeleton for future improvements */
04049    /* Mostly created to return proper answers on notifications on outbound REFER's */
04050    int res = 0;
04051    const char *event = get_header(req, "Event");
04052    char *eventid = NULL;
04053    char *sep;
04054 
04055    if( (sep = strchr(event, ';')) ) {  /* XXX bug here - overwriting string ? */
04056       *sep++ = '\0';
04057       eventid = sep;
04058    }
04059    
04060    if (option_debug > 1 && sipdebug)
04061       ast_log(LOG_DEBUG, "Got NOTIFY Event: %s\n", event);
04062 
04063    if (strcmp(event, "refer")) {
04064       /* We don't understand this event. */
04065       /* Here's room to implement incoming voicemail notifications :-) */
04066       transmit_response(p, "489 Bad event", req);
04067       if (!p->lastinvite) 
04068          sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
04069       return -1;
04070    } else {
04071       /* Save nesting depth for now, since there might be other events we will
04072          support in the future */
04073 
04074       /* Handle REFER notifications */
04075 
04076       char buf[1024];
04077       char *cmd, *code;
04078       int respcode;
04079       int success = TRUE;
04080 
04081       /* EventID for each transfer... EventID is basically the REFER cseq 
04082 
04083        We are getting notifications on a call that we transfered
04084        We should hangup when we are getting a 200 OK in a sipfrag
04085        Check if we have an owner of this event */
04086       
04087       /* Check the content type */
04088       if (strncasecmp(get_header(req, "Content-Type"), "message/sipfrag", strlen("message/sipfrag"))) {
04089          /* We need a sipfrag */
04090          transmit_response(p, "400 Bad request", req);
04091          sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
04092          return -1;
04093       }
04094 
04095       /* Get the text of the attachment */
04096       if (get_msg_text(buf, sizeof(buf), req)) {
04097          ast_log(LOG_WARNING, "Unable to retrieve attachment from NOTIFY %s\n", p->callid);
04098          transmit_response(p, "400 Bad request", req);
04099          sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
04100          return -1;
04101       }
04102 
04103       /*
04104       From the RFC...
04105       A minimal, but complete, implementation can respond with a single
04106          NOTIFY containing either the body:
04107                SIP/2.0 100 Trying
04108       
04109          if the subscription is pending, the body:
04110                SIP/2.0 200 OK
04111          if the reference was successful, the body:
04112                SIP/2.0 503 Service Unavailable
04113          if the reference failed, or the body:
04114                SIP/2.0 603 Declined
04115 
04116          if the REFER request was accepted before approval to follow the
04117          reference could be obtained and that approval was subsequently denied
04118          (see Section 2.4.7).
04119       
04120       If there are several REFERs in the same dialog, we need to
04121       match the ID of the event header...
04122       */
04123       if (option_debug > 2)
04124          ast_log(LOG_DEBUG, "* SIP Transfer NOTIFY Attachment: \n---%s\n---\n", buf);
04125       cmd = ast_skip_blanks(buf);
04126       code = cmd;
04127       /* We are at SIP/2.0 */
04128       while(*code && (*code > 32)) {   /* Search white space */
04129          code++;
04130       }
04131       *code++ = '\0';
04132       code = ast_skip_blanks(code);
04133       sep = code;
04134       sep++;
04135       while(*sep && (*sep > 32)) {  /* Search white space */
04136          sep++;
04137       }
04138       *sep++ = '\0';       /* Response string */
04139       respcode = atoi(code);
04140       switch (respcode) {
04141       case 100:   /* Trying: */
04142          /* Don't do anything yet */
04143          break;
04144       case 183:   /* Ringing: */
04145          /* Don't do anything yet */
04146          break;
04147       case 200:   /* OK: The new call is up, hangup this call */
04148          /* Hangup the call that we are replacing */
04149          break;
04150       case 301: /* Moved permenantly */
04151       case 302: /* Moved temporarily */
04152          /* Do we get the header in the packet in this case? */
04153          success = FALSE;
04154          break;
04155       case 503:   /* Service Unavailable: The new call failed */
04156             /* Cancel transfer, continue the call */
04157          success = FALSE;
04158          break;
04159       case 603:   /* Declined: Not accepted */
04160             /* Cancel transfer, continue the current call */
04161          success = FALSE;
04162          break;
04163       }
04164       if (!success) {
04165          ast_log(LOG_NOTICE, "Transfer failed. Sorry. Nothing further to do with this call\n");
04166       }
04167       
04168       /* Confirm that we received this packet */
04169       transmit_response(p, "200 OK", req);
04170       return res;
04171    };
04172 }

static int handle_request_options struct sip_dialog p,
struct sip_request req
[static]
 

Handle incoming OPTIONS request.

Definition at line 4175 of file chan_sip3.c.

References ast_string_field_set, ast_strlen_zero(), build_contact(), context, sip_globals::default_context, DEFAULT_TRANS_TIMEOUT, get_destination(), global, sip_dialog::lastinvite, sip_scheddestroy(), transmit_response_with_attachment(), WITH_ALLOW, and XMIT_UNRELIABLE.

04176 {
04177    int res;
04178 
04179    res = get_destination(p, req);
04180    build_contact(p);
04181    /* XXX Should we authenticate OPTIONS? XXX */
04182    if (ast_strlen_zero(p->context))
04183       ast_string_field_set(p, context, global.default_context);
04184    if (res < 0)
04185       transmit_response_with_attachment(WITH_ALLOW, p, "404 Not Found", req, XMIT_UNRELIABLE);
04186    else 
04187       transmit_response_with_attachment(WITH_ALLOW, p, "200 OK", req, XMIT_UNRELIABLE);
04188    /* Destroy if this OPTIONS was the opening request, but not if
04189       it's in the middle of a normal call flow. */
04190    if (!p->lastinvite)
04191       sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
04192 
04193    return res;
04194 }

static int handle_request_register struct sip_dialog p,
struct sip_request req,
struct sockaddr_in *  sin,
char *  e
[static]
 

Handle incoming REGISTER request.

Definition at line 5212 of file chan_sip3.c.

References append_history, ast_inet_ntoa(), ast_log(), ast_test_flag, ast_verbose(), AUTH_NOT_FOUND, AUTH_SECRET_FAILED, AUTH_UNKNOWN_DOMAIN, AUTH_USERNAME_MISMATCH, check_via(), DEFAULT_TRANS_TIMEOUT, get_header(), LOG_NOTICE, option_debug, register_verify(), set_initreq(), SIP_PKT_DEBUG, and sip_scheddestroy().

05213 {
05214    enum check_auth_result res;
05215 
05216    static int register_counter = 0;
05217 
05218    register_counter++;
05219    if (option_debug > 3)
05220       ast_log(LOG_DEBUG, "-REGISTRATIONS- register counter %d\n", register_counter);
05221 
05222    /* Use this as the basis */
05223    if (ast_test_flag(req, SIP_PKT_DEBUG))
05224       ast_verbose("Using latest REGISTER request as basis request\n");
05225    set_initreq(p, req);
05226    check_via(p, req);
05227    if ((res = register_verify(p, sin, req, e)) < 0) {
05228       const char *reason = "";
05229 
05230       switch (res) {
05231       case AUTH_SECRET_FAILED:
05232          reason = "Wrong password";
05233          break;
05234       case AUTH_USERNAME_MISMATCH:
05235          reason = "Username/auth name mismatch";
05236          break;
05237       case AUTH_NOT_FOUND:
05238          reason = "No matching peer found";
05239          break;
05240       case AUTH_UNKNOWN_DOMAIN:
05241          reason = "Not a local domain";
05242          break;
05243       default:
05244          break;
05245       }
05246       ast_log(LOG_NOTICE, "Registration from '%s' failed for '%s' - %s\n",
05247          get_header(req, "To"), ast_inet_ntoa(sin->sin_addr),
05248          reason);
05249    }
05250    if (res < 1) {
05251       /* Destroy the session, but keep us around for just a bit in case they don't
05252          get our 200 OK */
05253       sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
05254    }
05255    append_history(p, "RegRequest", "%s : Account %s", res ? "Failed": "Succeeded", get_header(req, "To")