Index: channels/chan_sip.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v retrieving revision 1.385 diff -u -r1.385 chan_sip.c --- channels/chan_sip.c 12 May 2004 23:35:50 -0000 1.385 +++ channels/chan_sip.c 13 May 2004 18:23:27 -0000 @@ -86,6 +86,7 @@ #define CALLERID_UNKNOWN "Unknown" +/* --- Choices for DTMF support in SIP channel */ #define SIP_DTMF_RFC2833 (1 << 0) #define SIP_DTMF_INBAND (1 << 1) #define SIP_DTMF_INFO (1 << 2) @@ -98,8 +99,10 @@ #define DEFAULT_FREQ_NOTOK 10 * 1000 /* How often to check, if the host is down... */ #define DEFAULT_RETRANS 1000 /* How frequently to retransmit */ -#define MAX_RETRANS 5 /* Try only 5 times for retransmissions */ +#define MAX_RETRANS 5 /* Try only 5 times for retransmissions */ +/* MYSQL_FRIENDS: Check if peer exists in database and read some configuration + from databse (not all options supported though) */ #ifdef MYSQL_FRIENDS static ast_mutex_t mysqllock = AST_MUTEX_INITIALIZER; static MYSQL *mysql; @@ -137,7 +140,7 @@ static int pedanticsipchecking = 0; -static int autocreatepeer = 0; +static int autocreatepeer = 0; static int relaxdtmf = 0; @@ -174,9 +177,9 @@ static int videosupport = 0; +static int globaldtmfmode = SIP_DTMF_RFC2833; /* DTMF mode default */ static int recordhistory = 0; -static int globaldtmfmode = SIP_DTMF_RFC2833; static char globalmusicclass[MAX_LANGUAGE] = ""; /* Global music on hold class */ static char global_realm[AST_MAX_EXTENSION] = "asterisk"; /* Default realm */ @@ -201,6 +204,7 @@ struct sip_codec_pref *next; } *prefs; +/* sip_request: The data grabbed from the UDP socket */ struct sip_request { char *rlPart1; /* SIP Method Name or "SIP/2.0" protocol version */ char *rlPart2; /* The Request URI or Response Status */ @@ -224,6 +228,7 @@ struct sip_history *next; }; +/* sip_pvt: PVT structures are used for each SIP conversation, ie. a call */ static struct sip_pvt { ast_mutex_t lock; /* Channel private lock */ char callid[80]; /* Global CallID */ @@ -321,6 +326,7 @@ #define FLAG_RESPONSE (1 << 0) #define FLAG_FATAL (1 << 1) +/* sip packet - read in sipsock_read, transmitted in send_request */ struct sip_pkt { struct sip_pkt *next; /* Next packet */ int retrans; /* Retransmission number */ @@ -332,6 +338,7 @@ char data[0]; }; +/* Structure for SIP user data. User's place calls to us */ struct sip_user { /* Users who can access various contexts */ char name[80]; @@ -362,6 +369,7 @@ struct sip_user *next; }; +/* Structure for SIP peer data, we place calls to peers if registred or fixed IP address (host) */ struct sip_peer { char name[80]; char secret[80]; @@ -418,37 +426,41 @@ #define REG_STATE_TIMEOUT 5 #define REG_STATE_NOAUTH 6 +/* sip_registry: Registrations with other SIP proxies */ struct sip_registry { - struct sockaddr_in addr; /* Who we connect to for registration purposes */ - char username[80]; /* Who we are registering as */ - char authuser[80]; /* Who we *authenticate* as */ + struct sockaddr_in addr; /* Who we connect to for registration purposes */ + char username[80]; /* Who we are registering as */ + char authuser[80]; /* Who we *authenticate* as */ char hostname[80]; - char secret[80]; /* Password or key name in []'s */ + char secret[80]; /* Password or key name in []'s */ char md5secret[80]; - char contact[80]; /* Contact extension */ + char contact[80]; /* Contact extension */ char random[80]; - int expire; /* Sched ID of expiration */ - int timeout; /* sched id of sip_reg_timeout */ - int refresh; /* How often to refresh */ - struct sip_pvt *call; /* create a sip_pvt structure for each outbound "registration call" in progress */ + int expire; /* Sched ID of expiration */ + int timeout; /* sched id of sip_reg_timeout */ + int refresh; /* How often to refresh */ + struct sip_pvt *call; /* create a sip_pvt structure for each outbound "registration call" in progress */ int regstate; int callid_valid; /* 0 means we haven't chosen callid for this registry yet. */ char callid[80]; /* Global CallID for this registry */ unsigned int ocseq; /* Sequence number we got to for REGISTERs for this registry */ - struct sockaddr_in us; /* Who the server thinks we are */ + struct sockaddr_in us; /* Who the server thinks we are */ struct sip_registry *next; }; +/*--- The user list: Users and friends ---*/ static struct ast_user_list { struct sip_user *users; ast_mutex_t lock; } userl = { NULL, AST_MUTEX_INITIALIZER }; +/*--- The peer list: Peers and Friends ---*/ static struct ast_peer_list { struct sip_peer *peers; ast_mutex_t lock; } peerl = { NULL, AST_MUTEX_INITIALIZER }; +/*--- The register list: Other SIP proxys we register with and call ---*/ static struct ast_register_list { struct sip_registry *registrations; ast_mutex_t lock; @@ -483,7 +495,6 @@ static int transmit_refer(struct sip_pvt *p, char *dest); static struct sip_peer *temp_peer(char *name); static int do_proxy_auth(struct sip_pvt *p, struct sip_request *req, char *header, char *respheader, char *msg, int init); -/* static char *getsipuri(char *header); */ static void free_old_route(struct sip_route *route); static int build_reply_digest(struct sip_pvt *p, char *orig_header, char *digest, int digest_len); static int update_user_counter(struct sip_pvt *fup, int event); @@ -492,6 +503,7 @@ static int sip_debug_test_addr(struct sockaddr_in *addr); static int sip_debug_test_pvt(struct sip_pvt *p); +/*--- __sip_xmit: Transmit SIP message ---*/ static int __sip_xmit(struct sip_pvt *p, char *data, int len) { int res; @@ -507,6 +519,8 @@ static void sip_destroy(struct sip_pvt *p); +/*--- ast_sip_ouraddrfor: NAT fix - decide which IP address to use for ASterisk server? ---*/ +/* Only used for outbound registrations */ static int ast_sip_ouraddrfor(struct in_addr *them, struct in_addr *us) { /* @@ -562,6 +576,7 @@ return 0; } +/*--- retrans_pkt: Retransmit SIP message if no answer ---*/ static int retrans_pkt(void *data) { struct sip_pkt *pkt=data; @@ -606,6 +621,7 @@ return res; } +/*--- __sip_reliable_xmit: transmit packet with retransmits ---*/ static int __sip_reliable_xmit(struct sip_pvt *p, int seqno, int resp, char *data, int len, int fatal) { struct sip_pkt *pkt; @@ -633,6 +649,7 @@ return 0; } +/*--- __sip_autodestruct: Kill a call (called by scheduler) ---*/ static int __sip_autodestruct(void *data) { struct sip_pvt *p = data; @@ -648,6 +665,7 @@ return 0; } +/*--- sip_scheddestroy: Schedule destruction of SIP call ---*/ static int sip_scheddestroy(struct sip_pvt *p, int ms) { char tmp[80]; @@ -663,6 +681,7 @@ return 0; } +/*--- sip_cancel_destroy: Cancel destruction of SIP call ---*/ static int sip_cancel_destroy(struct sip_pvt *p) { if (p->autokillid > -1) @@ -672,6 +691,7 @@ return 0; } +/*--- __sip_ack: Acknowledges receipt of a packet and stops retransmission ---*/ static int __sip_ack(struct sip_pvt *p, int seqno, int resp) { struct sip_pkt *cur, *prev = NULL; @@ -703,6 +723,7 @@ return res; } +/*--- __sip_semi_ack: Acks receipt of packet, keep it around (used for provisional responses) ---*/ static int __sip_semi_ack(struct sip_pvt *p, int seqno, int resp) { struct sip_pkt *cur; @@ -723,6 +744,7 @@ return res; } +/*--- send_response: Transmit response on SIP request---*/ static int send_response(struct sip_pvt *p, struct sip_request *req, int reliable, int seqno) { int res; @@ -744,6 +766,7 @@ return res; } +/*--- send_request: Send SIP Request to the other part of the dialogue ---*/ static int send_request(struct sip_pvt *p, struct sip_request *req, int reliable, int seqno) { int res; @@ -763,6 +786,7 @@ return res; } +/*--- ditch_braces: Pick out text in braces from character string ---*/ static char *ditch_braces(char *tmp) { char *c = tmp; @@ -780,6 +804,8 @@ return c; } +/*--- sip_sendtext: Send SIP MESSAGE text within a call ---*/ +/* Called from PBX core text message functions */ static int sip_sendtext(struct ast_channel *ast, char *text) { struct sip_pvt *p = ast->pvt->pvt; @@ -797,6 +823,8 @@ #ifdef MYSQL_FRIENDS +/*--- mysql_update_peer: Update peer from database ---*/ +/* This function adds registration state to database */ static void mysql_update_peer(char *peer, struct sockaddr_in *sin, char *username, int expiry) { if (mysql && (strlen(peer) < 128)) { @@ -819,6 +847,7 @@ } } +/*--- mysql_peer: Get peer from database ---*/ static struct sip_peer *mysql_peer(char *peer, struct sockaddr_in *sin) { struct sip_peer *p; @@ -898,6 +927,7 @@ } #endif /* MYSQL_FRIENDS */ +/*--- update_peer: Update peer data in database (if used) ---*/ static void update_peer(struct sip_peer *p, int expiry) { #ifdef MYSQL_FRIENDS @@ -907,6 +937,7 @@ return; } +/*--- find_peer: Locate peer by name or ip address */ static struct sip_peer *find_peer(char *peer, struct sockaddr_in *sin) { struct sip_peer *p = NULL; @@ -942,6 +973,7 @@ return(p); } +/*--- find_user: Locate user by name */ static struct sip_user *find_user(char *name) { struct sip_user *u = NULL; @@ -957,8 +989,8 @@ return(u); } +/*--- sip_debug_test_addr: See if we pass debug IP filter */ static int sip_debug_test_addr(struct sockaddr_in *addr) { - /* See if we pass debug IP filter */ if (sipdebug == 0) return 0; if (debugaddr.sin_addr.s_addr) { if (((ntohs(debugaddr.sin_port) != 0) && @@ -973,6 +1005,9 @@ return (sipdebug && sip_debug_test_addr((p->nat ? &p->recv : &p->sa))); } +/*--- create_addr: create address structure from peer definition ---*/ +/* Or, if peer not found, find it in the global DNS */ +/* returns TRUE on failure, FALSE on success */ static int create_addr(struct sip_pvt *r, char *peer) { struct hostent *hp; @@ -1094,6 +1129,7 @@ } } +/*--- auto_congest: Scheduled congestion on a call ---*/ static int auto_congest(void *nothing) { struct sip_pvt *p = nothing; @@ -1110,6 +1146,7 @@ return 0; } +/*--- sip_prefs_free: Free codec list in preference structure ---*/ static void sip_prefs_free(void) { struct sip_codec_pref *cur, *next; @@ -1122,6 +1159,7 @@ prefs = NULL; } +/*--- sip_pref_remove: Remove codec from pref list ---*/ static void sip_pref_remove(int format) { struct sip_codec_pref *cur, *prev=NULL; @@ -1140,6 +1178,7 @@ } } +/*--- sip_pref_append: Append codec to list ---*/ static int sip_pref_append(int format) { struct sip_codec_pref *cur, *tmp; @@ -1159,6 +1198,7 @@ return 0; } +/*--- sip_codec_choose: Pick a codec ---*/ static int sip_codec_choose(int formats) { struct sip_codec_pref *cur; @@ -1172,6 +1212,8 @@ return ast_best_codec(formats); } +/*--- sip_call: Initiate SIP call from PBX ---*/ +/* used from the dial() application */ static int sip_call(struct ast_channel *ast, char *dest, int timeout) { int res; @@ -1220,6 +1262,7 @@ return res; } +/*--- __sip_destroy: Execute destrucion of call structure, release memory---*/ static void __sip_destroy(struct sip_pvt *p, int lockowner) { struct sip_pvt *cur, *prev = NULL; @@ -1298,6 +1341,8 @@ } } +/*--- update_user_counter: Handle incominglimit and outgoinglimit for SIP users ---*/ +/* Note: This is going to be replaced by app_groupcount */ static int update_user_counter(struct sip_pvt *fup, int event) { char name[256] = ""; @@ -1362,6 +1407,7 @@ return 0; } +/*--- sip_destroy: Destroy SIP call structure ---*/ static void sip_destroy(struct sip_pvt *p) { ast_mutex_lock(&iflock); @@ -1369,12 +1415,21 @@ ast_mutex_unlock(&iflock); } + static int transmit_response_reliable(struct sip_pvt *p, char *msg, struct sip_request *req, int fatal); static int hangup_sip2cause(int cause) { - switch(cause) - { +/* Possible values from causes.h + AST_CAUSE_NOTDEFINED AST_CAUSE_NORMAL AST_CAUSE_BUSY + AST_CAUSE_FAILURE AST_CAUSE_CONGESTION AST_CAUSE_UNALLOCATED +*/ + + switch(cause) { + case 404: /* Not found */ + return AST_CAUSE_UNALLOCATED; + case 483: /* Too many hops */ + return AST_CAUSE_FAILURE; case 486: return AST_CAUSE_BUSY; default: @@ -1388,6 +1443,10 @@ { switch(cause) { + case AST_CAUSE_FAILURE: + return "500 Server internal failure"; + case AST_CAUSE_CONGESTION: + return "503 Service Unavailable"; case AST_CAUSE_BUSY: return "486 Busy"; default: @@ -1397,6 +1456,7 @@ return 0; } +/*--- sip_hangup: Hangup SIP call */ static int sip_hangup(struct ast_channel *ast) { struct sip_pvt *p = ast->pvt->pvt; @@ -1480,6 +1540,7 @@ return 0; } +/*--- sip_answer: Answer SIP call , send 200 OK on Invite */ static int sip_answer(struct ast_channel *ast) { int res = 0,fmt; @@ -1508,6 +1569,7 @@ return res; } +/*--- sip_write: Send response, support audio media ---*/ static int sip_write(struct ast_channel *ast, struct ast_frame *frame) { struct sip_pvt *p = ast->pvt->pvt; @@ -1551,6 +1613,8 @@ return res; } +/*--- sip_fixup: Fix up a channel: If a channel is consumed, this is called. + Basically update any ->owner links ----*/ static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan) { struct sip_pvt *p = newchan->pvt->pvt; @@ -1565,6 +1629,8 @@ return 0; } +/*--- sip_senddigit: Send DTMF character on SIP channel */ +/* within one call, we're able to transmit in many methods simultaneously */ static int sip_senddigit(struct ast_channel *ast, char digit) { struct sip_pvt *p = ast->pvt->pvt; @@ -1580,6 +1646,8 @@ return 0; } + +/*--- sip_transfer: Transfer SIP call */ static int sip_transfer(struct ast_channel *ast, char *dest) { struct sip_pvt *p = ast->pvt->pvt; @@ -1588,6 +1656,9 @@ return res; } +/*--- sip_indicate: Play indication to user */ +/* With SIP a lot of indications is sent as messages, letting the device play + the indication - busy signal, congestion etc */ static int sip_indicate(struct ast_channel *ast, int condition) { struct sip_pvt *p = ast->pvt->pvt; @@ -1637,6 +1708,8 @@ +/*--- sip_new: Initiate a call in the SIP channel */ +/* called from sip_request_call (calls from the pbx ) */ static struct ast_channel *sip_new(struct sip_pvt *i, int state, char *title) { struct ast_channel *tmp; @@ -1756,9 +1829,14 @@ { "Content-Length", "l" }, { "Subject", "s" }, { "To", "t" }, + { "Supported", "k" }, + { "Refer-To", "r" }, + { "Allow-Events", "u" }, + { "Event", "o" }, { "Via", "v" }, }; +/*--- get_sdp_by_line: Reads one line of SIP message body */ static char* get_sdp_by_line(char* line, char *name, int nameLen) { if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') { char* r = line + nameLen + 1; @@ -1769,6 +1847,8 @@ return ""; } +/*--- get_sdp: Gets all kind of SIP message bodies, including SDP, + but the name wrongly applies _only_ sdp */ static char *get_sdp(struct sip_request *req, char *name) { int x; int len = strlen(name); @@ -1781,6 +1861,7 @@ return ""; } + static void sdpLineNum_iterator_init(int* iterator) { *iterator = 0; } @@ -1820,12 +1901,14 @@ return ""; } +/*--- get_header: Get header from SIP request ---*/ static char *get_header(struct sip_request *req, char *name) { int start = 0; return __get_header(req, name, &start); } +/*--- sip_rtp_read: Read RTP from network ---*/ static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p) { /* Retrieve audio/etc from channel. Assumes p->lock is already held. */ @@ -1833,16 +1916,16 @@ static struct ast_frame null_frame = { AST_FRAME_NULL, }; switch(ast->fdno) { case 0: - f = ast_rtp_read(p->rtp); + f = ast_rtp_read(p->rtp); /* RTP Audio */ break; case 1: - f = ast_rtcp_read(p->rtp); + f = ast_rtcp_read(p->rtp); /* RTCP Control Channel */ break; case 2: - f = ast_rtp_read(p->vrtp); + f = ast_rtp_read(p->vrtp); /* RTP Video */ break; case 3: - f = ast_rtcp_read(p->vrtp); + f = ast_rtcp_read(p->vrtp); /* RTCP Control Channel for video */ break; default: f = &null_frame; @@ -1869,6 +1952,7 @@ return f; } +/*--- sip_read: Read SIP RTP from channel */ static struct ast_frame *sip_read(struct ast_channel *ast) { struct ast_frame *fr; @@ -1879,6 +1963,7 @@ return fr; } +/*--- build_callid: Build SIP CALLID header ---*/ static void build_callid(char *callid, int len, struct in_addr ourip) { int res; @@ -1894,6 +1979,7 @@ snprintf(callid, len, "@%s", inet_ntoa(ourip)); } +/*--- sip_alloc: Allocate SIP_PVT structure and set defaults ---*/ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useglobalnat) { struct sip_pvt *p; @@ -1965,6 +2051,8 @@ return p; } +/*--- find_call: Connect incoming SIP message to current call or create new call structure */ +/* Called by handle_request ,sipsock_read */ static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin) { struct sip_pvt *p; @@ -2031,6 +2119,7 @@ return p; } +/*--- sip_register: Parse register=> line in sip.conf and add to registry */ static int sip_register(char *value, int lineno) { struct sip_registry *reg; @@ -2113,6 +2202,8 @@ return 0; } +/*--- lws2sws: Parse multiline SIP headers into one header */ +/* This is enabled if pedanticsipchecking is enabled */ static int lws2sws(char *msgbuf, int len) { int h = 0, t = 0; @@ -2158,6 +2249,7 @@ return t; } +/*--- parse: Parse a SIP message ----*/ static void parse(struct sip_request *req) { /* Divide fields by NULL's */ @@ -2224,6 +2316,7 @@ ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c); } +/*--- process_sdp: Process SIP SDP ---*/ static int process_sdp(struct sip_pvt *p, struct sip_request *req) { char *m; @@ -2381,6 +2474,7 @@ } +/*--- add_header: Add header to SIP message */ static int add_header(struct sip_request *req, char *var, char *value) { if (req->len >= sizeof(req->data) - 4) { @@ -2403,6 +2497,7 @@ return 0; } +/*--- add_blank_header: Add blank header to SIP message */ static int add_blank_header(struct sip_request *req) { if (req->len >= sizeof(req->data) - 4) { @@ -2425,6 +2520,7 @@ return 0; } +/*--- add_line: Add content (not header) to SIP message */ static int add_line(struct sip_request *req, char *line) { if (req->len >= sizeof(req->data) - 4) { @@ -2448,6 +2544,7 @@ return 0; } +/*--- copy_header: Copy one header field from one request to another */ static int copy_header(struct sip_request *req, struct sip_request *orig, char *field) { char *tmp; @@ -2460,6 +2557,7 @@ return -1; } +/*--- copy_all_header: Copy all headers from one request to another ---*/ static int copy_all_header(struct sip_request *req, struct sip_request *orig, char *field) { char *tmp; @@ -2477,6 +2575,7 @@ return copied ? 0 : -1; } +/*--- copy_via_headers: Copy SIP VIA Headers from one request to another ---*/ static int copy_via_headers(struct sip_pvt *p, struct sip_request *req, struct sip_request *orig, char *field) { char *tmp; @@ -2513,7 +2612,7 @@ return 0; } -/* Add Route: header into request per learned route */ +/*--- add_route: Add route header into request per learned route ---*/ static void add_route(struct sip_request *req, struct sip_route *route) { char r[256], *p; @@ -2539,6 +2638,7 @@ add_header(req, "Route", r); } +/*--- set_destination: Set destination from SIP URI ---*/ static void set_destination(struct sip_pvt *p, char *uri) { char *h, *maddr, hostname[256]; @@ -2598,6 +2698,7 @@ ast_verbose("set_destination: set destination to %s, port %d\n", inet_ntoa(p->sa.sin_addr), port); } +/*--- init_resp: Initialize SIP response, based on SIP request ---*/ static int init_resp(struct sip_request *req, char *resp, struct sip_request *orig) { /* Initialize a response */ @@ -2615,6 +2716,7 @@ return 0; } +/*--- init_req: Initialize SIP request ---*/ static int init_req(struct sip_request *req, char *resp, char *recip) { /* Initialize a response */ @@ -2632,6 +2734,7 @@ return 0; } + static int respprep(struct sip_request *resp, struct sip_pvt *p, char *msg, struct sip_request *req) { char newto[256] = "", *ot; @@ -2771,15 +2874,19 @@ return send_response(p, &resp, reliable, seqno); } +/*--- transmit_response: Transmit response, no retransmits */ static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req) { return __transmit_response(p, msg, req, 0); } + +/*--- transmit_response: Transmit response, Make sure you get a reply */ static int transmit_response_reliable(struct sip_pvt *p, char *msg, struct sip_request *req, int fatal) { return __transmit_response(p, msg, req, fatal ? 2 : 1); } +/*--- append_date: Append date to SIP message ---*/ static void append_date(struct sip_request *req) { char tmpdat[256]; @@ -2791,6 +2898,7 @@ add_header(req, "Date", tmpdat); } +/*--- transmit_response_with_date: Append date and content length before transmitting response ---*/ static int transmit_response_with_date(struct sip_pvt *p, char *msg, struct sip_request *req) { struct sip_request resp; @@ -2801,6 +2909,7 @@ return send_response(p, &resp, 0, 0); } +/*--- transmit_response_with_allow: Append Accept header, content length before transmitting response ---*/ static int transmit_response_with_allow(struct sip_pvt *p, char *msg, struct sip_request *req, int reliable) { struct sip_request resp; @@ -2811,6 +2920,7 @@ return send_response(p, &resp, reliable, 0); } +/* transmit_response_with_auth: Respond with authorization request */ static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_request *req, char *randdata, int reliable) { struct sip_request resp; @@ -2828,6 +2938,7 @@ return send_response(p, &resp, reliable, seqno); } +/*--- add_text: Add text body to SIP message ---*/ static int add_text(struct sip_request *req, char *text) { /* XXX Convert \n's to \r\n's XXX */ @@ -2840,6 +2951,8 @@ return 0; } +/*--- add_digit: add DTMF INFO tone to sip message ---*/ +/* Always adds default duration 250 ms, regardless of what came in over the line */ static int add_digit(struct sip_request *req, char digit) { char tmp[256]; @@ -2854,6 +2967,7 @@ return 0; } +/*--- add_sdp: Add Session Description Protocol message ---*/ static int add_sdp(struct sip_request *resp, struct sip_pvt *p, struct ast_rtp *rtp, struct ast_rtp *vrtp) { int len; @@ -3031,6 +3145,7 @@ return 0; } +/*--- copy_request: copy SIP request (mostly used to save request for responses) ---*/ static void copy_request(struct sip_request *dst,struct sip_request *src) { long offset; @@ -3045,6 +3160,7 @@ dst->line[x] += offset; } +/*--- transmit_response_with_sdp: Used for 200 OK ---*/ static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, int retrans) { struct sip_request resp; @@ -3058,6 +3174,7 @@ return send_response(p, &resp, retrans, seqno); } +/*--- determine_firstline_parts: parse first line of incoming SIP request */ static int determine_firstline_parts( struct sip_request *req ) { char *e, *cmd; @@ -3117,6 +3234,9 @@ return 1; } +/* transmit_reinvite_with_sdp: Transmit reinvite with SDP :-) ---*/ +/* A re-invite is basically a new INVITE with the same CALL-ID and TAG as the + INVITE that opened the SIP dialogue */ static int transmit_reinvite_with_sdp(struct sip_pvt *p, struct ast_rtp *rtp, struct ast_rtp *vrtp) { struct sip_request req; @@ -3138,6 +3258,7 @@ return send_request(p, &req, 1, p->ocseq); } +/*--- extract_uri: Check Contact: URI of SIP message ---*/ static void extract_uri(struct sip_pvt *p, struct sip_request *req) { char stripped[256]=""; @@ -3158,6 +3279,7 @@ strncpy(p->uri, c, sizeof(p->uri) - 1); } +/*--- build_contact: Build contact header - the contact header we send out ---*/ static void build_contact(struct sip_pvt *p) { /* Construct Contact: header */ @@ -3167,6 +3289,7 @@ snprintf(p->our_contact, sizeof(p->our_contact), "", p->exten, inet_ntoa(p->ourip)); } +/*--- initreqprep: Initiate SIP request to peer/user ---*/ static void initreqprep(struct sip_request *req, struct sip_pvt *p, char *cmd, char *vxml_url) { char invite[256]; @@ -3240,6 +3363,8 @@ add_header(req, "User-Agent", "Asterisk PBX"); } + +/*--- transmit_invite: Build REFER/INVITE/OPTIONS message and trasmit it ---*/ static int transmit_invite(struct sip_pvt *p, char *cmd, int sdp, char *auth, char *authheader, char *vxml_url, char *distinctive_ring, int init) { struct sip_request req; @@ -3262,7 +3387,7 @@ add_header(&req, "Referred-By", p->referred_by); } - if (distinctive_ring) + if (distinctive_ring && !ast_strlen_zero(distinctive_ring)) { add_header(&req, "Alert-info",distinctive_ring); } @@ -3286,6 +3411,7 @@ return send_request(p, &req, init ? 2 : 1, p->ocseq); } +/*--- transmit_state_notify: Used in the SUBSCRIBE notification subsystem ----*/ static int transmit_state_notify(struct sip_pvt *p, int state, int full) { char tmp[4000]; @@ -3374,6 +3500,12 @@ return send_request(p, &req, 1, p->ocseq); } +/*--- transmit_notify: Notify user of messages waiting in voicemail ---*/ +/* Notification only works for registred peers with mailbox= definitions + * in sip.conf + * We use the SIP Event package message-summary + * MIME type defaults to "application/simple-message-summary"; + */ static int transmit_notify(struct sip_pvt *p, int newmsgs, int oldmsgs) { struct sip_request req; @@ -3405,6 +3537,7 @@ static int transmit_register(struct sip_registry *r, char *cmd, char *auth, char *authheader); +/*--- sip_reregister: Update registration with SIP Proxy---*/ static int sip_reregister(void *data) { /* if we are here, we know that we need to reregister. */ @@ -3416,7 +3549,7 @@ return 0; } - +/*--- __sip_do_register: Register with SIP proxy ---*/ static int __sip_do_register(struct sip_registry *r) { int res; @@ -3424,6 +3557,7 @@ return res; } +/*--- sip_reg_timeout: Registration timeout, register again */ static int sip_reg_timeout(void *data) { /* if we are here, our registration timed out, so we'll just do it over */ @@ -3447,6 +3581,7 @@ return 0; } +/*--- transmit_register: Transmit register to SIP proxy ---*/ static int transmit_register(struct sip_registry *r, char *cmd, char *auth, char *authheader) { struct sip_request req; @@ -3563,6 +3698,7 @@ return send_request(p, &req, 2, p->ocseq); } +/*--- transmit_message_with_text: Transmit text with SIP MESSAGE method ---*/ static int transmit_message_with_text(struct sip_pvt *p, char *text) { struct sip_request req; @@ -3571,6 +3707,7 @@ return send_request(p, &req, 1, p->ocseq); } +/*--- transmit_refer: Transmit SIP REFER message ---*/ static int transmit_refer(struct sip_pvt *p, char *dest) { struct sip_request req; @@ -3611,6 +3748,8 @@ return send_request(p, &req, 1, p->ocseq); } +/*--- transmit_info_with_digit: Send SIP INFO dtmf message, see Cisco documentation on cisco.co +m ---*/ static int transmit_info_with_digit(struct sip_pvt *p, char digit) { struct sip_request req; @@ -3619,6 +3758,7 @@ return send_request(p, &req, 1, p->ocseq); } +/*--- transmit_request: transmit generic SIP request ---*/ static int transmit_request(struct sip_pvt *p, char *msg, int seqno, int reliable, int newbranch) { struct sip_request resp; @@ -3628,6 +3768,7 @@ return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq); } +/*--- transmit_request_with_auth: Transmit SIP request, auth added ---*/ static int transmit_request_with_auth(struct sip_pvt *p, char *msg, int seqno, int reliable, int newbranch) { struct sip_request resp; @@ -3645,6 +3786,7 @@ return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq); } +/*--- expire_register: Expire registration of SIP peer ---*/ static int expire_register(void *data) { struct sip_peer *p = data; @@ -3661,6 +3803,7 @@ static int sip_poke_peer(struct sip_peer *peer); +/*--- reg_source_db: Save registration in Asterisk DB ---*/ static void reg_source_db(struct sip_peer *p) { char data[80]; @@ -3701,6 +3844,7 @@ } } +/*--- parse_contact: Parse contact header and save registration ---*/ static int parse_contact(struct sip_pvt *pvt, struct sip_peer *p, struct sip_request *req) { char contact[80]= ""; @@ -3818,6 +3962,7 @@ return 0; } +/*--- free_old_route: Remove route from route list ---*/ static void free_old_route(struct sip_route *route) { struct sip_route *next; @@ -3828,6 +3973,7 @@ } } +/*--- list_route: List all routes - mostly for debugging ---*/ static void list_route(struct sip_route *route) { if (!route) { @@ -3840,6 +3986,7 @@ } } +/*--- build_route: Build route headers ---*/ static void build_route(struct sip_pvt *p, struct sip_request *req, int backwards) { struct sip_route *thishop, *head, *tail; @@ -3935,6 +4082,7 @@ list_route(p->route); } +/*--- md5_hash: Produce MD5 hash of value. Used for authentication ---*/ static void md5_hash(char *output, char *input) { struct MD5Context md5; @@ -3949,6 +4097,9 @@ ptr += sprintf(ptr, "%2.2x", digest[x]); } +/*--- check_auth: Check user authorization from peer definition ---*/ +/* Some actions, like REGISTER and INVITEs from peers require + authentication (if peer have secret set) */ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata, int randlen, char *username, char *secret, char *md5secret, char *method, char *uri, int reliable, int ignore) { int res = -1; @@ -4051,6 +4202,7 @@ return res; } +/*--- cb_extensionstate: Part of thte SUBSCRIBE support subsystem ---*/ static int cb_extensionstate(char *context, char* exten, int state, void *data) { struct sip_pvt *p = data; @@ -4067,6 +4219,7 @@ return 0; } +/*--- register_verify: Verify registration of user */ static int register_verify(struct sip_pvt *p, struct sockaddr_in *sin, struct sip_request *req, char *uri, int ignore) { int res = -1; @@ -4163,6 +4316,7 @@ return res; } +/*--- get_rdnis: get referring dnis ---*/ static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq) { char tmp[256] = "", *c, *a; @@ -4189,6 +4343,8 @@ return 0; } + +/*--- get_destination: Find out who the call is for --*/ static int get_destination(struct sip_pvt *p, struct sip_request *oreq) { char tmp[256] = "", *c, *a; @@ -4252,6 +4408,7 @@ return -1; } +/*--- hex2int: Convert hex code to integer ---*/ static int hex2int(char a) { if ((a >= '0') && (a <= '9')) { @@ -4264,6 +4421,7 @@ return 0; } +/*--- get_refer_info: Call transfer support (new standard) ---*/ static int get_refer_info(struct sip_pvt *p, struct sip_request *oreq) { char tmp[256] = "", *c, *a; @@ -4382,6 +4540,7 @@ return -1; } +/*--- get_also_info: Call transfer support (old way, depreciated)--*/ static int get_also_info(struct sip_pvt *p, struct sip_request *oreq) { char tmp[256] = "", *c, *a; @@ -4424,6 +4583,7 @@ return -1; } +/*--- check_via: check Via: headers ---*/ static int check_via(struct sip_pvt *p, struct sip_request *req) { char via[256] = ""; @@ -4469,6 +4629,8 @@ } return 0; } + +/*--- get_calleridname: Get caller id name from SIP headers ---*/ static char *get_calleridname(char *input,char *output) { char *end = strchr(input,'<'); @@ -4496,6 +4658,8 @@ } return output; } + +/*--- check_user: Check if matching user or peer is defined ---*/ static int check_user(struct sip_pvt *p, struct sip_request *req, char *cmd, char *uri, int reliable, struct sockaddr_in *sin, int ignore) { struct sip_user *user; @@ -4650,6 +4814,7 @@ return res; } +/*--- get_msg_text: Get text out of a SIP MESSAGE ---*/ static int get_msg_text(char *buf, int len, struct sip_request *req) { int x; @@ -4669,6 +4834,9 @@ return 0; } + +/*--- receive_message: Receive SIP MESSAGE method messages ---*/ +/* we handle messages within current calls currently */ static void receive_message(struct sip_pvt *p, struct sip_request *req) { char buf[1024]; @@ -4690,6 +4858,8 @@ } } +/*--- sip_show_inuse: CLI Command to show calls within limits set by + outgoinglimit and incominglimit ---*/ static int sip_show_inuse(int fd, int argc, char *argv[]) { #define FORMAT "%-15.15s %-15.15s %-15.15s %-15.15s %-15.15s\n" #define FORMAT2 "%-15.15s %-15.15s %-15.15s %-15.15s %-15.15s\n" @@ -4721,8 +4891,8 @@ #undef FORMAT #undef FORMAT2 } - - + +/*--- sip_show_users: CLI Command 'SIP Show Users' ---*/ static int sip_show_users(int fd, int argc, char *argv[]) { #define FORMAT "%-15.15s %-15.15s %-15.15s %-15.15s %-5.5s\n" @@ -4740,6 +4910,7 @@ #undef FORMAT } +/*--- sip_show_peers: CLI Show Peers command */ static int sip_show_peers(int fd, int argc, char *argv[]) { #define FORMAT2 "%-15.15s %-15.15s %s %s %s %-15.15s %-8s %-10s\n" @@ -4949,6 +5120,7 @@ return RESULT_SUCCESS; } +/*--- sip_show_registry: Show SIP Registry (registrations with other SIP proxies ---*/ static int sip_show_registry(int fd, int argc, char *argv[]) { #define FORMAT2 "%-20.20s %-12.12s %8.8s %-20.20s\n" @@ -5028,6 +5200,7 @@ #undef FORMAT3 } +/*--- complete_sipch: Support routine for 'sip show channel' CLI ---*/ static char *complete_sipch(char *line, char *word, int pos, int state) { int which=0; @@ -5150,6 +5323,8 @@ } +/*--- receive_info: Receive SIP INFO Message ---*/ +/* Doesn't read the duration of the DTMF signal */ static void receive_info(struct sip_pvt *p, struct sip_request *req) { char buf[1024] = ""; @@ -5212,6 +5387,7 @@ return; } +/*--- sip_do_debug: Enable SIP Debugging in CLI ---*/ static int sip_do_debug_ip(int fd, int argc, char *argv[]) { struct hostent *hp; @@ -5310,6 +5486,7 @@ return RESULT_SUCCESS; } +/*--- sip_no_debug: Disable SIP Debugging in CLI ---*/ static int sip_no_debug(int fd, int argc, char *argv[]) { if (argc != 3) @@ -5321,6 +5498,7 @@ static int reply_digest(struct sip_pvt *p, struct sip_request *req, char *header, char *respheader, char *digest, int digest_len); +/*--- do_register_auth: Challenge for registration ---*/ static int do_register_auth(struct sip_pvt *p, struct sip_request *req, char *header, char *respheader) { char digest[1024]; p->authtries++; @@ -5332,6 +5510,7 @@ return transmit_register(p->registry,"REGISTER",digest, respheader); } +/*--- do_proxy_auth: Challenge user ---*/ static int do_proxy_auth(struct sip_pvt *p, struct sip_request *req, char *header, char *respheader, char *msg, int init) { char digest[1024]; p->authtries++; @@ -5343,6 +5522,9 @@ return transmit_invite(p,msg,!strcasecmp(msg, "INVITE"),digest, respheader, NULL,NULL, init); } +/*--- reply_digest: reply to authentication for outbound registrations ---*/ +/* This is used for register= servers in sip.conf, SIP proxies we register + with for receiving calls from. */ static int reply_digest(struct sip_pvt *p, struct sip_request *req, char *header, char *orig_header, char *digest, int digest_len) { char tmp[512] = ""; @@ -5436,6 +5618,9 @@ return 0; } +/*--- build_reply_digest: Build reply digest ---*/ +/* Build digest challenge for authentication of peers (for registration) + and users (for calls). Also used for authentication of CANCEL and BYE */ static int build_reply_digest(struct sip_pvt *p, char* orig_header, char* digest, int digest_len) { char a1[256]; @@ -5590,6 +5775,7 @@ return 0; } +/*--- parse_moved_contact: Parse 302 Moved temporalily response */ static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req) { char tmp[256] = ""; @@ -5606,6 +5792,7 @@ strncpy(p->owner->call_forward, s, sizeof(p->owner->call_forward) - 1); } +/*--- handle_response: Handle SIP response in dialogue ---*/ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int ignore) { char *to; @@ -5934,6 +6121,7 @@ } } +/*--- attempt_transfer: Attempt transfer of SIP call ---*/ static int attempt_transfer(struct sip_pvt *p1, struct sip_pvt *p2) { if (!p1->owner || !p2->owner) { @@ -5969,6 +6157,8 @@ return 0; } +/*--- handle_request: Handle SIP requests (methods) ---*/ +/* this is where all incoming requests go first */ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int *recount) { /* Called with p->lock held, as well as p->owner->lock if appropriate, keeping things @@ -6437,6 +6627,8 @@ return 0; } +/*--- sipsock_read: Read data from SIP socket ---*/ +/* Successful messages is connected to SIP call and forwarded to handle_request() */ static int sipsock_read(int *id, int fd, short events, void *ignore) { struct sip_request req; @@ -6494,6 +6686,7 @@ return 1; } +/*--- sip_send_mwi_to_peer: Send message waiting indication ---*/ static int sip_send_mwi_to_peer(struct sip_peer *peer) { /* Called with peerl lock, but releases it */ @@ -6538,6 +6731,7 @@ return 0; } +/*--- do_monitor: The SIP monitoring thread ---*/ static void *do_monitor(void *data) { int res; @@ -6631,6 +6825,7 @@ } +/*--- restart_monitor: Start the channel monitor thread ---*/ static int restart_monitor(void) { pthread_attr_t attr; @@ -6663,6 +6858,7 @@ return 0; } +/*--- sip_poke_noanswer: No answer to Qualify poke ---*/ static int sip_poke_noanswer(void *data) { struct sip_peer *peer = data; @@ -6680,6 +6876,7 @@ return 0; } +/*--- sip_poke_peer: Check availability of peer, also keep NAT open ---*/ static int sip_poke_peer(struct sip_peer *peer) { struct sip_pvt *p; @@ -6730,6 +6927,7 @@ return 0; } +/*--- sip_devicestate: Part of PBX channel interface ---*/ static int sip_devicestate(void *data) { char *ext, *host; @@ -6774,6 +6972,8 @@ return res; } +/*--- sip_request: PBX interface function -build SIP pvt structure ---*/ +/* SIP calls initiated by the PBX arrive here */ static struct ast_channel *sip_request(char *type, int format, void *data) { int oldformat; @@ -6842,6 +7042,7 @@ return tmpc; } +/*--- build_user: Initiate a SIP user structure from sip.conf ---*/ static struct sip_user *build_user(char *name, struct ast_variable *v) { struct sip_user *user; @@ -6955,6 +7156,7 @@ return user; } +/*--- temp_peer: Create temporary peer (used in autocreatepeer mode) ---*/ static struct sip_peer *temp_peer(char *name) { struct sip_peer *peer; @@ -6980,6 +7182,7 @@ return peer; } +/*--- build_peer: Build peer from config file ---*/ static struct sip_peer *build_peer(char *name, struct ast_variable *v) { struct sip_peer *peer; @@ -7162,6 +7365,7 @@ return peer; } +/*--- reload_config: Re-read SIP.conf config file ---*/ static int reload_config(void) { struct ast_config *cfg; @@ -7478,6 +7682,8 @@ static char *synopsis_dtmfmode = "Change the dtmfmode for a SIP call"; static char *descrip_dtmfmode = "SIPDtmfMode(inband|info|rfc2833): Changes the dtmfmode for a SIP call\n"; static char *app_dtmfmode = "SIPDtmfMode"; + +/*--- sip_dtmfmode: change the DTMFmode for a SIP call (application) ---*/ static int sip_dtmfmode(struct ast_channel *chan, void *data) { struct sip_pvt *p; @@ -7535,6 +7741,8 @@ get_codec: sip_get_codec, }; +/*--- delete_users: Delete all registred users ---*/ +/* Also, check registations with other SIP proxies */ static void delete_users(void) { struct sip_user *user, *userlast; @@ -7581,6 +7789,7 @@ ast_mutex_unlock(&peerl.lock); } +/*--- prune_peers: Delete all peers marked for deletion ---*/ static void prune_peers(void) { /* Prune peers who still are supposed to be deleted */ @@ -7609,6 +7818,7 @@ ast_mutex_unlock(&peerl.lock); } +/*--- sip_do_reload: Reload module */ static int sip_do_reload(void) { struct sip_registry *reg; @@ -7630,6 +7840,7 @@ return 0; } +/*--- sip_reload: Force reload of module from cli ---*/ static int sip_reload(int fd, int argc, char *argv[]) { @@ -7651,6 +7862,7 @@ static struct ast_cli_entry cli_sip_reload = { { "sip", "reload", NULL }, sip_reload, "Reload SIP configuration", sip_reload_usage }; +/*--- load_module: PBX load module - initialization ---*/ int load_module() { int res; @@ -7806,29 +8018,4 @@ return desc; } -#if 0 -/* XXX What is this? - */ -static char *getsipuri(char *header) -{ - char *c, *d, *retval; - int n; - - if (!(c=strstr(header, "sip"))) { - return NULL; - } - - if (!(d=strchr(c, '@'))) { - return NULL; - } - - n=d-c; - - retval=(char *)malloc(n+1); - strncpy(retval, c, n); - *(retval+n)='\0'; - - return retval; -} -#endif