From 8d0be259cb0ed8c33a373bbdfe88aafe4cfc27c0 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 29 Nov 2012 12:54:22 +0100 Subject: 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. --- openbsc/include/openbsc/mgcp.h | 6 ++-- openbsc/src/libmgcp/mgcp_protocol.c | 58 ++++++++++++++++++++++++++++++------- openbsc/tests/mgcp/mgcp_test.c | 58 +++++++++++++++++++++++++++++++++++++ openbsc/tests/mgcp/mgcp_test.ok | 2 ++ 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 - * (C) 2009-2011 by On-Waves + * (C) 2009-2012 by Holger Hans Peter Freyther + * (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 - * (C) 2009-2011 by On-Waves + * (C) 2009-2012 by Holger Hans Peter Freyther + * (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 -- cgit v1.2.3