blob: 007b90c6accd61c415c84ec3d23e2bd3b1d2b3fb [file] [log] [blame]
Neels Hofmeyre9920f22017-07-10 15:07:22 +02001/*
2 * (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
3 * All Rights Reserved
4 *
5 * Author: Neels Hofmeyr
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
Neels Hofmeyrbd86f942018-02-21 16:45:38 +010021#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
22
Neels Hofmeyre9920f22017-07-10 15:07:22 +020023#include <string.h>
24
25#include <osmocom/core/msgb.h>
26#include <osmocom/core/application.h>
Neels Hofmeyr3a8e7232017-09-04 01:02:56 +020027#include <osmocom/mgcp_client/mgcp_client.h>
28#include <osmocom/mgcp_client/mgcp_client_internal.h>
Neels Hofmeyrc8f37cb2017-11-30 13:43:11 +010029#include <errno.h>
Neels Hofmeyre9920f22017-07-10 15:07:22 +020030
31void *ctx;
32
33#define buf_len 4096
34
35#if 0
36static struct msgb *from_hex(const char *hex)
37{
38 struct msgb *msg = msgb_alloc(buf_len, "mgcpgw_test_from_hex");
39 unsigned int l = osmo_hexparse(hex, msg->data, buf_len);
40 msg->l2h = msgb_put(msg, l);
41 return msg;
42}
43
44static struct msgb *mgcp_from_str(const char *head, const char *params)
45{
46 struct msgb *msg = msgb_alloc(buf_len, "mgcp_from_str");
47 unsigned int l;
48 char *data;
49 l = strlen(head);
50 msg->l2h = msgb_put(msg, l);
51 data = (char*)msgb_l2(msg);
Philipp Maierf8bfbe82017-11-23 19:32:31 +010052 osmo_strlcpy(data, head, l);
Neels Hofmeyre9920f22017-07-10 15:07:22 +020053
54 data = (char*)msgb_put(msg, 1);
55 *data = '\n';
56
57 l = strlen(params);
58 data = (char*)msgb_put(msg, l);
Philipp Maierf8bfbe82017-11-23 19:32:31 +010059 osmo_strlcpy(data, params, l);
Neels Hofmeyre9920f22017-07-10 15:07:22 +020060
61 return msg;
62}
63#endif
64
65static struct msgb *from_str(const char *str)
66{
67 struct msgb *msg = msgb_alloc(buf_len, "from_str");
68 unsigned int l = strlen(str);
69 char *data;
70 msg->l2h = msgb_put(msg, l);
71 data = (char*)msgb_l2(msg);
Philipp Maierf8bfbe82017-11-23 19:32:31 +010072 osmo_strlcpy(data, str, l);
Neels Hofmeyre9920f22017-07-10 15:07:22 +020073 return msg;
74}
75
Neels Hofmeyr3a8e7232017-09-04 01:02:56 +020076static struct mgcp_client_conf conf;
77struct mgcp_client *mgcp = NULL;
Neels Hofmeyre9920f22017-07-10 15:07:22 +020078
Neels Hofmeyrc8f37cb2017-11-30 13:43:11 +010079static int reply_to(mgcp_trans_id_t trans_id, int code, const char *comment,
Neels Hofmeyre9920f22017-07-10 15:07:22 +020080 int conn_id, const char *params)
81{
82 static char compose[4096 - 128];
83 int len;
84
85 len = snprintf(compose, sizeof(compose),
86 "%d %u %s\r\nI: %d\n\n%s",
87 code, trans_id, comment, conn_id, params);
88 OSMO_ASSERT(len < sizeof(compose));
89 OSMO_ASSERT(len > 0);
90
91 printf("composed response:\n-----\n%s\n-----\n",
92 compose);
Neels Hofmeyrc8f37cb2017-11-30 13:43:11 +010093 return mgcp_client_rx(mgcp, from_str(compose));
Neels Hofmeyre9920f22017-07-10 15:07:22 +020094}
95
96void test_response_cb(struct mgcp_response *response, void *priv)
97{
98 OSMO_ASSERT(priv == mgcp);
99 mgcp_response_parse_params(response);
100
101 printf("response cb received:\n"
102 " head.response_code = %d\n"
103 " head.trans_id = %u\n"
104 " head.comment = %s\n"
Philipp Maier06da85e2017-10-05 18:49:24 +0200105 " audio_port = %u\n"
106 " audio_ip = %s\n",
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200107 response->head.response_code,
108 response->head.trans_id,
109 response->head.comment,
Philipp Maier06da85e2017-10-05 18:49:24 +0200110 response->audio_port,
111 response->audio_ip
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200112 );
113}
114
115mgcp_trans_id_t dummy_mgcp_send(struct msgb *msg)
116{
117 mgcp_trans_id_t trans_id;
118 trans_id = msg->cb[MSGB_CB_MGCP_TRANS_ID];
119 char *end;
120
Neels Hofmeyr3a8e7232017-09-04 01:02:56 +0200121 OSMO_ASSERT(mgcp_client_pending_add(mgcp, trans_id, test_response_cb, mgcp));
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200122
123 end = (char*)msgb_put(msg, 1);
124 *end = '\0';
125 printf("composed:\n-----\n%s\n-----\n",
126 (char*)msgb_l2(msg));
127
128 talloc_free(msg);
129 return trans_id;
130}
131
132void test_crcx(void)
133{
134 struct msgb *msg;
135 mgcp_trans_id_t trans_id;
136
137 printf("\n===== %s =====\n", __func__);
138
139 if (mgcp)
140 talloc_free(mgcp);
Neels Hofmeyr3a8e7232017-09-04 01:02:56 +0200141 mgcp = mgcp_client_init(ctx, &conf);
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200142
143 msg = mgcp_msg_crcx(mgcp, 23, 42, MGCP_CONN_LOOPBACK);
144 trans_id = dummy_mgcp_send(msg);
145
146 reply_to(trans_id, 200, "OK", 1,
147 "v=0\r\n"
148 "o=- 1 23 IN IP4 10.9.1.120\r\n"
149 "s=-\r\n"
150 "c=IN IP4 10.9.1.120\r\n"
151 "t=0 0\r\n"
152 "m=audio 16002 RTP/AVP 98\r\n"
153 "a=rtpmap:98 AMR/8000\r\n"
154 "a=ptime:20\r\n");
155}
156
Philipp Maier1dc6be62017-10-05 18:25:37 +0200157void test_mgcp_msg(void)
158{
159 struct msgb *msg;
160 char audio_ip_overflow[5000];
161
162 /* A message struct prefilled with some arbitary values */
163 struct mgcp_msg mgcp_msg = {
164 .audio_ip = "192.168.100.23",
165 .endpoint = "23@mgw",
166 .audio_port = 1234,
167 .call_id = 47,
Philipp Maier01d24a32017-11-21 17:26:09 +0100168 .conn_id = "11",
Philipp Maier1dc6be62017-10-05 18:25:37 +0200169 .conn_mode = MGCP_CONN_RECV_SEND
170 };
171
172 if (mgcp)
173 talloc_free(mgcp);
174 mgcp = mgcp_client_init(ctx, &conf);
175
176 printf("\n");
177
178 printf("Generated CRCX message:\n");
179 mgcp_msg.verb = MGCP_VERB_CRCX;
180 mgcp_msg.presence =
181 (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
182 MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE);
183 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
184 printf("%s\n", (char *)msg->data);
185
186 printf("Generated MDCX message:\n");
187 mgcp_msg.verb = MGCP_VERB_MDCX;
188 mgcp_msg.presence =
189 (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
190 MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE |
191 MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT);
192 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
193 printf("%s\n", (char *)msg->data);
194
195 printf("Generated DLCX message:\n");
196 mgcp_msg.verb = MGCP_VERB_DLCX;
197 mgcp_msg.presence =
198 (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
199 MGCP_MSG_PRESENCE_CONN_ID);
200 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
201 printf("%s\n", (char *)msg->data);
202
203 printf("Generated AUEP message:\n");
204 mgcp_msg.verb = MGCP_VERB_AUEP;
205 mgcp_msg.presence = (MGCP_MSG_PRESENCE_ENDPOINT);
206 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
207 printf("%s\n", msg->data);
208
209 printf("Generated RSIP message:\n");
210 mgcp_msg.verb = MGCP_VERB_RSIP;
211 mgcp_msg.presence = (MGCP_MSG_PRESENCE_ENDPOINT);
212 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
213 printf("%s\n", (char *)msg->data);
214
215 printf("Overfolow test:\n");
216 mgcp_msg.verb = MGCP_VERB_MDCX;
217 mgcp_msg.presence =
218 (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
219 MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE |
220 MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT);
221 memset(audio_ip_overflow, 'X', sizeof(audio_ip_overflow));
222 audio_ip_overflow[sizeof(audio_ip_overflow) - 1] = '\0';
223 mgcp_msg.audio_ip = audio_ip_overflow;
224 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
225 OSMO_ASSERT(msg == NULL);
226
227 printf("\n");
228 msgb_free(msg);
229}
230
Neels Hofmeyrc8f37cb2017-11-30 13:43:11 +0100231void test_mgcp_client_cancel()
232{
233 mgcp_trans_id_t trans_id;
234 struct msgb *msg;
235 struct mgcp_msg mgcp_msg = {
236 .verb = MGCP_VERB_CRCX,
237 .audio_ip = "192.168.100.23",
238 .endpoint = "23@mgw",
239 .audio_port = 1234,
240 .call_id = 47,
Philipp Maier922ae9a2017-12-04 15:53:37 +0100241 .conn_id = "11",
Neels Hofmeyrc8f37cb2017-11-30 13:43:11 +0100242 .conn_mode = MGCP_CONN_RECV_SEND,
243 .presence = (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID
244 | MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE),
245 };
246
247 printf("\n%s():\n", __func__);
248 fprintf(stderr, "\n%s():\n", __func__);
249
250 if (mgcp)
251 talloc_free(mgcp);
252 mgcp = mgcp_client_init(ctx, &conf);
253
254 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
255 trans_id = mgcp_msg_trans_id(msg);
256 fprintf(stderr, "- composed msg with trans_id=%u\n", trans_id);
257
258 fprintf(stderr, "- not in queue yet, cannot cancel yet\n");
259 OSMO_ASSERT(mgcp_client_cancel(mgcp, trans_id) == -ENOENT);
260
261 fprintf(stderr, "- enqueue\n");
262 dummy_mgcp_send(msg);
263
264 fprintf(stderr, "- cancel succeeds\n");
265 OSMO_ASSERT(mgcp_client_cancel(mgcp, trans_id) == 0);
266
267 fprintf(stderr, "- late response gets discarded\n");
268 OSMO_ASSERT(reply_to(trans_id, 200, "OK", 1, "v=0\r\n") == -ENOENT);
269
270 fprintf(stderr, "- canceling again does nothing\n");
271 OSMO_ASSERT(mgcp_client_cancel(mgcp, trans_id) == -ENOENT);
272
273 fprintf(stderr, "%s() done\n", __func__);
274}
275
Neels Hofmeyra8c6a9c2018-02-21 15:36:45 +0100276struct sdp_section_start_test {
277 const char *body;
278 int expect_rc;
279 struct mgcp_response expect_params;
280};
281
282static struct sdp_section_start_test sdp_section_start_tests[] = {
283 {
284 .body = "",
285 .expect_rc = -EINVAL,
286 },
287 {
288 .body = "\n\n",
289 },
290 {
291 .body = "\r\n\r\n",
292 },
293 {
294 .body = "\n\r\n\r",
295 },
296 {
297 .body = "some mgcp header data\r\nand header params"
298 "\n\n"
299 "m=audio 23\r\n",
300 .expect_params = {
301 .audio_port = 23,
302 },
303 },
304 {
305 .body = "some mgcp header data\r\nand header params"
306 "\r\n\r\n"
307 "m=audio 23\r\n",
308 .expect_params = {
309 .audio_port = 23,
310 },
311 },
312 {
313 .body = "some mgcp header data\r\nand header params"
314 "\n\r\n\r"
315 "m=audio 23\r\n",
316 .expect_params = {
317 .audio_port = 23,
318 },
319 },
320 {
321 .body = "some mgcp header data\r\nand header params"
322 "\n\r\n"
323 "m=audio 23\r\n",
324 .expect_rc = -EINVAL,
325 },
326 {
327 .body = "some mgcp header data\r\nand header params"
328 "\r\n\r"
329 "m=audio 23\r\n",
330 .expect_rc = -EINVAL,
331 },
332 {
333 .body = "some mgcp header data\r\nand header params"
334 "\n\r\r"
335 "m=audio 23\r\n",
336 .expect_rc = -EINVAL,
337 },
338};
339
340void test_sdp_section_start()
341{
342 int i;
343 int failures = 0;
344
345 for (i = 0; i < ARRAY_SIZE(sdp_section_start_tests); i++) {
346 int rc;
347 struct sdp_section_start_test *t = &sdp_section_start_tests[i];
348 struct mgcp_response *r = talloc_zero(ctx, struct mgcp_response);
349
350 r->body = talloc_strdup(r, t->body);
351
352 printf("\n%s() test [%d]:\n", __func__, i);
353 fprintf(stderr, "\n%s() test [%d]:\n", __func__, i);
354 fprintf(stderr, "body: \"%s\"\n", osmo_escape_str(r->body, -1));
355
356 rc = mgcp_response_parse_params(r);
357
358 fprintf(stderr, "got rc=%d\n", rc);
359 if (rc != t->expect_rc) {
360 fprintf(stderr, "FAIL: Expected rc=%d\n", t->expect_rc);
361 failures++;
362 }
363 if (rc) {
364 talloc_free(r);
365 continue;
366 }
367
368 fprintf(stderr, "got audio_port=%u\n", t->expect_params.audio_port);
369 if (r->audio_port != t->expect_params.audio_port) {
370 fprintf(stderr, "FAIL: Expected audio_port=%u\n", t->expect_params.audio_port);
371 failures++;
372 }
373 talloc_free(r);
374 }
375
Neels Hofmeyra8c6a9c2018-02-21 15:36:45 +0100376 OSMO_ASSERT(!failures);
Neels Hofmeyra8c6a9c2018-02-21 15:36:45 +0100377}
378
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200379static const struct log_info_cat log_categories[] = {
380};
381
382const struct log_info log_info = {
383 .cat = log_categories,
384 .num_cat = ARRAY_SIZE(log_categories),
385};
386
387
388int main(int argc, char **argv)
389{
Neels Hofmeyr3a8e7232017-09-04 01:02:56 +0200390 ctx = talloc_named_const(NULL, 1, "mgcp_client_test");
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200391 msgb_talloc_ctx_init(ctx, 0);
Neels Hofmeyr60f8e312018-03-30 23:01:07 +0200392 osmo_init_logging2(ctx, &log_info);
Philipp Maier8348abb2017-10-25 12:14:13 +0200393 log_set_print_filename(osmo_stderr_target, 0);
394 log_set_print_timestamp(osmo_stderr_target, 0);
395 log_set_use_color(osmo_stderr_target, 0);
396 log_set_print_category(osmo_stderr_target, 1);
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200397
Neels Hofmeyrc8f37cb2017-11-30 13:43:11 +0100398 log_set_category_filter(osmo_stderr_target, DLMGCP, 1, LOGL_DEBUG);
399
Neels Hofmeyr3a8e7232017-09-04 01:02:56 +0200400 mgcp_client_conf_init(&conf);
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200401
402 test_crcx();
Philipp Maier1dc6be62017-10-05 18:25:37 +0200403 test_mgcp_msg();
Neels Hofmeyrc8f37cb2017-11-30 13:43:11 +0100404 test_mgcp_client_cancel();
Neels Hofmeyra8c6a9c2018-02-21 15:36:45 +0100405 test_sdp_section_start();
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200406
407 printf("Done\n");
408 fprintf(stderr, "Done\n");
409 return EXIT_SUCCESS;
410}