summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2011-07-20 20:44:54 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2011-08-22 18:22:15 +0200
commit3488c3ddc46d74b7b2bbc879692dbf6e7ad2ecc3 (patch)
tree6a2c821532b55f0cb9f3ac5149f23ec358d5443e
parentc7e49d35eafe74b3cdbfb5ae12104c6b3d33a02e (diff)
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.
-rw-r--r--openbsc/src/libmgcp/mgcp_protocol.c68
1 files changed, 44 insertions, 24 deletions
diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c
index a81c42211..538c35015 100644
--- a/openbsc/src/libmgcp/mgcp_protocol.c
+++ b/openbsc/src/libmgcp/mgcp_protocol.c
@@ -510,12 +510,49 @@ static struct msgb *handle_create_con(struct mgcp_config *cfg, struct msgb *msg)
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 @@ static struct msgb *handle_create_con(struct mgcp_config *cfg, struct msgb *msg)
}
}
- /* 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;