summaryrefslogtreecommitdiff
path: root/tests/mgcp/mgcp_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/mgcp/mgcp_test.c')
-rw-r--r--tests/mgcp/mgcp_test.c235
1 files changed, 194 insertions, 41 deletions
diff --git a/tests/mgcp/mgcp_test.c b/tests/mgcp/mgcp_test.c
index f6c421a..56d0cee 100644
--- a/tests/mgcp/mgcp_test.c
+++ b/tests/mgcp/mgcp_test.c
@@ -26,6 +26,8 @@
#include <osmocom/mgcp/mgcp_stat.h>
#include <osmocom/mgcp/mgcp_msg.h>
#include <osmocom/mgcp/mgcp_endp.h>
+#include <osmocom/mgcp/mgcp_sdp.h>
+#include <osmocom/mgcp/mgcp_codec.h>
#include <osmocom/core/application.h>
#include <osmocom/core/talloc.h>
@@ -156,8 +158,8 @@ static void test_strline(void)
"s=-\r\n" \
"c=IN IP4 0.0.0.0\r\n" \
"t=0 0\r\n" \
- "m=audio 16002 RTP/AVP 96\r\n" \
- "a=rtpmap:96 AMR\r\n" \
+ "m=audio 16002 RTP/AVP 112\r\n" \
+ "a=rtpmap:112 AMR\r\n" \
"a=ptime:40\r\n"
#define MDCX4_PT1 \
@@ -404,7 +406,7 @@ static void test_strline(void)
"v=0\r\n" \
"o=- 1439038275 1439038275 IN IP4 192.168.181.247\r\n" \
"s=-\r\nc=IN IP4 192.168.181.247\r\n" \
- "t=0 0\r\nm=audio 29084 RTP/AVP 255 0 8 3 18 4 96 97 101\r\n" \
+ "t=0 0\r\nm=audio 29084 RTP/AVP 0 8 3 18 4 96 97 101\r\n" \
"a=rtpmap:0 PCMU/8000\r\n" \
"a=rtpmap:8 PCMA/8000\r\n" \
"a=rtpmap:3 gsm/8000\r\n" \
@@ -425,7 +427,24 @@ static void test_strline(void)
"I: %s\r\n" \
"\r\n" \
"c=IN IP4 8.8.8.8\r\n" \
- "m=audio 16434 RTP/AVP 255\r\n"
+ "m=audio 16434 RTP/AVP 3\r\n"
+
+#define CRCX_NO_LCO_NO_SDP \
+ "CRCX 2 6@mgw MGCP 1.0\r\n" \
+ "M: recvonly\r\n" \
+ "C: 2\r\n"
+
+#define CRCX_NO_LCO_NO_SDP_RET \
+ "200 2 OK\r\n" \
+ "I: %s\r\n" \
+ "\r\n" \
+ "v=0\r\n" \
+ "o=- %s 23 IN IP4 0.0.0.0\r\n" \
+ "s=-\r\n" \
+ "c=IN IP4 0.0.0.0\r\n" \
+ "t=0 0\r\n" \
+ "m=audio 16008 RTP/AVP 0\r\n" \
+ "a=ptime:20\r\n"
struct mgcp_test {
const char *name;
@@ -462,6 +481,7 @@ static const struct mgcp_test tests[] = {
{"MDCX3", MDCX3, MDCX3_FMTP_RET, PTYPE_NONE,.extra_fmtp =
"a=fmtp:126 0/1/2"},
{"DLCX", DLCX, DLCX_RET, PTYPE_IGNORE,.extra_fmtp = "a=fmtp:126 0/1/2"},
+ {"CRCX", CRCX_NO_LCO_NO_SDP, CRCX_NO_LCO_NO_SDP_RET, 97},
};
static const struct mgcp_test retransmit[] = {
@@ -764,14 +784,14 @@ static void test_messages(void)
fprintf(stderr, "endpoint %d: "
"payload type %d (expected %d)\n",
last_endpoint,
- conn->end.codec.payload_type, t->ptype);
+ conn->end.codec->payload_type, t->ptype);
if (t->ptype != PTYPE_IGNORE)
- OSMO_ASSERT(conn->end.codec.payload_type ==
+ OSMO_ASSERT(conn->end.codec->payload_type ==
t->ptype);
/* Reset them again for next test */
- conn->end.codec.payload_type = PTYPE_NONE;
+ conn->end.codec->payload_type = PTYPE_NONE;
}
}
@@ -917,23 +937,43 @@ static const struct pl_test pl_test_dat[] = {
static void test_packet_loss_calc(void)
{
int i;
+ struct mgcp_endpoint endp;
+ struct mgcp_trunk_config trunk;
+
printf("Testing packet loss calculation.\n");
+ memset(&endp, 0, sizeof(endp));
+ memset(&trunk, 0, sizeof(trunk));
+
+ endp.type = &ep_typeset.rtp;
+ trunk.vty_number_endpoints = 1;
+ trunk.endpoints = &endp;
+ endp.tcfg = &trunk;
+ INIT_LLIST_HEAD(&endp.conns);
+
for (i = 0; i < ARRAY_SIZE(pl_test_dat); ++i) {
uint32_t expected;
int loss;
- struct mgcp_rtp_state state;
- struct mgcp_rtp_end rtp;
- memset(&state, 0, sizeof(state));
- memset(&rtp, 0, sizeof(rtp));
- state.stats.initialized = 1;
- state.stats.base_seq = pl_test_dat[i].base_seq;
- state.stats.max_seq = pl_test_dat[i].max_seq;
- state.stats.cycles = pl_test_dat[i].cycles;
+ struct mgcp_conn_rtp *conn = NULL;
+ struct mgcp_conn *_conn = NULL;
+ struct mgcp_rtp_state *state;
+ struct rate_ctr *packets_rx;
- rtp.stats.packets_rx = pl_test_dat[i].packets;
- calc_loss(&state, &rtp, &expected, &loss);
+ _conn =
+ mgcp_conn_alloc(NULL, &endp, MGCP_CONN_TYPE_RTP,
+ "test-connection");
+ conn = mgcp_conn_get_rtp(&endp, _conn->id);
+ state = &conn->state;
+ packets_rx = &conn->rate_ctr_group->ctr[RTP_PACKETS_RX_CTR];
+
+ state->stats.initialized = 1;
+ state->stats.base_seq = pl_test_dat[i].base_seq;
+ state->stats.max_seq = pl_test_dat[i].max_seq;
+ state->stats.cycles = pl_test_dat[i].cycles;
+
+ packets_rx->current = pl_test_dat[i].packets;
+ calc_loss(conn, &expected, &loss);
if (loss != pl_test_dat[i].loss
|| expected != pl_test_dat[i].expected) {
@@ -942,7 +982,10 @@ static void test_packet_loss_calc(void)
i, loss, pl_test_dat[i].loss, expected,
pl_test_dat[i].expected);
}
+
+ mgcp_conn_free_all(&endp);
}
+
}
int mgcp_parse_stats(struct msgb *msg, uint32_t *ps, uint32_t *os,
@@ -1129,10 +1172,12 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
uint32_t last_ssrc = 0;
uint32_t last_timestamp = 0;
uint32_t last_seqno = 0;
- int last_in_ts_err_cnt = 0;
- int last_out_ts_err_cnt = 0;
+ uint64_t last_in_ts_err_cnt = 0;
+ uint64_t last_out_ts_err_cnt = 0;
struct mgcp_conn_rtp *conn = NULL;
struct mgcp_conn *_conn = NULL;
+ struct rate_ctr test_ctr_in;
+ struct rate_ctr test_ctr_out;
printf("Testing packet error detection%s%s.\n",
patch_ssrc ? ", patch SSRC" : "",
@@ -1142,6 +1187,11 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
memset(&endp, 0, sizeof(endp));
memset(&state, 0, sizeof(state));
+ memset(&test_ctr_in, 0, sizeof(test_ctr_in));
+ memset(&test_ctr_out, 0, sizeof(test_ctr_out));
+ state.in_stream.err_ts_ctr = &test_ctr_in;
+ state.out_stream.err_ts_ctr = &test_ctr_out;
+
endp.type = &ep_typeset.rtp;
trunk.vty_number_endpoints = 1;
@@ -1160,7 +1210,8 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
rtp = &conn->end;
- rtp->codec.payload_type = 98;
+ OSMO_ASSERT(mgcp_codec_add(conn, PTYPE_UNDEFINED, "AMR/8000/1") == 0);
+ rtp->codec = &rtp->codecs[0];
for (i = 0; i < ARRAY_SIZE(test_rtp_packets1); ++i) {
struct rtp_packet_info *info = test_rtp_packets1 + i;
@@ -1186,18 +1237,18 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
state.in_stream.last_tsdelta, state.in_stream.last_seq);
printf("Out TS change: %d, dTS: %d, Seq change: %d, "
- "TS Err change: in %+d, out %+d\n",
+ "TS Err change: in +%u, out +%u\n",
state.out_stream.last_timestamp - last_timestamp,
state.out_stream.last_tsdelta,
state.out_stream.last_seq - last_seqno,
- state.in_stream.err_ts_counter - last_in_ts_err_cnt,
- state.out_stream.err_ts_counter - last_out_ts_err_cnt);
+ (unsigned int) (state.in_stream.err_ts_ctr->current - last_in_ts_err_cnt),
+ (unsigned int) (state.out_stream.err_ts_ctr->current - last_out_ts_err_cnt));
printf("Stats: Jitter = %u, Transit = %d\n",
calc_jitter(&state), state.stats.transit);
- last_in_ts_err_cnt = state.in_stream.err_ts_counter;
- last_out_ts_err_cnt = state.out_stream.err_ts_counter;
+ last_in_ts_err_cnt = state.in_stream.err_ts_ctr->current;
+ last_out_ts_err_cnt = state.out_stream.err_ts_ctr->current;
last_timestamp = state.out_stream.last_timestamp;
last_seqno = state.out_stream.last_seq;
}
@@ -1236,8 +1287,7 @@ static void test_multilple_codec(void)
endp = &cfg->trunk.endpoints[last_endpoint];
conn = mgcp_conn_get_rtp(endp, conn_id);
OSMO_ASSERT(conn);
- OSMO_ASSERT(conn->end.codec.payload_type == 18);
- OSMO_ASSERT(conn->end.alt_codec.payload_type == 97);
+ OSMO_ASSERT(conn->end.codec->payload_type == 18);
/* Allocate 2@mgw with three codecs, last one ignored */
last_endpoint = -1;
@@ -1252,10 +1302,14 @@ static void test_multilple_codec(void)
endp = &cfg->trunk.endpoints[last_endpoint];
conn = mgcp_conn_get_rtp(endp, conn_id);
OSMO_ASSERT(conn);
- OSMO_ASSERT(conn->end.codec.payload_type == 18);
- OSMO_ASSERT(conn->end.alt_codec.payload_type == 97);
-
- /* Allocate 3@mgw with no codecs, check for PT == -1 */
+ OSMO_ASSERT(conn->end.codec->payload_type == 18);
+
+ /* Allocate 3@mgw with no codecs, check for PT == 0 */
+ /* Note: It usually makes no sense to leave the payload type list
+ * out. However RFC 2327 does not clearly forbid this case and
+ * it makes and since we already decided in OS#2658 that a missing
+ * LCO should pick a sane default codec, it makes sense to expect
+ * the same behaviour if SDP lacks proper payload type information */
last_endpoint = -1;
inp = create_msg(CRCX_MULT_3, NULL);
resp = mgcp_handle_message(cfg, inp);
@@ -1268,8 +1322,7 @@ static void test_multilple_codec(void)
endp = &cfg->trunk.endpoints[last_endpoint];
conn = mgcp_conn_get_rtp(endp, conn_id);
OSMO_ASSERT(conn);
- OSMO_ASSERT(conn->end.codec.payload_type == -1);
- OSMO_ASSERT(conn->end.alt_codec.payload_type == -1);
+ OSMO_ASSERT(conn->end.codec->payload_type == 0);
/* Allocate 4@mgw with a single codec */
last_endpoint = -1;
@@ -1284,8 +1337,7 @@ static void test_multilple_codec(void)
endp = &cfg->trunk.endpoints[last_endpoint];
conn = mgcp_conn_get_rtp(endp, conn_id);
OSMO_ASSERT(conn);
- OSMO_ASSERT(conn->end.codec.payload_type == 18);
- OSMO_ASSERT(conn->end.alt_codec.payload_type == -1);
+ OSMO_ASSERT(conn->end.codec->payload_type == 18);
/* Allocate 5@mgw at select GSM.. */
last_endpoint = -1;
@@ -1303,8 +1355,7 @@ static void test_multilple_codec(void)
endp = &cfg->trunk.endpoints[last_endpoint];
conn = mgcp_conn_get_rtp(endp, conn_id);
OSMO_ASSERT(conn);
- OSMO_ASSERT(conn->end.codec.payload_type == 3);
- OSMO_ASSERT(conn->end.alt_codec.payload_type == -1);
+ OSMO_ASSERT(conn->end.codec->payload_type == 3);
inp = create_msg(MDCX_NAT_DUMMY, conn_id);
last_endpoint = -1;
@@ -1315,8 +1366,7 @@ static void test_multilple_codec(void)
endp = &cfg->trunk.endpoints[last_endpoint];
conn = mgcp_conn_get_rtp(endp, conn_id);
OSMO_ASSERT(conn);
- OSMO_ASSERT(conn->end.codec.payload_type == 3);
- OSMO_ASSERT(conn->end.alt_codec.payload_type == -1);
+ OSMO_ASSERT(conn->end.codec->payload_type == 3);
OSMO_ASSERT(conn->end.rtp_port == htons(16434));
memset(&addr, 0, sizeof(addr));
inet_aton("8.8.8.8", &addr);
@@ -1346,8 +1396,7 @@ static void test_multilple_codec(void)
endp = &cfg->trunk.endpoints[last_endpoint];
conn = mgcp_conn_get_rtp(endp, conn_id);
OSMO_ASSERT(conn);
- OSMO_ASSERT(conn->end.codec.payload_type == 255);
- OSMO_ASSERT(conn->end.alt_codec.payload_type == 0);
+ OSMO_ASSERT(conn->end.codec->payload_type == 0);
talloc_free(cfg);
}
@@ -1465,6 +1514,108 @@ const struct log_info log_info = {
.num_cat = ARRAY_SIZE(log_categories),
};
+static void test_get_lco_identifier(void)
+{
+ char *test;
+ printf("Testing get_lco_identifier()\n");
+
+ /* Normal case at the beginning */
+ test = "p:10, a:PCMU";
+ printf("%s -> %s\n", test, get_lco_identifier(test));
+
+ test = "p:10, a:PCMU";
+ printf("%s -> %s\n", test, get_lco_identifier(test));
+
+ /* Begin parsing in the middle of the value part of
+ * the previous LCO option value */
+ test = "XXXX, p:10, a:PCMU";
+ printf("'%s' -> '%s'\n", test, get_lco_identifier(test));
+
+ test = "XXXX,p:10,a:PCMU";
+ printf("'%s' -> '%s'\n", test, get_lco_identifier(test));
+
+ test = "10,a:PCMU";
+ printf("'%s' -> '%s'\n", test, get_lco_identifier(test));
+
+ test = "10, a:PCMU";
+ printf("'%s' -> '%s'\n", test, get_lco_identifier(test));
+
+ test = "10,a: PCMU";
+ printf("'%s' -> '%s'\n", test, get_lco_identifier(test));
+
+ test = "10 ,a: PCMU";
+ printf("'%s' -> '%s'\n", test, get_lco_identifier(test));
+
+ /* Begin parsing right at the end of the previous LCO
+ * option value */
+ test = ", a:PCMU";
+ printf("'%s' -> '%s'\n", test, get_lco_identifier(test));
+
+ test = " a:PCMU";
+ printf("'%s' -> '%s'\n", test, get_lco_identifier(test));
+
+ /* Empty string, result should be (null) */
+ test = "";
+ printf("'%s' -> '%s'\n", test, get_lco_identifier(test));
+
+ /* Missing colons, result should be (null) */
+ test = "p10, aPCMU";
+ printf("%s -> %s\n", test, get_lco_identifier(test));
+
+ /* Colon separated from the identifier, result should be (null) */
+ test = "10,a :PCMU";
+ printf("'%s' -> '%s'\n", test, get_lco_identifier(test));
+}
+
+static void test_check_local_cx_options(void *ctx)
+{
+ /* Legal cases */
+ OSMO_ASSERT(check_local_cx_options(ctx, "p:10, a:PCMU") == 0);
+ OSMO_ASSERT(check_local_cx_options(ctx, "a:PCMU") == 0);
+ OSMO_ASSERT(check_local_cx_options(ctx, "a:PCMU, p:10, IN:10") == 0);
+ OSMO_ASSERT(check_local_cx_options(ctx, "one:AAA, two:BB, tree:C") ==
+ 0);
+ OSMO_ASSERT(check_local_cx_options(ctx, "p:10, a:PCMU") == 0);
+ OSMO_ASSERT(check_local_cx_options(ctx, "p:10, a:G726-32") == 0);
+ OSMO_ASSERT(check_local_cx_options(ctx, "p:10-20, b:64") == 0);
+ OSMO_ASSERT(check_local_cx_options(ctx, "b:32-64, e:off") == 0);
+ OSMO_ASSERT(check_local_cx_options(ctx, "p:10, a:PCMU;G726-32") == 0);
+
+ /* Illegal spaces before and after colon */
+ OSMO_ASSERT(check_local_cx_options(ctx, "a:PCMU, p :10") == -1);
+ OSMO_ASSERT(check_local_cx_options(ctx, "a :PCMU, p:10") == -1);
+ OSMO_ASSERT(check_local_cx_options(ctx, "p: 10, a:PCMU") == -1);
+
+ /* Check if multiple appearances of LCOs are rejected */
+ OSMO_ASSERT(check_local_cx_options(ctx, "p:10, a:PCMU, p:10") == -1);
+ OSMO_ASSERT(check_local_cx_options(ctx, "p:10, a:PCMU, a:PCMU, p:10") ==
+ -1);
+ OSMO_ASSERT(check_local_cx_options(ctx, "p:10, p:10") == -1);
+
+ /* Check if empty LCO are rejected */
+ OSMO_ASSERT(check_local_cx_options(ctx, "p: , a:PCMU") == -1);
+ OSMO_ASSERT(check_local_cx_options(ctx, "p: , a: PCMU") == -1);
+ OSMO_ASSERT(check_local_cx_options(ctx, "p:10, a: PCMU") == -1);
+ OSMO_ASSERT(check_local_cx_options(ctx, "p:, a:PCMU") == -1);
+ OSMO_ASSERT(check_local_cx_options(ctx, "p:10, a:") == -1);
+
+ /* Garbeled beginning and ends */
+ OSMO_ASSERT(check_local_cx_options(ctx, ":10, a:10") == -1);
+ OSMO_ASSERT(check_local_cx_options(ctx, "10, a:PCMU") == -1);
+ OSMO_ASSERT(check_local_cx_options(ctx, ", a:PCMU") == -1);
+ OSMO_ASSERT(check_local_cx_options(ctx, " a:PCMU") == -1);
+ OSMO_ASSERT(check_local_cx_options(ctx, "a:PCMU,") == -1);
+ OSMO_ASSERT(check_local_cx_options(ctx, "a:PCMU, ") == -1);
+
+ /* Illegal strings */
+ OSMO_ASSERT(check_local_cx_options(ctx, " ") == -1);
+ OSMO_ASSERT(check_local_cx_options(ctx, "") == -1);
+ OSMO_ASSERT(check_local_cx_options(ctx, "AAA") == -1);
+ OSMO_ASSERT(check_local_cx_options(ctx, ":,") == -1);
+ OSMO_ASSERT(check_local_cx_options(ctx, ",:") == -1);
+ OSMO_ASSERT(check_local_cx_options(ctx, ",,,") == -1);
+}
+
int main(int argc, char **argv)
{
void *ctx = talloc_named_const(NULL, 0, "mgcp_test");
@@ -1486,6 +1637,8 @@ int main(int argc, char **argv)
test_no_cycle();
test_no_name();
test_osmux_cid();
+ test_get_lco_identifier();
+ test_check_local_cx_options(ctx);
OSMO_ASSERT(talloc_total_size(msgb_ctx) == 0);
OSMO_ASSERT(talloc_total_blocks(msgb_ctx) == 1);