blob: 9f09a99bec87ef8f4e96f3a4cb18b875cf49aabf [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 Hofmeyr1d121482018-09-03 21:05:13 +020080 const char *params)
Neels Hofmeyre9920f22017-07-10 15:07:22 +020081{
82 static char compose[4096 - 128];
83 int len;
84
85 len = snprintf(compose, sizeof(compose),
Neels Hofmeyr1d121482018-09-03 21:05:13 +020086 "%d %u %s\r\n%s",
87 code, trans_id, comment, params);
Neels Hofmeyre9920f22017-07-10 15:07:22 +020088 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{
Philipp Maier704c4f02018-06-07 18:51:31 +020098 unsigned int i;
Neels Hofmeyre9920f22017-07-10 15:07:22 +020099 OSMO_ASSERT(priv == mgcp);
100 mgcp_response_parse_params(response);
101
Philipp Maier704c4f02018-06-07 18:51:31 +0200102 printf("response cb received:\n");
103 printf(" head.response_code = %d\n", response->head.response_code);
104 printf(" head.trans_id = %u\n", response->head.trans_id);
Neels Hofmeyr40f50332018-09-03 21:12:48 +0200105 printf(" head.conn_id = %s\n", response->head.conn_id);
Philipp Maier704c4f02018-06-07 18:51:31 +0200106 printf(" head.comment = %s\n", response->head.comment);
107 printf(" audio_port = %u\n", response->audio_port);
108 printf(" audio_ip = %s\n", response->audio_ip);
109 printf(" ptime = %u\n", response->ptime);
110 printf(" codecs_len = %u\n", response->codecs_len);
111 for(i=0;i<response->codecs_len;i++)
112 printf(" codecs[%u] = %u\n", i, response->codecs[i]);
113 printf(" ptmap_len = %u\n", response->ptmap_len);
114 for(i=0;i<response->ptmap_len;i++) {
115 printf(" ptmap[%u].codec = %u\n", i, response->ptmap[i].codec);
Pau Espin Pedrol21cdbfc2019-04-23 12:36:32 +0200116 printf(" ptmap[%u].pt = %u\n", i, response->ptmap[i].pt);
Philipp Maier704c4f02018-06-07 18:51:31 +0200117 }
Pau Espin Pedrol21cdbfc2019-04-23 12:36:32 +0200118
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200119}
120
121mgcp_trans_id_t dummy_mgcp_send(struct msgb *msg)
122{
123 mgcp_trans_id_t trans_id;
124 trans_id = msg->cb[MSGB_CB_MGCP_TRANS_ID];
125 char *end;
126
Neels Hofmeyr3a8e7232017-09-04 01:02:56 +0200127 OSMO_ASSERT(mgcp_client_pending_add(mgcp, trans_id, test_response_cb, mgcp));
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200128
129 end = (char*)msgb_put(msg, 1);
130 *end = '\0';
131 printf("composed:\n-----\n%s\n-----\n",
132 (char*)msgb_l2(msg));
133
134 talloc_free(msg);
135 return trans_id;
136}
137
Philipp Maier1dc6be62017-10-05 18:25:37 +0200138void test_mgcp_msg(void)
139{
140 struct msgb *msg;
141 char audio_ip_overflow[5000];
142
143 /* A message struct prefilled with some arbitary values */
144 struct mgcp_msg mgcp_msg = {
145 .audio_ip = "192.168.100.23",
146 .endpoint = "23@mgw",
147 .audio_port = 1234,
148 .call_id = 47,
Philipp Maier01d24a32017-11-21 17:26:09 +0100149 .conn_id = "11",
Philipp Maier704c4f02018-06-07 18:51:31 +0200150 .conn_mode = MGCP_CONN_RECV_SEND,
151 .ptime = 20,
152 .codecs[0] = CODEC_GSM_8000_1,
153 .codecs[1] = CODEC_AMR_8000_1,
154 .codecs[2] = CODEC_GSMEFR_8000_1,
155 .codecs_len = 1,
156 .ptmap[0].codec = CODEC_GSMEFR_8000_1,
157 .ptmap[0].pt = 96,
Neels Hofmeyre6d8e912018-08-23 16:36:48 +0200158 .ptmap_len = 1,
159 .x_osmo_ign = MGCP_X_OSMO_IGN_CALLID,
Pau Espin Pedrol900cd652019-04-24 22:06:22 +0200160 .x_osmo_osmux_cid = -1, /* wildcard */
Philipp Maier1dc6be62017-10-05 18:25:37 +0200161 };
162
163 if (mgcp)
164 talloc_free(mgcp);
165 mgcp = mgcp_client_init(ctx, &conf);
166
167 printf("\n");
168
169 printf("Generated CRCX message:\n");
170 mgcp_msg.verb = MGCP_VERB_CRCX;
171 mgcp_msg.presence =
172 (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
173 MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE);
174 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
175 printf("%s\n", (char *)msg->data);
176
Philipp Maier704c4f02018-06-07 18:51:31 +0200177 printf("Generated CRCX message (two codecs):\n");
178 mgcp_msg.verb = MGCP_VERB_CRCX;
179 mgcp_msg.presence =
180 (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
181 MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE);
182 mgcp_msg.codecs_len = 2;
183 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
Pau Espin Pedrol21cdbfc2019-04-23 12:36:32 +0200184 mgcp_msg.codecs_len = 1;
Philipp Maier704c4f02018-06-07 18:51:31 +0200185 printf("%s\n", (char *)msg->data);
186
187 printf("Generated CRCX message (three codecs, one with custom pt):\n");
188 mgcp_msg.verb = MGCP_VERB_CRCX;
189 mgcp_msg.presence =
190 (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
191 MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE);
192 mgcp_msg.codecs_len = 3;
193 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
Pau Espin Pedrol21cdbfc2019-04-23 12:36:32 +0200194 mgcp_msg.codecs_len = 1;
195 printf("%s\n", (char *)msg->data);
Philipp Maier704c4f02018-06-07 18:51:31 +0200196
Philipp Maier1dc6be62017-10-05 18:25:37 +0200197 printf("Generated MDCX message:\n");
198 mgcp_msg.verb = MGCP_VERB_MDCX;
199 mgcp_msg.presence =
200 (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
201 MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE |
202 MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT);
203 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
204 printf("%s\n", (char *)msg->data);
205
Philipp Maier704c4f02018-06-07 18:51:31 +0200206 printf("Generated MDCX message (two codecs):\n");
207 mgcp_msg.verb = MGCP_VERB_MDCX;
208 mgcp_msg.presence =
209 (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
210 MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE |
211 MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT);
212 mgcp_msg.codecs_len = 2;
213 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
Pau Espin Pedrol21cdbfc2019-04-23 12:36:32 +0200214 mgcp_msg.codecs_len = 1;
Philipp Maier704c4f02018-06-07 18:51:31 +0200215 printf("%s\n", (char *)msg->data);
216
217 printf("Generated MDCX message (three codecs, one with custom pt):\n");
218 mgcp_msg.verb = MGCP_VERB_MDCX;
219 mgcp_msg.presence =
220 (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
221 MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE |
222 MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT);
223 mgcp_msg.codecs_len = 3;
224 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
Pau Espin Pedrol21cdbfc2019-04-23 12:36:32 +0200225 mgcp_msg.codecs_len = 1;
226 printf("%s\n", (char *)msg->data);
Philipp Maier704c4f02018-06-07 18:51:31 +0200227
Philipp Maier1dc6be62017-10-05 18:25:37 +0200228 printf("Generated DLCX message:\n");
229 mgcp_msg.verb = MGCP_VERB_DLCX;
230 mgcp_msg.presence =
231 (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
232 MGCP_MSG_PRESENCE_CONN_ID);
233 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
234 printf("%s\n", (char *)msg->data);
235
236 printf("Generated AUEP message:\n");
237 mgcp_msg.verb = MGCP_VERB_AUEP;
238 mgcp_msg.presence = (MGCP_MSG_PRESENCE_ENDPOINT);
239 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
240 printf("%s\n", msg->data);
241
242 printf("Generated RSIP message:\n");
243 mgcp_msg.verb = MGCP_VERB_RSIP;
244 mgcp_msg.presence = (MGCP_MSG_PRESENCE_ENDPOINT);
245 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
246 printf("%s\n", (char *)msg->data);
247
Neels Hofmeyre6d8e912018-08-23 16:36:48 +0200248 printf("Generate X-Osmo-IGN message:\n");
249 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
250 mgcp_msg.verb = MGCP_VERB_CRCX;
251 mgcp_msg.presence =
252 (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
253 MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE
254 | MGCP_MSG_PRESENCE_X_OSMO_IGN);
255 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
256 printf("%s\n", (char *)msg->data);
257
Pau Espin Pedrol900cd652019-04-24 22:06:22 +0200258 printf("Generate X-Osmo-Osmux message:\n");
259 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
260 mgcp_msg.verb = MGCP_VERB_CRCX;
261 mgcp_msg.presence =
262 (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
263 MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE
264 | MGCP_MSG_PRESENCE_X_OSMO_OSMUX_CID);
265 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
266 printf("%s\n", (char *)msg->data);
267
268 printf("Generate X-Osmo-Osmux message (fixed CID 2):\n");
269 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
270 mgcp_msg.verb = MGCP_VERB_CRCX;
271 mgcp_msg.x_osmo_osmux_cid = 2;
272 mgcp_msg.presence =
273 (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
274 MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE
275 | MGCP_MSG_PRESENCE_X_OSMO_OSMUX_CID);
276 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
277 printf("%s\n", (char *)msg->data);
278
Pau Espin Pedrolca538fc2019-05-10 16:49:59 +0200279 printf("Generate X-Osmo-Osmux message (MDCX):\n");
280 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
281 mgcp_msg.verb = MGCP_VERB_MDCX;
282 mgcp_msg.x_osmo_osmux_cid = 2;
283 mgcp_msg.presence =
284 (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
285 MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE
286 | MGCP_MSG_PRESENCE_X_OSMO_OSMUX_CID);
287 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
288 printf("%s\n", (char *)msg->data);
289
Philipp Maier1dc6be62017-10-05 18:25:37 +0200290 printf("Overfolow test:\n");
291 mgcp_msg.verb = MGCP_VERB_MDCX;
292 mgcp_msg.presence =
293 (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
294 MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE |
295 MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT);
296 memset(audio_ip_overflow, 'X', sizeof(audio_ip_overflow));
Pau Espin Pedrol9dc73592020-08-28 20:21:55 +0200297 audio_ip_overflow[1] = '.';
Philipp Maier1dc6be62017-10-05 18:25:37 +0200298 audio_ip_overflow[sizeof(audio_ip_overflow) - 1] = '\0';
299 mgcp_msg.audio_ip = audio_ip_overflow;
300 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
301 OSMO_ASSERT(msg == NULL);
302
Pau Espin Pedrol9dc73592020-08-28 20:21:55 +0200303 printf("IPv6 test:\n");
304 mgcp_msg.verb = MGCP_VERB_MDCX;
305 mgcp_msg.presence =
306 (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
307 MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE |
308 MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT);
309 mgcp_msg.audio_ip = "2001:db8:1::ab9:c0a8:102";
310 mgcp->actual.remote_addr = "::1";
311 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
312 printf("%s\n", (char *)msg->data);
313
Philipp Maier1dc6be62017-10-05 18:25:37 +0200314 printf("\n");
315 msgb_free(msg);
316}
317
Neels Hofmeyrc8f37cb2017-11-30 13:43:11 +0100318void test_mgcp_client_cancel()
319{
320 mgcp_trans_id_t trans_id;
321 struct msgb *msg;
322 struct mgcp_msg mgcp_msg = {
323 .verb = MGCP_VERB_CRCX,
324 .audio_ip = "192.168.100.23",
325 .endpoint = "23@mgw",
326 .audio_port = 1234,
327 .call_id = 47,
Philipp Maier922ae9a2017-12-04 15:53:37 +0100328 .conn_id = "11",
Neels Hofmeyrc8f37cb2017-11-30 13:43:11 +0100329 .conn_mode = MGCP_CONN_RECV_SEND,
330 .presence = (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID
331 | MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE),
Philipp Maier704c4f02018-06-07 18:51:31 +0200332 .ptime = 20,
333 .codecs[0] = CODEC_AMR_8000_1,
Pau Espin Pedrol21cdbfc2019-04-23 12:36:32 +0200334 .codecs_len = 1
Neels Hofmeyrc8f37cb2017-11-30 13:43:11 +0100335 };
336
337 printf("\n%s():\n", __func__);
338 fprintf(stderr, "\n%s():\n", __func__);
339
340 if (mgcp)
341 talloc_free(mgcp);
342 mgcp = mgcp_client_init(ctx, &conf);
343
344 msg = mgcp_msg_gen(mgcp, &mgcp_msg);
345 trans_id = mgcp_msg_trans_id(msg);
346 fprintf(stderr, "- composed msg with trans_id=%u\n", trans_id);
347
348 fprintf(stderr, "- not in queue yet, cannot cancel yet\n");
349 OSMO_ASSERT(mgcp_client_cancel(mgcp, trans_id) == -ENOENT);
350
351 fprintf(stderr, "- enqueue\n");
352 dummy_mgcp_send(msg);
353
354 fprintf(stderr, "- cancel succeeds\n");
355 OSMO_ASSERT(mgcp_client_cancel(mgcp, trans_id) == 0);
356
357 fprintf(stderr, "- late response gets discarded\n");
Neels Hofmeyrb1bb1fa2018-09-03 21:07:26 +0200358 OSMO_ASSERT(reply_to(trans_id, 200, "OK", "I: 1\r\n\r\nv=0\r\n") == -ENOENT);
Neels Hofmeyrc8f37cb2017-11-30 13:43:11 +0100359
360 fprintf(stderr, "- canceling again does nothing\n");
361 OSMO_ASSERT(mgcp_client_cancel(mgcp, trans_id) == -ENOENT);
362
363 fprintf(stderr, "%s() done\n", __func__);
364}
365
Neels Hofmeyra8c6a9c2018-02-21 15:36:45 +0100366struct sdp_section_start_test {
367 const char *body;
368 int expect_rc;
369 struct mgcp_response expect_params;
370};
371
372static struct sdp_section_start_test sdp_section_start_tests[] = {
373 {
374 .body = "",
Neels Hofmeyre8278312019-09-19 03:06:46 +0200375 .expect_rc = 0,
Neels Hofmeyra8c6a9c2018-02-21 15:36:45 +0100376 },
377 {
378 .body = "\n\n",
379 },
380 {
381 .body = "\r\n\r\n",
382 },
383 {
384 .body = "\n\r\n\r",
385 },
386 {
387 .body = "some mgcp header data\r\nand header params"
388 "\n\n"
389 "m=audio 23\r\n",
390 .expect_params = {
391 .audio_port = 23,
392 },
393 },
394 {
395 .body = "some mgcp header data\r\nand header params"
396 "\r\n\r\n"
397 "m=audio 23\r\n",
398 .expect_params = {
399 .audio_port = 23,
400 },
401 },
402 {
403 .body = "some mgcp header data\r\nand header params"
404 "\n\r\n\r"
405 "m=audio 23\r\n",
406 .expect_params = {
407 .audio_port = 23,
408 },
409 },
410 {
411 .body = "some mgcp header data\r\nand header params"
412 "\n\r\n"
413 "m=audio 23\r\n",
Neels Hofmeyre8278312019-09-19 03:06:46 +0200414 .expect_rc = 0,
Neels Hofmeyra8c6a9c2018-02-21 15:36:45 +0100415 },
416 {
417 .body = "some mgcp header data\r\nand header params"
418 "\r\n\r"
419 "m=audio 23\r\n",
Neels Hofmeyre8278312019-09-19 03:06:46 +0200420 .expect_rc = 0,
Neels Hofmeyra8c6a9c2018-02-21 15:36:45 +0100421 },
422 {
423 .body = "some mgcp header data\r\nand header params"
424 "\n\r\r"
425 "m=audio 23\r\n",
Neels Hofmeyre8278312019-09-19 03:06:46 +0200426 .expect_rc = 0,
Neels Hofmeyra8c6a9c2018-02-21 15:36:45 +0100427 },
Pau Espin Pedrol9dc73592020-08-28 20:21:55 +0200428 {
429 .body = "some mgcp header data\r\nand header params"
430 "\r\n\r\n"
431 "c=IN IP4 1.2.3.4\r\n",
432 .expect_params = {
433 .audio_ip = "1.2.3.4",
434 },
435 .expect_rc = 0,
436 },
437 {
438 .body = "some mgcp header data\r\nand header params"
439 "\r\n\r\n"
440 "c=IN IP6 2001:db8:1::ab9:c0a8:102\r\n",
441 .expect_params = {
442 .audio_ip = "2001:db8:1::ab9:c0a8:102",
443 },
444 .expect_rc = 0,
445 },
446 {
447 .body = "some mgcp header data\r\nand header params"
448 "\r\n\r\n"
449 "c=IN IP6 1.2.3.4\r\n",
450 .expect_rc = -22,
451 },
452 {
453 .body = "some mgcp header data\r\nand header params"
454 "\r\n\r\n"
455 "c=IN IP4 ::1\r\n",
456 .expect_rc = -22,
457 },
458 {
459 .body = "some mgcp header data\r\nand header params"
460 "\r\n\r\n"
461 "c=IN IP4 notanip\r\n",
462 .expect_rc = -22,
463 },
464 {
465 .body = "some mgcp header data\r\nand header params"
466 "\r\n\r\n"
467 "c=IN IP4 1.2.3.4.5.6\r\n",
468 .expect_rc = -22,
469 },
470 {
471 .body = "some mgcp header data\r\nand header params"
472 "\r\n\r\n"
473 "c=IN IP4 1.2 .3\r\n",
474 .expect_rc = -22,
475 },
476 {
477 .body = "some mgcp header data\r\nand header params"
478 "\r\n\r\n"
479 "c=IN IP4 1.2 .3\r\n",
480 .expect_rc = -22,
481 },
482 {
483 .body = "some mgcp header data\r\nand header params"
484 "\r\n\r\n"
485 "c=IN IP4 \r\n",
486 .expect_rc = -22,
487 },
Neels Hofmeyra8c6a9c2018-02-21 15:36:45 +0100488};
489
490void test_sdp_section_start()
491{
492 int i;
493 int failures = 0;
494
495 for (i = 0; i < ARRAY_SIZE(sdp_section_start_tests); i++) {
496 int rc;
497 struct sdp_section_start_test *t = &sdp_section_start_tests[i];
498 struct mgcp_response *r = talloc_zero(ctx, struct mgcp_response);
499
500 r->body = talloc_strdup(r, t->body);
501
502 printf("\n%s() test [%d]:\n", __func__, i);
503 fprintf(stderr, "\n%s() test [%d]:\n", __func__, i);
504 fprintf(stderr, "body: \"%s\"\n", osmo_escape_str(r->body, -1));
505
506 rc = mgcp_response_parse_params(r);
507
508 fprintf(stderr, "got rc=%d\n", rc);
509 if (rc != t->expect_rc) {
510 fprintf(stderr, "FAIL: Expected rc=%d\n", t->expect_rc);
511 failures++;
512 }
513 if (rc) {
514 talloc_free(r);
515 continue;
516 }
517
Pau Espin Pedrol9dc73592020-08-28 20:21:55 +0200518 fprintf(stderr, "got audio_ip=\"%s\"\n", r->audio_ip);
519 if (strcmp(r->audio_ip, t->expect_params.audio_ip)) {
520 fprintf(stderr, "FAIL: Expected audio_ip=\"%s\"\n", t->expect_params.audio_ip);
521 failures++;
522 }
523 fprintf(stderr, "got audio_port=%u\n", r->audio_port);
Neels Hofmeyra8c6a9c2018-02-21 15:36:45 +0100524 if (r->audio_port != t->expect_params.audio_port) {
525 fprintf(stderr, "FAIL: Expected audio_port=%u\n", t->expect_params.audio_port);
526 failures++;
527 }
528 talloc_free(r);
529 }
530
Neels Hofmeyra8c6a9c2018-02-21 15:36:45 +0100531 OSMO_ASSERT(!failures);
Neels Hofmeyra8c6a9c2018-02-21 15:36:45 +0100532}
533
Philipp Maier704c4f02018-06-07 18:51:31 +0200534static void test_map_pt_to_codec(void)
535{
536 /* Full form */
537 OSMO_ASSERT(map_str_to_codec("PCMU/8000/1") == CODEC_PCMU_8000_1);
538 OSMO_ASSERT(map_str_to_codec("GSM/8000/1") == CODEC_GSM_8000_1);
539 OSMO_ASSERT(map_str_to_codec("PCMA/8000/1") == CODEC_PCMA_8000_1);
540 OSMO_ASSERT(map_str_to_codec("G729/8000/1") == CODEC_G729_8000_1);
541 OSMO_ASSERT(map_str_to_codec("GSM-EFR/8000/1") == CODEC_GSMEFR_8000_1);
542 OSMO_ASSERT(map_str_to_codec("GSM-HR-08/8000/1") == CODEC_GSMHR_8000_1);
543 OSMO_ASSERT(map_str_to_codec("AMR/8000/1") == CODEC_AMR_8000_1);
544 OSMO_ASSERT(map_str_to_codec("AMR-WB/16000/1") == CODEC_AMRWB_16000_1);
545
546 /* Short form */
547 OSMO_ASSERT(map_str_to_codec("GSM-EFR") == CODEC_GSMEFR_8000_1);
548 OSMO_ASSERT(map_str_to_codec("G729") == CODEC_G729_8000_1);
549 OSMO_ASSERT(map_str_to_codec("GSM-HR-08") == CODEC_GSMHR_8000_1);
550
551 /* We do not care about what is after the first delimiter */
552 OSMO_ASSERT(map_str_to_codec("AMR-WB/123///456") == CODEC_AMRWB_16000_1);
553 OSMO_ASSERT(map_str_to_codec("PCMA/asdf") == CODEC_PCMA_8000_1);
554 OSMO_ASSERT(map_str_to_codec("GSM/qwertz") == CODEC_GSM_8000_1);
555
556 /* A trailing delimiter should not hurt */
557 OSMO_ASSERT(map_str_to_codec("AMR/") == CODEC_AMR_8000_1);
558 OSMO_ASSERT(map_str_to_codec("G729/") == CODEC_G729_8000_1);
559 OSMO_ASSERT(map_str_to_codec("GSM/") == CODEC_GSM_8000_1);
560
561 /* This is expected to fail */
562 OSMO_ASSERT(map_str_to_codec("INVALID/1234/7") == -1);
563 OSMO_ASSERT(map_str_to_codec(NULL) == -1);
564 OSMO_ASSERT(map_str_to_codec("") == -1);
565 OSMO_ASSERT(map_str_to_codec("/////") == -1);
566
567 /* The buffers are 64 bytes long, check what happens with overlong
568 * strings as input (This schould still work.) */
569 OSMO_ASSERT(map_str_to_codec("AMR-WB/16000/1############################################################################################################") == CODEC_AMRWB_16000_1);
570
571 /* This should not work, as there is no delimiter after the codec
572 * name */
573 OSMO_ASSERT(map_str_to_codec("AMR-WB####################################################################################################################") == -1);
574}
575
576static void test_map_codec_to_pt_and_map_pt_to_codec(void)
577{
578 struct ptmap ptmap[10];
579 unsigned int ptmap_len;
580 unsigned int i;
581
582 ptmap[0].codec = CODEC_GSMEFR_8000_1;
583 ptmap[0].pt = 96;
584 ptmap[1].codec = CODEC_GSMHR_8000_1;
585 ptmap[1].pt = 97;
586 ptmap[2].codec = CODEC_AMR_8000_1;
587 ptmap[2].pt = 98;
588 ptmap[3].codec = CODEC_AMRWB_16000_1;
589 ptmap[3].pt = 99;
590 ptmap_len = 4;
591
592 /* Mappings that are covered by the table */
593 for (i = 0; i < ptmap_len; i++)
594 printf(" %u => %u\n", ptmap[i].codec, map_codec_to_pt(ptmap, ptmap_len, ptmap[i].codec));
595 for (i = 0; i < ptmap_len; i++)
596 printf(" %u <= %u\n", ptmap[i].pt, map_pt_to_codec(ptmap, ptmap_len, ptmap[i].pt));
597 printf("\n");
598
599 /* Map some codecs/payload types from the static range, result must
600 * always be a 1:1 mapping */
601 printf(" %u => %u\n", CODEC_PCMU_8000_1, map_codec_to_pt(ptmap, ptmap_len, CODEC_PCMU_8000_1));
602 printf(" %u => %u\n", CODEC_GSM_8000_1, map_codec_to_pt(ptmap, ptmap_len, CODEC_GSM_8000_1));
603 printf(" %u => %u\n", CODEC_PCMA_8000_1, map_codec_to_pt(ptmap, ptmap_len, CODEC_PCMA_8000_1));
604 printf(" %u => %u\n", CODEC_G729_8000_1, map_codec_to_pt(ptmap, ptmap_len, CODEC_G729_8000_1));
605 printf(" %u <= %u\n", CODEC_PCMU_8000_1, map_pt_to_codec(ptmap, ptmap_len, CODEC_PCMU_8000_1));
606 printf(" %u <= %u\n", CODEC_GSM_8000_1, map_pt_to_codec(ptmap, ptmap_len, CODEC_GSM_8000_1));
607 printf(" %u <= %u\n", CODEC_PCMA_8000_1, map_pt_to_codec(ptmap, ptmap_len, CODEC_PCMA_8000_1));
608 printf(" %u <= %u\n", CODEC_G729_8000_1, map_pt_to_codec(ptmap, ptmap_len, CODEC_G729_8000_1));
609 printf("\n");
610
611 /* Try to do mappings from statically defined range to danymic range and vice versa. This
612 * is illegal and should result into a 1:1 mapping */
613 ptmap[3].codec = CODEC_AMRWB_16000_1;
614 ptmap[3].pt = 2;
615 ptmap[4].codec = CODEC_PCMU_8000_1;
616 ptmap[4].pt = 100;
617 ptmap_len = 5;
618
619 /* Apply all mappings again, the illegal ones we defined should result into 1:1 mappings */
620 for (i = 0; i < ptmap_len; i++)
621 printf(" %u => %u\n", ptmap[i].codec, map_codec_to_pt(ptmap, ptmap_len, ptmap[i].codec));
622 for (i = 0; i < ptmap_len; i++)
623 printf(" %u <= %u\n", ptmap[i].pt, map_pt_to_codec(ptmap, ptmap_len, ptmap[i].pt));
624 printf("\n");
625}
626
Philipp Maier48635912020-06-25 20:16:22 +0200627void test_mgcp_client_e1_epname(void)
628{
629 char *epname;
630
631 if (mgcp)
632 talloc_free(mgcp);
633 mgcp = mgcp_client_init(ctx, &conf);
634
635 /* Valid endpoint names */
636 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 1, 15, 64, 0);
637 printf("%s\n", epname);
638 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 2, 14, 32, 0);
639 printf("%s\n", epname);
640 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 3, 13, 32, 4);
641 printf("%s\n", epname);
642 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 4, 12, 16, 0);
643 printf("%s\n", epname);
644 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 5, 11, 16, 2);
645 printf("%s\n", epname);
646 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 6, 10, 16, 4);
647 printf("%s\n", epname);
648 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 7, 9, 16, 6);
649 printf("%s\n", epname);
650 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 8, 8, 8, 0);
651 printf("%s\n", epname);
652 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 9, 7, 8, 1);
653 printf("%s\n", epname);
654 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 10, 6, 8, 2);
655 printf("%s\n", epname);
656 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 11, 5, 8, 3);
657 printf("%s\n", epname);
658 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 12, 4, 8, 4);
659 printf("%s\n", epname);
660 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 13, 3, 8, 5);
661 printf("%s\n", epname);
662 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 14, 2, 8, 6);
663 printf("%s\n", epname);
664 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 15, 1, 8, 7);
665 printf("%s\n", epname);
666
667 /* A few invalid enpoint names */
668 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 15, 1, 128, 0);
669 OSMO_ASSERT(epname == NULL);
670 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 15, 1, 8, 16);
671 OSMO_ASSERT(epname == NULL);
672 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 15, 0, 8, 2);
673 OSMO_ASSERT(epname == NULL);
674 epname = (char *)mgcp_client_e1_epname(ctx, mgcp, 15, 64, 8, 2);
675 OSMO_ASSERT(epname == NULL);
676}
677
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200678static const struct log_info_cat log_categories[] = {
679};
680
681const struct log_info log_info = {
682 .cat = log_categories,
683 .num_cat = ARRAY_SIZE(log_categories),
684};
685
686
687int main(int argc, char **argv)
688{
Neels Hofmeyr3a8e7232017-09-04 01:02:56 +0200689 ctx = talloc_named_const(NULL, 1, "mgcp_client_test");
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200690 msgb_talloc_ctx_init(ctx, 0);
Neels Hofmeyr60f8e312018-03-30 23:01:07 +0200691 osmo_init_logging2(ctx, &log_info);
Pau Espin Pedrolace0b942021-02-19 13:33:52 +0100692 log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
Philipp Maier8348abb2017-10-25 12:14:13 +0200693 log_set_print_timestamp(osmo_stderr_target, 0);
694 log_set_use_color(osmo_stderr_target, 0);
Pau Espin Pedrolace0b942021-02-19 13:33:52 +0100695 log_set_print_category_hex(osmo_stderr_target, 0);
Philipp Maier8348abb2017-10-25 12:14:13 +0200696 log_set_print_category(osmo_stderr_target, 1);
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200697
Neels Hofmeyrc8f37cb2017-11-30 13:43:11 +0100698 log_set_category_filter(osmo_stderr_target, DLMGCP, 1, LOGL_DEBUG);
699
Neels Hofmeyr3a8e7232017-09-04 01:02:56 +0200700 mgcp_client_conf_init(&conf);
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200701
Philipp Maier1dc6be62017-10-05 18:25:37 +0200702 test_mgcp_msg();
Neels Hofmeyrc8f37cb2017-11-30 13:43:11 +0100703 test_mgcp_client_cancel();
Neels Hofmeyra8c6a9c2018-02-21 15:36:45 +0100704 test_sdp_section_start();
Philipp Maier704c4f02018-06-07 18:51:31 +0200705 test_map_codec_to_pt_and_map_pt_to_codec();
706 test_map_pt_to_codec();
Philipp Maier48635912020-06-25 20:16:22 +0200707 test_mgcp_client_e1_epname();
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200708
709 printf("Done\n");
710 fprintf(stderr, "Done\n");
711 return EXIT_SUCCESS;
712}