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>2012-05-02 19:24:30 +0200
commit56d7809215ca36c1da674b2dcf3b05bacec496d6 (patch)
tree3c1eb9523ce8e331a68d69b5c1fb6ba3152166d5
parent328141b78197815bb9000948525080eef73c7bca (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;