[asterisk-commits] dvossel: branch dvossel/sip_forked_responses r289175 - /team/dvossel/sip_fork...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Sep 28 16:51:44 CDT 2010
Author: dvossel
Date: Tue Sep 28 16:51:39 2010
New Revision: 289175
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=289175
Log:
This update terminates an outgoing forked Request.
Modified:
team/dvossel/sip_forked_responses/channels/chan_sip.c
Modified: team/dvossel/sip_forked_responses/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/sip_forked_responses/channels/chan_sip.c?view=diff&rev=289175&r1=289174&r2=289175
==============================================================================
--- team/dvossel/sip_forked_responses/channels/chan_sip.c (original)
+++ team/dvossel/sip_forked_responses/channels/chan_sip.c Tue Sep 28 16:51:39 2010
@@ -7108,8 +7108,8 @@
return NULL;
}
- /* If this dialog is created as the result of an incoming Request. Lets store
- * some information about that request */
+ /* If this dialog is created as a result of a request or response, lets store
+ * some information about it in the dialog. */
if (req) {
char *sent_by, *branch;
const char *cseq = get_header(req, "Cseq");
@@ -7257,7 +7257,7 @@
SIP_REQ_MATCH,
SIP_REQ_NOT_MATCH,
SIP_REQ_LOOP_DETECTED, /* multiple incoming requests containing different branch parameters have been detected */
- SIP_REQ_FORKED_REQUEST, /* an outgoing request has been forked resulting in multiple separate 200ok responses */
+ SIP_REQ_FORKED, /* an outgoing request has been forked resulting in multiple separate 200ok responses */
};
/*
@@ -7316,7 +7316,7 @@
!ast_strlen_zero(invite_branch) &&
!ast_strlen_zero(arg->viabranch) &&
!strcmp(invite_branch, arg->viabranch)) {
- return SIP_REQ_FORKED_REQUEST;
+ return SIP_REQ_FORKED;
}
/* The totag did not match the one we had stored, and this is not a Forked Request. */
@@ -7418,6 +7418,36 @@
return SIP_REQ_MATCH;
}
+/*! \brief This function creates a dialog to handle a forked request. This dialog
+ * exists only to properly terminiate the the forked request immediately.
+ */
+static void forked_invite_init(struct sip_request *req, const char *new_theirtag, struct sip_pvt *original, struct ast_sockaddr *addr)
+{
+ struct sip_pvt *p;
+
+ if (!(p = sip_alloc(original->callid, addr, 1, SIP_INVITE, req))) {
+ return; /* alloc error */
+ }
+ p->invitestate = INV_TERMINATED;
+ p->ocseq = original->ocseq;
+ p->branch = original->branch;
+
+ memcpy(&p->flags, &original->flags, sizeof(p->flags));
+ copy_request(&p->initreq, &original->initreq);
+ ast_string_field_set(p, theirtag, new_theirtag);
+ ast_copy_string(p->tag, original->tag, sizeof(p->tag));
+ ast_string_field_set(p, uri, original->uri);
+ ast_string_field_set(p, our_contact, original->our_contact);
+ ast_string_field_set(p, fullcontact, original->fullcontact);
+ parse_ok_contact(p, req);
+
+ transmit_request(p, SIP_ACK, p->ocseq, XMIT_UNRELIABLE, TRUE);
+ transmit_request(p, SIP_BYE, 0, XMIT_RELIABLE, TRUE);
+
+ pvt_set_needdestroy(p, "forked request"); /* this dialog will terminate once the BYE is responed to or times out. */
+ dialog_unref(p, "setup forked invite termination");
+}
+
/*! \brief find or create a dialog structure for an incoming SIP message.
* Connect incoming SIP message to current dialog or create new dialog structure
* Returns a reference to the sip_pvt object, remember to give it back once done.
@@ -7490,6 +7520,9 @@
struct sip_pvt tmp_dialog = {
.callid = callid,
};
+ /* if a Outbound forked Request is detected, this pvt will point
+ * to the dialog the Request is forking off of. */
+ struct sip_pvt *fork_pvt = NULL;
struct match_req_args args = { 0, };
int found;
struct ao2_iterator *iterator = ao2_t_callback(dialogs,
@@ -7528,6 +7561,7 @@
case SIP_REQ_MATCH:
sip_pvt_lock(sip_pvt_ptr);
ao2_iterator_destroy(iterator);
+ dialog_unref(fork_pvt, "unref fork_pvt");
return sip_pvt_ptr; /* return pvt with ref */
case SIP_REQ_LOOP_DETECTED:
/* This is likely a forked Request that somehow resulted in us receiving multiple parts of the fork.
@@ -7535,9 +7569,12 @@
transmit_response_using_temp(callid, addr, 1, intended_method, req, "482 (Loop Detected)");
dialog_unref(sip_pvt_ptr, "pvt did not match incoming SIP msg, unref from search.");
ao2_iterator_destroy(iterator);
+ dialog_unref(fork_pvt, "unref fork_pvt");
return NULL;
- case SIP_REQ_FORKED_REQUEST:
- //todohere handle forked response
+ case SIP_REQ_FORKED:
+ dialog_unref(fork_pvt, "throwing way pvt to fork off of.");
+ fork_pvt = dialog_ref(sip_pvt_ptr, "this pvt has a forked request, save this off to copy information into new dialog\n");
+ /* fall through */
case SIP_REQ_NOT_MATCH:
default:
dialog_unref(sip_pvt_ptr, "pvt did not match incoming SIP msg, unref from search");
@@ -7545,6 +7582,18 @@
}
if (iterator) {
ao2_iterator_destroy(iterator);
+ }
+
+ /* Handle any possible forked requests. This must be done only after transaction matching is complete. */
+ if (fork_pvt) {
+ /* XXX right now we only support handling forked INVITE Requests. Any other
+ * forked request type must be added here. */
+ if (fork_pvt->method == SIP_INVITE) {
+ forked_invite_init(req, args.totag, fork_pvt, addr);
+ dialog_unref(fork_pvt, "throwing way old forked pvt");
+ return NULL;
+ }
+ fork_pvt = dialog_unref(fork_pvt, "throwing way pvt to fork off of");
}
} /* end of pedantic mode Request/Reponse to Dialog matching */
More information about the asterisk-commits
mailing list