mgcp: Make CRCX deal better with UDP retransmissions

When the CRCX 200 is lost on the way to the CallAgent we will
get another CRCX (retransmission) which was answered with a 400.

Change the code to extract the CallID, Mode and the optional
LocalOptions first. Then check if the endp is allocated with the
same call identifier, in that case return the current session
information.
diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c
index a81c422..538c350 100644
--- a/openbsc/src/libmgcp/mgcp_protocol.c
+++ b/openbsc/src/libmgcp/mgcp_protocol.c
@@ -510,12 +510,49 @@
 	struct mgcp_endpoint *endp;
 	int error_code = 400;
 
+	const char *local_options = NULL;
+	const char *callid = NULL;
+	const char *mode = NULL;
+	
+
 	found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
 	if (found != 0)
 		return create_err_response(510, "CRCX", trans_id);
 
 	tcfg = endp->tcfg;
 
+	/* parse CallID C: and LocalParameters L: */
+	MSG_TOKENIZE_START
+	switch (msg->l3h[line_start]) {
+	case 'L':
+		local_options = (const char *) &msg->l3h[line_start + 3];
+		break;
+	case 'C':
+		callid = (const char *) &msg->l3h[line_start + 3];
+		break;
+	case 'M':
+		mode = (const char *) & msg->l3h[line_start + 3];
+		break;
+	default:
+		LOGP(DMGCP, LOGL_NOTICE, "Unhandled option: '%c'/%d on 0x%x\n",
+			msg->l3h[line_start], msg->l3h[line_start],
+			ENDPOINT_NUMBER(endp));
+		break;
+	}
+	MSG_TOKENIZE_END
+
+	/* Check required data */
+	if (!callid || !mode) {
+		LOGP(DMGCP, LOGL_ERROR, "Missing callid and mode in CRCX on 0x%x\n",
+		     ENDPOINT_NUMBER(endp));
+		return create_err_response(400, "CRCX", trans_id);
+	}
+
+	/* this appears to be a retransmission, maybe check trans id */
+	if (endp->allocated &&
+	    memcmp(endp->callid, callid, strlen(endp->callid)) == 0)
+		return create_response_with_sdp(endp, "CRCX", trans_id);
+
 	if (endp->allocated) {
 		if (tcfg->force_realloc) {
 			LOGP(DMGCP, LOGL_NOTICE, "Endpoint 0x%x already allocated. Forcing realloc.\n",
@@ -530,33 +567,16 @@
 		}
 	}
 
-	/* parse CallID C: and LocalParameters L: */
-	MSG_TOKENIZE_START
-	switch (msg->l3h[line_start]) {
-	case 'L':
-		endp->local_options = talloc_strdup(tcfg->endpoints,
-			(const char *)&msg->l3h[line_start + 3]);
-		break;
-	case 'C':
-		endp->callid = talloc_strdup(tcfg->endpoints,
-			(const char *)&msg->l3h[line_start + 3]);
-		break;
-	case 'M':
-		if (parse_conn_mode((const char *)&msg->l3h[line_start + 3],
-			    &endp->conn_mode) != 0) {
+	/* copy some parameters */
+	endp->callid = talloc_strdup(tcfg->endpoints, callid);
+
+	if (local_options)
+		endp->local_options = talloc_strdup(tcfg->endpoints, local_options);
+
+	if (parse_conn_mode(mode, &endp->conn_mode) != 0) {
 		    error_code = 517;
 		    goto error2;
-		}
-
-		endp->orig_mode = endp->conn_mode;
-		break;
-	default:
-		LOGP(DMGCP, LOGL_NOTICE, "Unhandled option: '%c'/%d on 0x%x\n",
-			msg->l3h[line_start], msg->l3h[line_start],
-			ENDPOINT_NUMBER(endp));
-		break;
 	}
-	MSG_TOKENIZE_END
 
 	/* initialize */
 	endp->net_end.rtp_port = endp->net_end.rtcp_port = endp->bts_end.rtp_port = endp->bts_end.rtcp_port = 0;