aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2012-11-29 12:54:22 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2012-11-29 19:56:22 +0100
commit8d0be259cb0ed8c33a373bbdfe88aafe4cfc27c0 (patch)
tree5dd1fd93a27ee7cfafb5ae5d47ac1950cd556935
parent0d0c9ec5c54d8b66ec54c498c3dfcf0ba04372ca (diff)
mgcp: Begin handling of the RQNT message as needed for DTMF
Introduce a callback for the request and forward the signalrequest to the callback. This is not a full implementation of MGCP RQNT.
-rw-r--r--openbsc/include/openbsc/mgcp.h6
-rw-r--r--openbsc/src/libmgcp/mgcp_protocol.c58
-rw-r--r--openbsc/tests/mgcp/mgcp_test.c58
-rw-r--r--openbsc/tests/mgcp/mgcp_test.ok2
4 files changed, 111 insertions, 13 deletions
diff --git a/openbsc/include/openbsc/mgcp.h b/openbsc/include/openbsc/mgcp.h
index d618f3cdb..bb21e684e 100644
--- a/openbsc/include/openbsc/mgcp.h
+++ b/openbsc/include/openbsc/mgcp.h
@@ -1,8 +1,8 @@
/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
/*
- * (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-2011 by On-Waves
+ * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2012 by On-Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
@@ -83,6 +83,7 @@ typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint);
typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state);
typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id);
typedef int (*mgcp_reset)(struct mgcp_trunk_config *cfg);
+typedef int (*mgcp_rqnt)(struct mgcp_endpoint *endp, char tone, const char *data);
#define PORT_ALLOC_STATIC 0
#define PORT_ALLOC_DYNAMIC 1
@@ -148,6 +149,7 @@ struct mgcp_config {
mgcp_policy policy_cb;
mgcp_reset reset_cb;
mgcp_realloc realloc_cb;
+ mgcp_rqnt rqnt_cb;
void *data;
uint32_t last_call_id;
diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c
index 4b0222ffb..54af15b7b 100644
--- a/openbsc/src/libmgcp/mgcp_protocol.c
+++ b/openbsc/src/libmgcp/mgcp_protocol.c
@@ -2,8 +2,8 @@
/* The protocol implementation */
/*
- * (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-2011 by On-Waves
+ * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2012 by On-Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
@@ -822,6 +822,15 @@ static struct msgb *handle_rsip(struct mgcp_config *cfg, struct msgb *msg)
return NULL;
}
+static char extract_tone(const char *line)
+{
+ const char *str = strstr(line, "D/");
+ if (!str)
+ return CHAR_MAX;
+
+ return str[2];
+}
+
/*
* This can request like DTMF detection and forward, fax detection... it
* can also request when the notification should be send and such. We don't
@@ -831,18 +840,45 @@ static struct msgb *handle_noti_req(struct mgcp_config *cfg, struct msgb *msg)
{
const char *trans_id;
struct mgcp_endpoint *endp;
- int found;
- char *data = strtok((char *) msg->l3h, "\r\n");
+ int found, res = 0;
+ char *line, *save;
+ char tone = 0;
- found = mgcp_analyze_header(cfg, data, &trans_id, &endp);
- if (found != 0)
- return create_err_response(400, "RQNT", trans_id);
+ for_each_line((char *) msg->l3h, line, save) {
+ /* skip first line */
+ if ((char *) msg->l3h == line) {
+ found = mgcp_analyze_header(cfg, line, &trans_id,
+ &endp);
+ if (found != 0)
+ return create_err_response(400, "RQNT",
+ trans_id);
+
+ if (!endp->allocated) {
+ LOGP(DMGCP, LOGL_ERROR,
+ "Endpoint is not used. 0x%x\n",
+ ENDPOINT_NUMBER(endp));
+ return create_err_response(400, "RQNT",
+ trans_id);
+ }
+ }
- if (!endp->allocated) {
- LOGP(DMGCP, LOGL_ERROR, "Endpoint is not used. 0x%x\n", ENDPOINT_NUMBER(endp));
- return create_err_response(400, "RQNT", trans_id);
+ switch (line[0]) {
+ case 'S':
+ tone = extract_tone(line);
+ break;
+ }
}
- return create_ok_response(200, "RQNT", trans_id);
+
+ /* we didn't see a signal request with a tone */
+ if (tone == CHAR_MAX)
+ return create_ok_response(200, "RQNT", trans_id);
+
+ if (cfg->rqnt_cb)
+ res = cfg->rqnt_cb(endp, tone, (const char *) msg->l3h);
+
+ return res == 0 ?
+ create_ok_response(200, "RQNT", trans_id) :
+ create_err_response(res, "RQNT", trans_id);
}
struct mgcp_config *mgcp_config_alloc(void)
diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c
index 9b65666f4..74f5efee1 100644
--- a/openbsc/tests/mgcp/mgcp_test.c
+++ b/openbsc/tests/mgcp/mgcp_test.c
@@ -74,6 +74,15 @@
#define DLCX_RET "250 7 OK\r\n" \
"P: PS=0, OS=0, PR=0, OR=0, PL=0, JI=0\r\n"
+#define RQNT "RQNT 186908780 1@mgw MGCP 1.0\r\n" \
+ "X: B244F267488\r\n" \
+ "S: D/9\r\n"
+
+#define RQNT2 "RQNT 186908780 1@mgw MGCP 1.0\r\n" \
+ "X: ADD4F26746F\r\n" \
+ "R: D/[0-9#*](N), G/ft, fxr/t38\r\n"
+
+#define RQNT_RET "200 186908780 OK\r\n"
struct mgcp_test {
const char *name;
@@ -91,6 +100,8 @@ const struct mgcp_test tests[] = {
{ "SHORT2", SHORT2, SHORT2_RET },
{ "SHORT3", SHORT3, SHORT2_RET },
{ "SHORT4", SHORT4, SHORT2_RET },
+ { "RQNT1", RQNT, RQNT_RET },
+ { "RQNT2", RQNT2, RQNT_RET },
{ "DLCX", DLCX, DLCX_RET },
};
@@ -137,6 +148,52 @@ static void test_messages(void)
talloc_free(cfg);
}
+static int rqnt_cb(struct mgcp_endpoint *endp, char _tone, const char *data)
+{
+ ptrdiff_t tone = _tone;
+ endp->cfg->data = (void *) tone;
+ return 0;
+}
+
+static void test_rqnt_cb(void)
+{
+ struct mgcp_config *cfg;
+ struct msgb *inp, *msg;
+
+ cfg = mgcp_config_alloc();
+ cfg->rqnt_cb = rqnt_cb;
+
+ cfg->trunk.number_endpoints = 64;
+ mgcp_endpoints_allocate(&cfg->trunk);
+
+ mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1));
+
+ inp = create_msg(CRCX);
+ msgb_free(mgcp_handle_message(cfg, inp));
+ msgb_free(inp);
+
+ /* send the RQNT and check for the CB */
+ inp = create_msg(RQNT);
+ msg = mgcp_handle_message(cfg, inp);
+ if (strncmp((const char *) msg->l2h, "200", 3) != 0) {
+ printf("FAILED: message is not 200. '%s'\n", msg->l2h);
+ abort();
+ }
+
+ if (cfg->data != (void *) '9') {
+ printf("FAILED: callback not called: %p\n", cfg->data);
+ abort();
+ }
+
+ msgb_free(msg);
+ msgb_free(inp);
+
+ inp = create_msg(DLCX);
+ msgb_free(mgcp_handle_message(cfg, inp));
+ msgb_free(inp);
+ talloc_free(cfg);
+}
+
struct pl_test {
int cycles;
uint16_t base_seq;
@@ -195,6 +252,7 @@ int main(int argc, char **argv)
test_messages();
test_packet_loss_calc();
+ test_rqnt_cb();
printf("Done\n");
return EXIT_SUCCESS;
diff --git a/openbsc/tests/mgcp/mgcp_test.ok b/openbsc/tests/mgcp/mgcp_test.ok
index e61c0bc15..1143a0441 100644
--- a/openbsc/tests/mgcp/mgcp_test.ok
+++ b/openbsc/tests/mgcp/mgcp_test.ok
@@ -7,6 +7,8 @@ Testing SHORT1
Testing SHORT2
Testing SHORT3
Testing SHORT4
+Testing RQNT1
+Testing RQNT2
Testing DLCX
Testing packet loss calculation.
Done