From b57e5ff5efad32bab815f47f2cb4693c5176f684 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 29 Aug 2011 14:30:47 +0200 Subject: mgcp: Work on the decompress, compress... --- openbsc/include/openbsc/mgcp_internal.h | 2 +- openbsc/src/libmgcp/rtp_helper.c | 72 ++++++++++++++++++++++++++++++++- openbsc/tests/mgcp/mgcp_test.c | 46 ++++++++++++++++++++- 3 files changed, 117 insertions(+), 3 deletions(-) diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h index dc00112d3..c1b2bb338 100644 --- a/openbsc/include/openbsc/mgcp_internal.h +++ b/openbsc/include/openbsc/mgcp_internal.h @@ -175,7 +175,7 @@ struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index); int rtp_compress(struct mgcp_rtp_compr_state *state, struct msgb *msg, int endpoint, struct llist_head *rtp_packets); -struct llist_head rtp_decompress(struct mgcp_rtp_compr_state *state, void *ctx, +struct llist_head rtp_decompress(struct mgcp_rtp_compr_state *state, struct msgb *msg); diff --git a/openbsc/src/libmgcp/rtp_helper.c b/openbsc/src/libmgcp/rtp_helper.c index 77fc4c819..66687b19b 100644 --- a/openbsc/src/libmgcp/rtp_helper.c +++ b/openbsc/src/libmgcp/rtp_helper.c @@ -44,6 +44,29 @@ struct reduced_rtp_hdr { #define msgb_put_struct(msg, str) \ (str *) msgb_put(msg, sizeof(str)) + +static void fill_rtp_hdr(struct rtp_hdr *hdr) +{ + hdr->csrc_count = 0; + hdr->extension = 0; + hdr->padding = 0; + hdr->version = RTP_VERSION; + + /* detect stop of silence? */ + hdr->marker = 0; + hdr->payload_type = 98; +} + +static void fill_rtp_state(struct rtp_hdr *hdr, + struct mgcp_rtp_compr_state *state) +{ + hdr->ssrc = htonl(state->generated_ssrc); + hdr->sequence = htons(state->sequence++); + hdr->timestamp = htonl(state->timestamp); + state->timestamp += 160; +} + + /** * I try to compress these packets into one single stream. I have various * limitations. I do not support packets that jump backwards, the rtp_packets @@ -82,6 +105,15 @@ int rtp_compress(struct mgcp_rtp_compr_state *state, struct msgb *msg, continue; } + if (msgb_l2len(rtp) < sizeof(struct rtp_hdr) + 17) { + LOGP(DMGCP, LOGL_ERROR, + "We assume every payload is 17 byte: %d\n", + msgb_l2len(rtp) - sizeof(struct rtp_hdr)); + llist_del(&rtp->list); + talloc_free(rtp); + continue; + } + hdr = (struct rtp_hdr *) rtp->l2h; sequence = ntohs(hdr->sequence); if (sequence < last_sequence && sequence != 0) { @@ -120,11 +152,49 @@ int rtp_compress(struct mgcp_rtp_compr_state *state, struct msgb *msg, return count; } -struct llist_head rtp_decompress(struct mgcp_rtp_compr_state *state, void *ctx, +struct llist_head rtp_decompress(struct mgcp_rtp_compr_state *state, struct msgb *msg) { + struct reduced_rtp_hdr *rhdr; + int i; struct llist_head list; INIT_LLIST_HEAD(&list); + if (msgb_l2len(msg) < sizeof(*rhdr)) { + LOGP(DMGCP, LOGL_ERROR, "Compressed header does not fit.\n"); + return list; + } + + rhdr = (struct reduced_rtp_hdr *) msg->l2h; + if (rhdr->type != 0) { + LOGP(DMGCP, LOGL_ERROR, + "Type %d is not known.\n", rhdr->type); + return list; + } + + if (msgb_l2len(msg) < sizeof(*rhdr) + rhdr->payloads * 17) { + LOGP(DMGCP, LOGL_ERROR, + "Payloads do not fit. %d\n", rhdr->payloads); + return list; + } + + for (i = 0; i < rhdr->payloads; ++i) { + struct rtp_hdr *hdr; + struct msgb *out = msgb_alloc_headroom(4096, 128, "RTP decompr"); + if (!out) { + LOGP(DMGCP, LOGL_ERROR, "Failed to allocate: %d\n", i); + continue; + } + + out->l2h = msgb_put(out, 0); + hdr = msgb_put_struct(out, struct rtp_hdr); + fill_rtp_hdr(hdr); + fill_rtp_state(hdr, state); + + out->l3h = msgb_put(out, 17); + memcpy(out->l3h, &rhdr->data[i * 17], 17); + msgb_enqueue(&list, out); + } + return list; } diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c index 8c4ee84d0..30bc625c0 100644 --- a/openbsc/tests/mgcp/mgcp_test.c +++ b/openbsc/tests/mgcp/mgcp_test.c @@ -121,6 +121,9 @@ static struct msgb *from(const uint8_t *data, uint16_t len) void test_compress() { + int i = 0; + struct msgb *msg; + struct msgb *msg1 = FROM(packet_1); struct msgb *msg2 = FROM(packet_2); struct msgb *msg3 = FROM(packet_3); @@ -136,6 +139,9 @@ void test_compress() struct mgcp_rtp_compr_state state; memset(&state, 0, sizeof(state)); state.last_ts = UCHAR_MAX; + state.generated_ssrc = 0x6f0fb1da; + state.sequence = 52103; + state.timestamp = 4157323848u; struct msgb *out = msgb_alloc_headroom(4096, 128, "out"); out->l2h = msgb_put(out, 0); @@ -154,7 +160,45 @@ void test_compress() printf("output is: %s\n", osmo_hexdump(out->l2h, msgb_l2len(out))); - list = rtp_decompress(&state, NULL, out); + list = rtp_decompress(&state, out); + + llist_for_each_entry(msg, &list, list) { + const uint8_t *data; + int len; + + switch (++i) { + case 1: + data = packet_1; + len = sizeof(packet_1); + break; + case 2: + data = packet_2; + len = sizeof(packet_2); + break; + case 3: + data = packet_3; + len = sizeof(packet_3); + break; + case 4: + data = packet_4; + len = sizeof(packet_4); + break; + default: + fprintf(stderr, "Should not be reached.\n"); + abort(); + } + + if (msgb_l2len(msg) != len) { + fprintf(stderr, "Wrong len for %d %d\n", i, msgb_l2len(msg)); + abort(); + } + + if (memcmp(msg->l2h, data, len) != 0) { + fprintf(stderr, "Wrong data for %d, '%s'\n", + i, osmo_hexdump(msg->l2h, msgb_l2len(msg))); + abort(); + } + } msgb_free(out); } -- cgit v1.2.3