diff options
-rw-r--r-- | include/mgcp/mgcp.h | 6 | ||||
-rw-r--r-- | src/mgcp/mgcp_protocol.c | 42 | ||||
-rw-r--r-- | tests/mgcp/Makefile.am | 5 | ||||
-rw-r--r-- | tests/mgcp/mgcp_patch_test.c | 86 |
4 files changed, 132 insertions, 7 deletions
diff --git a/include/mgcp/mgcp.h b/include/mgcp/mgcp.h index e02da08..cde4594 100644 --- a/include/mgcp/mgcp.h +++ b/include/mgcp/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 @@ -165,6 +166,7 @@ struct mgcp_config { mgcp_policy policy_cb; mgcp_reset reset_cb; mgcp_realloc realloc_cb; + mgcp_rqnt rqnt_cb; void *data; /* trunk handling */ diff --git a/src/mgcp/mgcp_protocol.c b/src/mgcp/mgcp_protocol.c index f76342c..92559a3 100644 --- a/src/mgcp/mgcp_protocol.c +++ b/src/mgcp/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 @@ -879,6 +879,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 @@ -889,7 +898,8 @@ static struct msgb *handle_noti_req(struct mgcp_config *cfg, struct msgb *msg) struct mgcp_msg_ptr data_ptrs[6]; const char *trans_id; struct mgcp_endpoint *endp; - int found; + int found, res = 0, i, line_start; + char tone = 0; found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp); if (found != 0) @@ -899,7 +909,31 @@ static struct msgb *handle_noti_req(struct mgcp_config *cfg, struct msgb *msg) LOGP(DMGCP, LOGL_ERROR, "Endpoint is not used. 0x%x\n", ENDPOINT_NUMBER(endp)); return create_err_response(400, "RQNT", trans_id); } - return create_ok_response(200, "RQNT", trans_id); + + MSG_TOKENIZE_START + switch (msg->l3h[line_start]) { + case 'S': + tone = extract_tone((const char *)&msg->l3h[line_start]); + break; + } + MSG_TOKENIZE_END + + /* 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); + +error: + LOGP(DMGCP, LOGL_ERROR, "Malformed line: %s on 0x%x with: line_start: %d %d\n", + osmo_hexdump(msg->l3h, msgb_l3len(msg)), + ENDPOINT_NUMBER(endp), line_start, i); + return create_err_response(400, "RQNT", trans_id); } static void trunk_init(struct mgcp_trunk_config *trunk) diff --git a/tests/mgcp/Makefile.am b/tests/mgcp/Makefile.am index 008979b..e4aee29 100644 --- a/tests/mgcp/Makefile.am +++ b/tests/mgcp/Makefile.am @@ -4,5 +4,8 @@ noinst_PROGRAMS = mgcp_patch_test EXTRA_DIST = mgcp_patch_test.ok -mgcp_patch_test_SOURCES = mgcp_patch_test.c $(top_srcdir)/src/mgcp_patch.c +mgcp_patch_test_SOURCES = mgcp_patch_test.c $(top_srcdir)/src/mgcp_patch.c \ + $(top_srcdir)/src/mgcp/mgcp_protocol.c \ + $(top_srcdir)/src/mgcp/mgcp_network.c \ + $(top_srcdir)/src/debug.c mgcp_patch_test_LDADD = $(LIBOSMOCORE_LIBS) diff --git a/tests/mgcp/mgcp_patch_test.c b/tests/mgcp/mgcp_patch_test.c index 683ea01..834b3e4 100644 --- a/tests/mgcp/mgcp_patch_test.c +++ b/tests/mgcp/mgcp_patch_test.c @@ -17,9 +17,14 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <mgcp/mgcp.h> +#include <mgcp/mgcp_internal.h> #include <mgcp_patch.h> #include <ss7_application.h> +#include <osmocom/core/application.h> +#include <osmocom/core/talloc.h> + #include <string.h> #include <stdio.h> #include <stdlib.h> @@ -62,12 +67,44 @@ static const char mgcp_out[] = "a=T38FaxVersion:0\r\n" "a=T38MaxBitRate:14400\r\n"; +#define CRCX "CRCX 2 1@mgw MGCP 1.0\r\n" \ + "M: sendrecv\r\n" \ + "C: 2\r\n" \ + "\r\n" \ + "v=0\r\n" \ + "c=IN IP4 123.12.12.123\r\n" \ + "m=audio 5904 RTP/AVP 97\r\n" \ + "a=rtpmap:97 GSM-EFR/8000\r\n" + +#define DLCX "DLCX 7 1@mgw MGCP 1.0\r\n" \ + "C: 2\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" + #define ASSERT(a, cmp, b, text) \ if (!((a) cmp (b))) { \ fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, text); \ abort(); \ } +static struct msgb *create_msg(const char *str) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(4096, 128, "MGCP msg"); + int len = sprintf((char *)msg->data, str); + msg->l2h = msgb_put(msg, len); + return msg; +} + static void test_endp_name_rewriting() { struct ss7_application app; @@ -95,9 +132,58 @@ static void test_endp_name_rewriting() ASSERT(strcmp((const char *)msg_out->l2h, mgcp_out), ==, 0, "Text don't match"); } +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 mgcp_trunk_config *tcfg; + struct msgb *inp, *msg; + + cfg = mgcp_config_alloc(); + cfg->rqnt_cb = rqnt_cb; + + tcfg = mgcp_vtrunk_alloc(cfg, "mgw"); + tcfg->number_endpoints = 64; + mgcp_endpoints_allocate(tcfg); + + 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); +} + int main(int argc, char **argv) { + osmo_init_logging(&log_info); + test_endp_name_rewriting(); + test_rqnt_cb(); printf("All tests passed.\n"); return 0; |