![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
chan_sip3.c File Reference
Olle E. Johansson <oej@edvina.net> (all the chan_sip3 changes)
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_dialog * | get_sip_dialog_byid_locked (const char *callid, const char *totag, const char *fromtag) |
Lock dialog list lock and find matching pvt lock
| |
| 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
| |
| 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_channel * | sip_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_channel * | sip_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_dialog * | dialoglist = 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_context * | io |
| ast_config * | notify_types |
| sched_context * | sched |
| 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" |
|
|
Definition at line 406 of file chan_sip3.c. |
|
|
Definition at line 410 of file chan_sip3.c. |
|
|
Definition at line 473 of file chan_sip3.c. |
|
||||||||||||
|
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 }
|
|
|
|
|
||||||||||||||||||||||||||||||||
|
|
|
|
Make sure we don't reload twice at the same time.
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||||||||||
|
Callback for the devicestate notification (SUBSCRIBE) support subsystem.
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 }
|
|
|
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 }
|
|
||||||||||||||||||||||||||||
|
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 }
|
|
||||||||||||||||||||||||||||||||
|
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.
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(), |