diff options
Diffstat (limited to 'channels/chan_sip.c')
-rw-r--r-- | channels/chan_sip.c | 87 |
1 files changed, 43 insertions, 44 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 592a83414..ce03535fc 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -1220,7 +1220,6 @@ struct sip_pvt { ast_group_t callgroup; /*!< Call group */ ast_group_t pickupgroup; /*!< Pickup group */ int lastinvite; /*!< Last Cseq of invite */ - int lastnoninvite; /*!< Last Cseq of non-invite */ struct ast_flags flags[2]; /*!< SIP_ flags */ /* boolean or small integers that don't belong in flags */ @@ -1774,7 +1773,7 @@ static void sip_scheddestroy(struct sip_pvt *p, int ms); static int sip_cancel_destroy(struct sip_pvt *p); static struct sip_pvt *sip_destroy(struct sip_pvt *p); static int __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist); -static void __sip_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod); +static int __sip_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod); static void __sip_pretend_ack(struct sip_pvt *p); static int __sip_semi_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod); static int auto_congest(const void *arg); @@ -3094,10 +3093,11 @@ static int sip_cancel_destroy(struct sip_pvt *p) /*! \brief Acknowledges receipt of a packet and stops retransmission * called with p locked*/ -static void __sip_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod) +static int __sip_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod) { struct sip_pkt *cur, *prev = NULL; const char *msg = "Not Found"; /* used only for debugging */ + int res = FALSE; /* If we have an outbound proxy for this dialog, then delete it now since the rest of the requests in this dialog needs to follow the routing. @@ -3111,6 +3111,7 @@ static void __sip_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod) if (cur->seqno != seqno || cur->is_resp != resp) continue; if (cur->is_resp || cur->method == sipmethod) { + res = TRUE; msg = "Found"; if (!resp && (seqno == p->pendinginvite)) { ast_debug(1, "Acked pending invite %d\n", p->pendinginvite); @@ -3149,6 +3150,7 @@ static void __sip_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod) } ast_debug(1, "Stopping retransmission on '%s' of %s %d: Match %s\n", p->callid, resp ? "Response" : "Request", seqno, msg); + return res; } /*! \brief Pretend to ack all packets @@ -3173,7 +3175,7 @@ static void __sip_pretend_ack(struct sip_pvt *p) static int __sip_semi_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod) { struct sip_pkt *cur; - int res = -1; + int res = FALSE; for (cur = p->packets; cur; cur = cur->next) { if (cur->seqno == seqno && cur->is_resp == resp && @@ -3184,7 +3186,7 @@ static int __sip_semi_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod) ast_debug(4, "*** SIP TIMER: Cancelling retransmission #%d - %s (got response)\n", cur->retransid, sip_methods[sipmethod].text); } AST_SCHED_DEL(sched, cur->retransid); - res = 0; + res = TRUE; break; } } @@ -9707,8 +9709,6 @@ static int transmit_notify_with_sipfrag(struct sip_pvt *p, int cseq, char *messa if (!p->initreq.headers) initialize_initreq(p, &req); - p->lastnoninvite = p->ocseq; - return send_request(p, &req, XMIT_RELIABLE, p->ocseq); } @@ -16003,6 +16003,7 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_ struct ast_channel *owner; int sipmethod; int res = 1; + int ack_res; const char *c = get_header(req, "Cseq"); /* GCC 4.2 complains if I try to cast c as a char * when passing it to ast_skip_nonblanks, so make a copy of it */ char *c_copy = ast_strdupa(c); @@ -16019,10 +16020,16 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_ owner->hangupcause = hangup_sip2cause(resp); /* Acknowledge whatever it is destined for */ - if ((resp >= 100) && (resp <= 199)) - __sip_semi_ack(p, seqno, 0, sipmethod); - else - __sip_ack(p, seqno, 0, sipmethod); + if ((resp >= 100) && (resp <= 199)) { + ack_res = __sip_semi_ack(p, seqno, 0, sipmethod); + } else { + ack_res = __sip_ack(p, seqno, 0, sipmethod); + } + + if (ack_res == FALSE) { + append_history(p, "Ignore", "Ignoring this retransmit\n"); + return; + } /* If this is a NOTIFY for a subscription clear the flag that indicates that we have a NOTIFY pending */ if (!p->owner && sipmethod == SIP_NOTIFY && p->pendinginvite) @@ -19092,7 +19099,7 @@ static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct so /* Get the command XXX */ cmd = req->rlPart1; - e = req->rlPart2; + e = ast_skip_blanks(req->rlPart2); /* Save useragent of the client */ useragent = get_header(req, "User-Agent"); @@ -19101,40 +19108,32 @@ static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct so /* Find out SIP method for incoming request */ if (req->method == SIP_RESPONSE) { /* Response to our request */ - /* When we get here, we know this is a SIP dialog where we've sent - * a request and have a response, or at least get a response - * within an existing dialog. Do some sanity checks, then - * possibly process the request. In all cases, there function - * terminates at the end of this block + /* ignore means "don't do anything with it" but still have to + * respond appropriately. + * But in this case this is a response already, so we really + * have nothing to do with this message, and even setting the + * ignore flag is pointless. */ - int ret = 0; - - if (p->ocseq < seqno && seqno != p->lastnoninvite) { - ast_debug(1, "Ignoring out of order response %d (expecting %d)\n", seqno, p->ocseq); - ret = -1; - } else if (p->ocseq != seqno && seqno != p->lastnoninvite) { - /* ignore means "don't do anything with it" but still have to - * respond appropriately. - * But in this case this is a response already, so we really - * have nothing to do with this message, and even setting the - * ignore flag is pointless. - */ - req->ignore = 1; - append_history(p, "Ignore", "Ignoring this retransmit\n"); - } else if (e) { - e = ast_skip_blanks(e); - if (sscanf(e, "%d %n", &respid, &len) != 1) { - ast_log(LOG_WARNING, "Invalid response: '%s'\n", e); - /* XXX maybe should do ret = -1; */ - } else if (respid <= 0) { - ast_log(LOG_WARNING, "Invalid SIP response code: '%d'\n", respid); - /* XXX maybe should do ret = -1; */ - } else { /* finally, something worth processing */ - /* More SIP ridiculousness, we have to ignore bogus contacts in 100 etc responses */ - if ((respid == 200) || ((respid >= 300) && (respid <= 399))) - extract_uri(p, req); - handle_response(p, respid, e + len, req, seqno); + if (ast_strlen_zero(e)) { + return 0; + } + if (sscanf(e, "%d %n", &respid, &len) != 1) { + ast_log(LOG_WARNING, "Invalid response: '%s'\n", e); + return 0; + } + if (respid <= 0) { + ast_log(LOG_WARNING, "Invalid SIP response code: '%d'\n", respid); + return 0; + } + if (p->ocseq && (p->ocseq < seqno)) { + if (option_debug) + ast_log(LOG_DEBUG, "Ignoring out of order response %d (expecting %d)\n", seqno, p->ocseq); + return -1; + } else { + if ((respid == 200) || ((respid >= 300) && (respid <= 399))) { + extract_uri(p, req); } + handle_response(p, respid, e + len, req, seqno); } return 0; } |