[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