aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2011-08-29 14:30:47 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2011-08-30 15:04:16 +0200
commitb57e5ff5efad32bab815f47f2cb4693c5176f684 (patch)
tree375f0ef7e2cf763e4380dc778eed075136b6887d
parent4f4bffdf207b9526dddb5cb38d47d50e5b6a9709 (diff)
mgcp: Work on the decompress, compress...
-rw-r--r--openbsc/include/openbsc/mgcp_internal.h2
-rw-r--r--openbsc/src/libmgcp/rtp_helper.c72
-rw-r--r--openbsc/tests/mgcp/mgcp_test.c46
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);
}