summaryrefslogtreecommitdiff
path: root/channels/chan_sip.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels/chan_sip.c')
-rw-r--r--channels/chan_sip.c87
1 files changed, 43 insertions, 44 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 0ab125173..b0a72fa40 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -1751,7 +1751,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 flags that don't belong in flags */
@@ -2403,7 +2402,7 @@ static struct sip_pvt *sip_destroy(struct sip_pvt *p);
static void *dialog_unlink_all(struct sip_pvt *dialog, int lockowner, int lockdialoglist);
static void *registry_unref(struct sip_registry *reg, char *tag);
static void __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);
@@ -3891,10 +3890,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.
@@ -3909,6 +3909,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);
@@ -3949,6 +3950,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
@@ -3973,7 +3975,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 &&
@@ -3984,7 +3986,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;
}
}
@@ -11215,8 +11217,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);
}
@@ -18535,6 +18535,7 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
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);
@@ -18552,10 +18553,16 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
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)
@@ -21938,7 +21945,7 @@ static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct so
/* Get the command XXX */
cmd = REQ_OFFSET_TO_STR(req, rlPart1);
- e = REQ_OFFSET_TO_STR(req, rlPart2);
+ e = ast_skip_blanks(REQ_OFFSET_TO_STR(req, rlPart2));
/* Save useragent of the client */
useragent = get_header(req, "User-Agent");
@@ -21947,40 +21954,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 && p->lastinvite != seqno && p->lastnoninvite != seqno) {
- ast_debug(1, "Ignoring out of order response %d (expecting %d)\n", seqno, p->ocseq);
- ret = -1;
- } else if (p->ocseq != seqno && p->lastinvite != seqno && p->lastnoninvite != seqno) {
- /* 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;
}