![]() |
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(), 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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
||||||||||||||||||||||||
|
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 }
|
|
||||||||||||||||||||||||
|
${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 }
|
|
||||||||||||||||||||||||
|
${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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||||||
|
Lock dialog list lock and find matching pvt lock
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 }
|
|
||||||||||||||||||||
|
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 }
|
|
||||||||||||||||||||||||
|
Handle incoming SIP requests (methods).
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
Receive SIP INFO Message.
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 }
|
|
||||||||||||||||||||||||||||
|
Handle incoming INVITE request.
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||||||||||
|
Handle incoming notifications.
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||||||||||
|
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") |