[asterisk-commits] branch oej/02-labarea r21077 -
/team/oej/02-labarea/channels/chan_sip.c
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Tue Apr 18 00:08:55 MST 2006
Author: oej
Date: Tue Apr 18 02:08:46 2006
New Revision: 21077
URL: http://svn.digium.com/view/asterisk?rev=21077&view=rev
Log:
Fixing stuff focused on avoiding loops
Modified:
team/oej/02-labarea/channels/chan_sip.c
Modified: team/oej/02-labarea/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/oej/02-labarea/channels/chan_sip.c?rev=21077&r1=21076&r2=21077&view=diff
==============================================================================
--- team/oej/02-labarea/channels/chan_sip.c (original)
+++ team/oej/02-labarea/channels/chan_sip.c Tue Apr 18 02:08:46 2006
@@ -718,6 +718,20 @@
{ REFER_NOAUTH, "Failed - auth failure" }
} ;
+#ifdef SKREP
+struct sip_transaction {
+ AST_DECLARE_STRING_FIELDS(
+ AST_STRING_FIELD(skrep);
+ );
+ unsigned int cseq; /*!< This transactions outgoing seqno */
+ //enum transactiondirection dir; /*!< Direction of this transaction */
+ struct ast_flags flags[2]; /*!< SIP_ flags */
+ struct sip_request initreq; /*!< Initial request that opened the SIP dialog */
+ struct sip_pvt *pvtowner; /*!< SIP dialog we are referring */
+ /* Transaction Timers */
+}
+#endif
+
/*! \brief Structure to handle SIP transfers. Dynamically allocated when needed */
/* OEJ: Should be moved to string fields */
struct sip_refer {
@@ -737,13 +751,15 @@
enum referstatus status; /*!< REFER status */
};
+
/*! \brief sip_pvt: PVT structures are used for each SIP dialog, ie. a call, a registration, a subscribe */
static struct sip_pvt {
ast_mutex_t lock; /*!< Dialog private lock */
int method; /*!< SIP method that opened this dialog */
AST_DECLARE_STRING_FIELDS(
AST_STRING_FIELD(callid); /*!< Global CallID */
- AST_STRING_FIELD(viabranchtag); /*!< Via branch in this session */
+ AST_STRING_FIELD(viabranchtag); /*!< Topmost via branch captured in this session */
+ AST_STRING_FIELD(ourbranch); /*!< Our branch tag */
AST_STRING_FIELD(randdata); /*!< Random data */
AST_STRING_FIELD(accountcode); /*!< Account code */
AST_STRING_FIELD(realm); /*!< Authorization realm */
@@ -801,7 +817,6 @@
int callingpres; /*!< Calling presentation */
int authtries; /*!< Times we've tried to authenticate */
int expiry; /*!< How long we take to expire */
- long branch; /*!< One random number */
char tag[11]; /*!< Another random number */
int sessionid; /*!< SDP Session ID */
int sessionversion; /*!< SDP Session Version */
@@ -1110,6 +1125,7 @@
static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, char *e);
static void handle_request_info(struct sip_pvt *p, struct sip_request *req);
static int handle_request_options(struct sip_pvt *p, struct sip_request *req);
+static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
/*------Response handling functions */
static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
@@ -1321,8 +1337,8 @@
const char *rport = ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_RFC3581 ? ";rport" : "";
/* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */
- ast_string_field_build(p, via, "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x%s",
- ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch, rport);
+ ast_string_field_build(p, via, "SIP/2.0/UDP %s:%d;branch=%s%s",
+ ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->ourbranch, rport);
}
/*! \brief NAT fix - decide which IP address to use for ASterisk server?
@@ -2742,7 +2758,7 @@
__sip_pretend_ack(p);
/* Send a new request: CANCEL */
- transmit_request_with_auth(p, SIP_CANCEL, p->ocseq, XMIT_RELIABLE, 0);
+ transmit_request_with_auth(p, SIP_CANCEL, p->ocseq, XMIT_RELIABLE, TRUE);
/* Actually don't destroy us yet, wait for the 487 on our original
INVITE, but do set an autodestruct just in case we never get it. */
ast_clear_flag(&locflags, SIP_NEEDDESTROY);
@@ -2763,7 +2779,7 @@
} else { /* Call is in UP state, send BYE */
if (!p->pendinginvite) {
/* Send a hangup */
- transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
+ transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, TRUE);
} else {
/* Note we will need a BYE when this all settles out
but we can't send one while we have "INVITE" outstanding. */
@@ -3360,7 +3376,7 @@
/*! \brief Make our SIP dialog tag */
static void make_our_tag(char *tagbuf, size_t len)
{
- snprintf(tagbuf, len, "as%08lx", ast_random());
+ snprintf(tagbuf, len, "ast-%08lx", ast_random());
}
/*! \brief Allocate SIP_PVT structure and set defaults */
@@ -3368,6 +3384,7 @@
int useglobal_nat, const int intended_method)
{
struct sip_pvt *p;
+ char buf[33];
if (!(p = ast_calloc(1, sizeof(*p))))
return NULL;
@@ -3399,7 +3416,7 @@
ast_copy_flags(&p->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY);
ast_copy_flags(&p->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY);
- p->branch = ast_random();
+ ast_string_field_build(p, ourbranch, "z9hG4bK-ast-%s",generate_random_string(buf,sizeof(buf)));
make_our_tag(p->tag, sizeof(p->tag));
p->ocseq = INITIAL_CSEQ;
@@ -3490,7 +3507,7 @@
if (pedanticsipchecking) {
/* In principle Call-ID's uniquely identify a call, but with a forking SIP proxy
- we need more to identify a branch - so we have to check branch, from
+ we need more to identify a dialog - so we have to check branch, from
and to tags to identify a call leg.
For Asterisk to behave correctly, you need to turn on pedanticsipchecking
in sip.conf
@@ -3545,7 +3562,7 @@
if ((p = sip_alloc(req->callid, sin, 1, intended_method))) { /* Allocate new call */
ast_mutex_lock(&p->lock); /* Lock this new PVT while we are in action */
- find_via_branch(p, req);
+ find_via_branch(p, req); /* Find the branch and store it */
}
return p;
}
@@ -4338,11 +4355,13 @@
copy_via_headers(p, resp, req, "Via");
if (msg[0] == '2')
copy_all_header(resp, req, "Record-Route");
+ ast_log(LOG_DEBUG, "RESPPREP: Call ID in req: %s\n", ast_strlen_zero(req->callid) ? "<none>" : req->callid );
//if (!ast_strlen_zero(req->from))
//add_header(resp, "From", req->from);
//else
copy_header(resp, req, "From");
- ot = req->to ? req->to : get_header(req, "To");
+ //ot = req->to ? ast_strlen_zero(req->to) : get_header(req, "To");
+ ot = get_header(req, "To");
if (!strcasestr(ot, "tag=") && strncmp(msg, "100", 3)) {
/* Add the proper tag if we don't have it already. If they have specified
their tag, use it. Otherwise, use our own tag */
@@ -4406,7 +4425,9 @@
}
if (newbranch) {
- p->branch ^= ast_random();
+ char buf[33];
+ /* This is a new SIP transaction, create a new branch */
+ ast_string_field_build(p, ourbranch, "z9hG4bK-ast-%s",generate_random_string(buf,sizeof(buf)));
build_via(p);
}
@@ -5248,14 +5269,16 @@
req.method = sipmethod;
if (init) {
/* Bump branch even on initial requests */
- p->branch ^= ast_random();
+ char buf[33];
+ /* This is a new SIP transaction, create a new branch */
+ ast_string_field_build(p, ourbranch, "z9hG4bK-ast-%s",generate_random_string(buf,sizeof(buf)));
build_via(p);
if (init > 1)
initreqprep(&req, p, sipmethod);
else
- reqprep(&req, p, sipmethod, 0, 1);
+ reqprep(&req, p, sipmethod, 0, TRUE);
} else
- reqprep(&req, p, sipmethod, 0, 1);
+ reqprep(&req, p, sipmethod, 0, TRUE);
if (p->options && p->options->auth)
add_header(&req, p->options->authheader, p->options->auth);
@@ -5422,7 +5445,7 @@
*a = '\0';
mto = c;
- reqprep(&req, p, SIP_NOTIFY, 0, 1);
+ reqprep(&req, p, SIP_NOTIFY, 0, TRUE);
add_header(&req, "Event", subscriptiontype->event);
@@ -5552,7 +5575,8 @@
{
struct sip_request req;
char tmp[50];
- reqprep(&req, p, SIP_NOTIFY, 0, 1);
+
+ reqprep(&req, p, SIP_NOTIFY, 0, TRUE);
snprintf(tmp, sizeof(tmp), "refer;id=%d", cseq);
add_header(&req, "Event", tmp);
add_header(&req, "Subscription-state", "terminated;reason=noresource");
@@ -5679,6 +5703,7 @@
char tmp[80];
char addr[80];
struct sip_pvt *p;
+ char branch[33];
/* exit if we are already in process with this registrar ?*/
if ( r == NULL || ((auth==NULL) && (r->regstate==REG_STATE_REGSENT || r->regstate==REG_STATE_AUTHSENT))) {
@@ -5794,7 +5819,6 @@
snprintf(addr, sizeof(addr), "sip:%s", r->hostname);
ast_string_field_set(p, uri, addr);
- p->branch ^= ast_random();
memset(&req, 0, sizeof(req));
init_req(&req, sipmethod, addr);
@@ -5802,6 +5826,9 @@
/* Add to CSEQ */
snprintf(tmp, sizeof(tmp), "%u %s", ++r->ocseq, sip_methods[sipmethod].text);
p->ocseq = r->ocseq;
+
+ /* This is a new SIP transaction, create a new branch */
+ ast_string_field_build(p, ourbranch, "z9hG4bK-ast-%s",generate_random_string(branch,sizeof(branch)));
build_via(p);
add_header(&req, "Via", p->via);
@@ -5858,7 +5885,7 @@
{
struct sip_request req;
- reqprep(&req, p, SIP_MESSAGE, 0, 1);
+ reqprep(&req, p, SIP_MESSAGE, 0, TRUE);
add_text(&req, text);
return send_request(p, &req, 1, p->ocseq);
}
@@ -5907,7 +5934,7 @@
ast_string_field_set(p, refer_to, referto);
ast_string_field_set(p, referred_by, p->our_contact);
- reqprep(&req, p, SIP_REFER, 0, 1);
+ reqprep(&req, p, SIP_REFER, 0, TRUE);
add_header(&req, "Refer-To", referto);
add_header(&req, "Allow", ALLOWED_METHODS);
add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
@@ -5927,7 +5954,7 @@
static int transmit_info_with_digit(struct sip_pvt *p, char digit)
{
struct sip_request req;
- reqprep(&req, p, SIP_INFO, 0, 1);
+ reqprep(&req, p, SIP_INFO, 0, TRUE);
add_digit(&req, digit);
return send_request(p, &req, 1, p->ocseq);
}
@@ -9835,7 +9862,7 @@
{
/* Go ahead and send bye at this point */
if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
- transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
+ transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, TRUE);
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE);
} else if (ast_test_flag(&p->flags[0], SIP_NEEDREINVITE)) {
@@ -9937,6 +9964,11 @@
if (p->owner->_state != AST_STATE_UP) {
ast_queue_control(p->owner, AST_CONTROL_ANSWER);
} else { /* RE-invite */
+ /* Is this a 200 OK on a re-invite or something else?
+ Could be a 200 OK on another branch than the one
+ we acted on.
+ */
+ //if (SKREP
ast_queue_frame(p->owner, &ast_null_frame);
}
} else {
@@ -9947,13 +9979,13 @@
ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
}
/* If I understand this right, the branch is different for a non-200 ACK only */
- transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, 1);
+ transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, TRUE);
check_pendings(p);
break;
case 407: /* Proxy authentication */
case 401: /* Www auth */
/* First we ACK */
- transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, 0);
+ transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
if (p->options)
p->options->auth_type = (resp == 401 ? WWW_AUTH : PROXY_AUTH);
@@ -9973,7 +10005,7 @@
break;
case 403: /* Forbidden */
/* First we ACK */
- transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, 0);
+ transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
ast_log(LOG_WARNING, "Received response: \"Forbidden\" from '%s'\n", get_header(&p->initreq, "From"));
if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->owner)
ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
@@ -9981,7 +10013,7 @@
ast_set_flag(&p->flags[0], SIP_ALREADYGONE);
break;
case 404: /* Not found */
- transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, 0);
+ transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
if (p->owner && !ast_test_flag(req, SIP_PKT_IGNORE))
ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
ast_set_flag(&p->flags[0], SIP_ALREADYGONE);
@@ -9989,7 +10021,7 @@
case 481: /* Call leg does not exist */
/* Could be REFER or INVITE */
ast_log(LOG_WARNING, "Re-invite to non-existing call leg on other UA. SIP dialog '%s'. Giving up.\n", p->callid);
- transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, 0);
+ transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
break;
case 491: /* Pending */
/* we have to wait a while, then retransmit */
@@ -10216,7 +10248,7 @@
if (peer->pokeexpire > -1)
ast_sched_del(sched, peer->pokeexpire);
if (sipmethod == SIP_INVITE) /* Does this really happen? */
- transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, 0);
+ transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
/* Try again eventually */
@@ -10443,7 +10475,7 @@
}
/* ACK on invite */
if (sipmethod == SIP_INVITE)
- transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, 0);
+ transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
ast_set_flag(&p->flags[0], SIP_ALREADYGONE);
if (!p->owner)
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
@@ -11255,7 +11287,8 @@
transmit_notify_with_sipfrag(p, seqno, "200 OK");
/* Always increment on a BYE */
if (!nobye) {
- transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
+ /*! \note XXX Should this really be a new branch?? */
+ transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, TRUE);
ast_set_flag(&p->flags[0], SIP_ALREADYGONE);
}
}
@@ -11268,6 +11301,16 @@
check_via(p, req);
ast_set_flag(&p->flags[0], SIP_ALREADYGONE);
+
+ if (p->owner && p->owner->_state == AST_STATE_UP) {
+ /* This call is up, cancel is not accepted, we need a bye */
+ transmit_response(p, "200 OK", req);
+ ast_log(LOG_NOTICE, "Got CANCEL on a call that is already up...Call-ID: %s\n", p->callid);
+ return 0;
+ }
+
+ if (p->owner)
+ ast_queue_hangup(p->owner);
if (p->rtp) {
/* Immediately stop RTP */
ast_rtp_stop(p->rtp);
@@ -11276,10 +11319,6 @@
/* Immediately stop VRTP */
ast_rtp_stop(p->vrtp);
}
- if (p->owner)
- ast_queue_hangup(p->owner);
- else
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
if (p->initreq.len > 0) {
transmit_response_reliable(p, "487 Request Terminated", &p->initreq);
transmit_response(p, "200 OK", req);
@@ -11695,9 +11734,27 @@
ast_log(LOG_DEBUG, "**** Received %s (%d) - Command in SIP %s\n", sip_methods[p->method].text, sip_methods[p->method].id, cmd);
/* Check for loop in INVITE */
- if (p->icseq && (p->icseq == seqno) && req->method == SIP_INVITE) {
+ if (p->icseq && p->icseq == seqno && req->method == SIP_INVITE) {
+ char *branch = ast_strdupa(req->via);
+ char *tag;
+ char *s;
+ int ok = FALSE;
+ if (ast_strlen_zero(branch)) {
+ ast_log(LOG_DEBUG, "**** NO VIA HEADER in req->via\n");
+ branch = ast_strdupa(get_header(req, "Via"));
+ }
+ tag = strcasestr(branch, ";branch=");
+ if (tag) {
+ if ((s = strchr(tag, ';')))
+ *s = '\0';
+ tag += 8;
+ ast_log(LOG_DEBUG, "### Comparing our branch %s with request branch %s\n", p->viabranchtag, tag);
+
+ }
+ ok = TRUE;
//SKREP
ast_log(LOG_DEBUG, "**** Our initial VIA %s - This req VIA %s\n", p->initreq.via, req->via);
+ //if (strcasecmp(p->viabranchtag, ???? )
}
if (p->icseq && (p->icseq > seqno)) {
More information about the asterisk-commits
mailing list