diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 84c6b0b44ef284d022d8037ed7d5726382582a32..80f072dd301b8b7210cfe198e91691ed25de4681 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -133,23 +133,24 @@ static const char notify_config[] = "sip_notify.conf"; const struct cfsip_methods { int id; + int need_rtp; /* when this is the 'primary' use for a pvt structure, does it need RTP? */ char *text; } sip_methods[] = { - { 0, "-UNKNOWN-" }, - { SIP_REGISTER, "REGISTER" }, - { SIP_OPTIONS, "OPTIONS" }, - { SIP_NOTIFY, "NOTIFY" }, - { SIP_INVITE, "INVITE" }, - { SIP_ACK, "ACK" }, - { SIP_PRACK, "PRACK" }, - { SIP_BYE, "BYE" }, - { SIP_REFER, "REFER" }, - { SIP_SUBSCRIBE,"SUBSCRIBE" }, - { SIP_MESSAGE, "MESSAGE" }, - { SIP_UPDATE, "UPDATE" }, - { SIP_INFO, "INFO" }, - { SIP_CANCEL, "CANCEL" }, - { SIP_PUBLISH, "PUBLISH" } + { 0, 1, "-UNKNOWN-" }, + { SIP_REGISTER, 0, "REGISTER" }, + { SIP_OPTIONS, 0, "OPTIONS" }, + { SIP_NOTIFY, 0, "NOTIFY" }, + { SIP_INVITE, 1, "INVITE" }, + { SIP_ACK, 0, "ACK" }, + { SIP_PRACK, 0, "PRACK" }, + { SIP_BYE, 0, "BYE" }, + { SIP_REFER, 0, "REFER" }, + { SIP_SUBSCRIBE, 0, "SUBSCRIBE" }, + { SIP_MESSAGE, 0, "MESSAGE" }, + { SIP_UPDATE, 0, "UPDATE" }, + { SIP_INFO, 0, "INFO" }, + { SIP_CANCEL, 0, "CANCEL" }, + { SIP_PUBLISH, 0, "PUBLISH" } }; @@ -2494,7 +2495,7 @@ static void build_callid(char *callid, int len, struct in_addr ourip, char *from } /*--- sip_alloc: Allocate SIP_PVT structure and set defaults ---*/ -static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useglobal_nat) +static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useglobal_nat, const int intended_method) { struct sip_pvt *p; @@ -2519,32 +2520,40 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg } else { memcpy(&p->ourip, &__ourip, sizeof(p->ourip)); } - p->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); - if (videosupport) - p->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); + p->branch = rand(); p->tag = rand(); - /* Start with 101 instead of 1 */ p->ocseq = 101; - if (!p->rtp) { - ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno)); - ast_mutex_destroy(&p->lock); - if(p->chanvars) { - ast_variables_destroy(p->chanvars); - p->chanvars = NULL; + + if (sip_methods[intended_method].need_rtp) { + p->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); + if (videosupport) + p->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); + if (!p->rtp) { + ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno)); + ast_mutex_destroy(&p->lock); + if(p->chanvars) { + ast_variables_destroy(p->chanvars); + p->chanvars = NULL; + } + free(p); + return NULL; } - free(p); - return NULL; + ast_rtp_settos(p->rtp, tos); + if (p->vrtp) + ast_rtp_settos(p->vrtp, tos); + p->rtptimeout = global_rtptimeout; + p->rtpholdtimeout = global_rtpholdtimeout; + p->rtpkeepalive = global_rtpkeepalive; } - ast_rtp_settos(p->rtp, tos); - if (p->vrtp) - ast_rtp_settos(p->vrtp, tos); + if (useglobal_nat && sin) { /* Setup NAT structure according to global settings if we have an address */ ast_copy_flags(p, &global_flags, SIP_NAT); memcpy(&p->recv, sin, sizeof(p->recv)); - ast_rtp_setnat(p->rtp, (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)); + if (p->rtp) + ast_rtp_setnat(p->rtp, (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)); if (p->vrtp) ast_rtp_setnat(p->vrtp, (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)); } @@ -2558,9 +2567,6 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg ast_copy_flags(p, (&global_flags), SIP_PROMISCREDIR | SIP_TRUSTRPID | SIP_DTMF | SIP_REINVITE | SIP_PROG_INBAND | SIP_OSPAUTH); /* Assign default music on hold class */ strcpy(p->musicclass, global_musicclass); - p->rtptimeout = global_rtptimeout; - p->rtpholdtimeout = global_rtpholdtimeout; - p->rtpkeepalive = global_rtpkeepalive; p->capability = global_capability; if (ast_test_flag(p, SIP_DTMF) == SIP_DTMF_RFC2833) p->noncodeccapability |= AST_RTP_DTMF; @@ -2577,7 +2583,7 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg /*--- find_call: Connect incoming SIP message to current call or create new call structure */ /* Called by handle_request ,sipsock_read */ -static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin) +static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin, const int intended_method) { struct sip_pvt *p; char *callid; @@ -2633,7 +2639,7 @@ static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *si p = p->next; } ast_mutex_unlock(&iflock); - p = sip_alloc(callid, sin, 1); + p = sip_alloc(callid, sin, 1, intended_method); if (p) ast_mutex_lock(&p->lock); return p; @@ -4479,7 +4485,7 @@ static int transmit_register(struct sip_registry *r, int sipmethod, char *auth, r->callid_valid = 1; } /* Allocate SIP packet for registration */ - p=sip_alloc( r->callid, NULL, 0); + p=sip_alloc( r->callid, NULL, 0, SIP_REGISTER); if (!p) { ast_log(LOG_WARNING, "Unable to allocate registration call\n"); return 0; @@ -7423,7 +7429,7 @@ static int sip_notify(int fd, int argc, char *argv[]) struct sip_request req; struct ast_variable *var; - p = sip_alloc(NULL, NULL, 0); + p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY); if (!p) { ast_log(LOG_WARNING, "Unable to build sip pvt data for notify\n"); return RESULT_FAILURE; @@ -9055,10 +9061,6 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc /* Get the command */ cseq += len; - /* Determine the request URI for sip, sips or tel URIs */ - if( determine_firstline_parts( req ) < 0 ) { - return -1; - } cmd = req->rlPart1; e = req->rlPart2; @@ -9066,7 +9068,6 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc useragent = get_header(req, "User-Agent"); strncpy(p->useragent, useragent, sizeof(p->useragent)-1); - /* Find out SIP method for incoming request */ if (!strcasecmp(cmd, "SIP/2.0")) { /* Response to our request */ p->method = SIP_RESPONSE; @@ -9246,10 +9247,15 @@ static int sipsock_read(int *id, int fd, short events, void *ignore) /* Must have at least two headers */ return 1; } + + /* Determine the request URI for sip, sips or tel URIs */ + if (determine_firstline_parts(&req) < 0) + return 1; + /* Process request, with netlock held */ retrylock: ast_mutex_lock(&netlock); - p = find_call(&req, &sin); + p = find_call(&req, &sin, find_sip_method(req.rlPart1)); if (p) { /* Go ahead and lock the owner if it has one -- we may need it */ if (p->owner && ast_mutex_trylock(&p->owner->lock)) { @@ -9298,7 +9304,7 @@ static int sip_send_mwi_to_peer(struct sip_peer *peer) return 0; } - p = sip_alloc(NULL, NULL, 0); + p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY); if (!p) { ast_log(LOG_WARNING, "Unable to build sip pvt data for MWI\n"); return -1; @@ -9523,7 +9529,7 @@ static int sip_poke_peer(struct sip_peer *peer) ast_log(LOG_NOTICE, "Still have a call...\n"); sip_destroy(peer->call); } - p = peer->call = sip_alloc(NULL, NULL, 0); + p = peer->call = sip_alloc(NULL, NULL, 0, SIP_OPTIONS); if (!peer->call) { ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name); return -1; @@ -9626,7 +9632,7 @@ static struct ast_channel *sip_request(const char *type, int format, void *data, ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format %s while capability is %s\n", ast_getformatname(oldformat), ast_getformatname(global_capability)); return NULL; } - p = sip_alloc(NULL, NULL, 0); + p = sip_alloc(NULL, NULL, 0, SIP_INVITE); if (!p) { ast_log(LOG_WARNING, "Unable to build sip pvt data for '%s'\n", (char *)data); return NULL;