From 31b4729f2731c747b8b33c4646dd5ade2ace29bc Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Fri, 17 Aug 2018 18:15:21 +0200 Subject: [PATCH] Remove libosmo-legacy-mgcp and osmo-bsc-mgcp They are only used by openbsc.git programs and belong there. Change-Id: Id31bef052d3f9b8aada1824d6f7f995ebd39bbfd --- Makefile.am | 1 - README | 4 - configure.ac | 28 - contrib/systemd/osmo-bsc-mgcp.service | 11 - debian/control | 21 - debian/copyright | 36 - debian/libosmo-legacy-mgcp-dev.install | 4 - debian/libosmo-legacy-mgcp0.install | 1 - debian/osmo-bsc-mgcp.install | 2 - doc/examples/osmo-bsc_mgcp/mgcp.cfg | 14 - include/Makefile.am | 3 - include/osmocom/Makefile.am | 1 - include/osmocom/legacy_mgcp/Makefile.am | 4 - include/osmocom/legacy_mgcp/mgcp.h | 298 ---- include/osmocom/legacy_mgcp/mgcp_internal.h | 351 ---- include/osmocom/legacy_mgcp/mgcp_transcode.h | 94 - include/osmocom/legacy_mgcp/osmux.h | 41 - include/osmocom/legacy_mgcp/vty.h | 8 - libosmo-legacy-mgcp.pc.in | 10 - osmoappdesc.py | 2 - src/Makefile.am | 2 - src/libosmo-legacy-mgcp/Makefile.am | 51 - src/libosmo-legacy-mgcp/g711common.h | 187 -- src/libosmo-legacy-mgcp/mgcp_common.c | 54 - src/libosmo-legacy-mgcp/mgcp_network.c | 1202 ------------- src/libosmo-legacy-mgcp/mgcp_osmux.c | 588 ------- src/libosmo-legacy-mgcp/mgcp_protocol.c | 1665 ------------------ src/libosmo-legacy-mgcp/mgcp_sdp.c | 305 ---- src/libosmo-legacy-mgcp/mgcp_transcode.c | 611 ------- src/libosmo-legacy-mgcp/mgcp_vty.c | 1627 ----------------- src/osmo-bsc_mgcp/Makefile.am | 31 - src/osmo-bsc_mgcp/mgcp_main.c | 351 ---- tests/Makefile.am | 3 - tests/atlocal.in | 1 - tests/legacy_mgcp/Makefile.am | 61 - tests/legacy_mgcp/mgcp_test.c | 1242 ------------- tests/legacy_mgcp/mgcp_test.ok | 480 ----- tests/legacy_mgcp/mgcp_transcoding_test.c | 662 ------- tests/legacy_mgcp/mgcp_transcoding_test.ok | 539 ------ tests/testsuite.at | 13 - tests/vty_test_runner.py | 171 -- 41 files changed, 10780 deletions(-) delete mode 100644 contrib/systemd/osmo-bsc-mgcp.service delete mode 100644 debian/libosmo-legacy-mgcp-dev.install delete mode 100644 debian/libosmo-legacy-mgcp0.install delete mode 100644 debian/osmo-bsc-mgcp.install delete mode 100644 doc/examples/osmo-bsc_mgcp/mgcp.cfg delete mode 100644 include/osmocom/legacy_mgcp/Makefile.am delete mode 100644 include/osmocom/legacy_mgcp/mgcp.h delete mode 100644 include/osmocom/legacy_mgcp/mgcp_internal.h delete mode 100644 include/osmocom/legacy_mgcp/mgcp_transcode.h delete mode 100644 include/osmocom/legacy_mgcp/osmux.h delete mode 100644 include/osmocom/legacy_mgcp/vty.h delete mode 100644 libosmo-legacy-mgcp.pc.in delete mode 100644 src/libosmo-legacy-mgcp/Makefile.am delete mode 100644 src/libosmo-legacy-mgcp/g711common.h delete mode 100644 src/libosmo-legacy-mgcp/mgcp_common.c delete mode 100644 src/libosmo-legacy-mgcp/mgcp_network.c delete mode 100644 src/libosmo-legacy-mgcp/mgcp_osmux.c delete mode 100644 src/libosmo-legacy-mgcp/mgcp_protocol.c delete mode 100644 src/libosmo-legacy-mgcp/mgcp_sdp.c delete mode 100644 src/libosmo-legacy-mgcp/mgcp_transcode.c delete mode 100644 src/libosmo-legacy-mgcp/mgcp_vty.c delete mode 100644 src/osmo-bsc_mgcp/Makefile.am delete mode 100644 src/osmo-bsc_mgcp/mgcp_main.c delete mode 100644 tests/legacy_mgcp/Makefile.am delete mode 100644 tests/legacy_mgcp/mgcp_test.c delete mode 100644 tests/legacy_mgcp/mgcp_test.ok delete mode 100644 tests/legacy_mgcp/mgcp_transcoding_test.c delete mode 100644 tests/legacy_mgcp/mgcp_transcoding_test.ok delete mode 100644 tests/vty_test_runner.py diff --git a/Makefile.am b/Makefile.am index 8fb6e6cc9..3270e4f21 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,7 +18,6 @@ SUBDIRS = \ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = \ - libosmo-legacy-mgcp.pc \ libosmo-mgcp-client.pc \ $(NULL) diff --git a/README b/README index 7f55fe678..29883b8fd 100644 --- a/README +++ b/README @@ -19,10 +19,6 @@ OsmoBSC, and receives and sends RTP streams as configured via MGCP. The libosmo-mgcp-client library exposes utilities used by e.g. OsmoMSC (found in osmo-msc.git) to instruct OsmoMGW via its MGCP service. -The libosmo-mgcp library exposes MGCP server utilities used by e.g. OsmoBSC-NAT -(found in osmo-bsc.git) to navigate RTP streams through a NAT. -(At time of writing, this is still called libosmo-legacy-mgcp.) - Find OsmoMGW issue tracker and wiki online at https://osmocom.org/projects/osmo-mgw https://osmocom.org/projects/osmo-mgw/wiki diff --git a/configure.ac b/configure.ac index b0b0d2106..9f021df39 100644 --- a/configure.ac +++ b/configure.ac @@ -74,29 +74,6 @@ then CPPFLAGS="$CPPFLAGS $WERROR_FLAGS" fi -# Enable/disable transcoding within osmo-bsc_mgcp? -AC_ARG_ENABLE([mgcp-transcoding], [AS_HELP_STRING([--enable-mgcp-transcoding], [Build the MGCP gateway with internal transcoding enabled.])], - [osmo_ac_mgcp_transcoding="$enableval"],[osmo_ac_mgcp_transcoding="no"]) -AC_ARG_WITH([g729], [AS_HELP_STRING([--with-g729], [Enable G.729 encoding/decoding.])], [osmo_ac_with_g729="$withval"],[osmo_ac_with_g729="no"]) - -if test "$osmo_ac_mgcp_transcoding" = "yes" ; then - AC_CHECK_HEADERS([gsm.h gsm/gsm.h], [osmo_ac_found_gsm_headers=yes]) - if test "$osmo_ac_found_gsm_headers" != "yes" ; then - AC_MSG_ERROR([Unable to find the libgsm headers]) - fi - AC_SUBST(HAVE_GSM_H) - AC_SUBST(HAVE_GSM_GSM_H) - - AC_SEARCH_LIBS([gsm_create], [gsm], [LIBRARY_GSM="$LIBS";LIBS=""], [AC_MSG_ERROR([--enable-mgcp-transcoding: cannot find usable libgsm])]) - AC_SUBST(LIBRARY_GSM) - if test "$osmo_ac_with_g729" = "yes" ; then - PKG_CHECK_MODULES(LIBBCG729, libbcg729 >= 0.1, [AC_DEFINE([HAVE_BCG729], [1], [Use bgc729 decoder/encoder])]) - fi - AC_DEFINE(BUILD_MGCP_TRANSCODING, 1, [Define if we want to build the MGCP gateway with transcoding support]) -fi -AM_CONDITIONAL(BUILD_MGCP_TRANSCODING, test "x$osmo_ac_mgcp_transcoding" = "xyes") -AC_SUBST(osmo_ac_mgcp_transcoding) - dnl Checks for typedefs, structures and compiler characteristics # The following test is taken from WebKit's webkit.m4 @@ -158,22 +135,17 @@ dnl Generate the output AM_CONFIG_HEADER(bscconfig.h) AC_OUTPUT( - libosmo-legacy-mgcp.pc libosmo-mgcp-client.pc include/Makefile include/osmocom/Makefile - include/osmocom/legacy_mgcp/Makefile include/osmocom/mgcp_client/Makefile include/osmocom/mgcp/Makefile src/Makefile - src/libosmo-legacy-mgcp/Makefile src/libosmo-mgcp-client/Makefile src/libosmo-mgcp/Makefile - src/osmo-bsc_mgcp/Makefile src/osmo-mgw/Makefile tests/Makefile tests/atlocal - tests/legacy_mgcp/Makefile tests/mgcp_client/Makefile tests/mgcp/Makefile doc/Makefile diff --git a/contrib/systemd/osmo-bsc-mgcp.service b/contrib/systemd/osmo-bsc-mgcp.service deleted file mode 100644 index c040e6078..000000000 --- a/contrib/systemd/osmo-bsc-mgcp.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=OpenBSC MGCP - -[Service] -Type=simple -Restart=always -ExecStart=/usr/bin/osmo-bsc_mgcp -s -c /etc/osmocom/osmo-bsc-mgcp.cfg -RestartSec=2 - -[Install] -WantedBy=multi-user.target diff --git a/debian/control b/debian/control index 0fe098e6a..d51f4635d 100644 --- a/debian/control +++ b/debian/control @@ -33,24 +33,3 @@ Architecture: any Multi-Arch: same Depends: libosmo-mgcp-client3 (= ${binary:Version}), ${misc:Depends} Description: libosmo-mgcp-client: Osmocom's Media Gateway Control Protocol client utilities - -Package: osmo-bsc-mgcp -Architecture: any -Multi-Arch: foreign -Depends: libosmo-legacy-mgcp0, ${misc:Depends}, ${shlibs:Depends} -Description: OsmoBSC-MGCP: Osmocom's Legacy Media Gateway; use osmo-mgw instead. - -Package: libosmo-legacy-mgcp0 -Section: libs -Architecture: any -Multi-Arch: same -Pre-Depends: ${misc:Pre-Depends} -Depends: ${misc:Depends}, ${shlibs:Depends} -Description: libosmo-legacy-mgcp: Osmocom's Legacy Media Gateway server library; use libosmo-mgcp instead. - -Package: libosmo-legacy-mgcp-dev -Section: libdevel -Architecture: any -Multi-Arch: same -Depends: libosmo-legacy-mgcp0 (= ${binary:Version}), ${misc:Depends} -Description: libosmo-legacy-mgcp: Osmocom's Legacy Media Gateway server library; use libosmo-mgcp instead. diff --git a/debian/copyright b/debian/copyright index 467435f56..eb4b47812 100644 --- a/debian/copyright +++ b/debian/copyright @@ -40,30 +40,6 @@ License: GPL-2.0+ You should have received a copy of the GNU General Public License along with this program. If not, see . -Files: src/libosmo-legacy-mgcp/g711common.h -Copyright: 2000 Abramo Bagnara -License: GPL-2.0+ - Wrapper for linphone Codec class by Simon Morlat - . - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - . - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - . - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - . - The FSF address in the above text is the old one. - . - On Debian systems, the complete text of the GNU General Public License - Version 2 can be found in `/usr/share/common-licenses/GPL-2'. - Files: tests/vty_test_runner.py Copyright: 2013 Holger Hans Peter Freyther 2013 Katerina Barone-Adesi @@ -87,15 +63,3 @@ License: GPL-3.0+ Files: osmoappdesc.py Copyright: 2013 Katerina Barone-Adesi License: GPL-3.0+ - -Files: src/libosmo-legacy-mgcp/mgcp_osmux.c -Copyright: 2012-2013 On Waves ehf - 2012-2013 Pablo Neira Ayuso -License: AGPL-3.0+ - All rights not specifically granted under this license are reserved. - . - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published by the - Free Software Foundation; either version 3 of the License, or (at your - option) any later version. - diff --git a/debian/libosmo-legacy-mgcp-dev.install b/debian/libosmo-legacy-mgcp-dev.install deleted file mode 100644 index a57cb503f..000000000 --- a/debian/libosmo-legacy-mgcp-dev.install +++ /dev/null @@ -1,4 +0,0 @@ -usr/include/osmocom/legacy_mgcp -usr/lib/*/libosmo-legacy-mgcp.so -usr/lib/*/libosmo-legacy-mgcp.a -usr/lib/*/pkgconfig/libosmo-legacy-mgcp.pc diff --git a/debian/libosmo-legacy-mgcp0.install b/debian/libosmo-legacy-mgcp0.install deleted file mode 100644 index 90ca89d43..000000000 --- a/debian/libosmo-legacy-mgcp0.install +++ /dev/null @@ -1 +0,0 @@ -usr/lib/*/libosmo-legacy-mgcp.so.* diff --git a/debian/osmo-bsc-mgcp.install b/debian/osmo-bsc-mgcp.install deleted file mode 100644 index bed2f4798..000000000 --- a/debian/osmo-bsc-mgcp.install +++ /dev/null @@ -1,2 +0,0 @@ -usr/bin/osmo-bsc_mgcp -usr/share/doc/osmo-mgw/examples/osmo-bsc_mgcp/mgcp.cfg diff --git a/doc/examples/osmo-bsc_mgcp/mgcp.cfg b/doc/examples/osmo-bsc_mgcp/mgcp.cfg deleted file mode 100644 index 442162f94..000000000 --- a/doc/examples/osmo-bsc_mgcp/mgcp.cfg +++ /dev/null @@ -1,14 +0,0 @@ -! -! MGCP configuration example -! -mgcp - !local ip 10.23.24.2 - !bts ip 10.24.24.1 - !bind ip 10.23.24.1 - bind port 2427 - rtp base 4000 - rtp force-ptime 20 - sdp audio payload number 98 - sdp audio payload name AMR/8000 - number endpoints 31 - no rtcp-omit diff --git a/include/Makefile.am b/include/Makefile.am index e8fc2118c..c34553ac1 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -3,9 +3,6 @@ SUBDIRS = \ $(NULL) nobase_include_HEADERS = \ - osmocom/legacy_mgcp/mgcp.h \ - osmocom/legacy_mgcp/mgcp_internal.h \ - osmocom/legacy_mgcp/osmux.h \ osmocom/mgcp_client/mgcp_client.h \ osmocom/mgcp_client/mgcp_client_fsm.h \ osmocom/mgcp_client/mgcp_common.h \ diff --git a/include/osmocom/Makefile.am b/include/osmocom/Makefile.am index c752c40d4..9e7824964 100644 --- a/include/osmocom/Makefile.am +++ b/include/osmocom/Makefile.am @@ -1,5 +1,4 @@ SUBDIRS = \ - legacy_mgcp \ mgcp_client \ mgcp \ $(NULL) diff --git a/include/osmocom/legacy_mgcp/Makefile.am b/include/osmocom/legacy_mgcp/Makefile.am deleted file mode 100644 index 4a9550cb6..000000000 --- a/include/osmocom/legacy_mgcp/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -noinst_HEADERS = \ - mgcp_transcode.h \ - vty.h \ - $(NULL) diff --git a/include/osmocom/legacy_mgcp/mgcp.h b/include/osmocom/legacy_mgcp/mgcp.h deleted file mode 100644 index 7490e37d9..000000000 --- a/include/osmocom/legacy_mgcp/mgcp.h +++ /dev/null @@ -1,298 +0,0 @@ -/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */ - -/* - * (C) 2009-2012 by Holger Hans Peter Freyther - * (C) 2009-2012 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - -#ifndef OPENBSC_MGCP_H -#define OPENBSC_MGCP_H - -#include -#include -#include -#include - -#include -#include -#include -#include - -#define RTP_PORT_DEFAULT 4000 -#define RTP_PORT_NET_DEFAULT 16000 - -/** - * Calculate the RTP audio port for the given multiplex - * and the direction. This allows a semi static endpoint - * to port calculation removing the need for the BSC - * and the MediaGateway to communicate. - * - * Port usage explained: - * base + (multiplex * 2) + 0 == local port to wait for network packets - * base + (multiplex * 2) + 1 == local port for rtcp - * - * The above port will receive packets from the BTS that need - * to be patched and forwarded to the network. - * The above port will receive packets from the network that - * need to be patched and forwarded to the BTS. - * - * We assume to have a static BTS IP address so we can differentiate - * network and BTS. - * - */ -static inline int rtp_calculate_port(int multiplex, int base) -{ - return base + (multiplex * 2); -} - - -/* - * Handling of MGCP Endpoints and the MGCP Config - */ -struct mgcp_endpoint; -struct mgcp_config; -struct mgcp_trunk_config; -struct mgcp_rtp_end; - -#define MGCP_ENDP_CRCX 1 -#define MGCP_ENDP_DLCX 2 -#define MGCP_ENDP_MDCX 3 - -/* - * what to do with the msg? - * - continue as usual? - * - reject and send a failure code? - * - defer? do not send anything - */ -#define MGCP_POLICY_CONT 4 -#define MGCP_POLICY_REJECT 5 -#define MGCP_POLICY_DEFER 6 - -typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint); -typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state); -typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id); -typedef int (*mgcp_reset)(struct mgcp_trunk_config *cfg); -typedef int (*mgcp_rqnt)(struct mgcp_endpoint *endp, char tone); - -/** - * Return: - * < 0 in case no audio was processed - * >= 0 in case audio was processed. The remaining payload - * length will be returned. - */ -typedef int (*mgcp_processing)(struct mgcp_endpoint *endp, - struct mgcp_rtp_end *dst_end, - char *data, int *len, int buf_size); -typedef int (*mgcp_processing_setup)(struct mgcp_endpoint *endp, - struct mgcp_rtp_end *dst_end, - struct mgcp_rtp_end *src_end); - -typedef void (*mgcp_get_format)(struct mgcp_endpoint *endp, - int *payload_type, - const char**subtype_name, - const char**fmtp_extra); - -#define PORT_ALLOC_STATIC 0 -#define PORT_ALLOC_DYNAMIC 1 - -/** - * This holds information on how to allocate ports - */ -struct mgcp_port_range { - int mode; - - /* addr or NULL to fall-back to default */ - char *bind_addr; - - /* pre-allocated from a base? */ - int base_port; - - /* dynamically allocated */ - int range_start; - int range_end; - int last_port; -}; - -#define MGCP_KEEPALIVE_ONCE (-1) - -struct mgcp_trunk_config { - struct llist_head entry; - - struct mgcp_config *cfg; - - int trunk_nr; - int trunk_type; - - char *audio_fmtp_extra; - char *audio_name; - int audio_payload; - int audio_send_ptime; - int audio_send_name; - int audio_loop; - - int no_audio_transcoding; - - int omit_rtcp; - int keepalive_interval; - - /* RTP patching */ - int force_constant_ssrc; /* 0: don't, 1: once */ - int force_aligned_timing; - - /* spec handling */ - int force_realloc; - - /* timer */ - struct osmo_timer_list keepalive_timer; - - unsigned int number_endpoints; - struct mgcp_endpoint *endpoints; -}; - -enum mgcp_role { - MGCP_BSC = 0, - MGCP_BSC_NAT, -}; - -enum mgcp_connection_mode { - MGCP_CONN_NONE = 0, - MGCP_CONN_RECV_ONLY = 1, - MGCP_CONN_SEND_ONLY = 2, - MGCP_CONN_RECV_SEND = MGCP_CONN_RECV_ONLY | MGCP_CONN_SEND_ONLY, - MGCP_CONN_LOOPBACK = 4 | MGCP_CONN_RECV_SEND, -}; - -struct mgcp_config { - int source_port; - char *local_ip; - char *source_addr; - char *bts_ip; - char *call_agent_addr; - - struct in_addr bts_in; - - /* transcoder handling */ - char *transcoder_ip; - struct in_addr transcoder_in; - int transcoder_remote_base; - - /* RTP processing */ - mgcp_processing rtp_processing_cb; - mgcp_processing_setup setup_rtp_processing_cb; - - mgcp_get_format get_net_downlink_format_cb; - - struct osmo_wqueue gw_fd; - - struct mgcp_port_range bts_ports; - struct mgcp_port_range net_ports; - struct mgcp_port_range transcoder_ports; - int endp_dscp; - - int bts_force_ptime; - - mgcp_change change_cb; - mgcp_policy policy_cb; - mgcp_reset reset_cb; - mgcp_realloc realloc_cb; - mgcp_rqnt rqnt_cb; - void *data; - - uint32_t last_call_id; - - /* trunk handling */ - struct mgcp_trunk_config trunk; - struct llist_head trunks; - - /* only used for start with a static configuration */ - int last_net_port; - int last_bts_port; - - enum mgcp_role role; - - /* osmux translator: 0 means disabled, 1 means enabled */ - int osmux; - /* addr to bind the server to */ - char *osmux_addr; - /* The BSC-NAT may ask for enabling osmux on demand. This tells us if - * the osmux socket is already initialized. - */ - int osmux_init; - /* osmux batch factor: from 1 to 4 maximum */ - int osmux_batch; - /* osmux batch size (in bytes) */ - int osmux_batch_size; - /* osmux port */ - uint16_t osmux_port; - /* Pad circuit with dummy messages until we see the first voice - * message. - */ - uint16_t osmux_dummy; - - /* Use a jitterbuffer on the bts-side receiver */ - bool bts_use_jibuf; - /* Minimum and maximum buffer size for the jitter buffer, in ms */ - uint32_t bts_jitter_delay_min; - uint32_t bts_jitter_delay_max; -}; - -/* config management */ -struct mgcp_config *mgcp_config_alloc(void); -int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg, - enum mgcp_role role); -int mgcp_vty_init(void); -int mgcp_endpoints_allocate(struct mgcp_trunk_config *cfg); -void mgcp_release_endp(struct mgcp_endpoint *endp); -void mgcp_initialize_endp(struct mgcp_endpoint *endp); -int mgcp_reset_transcoder(struct mgcp_config *cfg); -void mgcp_format_stats(struct mgcp_endpoint *endp, char *stats, size_t size); -int mgcp_parse_stats(struct msgb *msg, uint32_t *ps, uint32_t *os, uint32_t *pr, uint32_t *_or, int *loss, uint32_t *jitter); - -void mgcp_trunk_set_keepalive(struct mgcp_trunk_config *tcfg, int interval); - -/* - * format helper functions - */ -struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg); - -/* adc helper */ -static inline int mgcp_timeslot_to_endpoint(int multiplex, int timeslot) -{ - if (timeslot == 0) { - LOGP(DLMGCP, LOGL_ERROR, "Timeslot should not be 0\n"); - timeslot = 255; - } - - return timeslot + (32 * multiplex); -} - -static inline void mgcp_endpoint_to_timeslot(int endpoint, int *multiplex, int *timeslot) -{ - *multiplex = endpoint / 32; - *timeslot = endpoint % 32; -} - -int mgcp_send_reset_ep(struct mgcp_endpoint *endp, int endpoint); -int mgcp_send_reset_all(struct mgcp_config *cfg); - - -int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port); -int mgcp_send(struct mgcp_endpoint *endp, int dest, int is_rtp, struct sockaddr_in *addr, char *buf, int rc); -int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len); - -#endif diff --git a/include/osmocom/legacy_mgcp/mgcp_internal.h b/include/osmocom/legacy_mgcp/mgcp_internal.h deleted file mode 100644 index 956bee074..000000000 --- a/include/osmocom/legacy_mgcp/mgcp_internal.h +++ /dev/null @@ -1,351 +0,0 @@ -/* MGCP Private Data */ - -/* - * (C) 2009-2012 by Holger Hans Peter Freyther - * (C) 2009-2012 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - -#pragma once - -#include - -#include -#include - -#define CI_UNUSED 0 - -enum mgcp_trunk_type { - MGCP_TRUNK_VIRTUAL, - MGCP_TRUNK_E1, -}; - -struct mgcp_rtp_stream_state { - uint32_t ssrc; - uint16_t last_seq; - uint32_t last_timestamp; - uint32_t err_ts_counter; - int32_t last_tsdelta; - uint32_t last_arrival_time; -}; - -struct mgcp_rtp_state { - int initialized; - int patch_ssrc; - - uint32_t orig_ssrc; - - int seq_offset; - - int32_t timestamp_offset; - uint32_t packet_duration; - - struct mgcp_rtp_stream_state in_stream; - struct mgcp_rtp_stream_state out_stream; - - /* jitter and packet loss calculation */ - int stats_initialized; - uint16_t stats_base_seq; - uint16_t stats_max_seq; - uint32_t stats_ssrc; - uint32_t stats_jitter; - int32_t stats_transit; - int stats_cycles; - bool patched_first_rtp_payload; /* FIXME: drop this, see OS#2459 */ -}; - -struct mgcp_rtp_codec { - uint32_t rate; - int channels; - uint32_t frame_duration_num; - uint32_t frame_duration_den; - - int payload_type; - char *audio_name; - char *subtype_name; -}; - -struct mgcp_rtp_end { - /* statistics */ - unsigned int packets; - unsigned int octets; - unsigned int dropped_packets; - struct in_addr addr; - - /* in network byte order */ - int rtp_port, rtcp_port; - - /* audio codec information */ - struct mgcp_rtp_codec codec; - struct mgcp_rtp_codec alt_codec; /* TODO/XXX: make it generic */ - - /* per endpoint data */ - int frames_per_packet; - uint32_t packet_duration_ms; - char *fmtp_extra; - int output_enabled; - int force_output_ptime; - - /* RTP patching */ - int force_constant_ssrc; /* -1: always, 0: don't, 1: once */ - int force_aligned_timing; - void *rtp_process_data; - - /* - * Each end has a socket... - */ - struct osmo_fd rtp; - struct osmo_fd rtcp; - - int local_port; - int local_alloc; -}; - -enum { - MGCP_TAP_BTS_IN, - MGCP_TAP_BTS_OUT, - MGCP_TAP_NET_IN, - MGCP_TAP_NET_OUT, - - /* last element */ - MGCP_TAP_COUNT -}; - -struct mgcp_rtp_tap { - int enabled; - struct sockaddr_in forward; -}; - -struct mgcp_lco { - char *string; - char *codec; - int pkt_period_min; /* time in ms */ - int pkt_period_max; /* time in ms */ -}; - -enum mgcp_type { - MGCP_RTP_DEFAULT = 0, - MGCP_RTP_TRANSCODED, - MGCP_OSMUX_BSC, - MGCP_OSMUX_BSC_NAT, -}; - -#include - -struct mgcp_endpoint { - int allocated; - uint32_t ci; - char *callid; - struct mgcp_lco local_options; - int conn_mode; - int orig_mode; - - /* backpointer */ - struct mgcp_config *cfg; - struct mgcp_trunk_config *tcfg; - - /* port status for bts/net */ - struct mgcp_rtp_end bts_end; - struct mgcp_rtp_end net_end; - - /* - * For transcoding we will send from the local_port - * of trans_bts and it will arrive at trans_net from - * where we will forward it to the network. - */ - struct mgcp_rtp_end trans_bts; - struct mgcp_rtp_end trans_net; - enum mgcp_type type; - - /* sequence bits */ - struct mgcp_rtp_state net_state; - struct mgcp_rtp_state bts_state; - - /* fields for re-transmission */ - char *last_trans; - char *last_response; - - /* tap for the endpoint */ - struct mgcp_rtp_tap taps[MGCP_TAP_COUNT]; - - struct { - /* Osmux state: disabled, activating, active */ - enum osmux_state state; - /* Allocated Osmux circuit ID for this endpoint */ - int allocated_cid; - /* Used Osmux circuit ID for this endpoint */ - uint8_t cid; - /* handle to batch messages */ - struct osmux_in_handle *in; - /* handle to unbatch messages */ - struct osmux_out_handle out; - /* statistics */ - struct { - uint32_t chunks; - uint32_t octets; - } stats; - } osmux; - - /* Jitter buffer */ - struct osmo_jibuf* bts_jb; - /* Use a jitterbuffer on the bts-side receiver */ - bool bts_use_jibuf; - /* Minimum and maximum buffer size for the jitter buffer, in ms */ - uint32_t bts_jitter_delay_min; - uint32_t bts_jitter_delay_max; -}; - -#define for_each_line(line, save) \ - for (line = strline_r(NULL, &save); line;\ - line = strline_r(NULL, &save)) - -static inline char *strline_r(char *str, char **saveptr) -{ - char *result; - - if (str) - *saveptr = str; - - result = *saveptr; - - if (*saveptr != NULL) { - *saveptr = strpbrk(*saveptr, "\r\n"); - - if (*saveptr != NULL) { - char *eos = *saveptr; - - if ((*saveptr)[0] == '\r' && (*saveptr)[1] == '\n') - (*saveptr)++; - (*saveptr)++; - if ((*saveptr)[0] == '\0') - *saveptr = NULL; - - *eos = '\0'; - } - } - - return result; -} - - - -#define ENDPOINT_NUMBER(endp) abs((int)(endp - endp->tcfg->endpoints)) - -/** - * Internal structure while parsing a request - */ -struct mgcp_parse_data { - struct mgcp_config *cfg; - struct mgcp_endpoint *endp; - char *trans; - char *save; - int found; -}; - -int mgcp_send_dummy(struct mgcp_endpoint *endp); -int mgcp_bind_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port); -int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port); -int mgcp_bind_trans_bts_rtp_port(struct mgcp_endpoint *enp, int rtp_port); -int mgcp_bind_trans_net_rtp_port(struct mgcp_endpoint *enp, int rtp_port); -int mgcp_free_rtp_port(struct mgcp_rtp_end *end); - -/* For transcoding we need to manage an in and an output that are connected */ -static inline int endp_back_channel(int endpoint) -{ - return endpoint + 60; -} - -struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index); -struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index); - -void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change, - struct mgcp_rtp_end *rtp); -uint32_t mgcp_rtp_packet_duration(struct mgcp_endpoint *endp, - struct mgcp_rtp_end *rtp); - -void mgcp_state_calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *, - uint32_t *expected, int *loss); -uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *); - -/* payload processing default functions */ -int mgcp_rtp_processing_default(struct mgcp_endpoint *endp, struct mgcp_rtp_end *dst_end, - char *data, int *len, int buf_size); - -int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp, - struct mgcp_rtp_end *dst_end, - struct mgcp_rtp_end *src_end); - -void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp, - int *payload_type, - const char**subtype_name, - const char**fmtp_extra); - -/* internal RTP Annex A counting */ -void mgcp_rtp_annex_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state, - const uint16_t seq, const int32_t transit, - const uint32_t ssrc); - -int mgcp_set_ip_tos(int fd, int tos); - -enum { - MGCP_DEST_NET = 0, - MGCP_DEST_BTS, -}; - - -#define MGCP_DUMMY_LOAD 0x23 - - -/** - * SDP related information - */ -/* Assume audio frame length of 20ms */ -#define DEFAULT_RTP_AUDIO_FRAME_DUR_NUM 20 -#define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000 -#define DEFAULT_RTP_AUDIO_PACKET_DURATION_MS 20 -#define DEFAULT_RTP_AUDIO_DEFAULT_RATE 8000 -#define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1 - -#define PTYPE_UNDEFINED (-1) -int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p); -int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec, - int payload_type, const char *audio_name); - - -/** - * Internal network related - */ -static inline const char *mgcp_net_src_addr(struct mgcp_endpoint *endp) -{ - if (endp->cfg->net_ports.bind_addr) - return endp->cfg->net_ports.bind_addr; - return endp->cfg->source_addr; -} - -static inline const char *mgcp_bts_src_addr(struct mgcp_endpoint *endp) -{ - if (endp->cfg->bts_ports.bind_addr) - return endp->cfg->bts_ports.bind_addr; - return endp->cfg->source_addr; -} - -int mgcp_msg_terminate_nul(struct msgb *msg); - -/** - * Internal jitter buffer related - */ -void mgcp_dejitter_udp_send(struct msgb *msg, void *data); diff --git a/include/osmocom/legacy_mgcp/mgcp_transcode.h b/include/osmocom/legacy_mgcp/mgcp_transcode.h deleted file mode 100644 index 6892debc3..000000000 --- a/include/osmocom/legacy_mgcp/mgcp_transcode.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * (C) 2014 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ -#ifndef OPENBSC_MGCP_TRANSCODE_H -#define OPENBSC_MGCP_TRANSCODE_H - -#include "bscconfig.h" - -#if HAVE_GSM_H -#include -#elif HAVE_GSM_GSM_H -#include -#endif -#ifdef HAVE_BCG729 -#include -#include -#endif - -enum audio_format { - AF_INVALID, - AF_S16, - AF_L16, - AF_GSM, - AF_G729, - AF_PCMA, - AF_PCMU -}; - - -struct mgcp_process_rtp_state { - /* decoding */ - enum audio_format src_fmt; - union { - gsm gsm_handle; -#ifdef HAVE_BCG729 - bcg729DecoderChannelContextStruct *g729_dec; -#endif - } src; - size_t src_frame_size; - size_t src_samples_per_frame; - - /* processing */ - - /* encoding */ - enum audio_format dst_fmt; - union { - gsm gsm_handle; -#ifdef HAVE_BCG729 - bcg729EncoderChannelContextStruct *g729_enc; -#endif - } dst; - size_t dst_frame_size; - size_t dst_samples_per_frame; - int dst_packet_duration; - - int is_running; - uint16_t next_seq; - uint32_t next_time; - int16_t samples[10*160]; - size_t sample_cnt; - size_t sample_offs; -}; - - -int mgcp_transcoding_setup(struct mgcp_endpoint *endp, - struct mgcp_rtp_end *dst_end, - struct mgcp_rtp_end *src_end); - -void mgcp_transcoding_net_downlink_format(struct mgcp_endpoint *endp, - int *payload_type, - const char**audio_name, - const char**fmtp_extra); - -int mgcp_transcoding_process_rtp(struct mgcp_endpoint *endp, - struct mgcp_rtp_end *dst_end, - char *data, int *len, int buf_size); - -int mgcp_transcoding_get_frame_size(void *state_, int nsamples, int dst); -#endif /* OPENBSC_MGCP_TRANSCODE_H */ diff --git a/include/osmocom/legacy_mgcp/osmux.h b/include/osmocom/legacy_mgcp/osmux.h deleted file mode 100644 index f3ea72a85..000000000 --- a/include/osmocom/legacy_mgcp/osmux.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _OPENBSC_OSMUX_H_ -#define _OPENBSC_OSMUX_H_ - -#include - -#define OSMUX_PORT 1984 - -enum { - OSMUX_ROLE_BSC = 0, - OSMUX_ROLE_BSC_NAT, -}; - -int osmux_init(int role, struct mgcp_config *cfg); -int osmux_enable_endpoint(struct mgcp_endpoint *endp, struct in_addr *addr, uint16_t port); -void osmux_disable_endpoint(struct mgcp_endpoint *endp); -void osmux_allocate_cid(struct mgcp_endpoint *endp); -void osmux_release_cid(struct mgcp_endpoint *endp); - -int osmux_xfrm_to_rtp(struct mgcp_endpoint *endp, int type, char *buf, int rc); -int osmux_xfrm_to_osmux(int type, char *buf, int rc, struct mgcp_endpoint *endp); - -int osmux_send_dummy(struct mgcp_endpoint *endp); - -int osmux_get_cid(void); -void osmux_put_cid(uint8_t osmux_cid); -int osmux_used_cid(void); - -enum osmux_state { - OSMUX_STATE_DISABLED = 0, - OSMUX_STATE_NEGOTIATING, - OSMUX_STATE_ACTIVATING, - OSMUX_STATE_ENABLED, -}; - -enum osmux_usage { - OSMUX_USAGE_OFF = 0, - OSMUX_USAGE_ON = 1, - OSMUX_USAGE_ONLY = 2, -}; - -#endif diff --git a/include/osmocom/legacy_mgcp/vty.h b/include/osmocom/legacy_mgcp/vty.h deleted file mode 100644 index bf6b7a85e..000000000 --- a/include/osmocom/legacy_mgcp/vty.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include - -enum mgcp_vty_node { - MGCP_NODE = _LAST_OSMOVTY_NODE + 1, - TRUNK_NODE, -}; diff --git a/libosmo-legacy-mgcp.pc.in b/libosmo-legacy-mgcp.pc.in deleted file mode 100644 index 62d9edc2a..000000000 --- a/libosmo-legacy-mgcp.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Osmocom legacy Media Gateway Control Protocol library -Description: C Utility Library -Version: @VERSION@ -Libs: -L${libdir} -losmo-legacy-mgcp -Cflags: -I${includedir}/ diff --git a/osmoappdesc.py b/osmoappdesc.py index c9ebf03b7..cee5a2444 100644 --- a/osmoappdesc.py +++ b/osmoappdesc.py @@ -17,11 +17,9 @@ app_configs = { "osmo-mgw": ["doc/examples/osmo-mgw/osmo-mgw.cfg"], - "osmo-bsc_mgcp": ["doc/examples/osmo-bsc_mgcp/mgcp.cfg"], } apps = [(4243, "src/osmo-mgw/osmo-mgw", "OsmoMGW", "osmo-mgw"), - (4243, "src/osmo-bsc_mgcp/osmo-bsc_mgcp", "OpenBSC MGCP", "osmo-bsc_mgcp"), ] vty_command = ["./src/osmo-mgw/osmo-mgw", "-c", diff --git a/src/Makefile.am b/src/Makefile.am index fab1bf0e0..f994f578b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,13 +21,11 @@ AM_LDFLAGS = \ # Libraries SUBDIRS = \ - libosmo-legacy-mgcp \ libosmo-mgcp-client \ libosmo-mgcp \ $(NULL) # Programs SUBDIRS += \ - osmo-bsc_mgcp \ osmo-mgw \ $(NULL) diff --git a/src/libosmo-legacy-mgcp/Makefile.am b/src/libosmo-legacy-mgcp/Makefile.am deleted file mode 100644 index 2d6b6dd93..000000000 --- a/src/libosmo-legacy-mgcp/Makefile.am +++ /dev/null @@ -1,51 +0,0 @@ -AM_CPPFLAGS = \ - $(all_includes) \ - -I$(top_srcdir)/include \ - -I$(top_builddir) \ - $(NULL) - -AM_CFLAGS = \ - -Wall \ - $(LIBOSMOCORE_CFLAGS) \ - $(LIBOSMOVTY_CFLAGS) \ - $(LIBOSMONETIF_CFLAGS) \ - $(COVERAGE_CFLAGS) \ - $(LIBBCG729_CFLAGS) \ - $(NULL) - -AM_LDFLAGS = \ - $(LIBOSMOCORE_LIBS) \ - $(LIBOSMOVTY_LIBS) \ - $(LIBOSMONETIF_LIBS) \ - $(COVERAGE_LDFLAGS) \ - $(LIBBCG729_LIBS) \ - $(LIBRARY_GSM) \ - $(NULL) - -# This is not at all related to the release version, but a range of supported -# API versions. Read TODO_RELEASE in the source tree's root! -LEGACY_MGCP_LIBVERSION=1:0:1 - -lib_LTLIBRARIES = \ - libosmo-legacy-mgcp.la \ - $(NULL) - -noinst_HEADERS = \ - g711common.h \ - $(NULL) - -libosmo_legacy_mgcp_la_SOURCES = \ - mgcp_common.c \ - mgcp_protocol.c \ - mgcp_network.c \ - mgcp_vty.c \ - mgcp_osmux.c \ - mgcp_sdp.c \ - $(NULL) -if BUILD_MGCP_TRANSCODING -libosmo_legacy_mgcp_la_SOURCES += \ - mgcp_transcode.c \ - $(NULL) -endif - -libosmo_legacy_mgcp_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LEGACY_MGCP_LIBVERSION) diff --git a/src/libosmo-legacy-mgcp/g711common.h b/src/libosmo-legacy-mgcp/g711common.h deleted file mode 100644 index cb35fc651..000000000 --- a/src/libosmo-legacy-mgcp/g711common.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * PCM - A-Law conversion - * Copyright (c) 2000 by Abramo Bagnara - * - * Wrapper for linphone Codec class by Simon Morlat - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -static inline int val_seg(int val) -{ - int r = 0; - val >>= 7; /*7 = 4 + 3*/ - if (val & 0xf0) { - val >>= 4; - r += 4; - } - if (val & 0x0c) { - val >>= 2; - r += 2; - } - if (val & 0x02) - r += 1; - return r; -} - -/* - * s16_to_alaw() - Convert a 16-bit linear PCM value to 8-bit A-law - * - * s16_to_alaw() accepts an 16-bit integer and encodes it as A-law data. - * - * Linear Input Code Compressed Code - * ------------------------ --------------- - * 0000000wxyza 000wxyz - * 0000001wxyza 001wxyz - * 000001wxyzab 010wxyz - * 00001wxyzabc 011wxyz - * 0001wxyzabcd 100wxyz - * 001wxyzabcde 101wxyz - * 01wxyzabcdef 110wxyz - * 1wxyzabcdefg 111wxyz - * - * For further information see John C. Bellamy's Digital Telephony, 1982, - * John Wiley & Sons, pps 98-111 and 472-476. - * G711 is designed for 13 bits input signal, this function add extra shifting to take this into account. - */ - -static inline unsigned char s16_to_alaw(int pcm_val) -{ - int mask; - int seg; - unsigned char aval; - - if (pcm_val >= 0) { - mask = 0xD5; - } else { - mask = 0x55; - pcm_val = -pcm_val; - if (pcm_val > 0x7fff) - pcm_val = 0x7fff; - } - - if (pcm_val < 256) /*256 = 32 << 3*/ - aval = pcm_val >> 4; /*4 = 1 + 3*/ - else { - /* Convert the scaled magnitude to segment number. */ - seg = val_seg(pcm_val); - aval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0x0f); - } - return aval ^ mask; -} - -/* - * alaw_to_s16() - Convert an A-law value to 16-bit linear PCM - * - */ -static inline int alaw_to_s16(unsigned char a_val) -{ - int t; - int seg; - - a_val ^= 0x55; - t = a_val & 0x7f; - if (t < 16) - t = (t << 4) + 8; - else { - seg = (t >> 4) & 0x07; - t = ((t & 0x0f) << 4) + 0x108; - t <<= seg -1; - } - return ((a_val & 0x80) ? t : -t); -} -/* - * s16_to_ulaw() - Convert a linear PCM value to u-law - * - * In order to simplify the encoding process, the original linear magnitude - * is biased by adding 33 which shifts the encoding range from (0 - 8158) to - * (33 - 8191). The result can be seen in the following encoding table: - * - * Biased Linear Input Code Compressed Code - * ------------------------ --------------- - * 00000001wxyza 000wxyz - * 0000001wxyzab 001wxyz - * 000001wxyzabc 010wxyz - * 00001wxyzabcd 011wxyz - * 0001wxyzabcde 100wxyz - * 001wxyzabcdef 101wxyz - * 01wxyzabcdefg 110wxyz - * 1wxyzabcdefgh 111wxyz - * - * Each biased linear code has a leading 1 which identifies the segment - * number. The value of the segment number is equal to 7 minus the number - * of leading 0's. The quantization interval is directly available as the - * four bits wxyz. * The trailing bits (a - h) are ignored. - * - * Ordinarily the complement of the resulting code word is used for - * transmission, and so the code word is complemented before it is returned. - * - * For further information see John C. Bellamy's Digital Telephony, 1982, - * John Wiley & Sons, pps 98-111 and 472-476. - */ - -static inline unsigned char s16_to_ulaw(int pcm_val) /* 2's complement (16-bit range) */ -{ - int mask; - int seg; - unsigned char uval; - - if (pcm_val < 0) { - pcm_val = 0x84 - pcm_val; - mask = 0x7f; - } else { - pcm_val += 0x84; - mask = 0xff; - } - if (pcm_val > 0x7fff) - pcm_val = 0x7fff; - - /* Convert the scaled magnitude to segment number. */ - seg = val_seg(pcm_val); - - /* - * Combine the sign, segment, quantization bits; - * and complement the code word. - */ - uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0x0f); - return uval ^ mask; -} - -/* - * ulaw_to_s16() - Convert a u-law value to 16-bit linear PCM - * - * First, a biased linear code is derived from the code word. An unbiased - * output can then be obtained by subtracting 33 from the biased code. - * - * Note that this function expects to be passed the complement of the - * original code word. This is in keeping with ISDN conventions. - */ -static inline int ulaw_to_s16(unsigned char u_val) -{ - int t; - - /* Complement to obtain normal u-law value. */ - u_val = ~u_val; - - /* - * Extract and bias the quantization bits. Then - * shift up by the segment number and subtract out the bias. - */ - t = ((u_val & 0x0f) << 3) + 0x84; - t <<= (u_val & 0x70) >> 4; - - return ((u_val & 0x80) ? (0x84 - t) : (t - 0x84)); -} diff --git a/src/libosmo-legacy-mgcp/mgcp_common.c b/src/libosmo-legacy-mgcp/mgcp_common.c deleted file mode 100644 index 444a06047..000000000 --- a/src/libosmo-legacy-mgcp/mgcp_common.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Media Gateway Control Protocol Media Gateway: RFC 3435 */ -/* Implementations useful both for the MGCP GW as well as MGCP GW clients */ - -/* - * (C) 2016 by sysmocom s.m.f.c. GmbH - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - -#include - -#include -#include - -const struct value_string mgcp_connection_mode_strs[] = { - { MGCP_CONN_NONE, "none" }, - { MGCP_CONN_RECV_SEND, "sendrecv" }, - { MGCP_CONN_SEND_ONLY, "sendonly" }, - { MGCP_CONN_RECV_ONLY, "recvonly" }, - { MGCP_CONN_LOOPBACK, "loopback" }, - { 0, NULL } -}; - -/* Ensure that the msg->l2h is NUL terminated. */ -int mgcp_msg_terminate_nul(struct msgb *msg) -{ - unsigned char *tail = msg->l2h + msgb_l2len(msg); /* char after l2 data */ - if (tail[-1] == '\0') - /* nothing to do */; - else if (msgb_tailroom(msg) > 0) - tail[0] = '\0'; - else if (tail[-1] == '\r' || tail[-1] == '\n') - tail[-1] = '\0'; - else { - LOGP(DLMGCP, LOGL_ERROR, "Cannot NUL terminate MGCP message: " - "Length: %d, Buffer size: %d\n", - msgb_l2len(msg), msg->data_len); - return -ENOTSUP; - } - return 0; -} diff --git a/src/libosmo-legacy-mgcp/mgcp_network.c b/src/libosmo-legacy-mgcp/mgcp_network.c deleted file mode 100644 index 7b161d279..000000000 --- a/src/libosmo-legacy-mgcp/mgcp_network.c +++ /dev/null @@ -1,1202 +0,0 @@ -/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */ -/* The protocol implementation */ - -/* - * (C) 2009-2012 by Holger Hans Peter Freyther - * (C) 2009-2012 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include - -#include -#include - -#include - -#warning "Make use of the rtp proxy code" - - -#define RTP_SEQ_MOD (1 << 16) -#define RTP_MAX_DROPOUT 3000 -#define RTP_MAX_MISORDER 100 -#define RTP_BUF_SIZE 4096 - -enum { - MGCP_PROTO_RTP, - MGCP_PROTO_RTCP, -}; - -/** - * This does not need to be a precision timestamp and - * is allowed to wrap quite fast. The returned value is - * 1/unit seconds. - */ -static uint32_t get_current_ts(unsigned unit) -{ - struct timespec tp; - uint64_t ret; - - if (!unit) - return 0; - - memset(&tp, 0, sizeof(tp)); - if (clock_gettime(CLOCK_MONOTONIC, &tp) != 0) - LOGP(DLMGCP, LOGL_NOTICE, - "Getting the clock failed.\n"); - - /* convert it to 1/unit seconds */ - ret = tp.tv_sec; - ret *= unit; - ret += (int64_t)tp.tv_nsec * unit / 1000 / 1000 / 1000; - - return ret; -} - -int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len) -{ - struct sockaddr_in out; - out.sin_family = AF_INET; - out.sin_port = port; - memcpy(&out.sin_addr, addr, sizeof(*addr)); - - return sendto(fd, buf, len, 0, (struct sockaddr *)&out, sizeof(out)); -} - -int mgcp_send_dummy(struct mgcp_endpoint *endp) -{ - static char buf[] = { MGCP_DUMMY_LOAD }; - int rc; - int was_rtcp = 0; - - rc = mgcp_udp_send(endp->net_end.rtp.fd, &endp->net_end.addr, - endp->net_end.rtp_port, buf, 1); - - if (rc == -1) - goto failed; - - if (endp->tcfg->omit_rtcp) - return rc; - - was_rtcp = 1; - rc = mgcp_udp_send(endp->net_end.rtcp.fd, &endp->net_end.addr, - endp->net_end.rtcp_port, buf, 1); - - if (rc >= 0) - return rc; - -failed: - LOGP(DLMGCP, LOGL_ERROR, - "Failed to send dummy %s packet: %s on: 0x%x to %s:%d\n", - was_rtcp ? "RTCP" : "RTP", - strerror(errno), ENDPOINT_NUMBER(endp), inet_ntoa(endp->net_end.addr), - was_rtcp ? endp->net_end.rtcp_port : endp->net_end.rtp_port); - - return -1; -} - -static int32_t compute_timestamp_aligment_error(struct mgcp_rtp_stream_state *sstate, - int ptime, uint32_t timestamp) -{ - int32_t timestamp_delta; - - if (ptime == 0) - return 0; - - /* Align according to: T - Tlast = k * Tptime */ - timestamp_delta = timestamp - sstate->last_timestamp; - - return timestamp_delta % ptime; -} - -static int check_rtp_timestamp(struct mgcp_endpoint *endp, - struct mgcp_rtp_state *state, - struct mgcp_rtp_stream_state *sstate, - struct mgcp_rtp_end *rtp_end, - struct sockaddr_in *addr, - uint16_t seq, uint32_t timestamp, - const char *text, int32_t *tsdelta_out) -{ - int32_t tsdelta; - int32_t timestamp_error; - - /* Not fully intialized, skip */ - if (sstate->last_tsdelta == 0 && timestamp == sstate->last_timestamp) - return 0; - - if (seq == sstate->last_seq) { - if (timestamp != sstate->last_timestamp) { - sstate->err_ts_counter += 1; - LOGP(DLMGCP, LOGL_ERROR, - "The %s timestamp delta is != 0 but the sequence " - "number %d is the same, " - "TS offset: %d, SeqNo offset: %d " - "on 0x%x SSRC: %u timestamp: %u " - "from %s:%d in %d\n", - text, seq, - state->timestamp_offset, state->seq_offset, - ENDPOINT_NUMBER(endp), sstate->ssrc, timestamp, - inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), - endp->conn_mode); - } - return 0; - } - - tsdelta = - (int32_t)(timestamp - sstate->last_timestamp) / - (int16_t)(seq - sstate->last_seq); - - if (tsdelta == 0) { - /* Don't update *tsdelta_out */ - LOGP(DLMGCP, LOGL_NOTICE, - "The %s timestamp delta is %d " - "on 0x%x SSRC: %u timestamp: %u " - "from %s:%d in %d\n", - text, tsdelta, - ENDPOINT_NUMBER(endp), sstate->ssrc, timestamp, - inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), - endp->conn_mode); - - return 0; - } - - if (sstate->last_tsdelta != tsdelta) { - if (sstate->last_tsdelta) { - LOGP(DLMGCP, LOGL_INFO, - "The %s timestamp delta changes from %d to %d " - "on 0x%x SSRC: %u timestamp: %u from %s:%d in %d\n", - text, sstate->last_tsdelta, tsdelta, - ENDPOINT_NUMBER(endp), sstate->ssrc, timestamp, - inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), - endp->conn_mode); - } - } - - if (tsdelta_out) - *tsdelta_out = tsdelta; - - timestamp_error = - compute_timestamp_aligment_error(sstate, state->packet_duration, - timestamp); - - if (timestamp_error) { - sstate->err_ts_counter += 1; - LOGP(DLMGCP, LOGL_NOTICE, - "The %s timestamp has an alignment error of %d " - "on 0x%x SSRC: %u " - "SeqNo delta: %d, TS delta: %d, dTS/dSeq: %d " - "from %s:%d in mode %d. ptime: %d\n", - text, timestamp_error, - ENDPOINT_NUMBER(endp), sstate->ssrc, - (int16_t)(seq - sstate->last_seq), - (int32_t)(timestamp - sstate->last_timestamp), - tsdelta, - inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), - endp->conn_mode, state->packet_duration); - } - return 1; -} - -/* Set the timestamp offset according to the packet duration. */ -static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp, - struct mgcp_rtp_state *state, - struct mgcp_rtp_end *rtp_end, - struct sockaddr_in *addr, - int16_t delta_seq, uint32_t in_timestamp) -{ - int32_t tsdelta = state->packet_duration; - int timestamp_offset; - uint32_t out_timestamp; - - if (tsdelta == 0) { - tsdelta = state->out_stream.last_tsdelta; - if (tsdelta != 0) { - LOGP(DLMGCP, LOGL_NOTICE, - "A fixed packet duration is not available on 0x%x, " - "using last output timestamp delta instead: %d " - "from %s:%d in %d\n", - ENDPOINT_NUMBER(endp), tsdelta, - inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), - endp->conn_mode); - } else { - tsdelta = rtp_end->codec.rate * 20 / 1000; - LOGP(DLMGCP, LOGL_NOTICE, - "Fixed packet duration and last timestamp delta " - "are not available on 0x%x, " - "using fixed 20ms instead: %d " - "from %s:%d in %d\n", - ENDPOINT_NUMBER(endp), tsdelta, - inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), - endp->conn_mode); - } - } - - out_timestamp = state->out_stream.last_timestamp + delta_seq * tsdelta; - timestamp_offset = out_timestamp - in_timestamp; - - if (state->timestamp_offset != timestamp_offset) { - state->timestamp_offset = timestamp_offset; - - LOGP(DLMGCP, LOGL_NOTICE, - "Timestamp offset change on 0x%x SSRC: %u " - "SeqNo delta: %d, TS offset: %d, " - "from %s:%d in %d\n", - ENDPOINT_NUMBER(endp), state->in_stream.ssrc, - delta_seq, state->timestamp_offset, - inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), - endp->conn_mode); - } - - return timestamp_offset; -} - -/* Set the timestamp offset according to the packet duration. */ -static int align_rtp_timestamp_offset(struct mgcp_endpoint *endp, - struct mgcp_rtp_state *state, - struct mgcp_rtp_end *rtp_end, - struct sockaddr_in *addr, - uint32_t timestamp) -{ - int timestamp_error = 0; - int ptime = state->packet_duration; - - /* Align according to: T + Toffs - Tlast = k * Tptime */ - - timestamp_error = compute_timestamp_aligment_error( - &state->out_stream, ptime, - timestamp + state->timestamp_offset); - - if (timestamp_error) { - state->timestamp_offset += ptime - timestamp_error; - - LOGP(DLMGCP, LOGL_NOTICE, - "Corrected timestamp alignment error of %d on 0x%x SSRC: %u " - "new TS offset: %d, " - "from %s:%d in %d\n", - timestamp_error, - ENDPOINT_NUMBER(endp), state->in_stream.ssrc, - state->timestamp_offset, inet_ntoa(addr->sin_addr), - ntohs(addr->sin_port), endp->conn_mode); - } - - OSMO_ASSERT(compute_timestamp_aligment_error(&state->out_stream, ptime, - timestamp + state->timestamp_offset) == 0); - - return timestamp_error; -} - -int mgcp_rtp_processing_default(struct mgcp_endpoint *endp, struct mgcp_rtp_end *dst_end, - char *data, int *len, int buf_size) -{ - return 0; -} - -int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp, - struct mgcp_rtp_end *dst_end, - struct mgcp_rtp_end *src_end) -{ - return 0; -} - -void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp, - int *payload_type, - const char**audio_name, - const char**fmtp_extra) -{ - /* Use the BTS side parameters when passing the SDP data (for - * downlink) to the net peer. - */ - *payload_type = endp->bts_end.codec.payload_type; - *audio_name = endp->bts_end.codec.audio_name; - *fmtp_extra = endp->bts_end.fmtp_extra; -} - - -void mgcp_rtp_annex_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state, - const uint16_t seq, const int32_t transit, - const uint32_t ssrc) -{ - int32_t d; - - /* initialize or re-initialize */ - if (!state->stats_initialized || state->stats_ssrc != ssrc) { - state->stats_initialized = 1; - state->stats_base_seq = seq; - state->stats_max_seq = seq - 1; - state->stats_ssrc = ssrc; - state->stats_jitter = 0; - state->stats_transit = transit; - state->stats_cycles = 0; - } else { - uint16_t udelta; - - /* - * The below takes the shape of the validation of - * Appendix A. Check if there is something weird with - * the sequence number, otherwise check for a wrap - * around in the sequence number. - * It can't wrap during the initialization so let's - * skip it here. The Appendix A probably doesn't have - * this issue because of the probation. - */ - udelta = seq - state->stats_max_seq; - if (udelta < RTP_MAX_DROPOUT) { - if (seq < state->stats_max_seq) - state->stats_cycles += RTP_SEQ_MOD; - } else if (udelta <= RTP_SEQ_MOD - RTP_MAX_MISORDER) { - LOGP(DLMGCP, LOGL_NOTICE, - "RTP seqno made a very large jump on 0x%x delta: %u\n", - ENDPOINT_NUMBER(endp), udelta); - } - } - - /* - * Calculate the jitter between the two packages. The TS should be - * taken closer to the read function. This was taken from the - * Appendix A of RFC 3550. Timestamp and arrival_time have a 1/rate - * resolution. - */ - d = transit - state->stats_transit; - state->stats_transit = transit; - if (d < 0) - d = -d; - state->stats_jitter += d - ((state->stats_jitter + 8) >> 4); - state->stats_max_seq = seq; -} - - - -/** - * The RFC 3550 Appendix A assumes there are multiple sources but - * some of the supported endpoints (e.g. the nanoBTS) can only handle - * one source and this code will patch RTP header to appear as if there - * is only one source. - * There is also no probation period for new sources. Every RTP header - * we receive will be seen as a switch in streams. - */ -void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state, - struct mgcp_rtp_end *rtp_end, struct sockaddr_in *addr, - char *data, int len) -{ - uint32_t arrival_time; - int32_t transit; - uint16_t seq; - uint32_t timestamp, ssrc; - struct rtp_hdr *rtp_hdr; - int payload = rtp_end->codec.payload_type; - - if (len < sizeof(*rtp_hdr)) - return; - - rtp_hdr = (struct rtp_hdr *) data; - seq = ntohs(rtp_hdr->sequence); - timestamp = ntohl(rtp_hdr->timestamp); - arrival_time = get_current_ts(rtp_end->codec.rate); - ssrc = ntohl(rtp_hdr->ssrc); - transit = arrival_time - timestamp; - - mgcp_rtp_annex_count(endp, state, seq, transit, ssrc); - - if (!state->initialized) { - state->initialized = 1; - state->in_stream.last_seq = seq - 1; - state->in_stream.ssrc = state->orig_ssrc = ssrc; - state->in_stream.last_tsdelta = 0; - state->packet_duration = mgcp_rtp_packet_duration(endp, rtp_end); - state->out_stream = state->in_stream; - state->out_stream.last_timestamp = timestamp; - state->out_stream.ssrc = ssrc - 1; /* force output SSRC change */ - LOGP(DLMGCP, LOGL_INFO, - "Initializing stream on 0x%x SSRC: %u timestamp: %u " - "pkt-duration: %d, from %s:%d in %d\n", - ENDPOINT_NUMBER(endp), state->in_stream.ssrc, - state->seq_offset, state->packet_duration, - inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), - endp->conn_mode); - if (state->packet_duration == 0) { - state->packet_duration = rtp_end->codec.rate * 20 / 1000; - LOGP(DLMGCP, LOGL_NOTICE, - "Fixed packet duration is not available on 0x%x, " - "using fixed 20ms instead: %d from %s:%d in %d\n", - ENDPOINT_NUMBER(endp), state->packet_duration, - inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), - endp->conn_mode); - } - } else if (state->in_stream.ssrc != ssrc) { - LOGP(DLMGCP, LOGL_NOTICE, - "The SSRC changed on 0x%x: %u -> %u " - "from %s:%d in %d\n", - ENDPOINT_NUMBER(endp), - state->in_stream.ssrc, rtp_hdr->ssrc, - inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), - endp->conn_mode); - - state->in_stream.ssrc = ssrc; - if (rtp_end->force_constant_ssrc) { - int16_t delta_seq; - - /* Always increment seqno by 1 */ - state->seq_offset = - (state->out_stream.last_seq + 1) - seq; - - /* Estimate number of packets that would have been sent */ - delta_seq = - (arrival_time - state->in_stream.last_arrival_time - + state->packet_duration/2) / - state->packet_duration; - - adjust_rtp_timestamp_offset(endp, state, rtp_end, addr, - delta_seq, timestamp); - - state->patch_ssrc = 1; - ssrc = state->orig_ssrc; - if (rtp_end->force_constant_ssrc != -1) - rtp_end->force_constant_ssrc -= 1; - - LOGP(DLMGCP, LOGL_NOTICE, - "SSRC patching enabled on 0x%x SSRC: %u " - "SeqNo offset: %d, TS offset: %d " - "from %s:%d in %d\n", - ENDPOINT_NUMBER(endp), state->in_stream.ssrc, - state->seq_offset, state->timestamp_offset, - inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), - endp->conn_mode); - } - - state->in_stream.last_tsdelta = 0; - } else { - /* Compute current per-packet timestamp delta */ - check_rtp_timestamp(endp, state, &state->in_stream, rtp_end, addr, - seq, timestamp, "input", - &state->in_stream.last_tsdelta); - - if (state->patch_ssrc) - ssrc = state->orig_ssrc; - } - - /* Save before patching */ - state->in_stream.last_timestamp = timestamp; - state->in_stream.last_seq = seq; - state->in_stream.last_arrival_time = arrival_time; - - if (rtp_end->force_aligned_timing && - state->out_stream.ssrc == ssrc && state->packet_duration) - /* Align the timestamp offset */ - align_rtp_timestamp_offset(endp, state, rtp_end, addr, timestamp); - - /* Store the updated SSRC back to the packet */ - if (state->patch_ssrc) - rtp_hdr->ssrc = htonl(ssrc); - - /* Apply the offset and store it back to the packet. - * This won't change anything if the offset is 0, so the conditional is - * omitted. */ - seq += state->seq_offset; - rtp_hdr->sequence = htons(seq); - timestamp += state->timestamp_offset; - rtp_hdr->timestamp = htonl(timestamp); - - /* Check again, whether the timestamps are still valid */ - if (state->out_stream.ssrc == ssrc) - check_rtp_timestamp(endp, state, &state->out_stream, rtp_end, - addr, seq, timestamp, "output", - &state->out_stream.last_tsdelta); - - /* Save output values */ - state->out_stream.last_seq = seq; - state->out_stream.last_timestamp = timestamp; - state->out_stream.ssrc = ssrc; - - if (payload < 0) - return; - -#if 0 - DEBUGP(DLMGCP, "Payload hdr payload %u -> endp payload %u\n", - rtp_hdr->payload_type, payload); - rtp_hdr->payload_type = payload; -#endif -} - -/* - * The below code is for dispatching. We have a dedicated port for - * the data coming from the net and one to discover the BTS. - */ -static int forward_data(int fd, struct mgcp_rtp_tap *tap, const char *buf, int len) -{ - if (!tap->enabled) - return 0; - - return sendto(fd, buf, len, 0, - (struct sockaddr *)&tap->forward, sizeof(tap->forward)); -} - -static int mgcp_send_transcoder(struct mgcp_rtp_end *end, - struct mgcp_config *cfg, int is_rtp, - const char *buf, int len) -{ - int rc; - int port; - struct sockaddr_in addr; - - port = is_rtp ? end->rtp_port : end->rtcp_port; - - addr.sin_family = AF_INET; - addr.sin_addr = cfg->transcoder_in; - addr.sin_port = port; - - rc = sendto(is_rtp ? - end->rtp.fd : - end->rtcp.fd, buf, len, 0, - (struct sockaddr *) &addr, sizeof(addr)); - - if (rc != len) - LOGP(DLMGCP, LOGL_ERROR, - "Failed to send data to the transcoder: %s\n", - strerror(errno)); - - return rc; -} - -void mgcp_dejitter_udp_send(struct msgb *msg, void *data) -{ - struct mgcp_rtp_end *rtp_end = (struct mgcp_rtp_end *) data; - - int rc = mgcp_udp_send(rtp_end->rtp.fd, &rtp_end->addr, - rtp_end->rtp_port, (char*) msg->data, msg->len); - if (rc != msg->len) - LOGP(DLMGCP, LOGL_ERROR, - "Failed to send data after jitter buffer: %d\n", rc); - msgb_free(msg); -} - -static int enqueue_dejitter(struct osmo_jibuf *jb, struct mgcp_rtp_end *rtp_end, char *buf, int len) -{ - struct msgb *msg; - msg = msgb_alloc(len, "mgcp-jibuf"); - if (!msg) - return -1; - - memcpy(msg->data, buf, len); - msgb_put(msg, len); - - if (osmo_jibuf_enqueue(jb, msg) < 0) { - rtp_end->dropped_packets += 1; - msgb_free(msg); - } - - return len; -} - -int mgcp_send(struct mgcp_endpoint *endp, int dest, int is_rtp, - struct sockaddr_in *addr, char *buf, int rc) -{ - struct mgcp_trunk_config *tcfg = endp->tcfg; - struct mgcp_rtp_end *rtp_end; - struct mgcp_rtp_state *rtp_state; - int tap_idx; - struct osmo_jibuf *jb; - - LOGP(DLMGCP, LOGL_DEBUG, - "endpoint %x dest %s tcfg->audio_loop %d endp->conn_mode %d (== loopback: %d)\n", - ENDPOINT_NUMBER(endp), - dest == MGCP_DEST_NET? "net" : "bts", - tcfg->audio_loop, - endp->conn_mode, - endp->conn_mode == MGCP_CONN_LOOPBACK); - - /* For loop toggle the destination and then dispatch. */ - if (tcfg->audio_loop) - dest = !dest; - - /* Loop based on the conn_mode, maybe undoing the above */ - if (endp->conn_mode == MGCP_CONN_LOOPBACK) - dest = !dest; - - if (dest == MGCP_DEST_NET) { - rtp_end = &endp->net_end; - rtp_state = &endp->bts_state; - tap_idx = MGCP_TAP_NET_OUT; - jb = endp->bts_jb; - } else { - rtp_end = &endp->bts_end; - rtp_state = &endp->net_state; - tap_idx = MGCP_TAP_BTS_OUT; - jb = NULL; - } - LOGP(DLMGCP, LOGL_DEBUG, - "endpoint %x dest %s net_end %s %d %d bts_end %s %d %d rtp_end %s %d %d\n", - ENDPOINT_NUMBER(endp), - dest == MGCP_DEST_NET? "net" : "bts", - - inet_ntoa(endp->net_end.addr), - ntohs(endp->net_end.rtp_port), - ntohs(endp->net_end.rtcp_port), - - inet_ntoa(endp->bts_end.addr), - ntohs(endp->bts_end.rtp_port), - ntohs(endp->bts_end.rtcp_port), - - inet_ntoa(rtp_end->addr), - ntohs(rtp_end->rtp_port), - ntohs(rtp_end->rtcp_port) - ); - - if (!rtp_end->output_enabled) { - rtp_end->dropped_packets += 1; - LOGP(DLMGCP, LOGL_DEBUG, - "endpoint %x output disabled, drop to %s %s %d %d\n", - ENDPOINT_NUMBER(endp), - dest == MGCP_DEST_NET? "net" : "bts", - inet_ntoa(rtp_end->addr), - ntohs(rtp_end->rtp_port), - ntohs(rtp_end->rtcp_port) - ); - } else if (is_rtp) { - int cont; - int nbytes = 0; - int len = rc; - do { - cont = endp->cfg->rtp_processing_cb(endp, rtp_end, - buf, &len, RTP_BUF_SIZE); - if (cont < 0) - break; - - mgcp_patch_and_count(endp, rtp_state, rtp_end, addr, buf, len); - LOGP(DLMGCP, LOGL_DEBUG, - "endpoint %x process/send to %s %s %d %d\n", - ENDPOINT_NUMBER(endp), - (dest == MGCP_DEST_NET)? "net" : "bts", - inet_ntoa(rtp_end->addr), - ntohs(rtp_end->rtp_port), - ntohs(rtp_end->rtcp_port) - ); - forward_data(rtp_end->rtp.fd, &endp->taps[tap_idx], - buf, len); - - /* FIXME: HACK HACK HACK. See OS#2459. - * The ip.access nano3G needs the first RTP payload's first two bytes to read hex - * 'e400', or it will reject the RAB assignment. It seems to not harm other femto - * cells (as long as we patch only the first RTP payload in each stream). - */ - if (tap_idx == MGCP_TAP_BTS_OUT - && !rtp_state->patched_first_rtp_payload) { - uint8_t *data = (uint8_t*)&buf[12]; - data[0] = 0xe4; - data[1] = 0x00; - rtp_state->patched_first_rtp_payload = true; - } - - if (jb) - rc = enqueue_dejitter(jb, rtp_end, buf, len); - else - rc = mgcp_udp_send(rtp_end->rtp.fd, - &rtp_end->addr, - rtp_end->rtp_port, buf, len); - - if (rc <= 0) - return rc; - nbytes += rc; - len = cont; - } while (len > 0); - return nbytes; - } else if (!tcfg->omit_rtcp) { - LOGP(DLMGCP, LOGL_DEBUG, - "endpoint %x send to %s %s %d %d\n", - ENDPOINT_NUMBER(endp), - dest == MGCP_DEST_NET? "net" : "bts", - inet_ntoa(rtp_end->addr), - ntohs(rtp_end->rtp_port), - ntohs(rtp_end->rtcp_port) - ); - - return mgcp_udp_send(rtp_end->rtcp.fd, - &rtp_end->addr, - rtp_end->rtcp_port, buf, rc); - } - - return 0; -} - -static int receive_from(struct mgcp_endpoint *endp, int fd, struct sockaddr_in *addr, - char *buf, int bufsize) -{ - int rc; - socklen_t slen = sizeof(*addr); - - rc = recvfrom(fd, buf, bufsize, 0, - (struct sockaddr *) addr, &slen); - if (rc < 0) { - LOGP(DLMGCP, LOGL_ERROR, "Failed to receive message on: 0x%x errno: %d/%s\n", - ENDPOINT_NUMBER(endp), errno, strerror(errno)); - return -1; - } - - /* do not forward aynthing... maybe there is a packet from the bts */ - if (!endp->allocated) - return -1; - - #warning "Slight spec violation. With connection mode recvonly we should attempt to forward." - - return rc; -} - -static int rtp_data_net(struct osmo_fd *fd, unsigned int what) -{ - char buf[RTP_BUF_SIZE]; - struct sockaddr_in addr; - struct mgcp_endpoint *endp; - int rc, proto; - - endp = (struct mgcp_endpoint *) fd->data; - - rc = receive_from(endp, fd->fd, &addr, buf, sizeof(buf)); - if (rc <= 0) - return -1; - - LOGP(DLMGCP, LOGL_DEBUG, - "endpoint %x", - ENDPOINT_NUMBER(endp)); - LOGPC(DLMGCP, LOGL_DEBUG, - " from net %s %d", - inet_ntoa(addr.sin_addr), - ntohs(addr.sin_port)); - LOGPC(DLMGCP, LOGL_DEBUG, - " net_end %s %d %d", - inet_ntoa(endp->net_end.addr), - ntohs(endp->net_end.rtp_port), - ntohs(endp->net_end.rtcp_port)); - LOGPC(DLMGCP, LOGL_DEBUG, - " bts_end %s %d %d\n", - inet_ntoa(endp->bts_end.addr), - ntohs(endp->bts_end.rtp_port), - ntohs(endp->bts_end.rtcp_port) - ); - - if (memcmp(&addr.sin_addr, &endp->net_end.addr, sizeof(addr.sin_addr)) != 0) { - LOGP(DLMGCP, LOGL_ERROR, - "rtp_data_net: Endpoint 0x%x data from wrong address %s vs. ", - ENDPOINT_NUMBER(endp), inet_ntoa(addr.sin_addr)); - LOGPC(DLMGCP, LOGL_ERROR, - "%s\n", inet_ntoa(endp->net_end.addr)); - return -1; - } - - switch(endp->type) { - case MGCP_RTP_DEFAULT: - case MGCP_RTP_TRANSCODED: - if (endp->net_end.rtp_port != addr.sin_port && - endp->net_end.rtcp_port != addr.sin_port) { - LOGP(DLMGCP, LOGL_ERROR, - "rtp_data_net: Data from wrong source port %d on 0x%x\n", - ntohs(addr.sin_port), ENDPOINT_NUMBER(endp)); - return -1; - } - break; - case MGCP_OSMUX_BSC: - case MGCP_OSMUX_BSC_NAT: - break; - } - - LOGP(DLMGCP, LOGL_DEBUG, - "rtp_data_net: Endpoint %x data from %s %d\n", - ENDPOINT_NUMBER(endp), - inet_ntoa(addr.sin_addr), - ntohs(addr.sin_port)); - - /* throw away the dummy message */ - if (rc == 1 && buf[0] == MGCP_DUMMY_LOAD) { - LOGP(DLMGCP, LOGL_NOTICE, "Filtered dummy from network on 0x%x\n", - ENDPOINT_NUMBER(endp)); - return 0; - } - - proto = fd == &endp->net_end.rtp ? MGCP_PROTO_RTP : MGCP_PROTO_RTCP; - endp->net_end.packets += 1; - endp->net_end.octets += rc; - - forward_data(fd->fd, &endp->taps[MGCP_TAP_NET_IN], buf, rc); - - switch (endp->type) { - case MGCP_RTP_DEFAULT: - return mgcp_send(endp, MGCP_DEST_BTS, proto == MGCP_PROTO_RTP, - &addr, buf, rc); - case MGCP_RTP_TRANSCODED: - return mgcp_send_transcoder(&endp->trans_net, endp->cfg, - proto == MGCP_PROTO_RTP, buf, rc); - case MGCP_OSMUX_BSC_NAT: - return osmux_xfrm_to_osmux(MGCP_DEST_BTS, buf, rc, endp); - case MGCP_OSMUX_BSC: /* Should not happen */ - break; - } - - LOGP(DLMGCP, LOGL_ERROR, "Bad MGCP type %u on endpoint %u\n", - endp->type, ENDPOINT_NUMBER(endp)); - return 0; -} - -static void discover_bts(struct mgcp_endpoint *endp, int proto, struct sockaddr_in *addr) -{ - struct mgcp_config *cfg = endp->cfg; - - if (proto == MGCP_PROTO_RTP && endp->bts_end.rtp_port == 0) { - if (!cfg->bts_ip || - memcmp(&addr->sin_addr, - &cfg->bts_in, sizeof(cfg->bts_in)) == 0 || - memcmp(&addr->sin_addr, - &endp->bts_end.addr, sizeof(endp->bts_end.addr)) == 0) { - - endp->bts_end.rtp_port = addr->sin_port; - endp->bts_end.addr = addr->sin_addr; - - LOGP(DLMGCP, LOGL_NOTICE, - "Found BTS for endpoint: 0x%x on port: %d/%d of %s\n", - ENDPOINT_NUMBER(endp), ntohs(endp->bts_end.rtp_port), - ntohs(endp->bts_end.rtcp_port), inet_ntoa(addr->sin_addr)); - } - } else if (proto == MGCP_PROTO_RTCP && endp->bts_end.rtcp_port == 0) { - if (memcmp(&endp->bts_end.addr, &addr->sin_addr, - sizeof(endp->bts_end.addr)) == 0) { - endp->bts_end.rtcp_port = addr->sin_port; - } - } -} - -static int rtp_data_bts(struct osmo_fd *fd, unsigned int what) -{ - char buf[RTP_BUF_SIZE]; - struct sockaddr_in addr; - struct mgcp_endpoint *endp; - int rc, proto; - - endp = (struct mgcp_endpoint *) fd->data; - - rc = receive_from(endp, fd->fd, &addr, buf, sizeof(buf)); - if (rc <= 0) - return -1; - - proto = fd == &endp->bts_end.rtp ? MGCP_PROTO_RTP : MGCP_PROTO_RTCP; - - /* We have no idea who called us, maybe it is the BTS. */ - /* it was the BTS... */ - discover_bts(endp, proto, &addr); - - if (memcmp(&endp->bts_end.addr, &addr.sin_addr, sizeof(addr.sin_addr)) != 0) { - LOGP(DLMGCP, LOGL_ERROR, - "rtp_data_bts: Data from wrong bts %s on 0x%x\n", - inet_ntoa(addr.sin_addr), ENDPOINT_NUMBER(endp)); - return -1; - } - - if (endp->bts_end.rtp_port != addr.sin_port && - endp->bts_end.rtcp_port != addr.sin_port) { - LOGP(DLMGCP, LOGL_ERROR, - "rtp_data_bts: ata from wrong bts source port %d on 0x%x\n", - ntohs(addr.sin_port), ENDPOINT_NUMBER(endp)); - return -1; - } - - LOGP(DLMGCP, LOGL_DEBUG, - "rtp_data_bts: Endpoint %x data from %s %d\n", - ENDPOINT_NUMBER(endp), - inet_ntoa(addr.sin_addr), - ntohs(addr.sin_port)); - - /* throw away the dummy message */ - if (rc == 1 && buf[0] == MGCP_DUMMY_LOAD) { - LOGP(DLMGCP, LOGL_NOTICE, "Filtered dummy from bts on 0x%x\n", - ENDPOINT_NUMBER(endp)); - return 0; - } - - /* do this before the loop handling */ - endp->bts_end.packets += 1; - endp->bts_end.octets += rc; - - forward_data(fd->fd, &endp->taps[MGCP_TAP_BTS_IN], buf, rc); - - switch (endp->type) { - case MGCP_RTP_DEFAULT: - LOGP(DLMGCP, LOGL_DEBUG, - "rtp_data_bts: Endpoint %x MGCP_RTP_DEFAULT\n", - ENDPOINT_NUMBER(endp)); - return mgcp_send(endp, MGCP_DEST_NET, proto == MGCP_PROTO_RTP, - &addr, buf, rc); - case MGCP_RTP_TRANSCODED: - return mgcp_send_transcoder(&endp->trans_bts, endp->cfg, - proto == MGCP_PROTO_RTP, buf, rc); - case MGCP_OSMUX_BSC: - /* OSMUX translation: BTS -> BSC */ - return osmux_xfrm_to_osmux(MGCP_DEST_NET, buf, rc, endp); - case MGCP_OSMUX_BSC_NAT: - break; /* Should not happen */ - } - - LOGP(DLMGCP, LOGL_ERROR, "Bad MGCP type %u on endpoint %u\n", - endp->type, ENDPOINT_NUMBER(endp)); - return 0; -} - -static int rtp_data_transcoder(struct mgcp_rtp_end *end, struct mgcp_endpoint *_endp, - int dest, struct osmo_fd *fd) -{ - char buf[RTP_BUF_SIZE]; - struct sockaddr_in addr; - struct mgcp_config *cfg; - int rc, proto; - - cfg = _endp->cfg; - rc = receive_from(_endp, fd->fd, &addr, buf, sizeof(buf)); - if (rc <= 0) - return -1; - - proto = fd == &end->rtp ? MGCP_PROTO_RTP : MGCP_PROTO_RTCP; - - if (memcmp(&addr.sin_addr, &cfg->transcoder_in, sizeof(addr.sin_addr)) != 0) { - LOGP(DLMGCP, LOGL_ERROR, - "Data not coming from transcoder dest: %d %s on 0x%x\n", - dest, inet_ntoa(addr.sin_addr), ENDPOINT_NUMBER(_endp)); - return -1; - } - - if (end->rtp_port != addr.sin_port && - end->rtcp_port != addr.sin_port) { - LOGP(DLMGCP, LOGL_ERROR, - "Data from wrong transcoder dest %d source port %d on 0x%x\n", - dest, ntohs(addr.sin_port), ENDPOINT_NUMBER(_endp)); - return -1; - } - - /* throw away the dummy message */ - if (rc == 1 && buf[0] == MGCP_DUMMY_LOAD) { - LOGP(DLMGCP, LOGL_NOTICE, "Filtered dummy from transcoder dest %d on 0x%x\n", - dest, ENDPOINT_NUMBER(_endp)); - return 0; - } - - end->packets += 1; - return mgcp_send(_endp, dest, proto == MGCP_PROTO_RTP, &addr, buf, rc); -} - -static int rtp_data_trans_net(struct osmo_fd *fd, unsigned int what) -{ - struct mgcp_endpoint *endp; - endp = (struct mgcp_endpoint *) fd->data; - - return rtp_data_transcoder(&endp->trans_net, endp, MGCP_DEST_NET, fd); -} - -static int rtp_data_trans_bts(struct osmo_fd *fd, unsigned int what) -{ - struct mgcp_endpoint *endp; - endp = (struct mgcp_endpoint *) fd->data; - - return rtp_data_transcoder(&endp->trans_bts, endp, MGCP_DEST_BTS, fd); -} - -int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port) -{ - struct sockaddr_in addr; - int on = 1; - - fd->fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd->fd < 0) { - LOGP(DLMGCP, LOGL_ERROR, "Failed to create UDP port.\n"); - return -1; - } - - setsockopt(fd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - inet_aton(source_addr, &addr.sin_addr); - - if (bind(fd->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - close(fd->fd); - fd->fd = -1; - return -1; - } - - return 0; -} - -int mgcp_set_ip_tos(int fd, int tos) -{ - int ret; - ret = setsockopt(fd, IPPROTO_IP, IP_TOS, - &tos, sizeof(tos)); - return ret != 0; -} - -static int bind_rtp(struct mgcp_config *cfg, const char *source_addr, - struct mgcp_rtp_end *rtp_end, int endpno) -{ - if (mgcp_create_bind(source_addr, &rtp_end->rtp, - rtp_end->local_port) != 0) { - LOGP(DLMGCP, LOGL_ERROR, "Failed to create RTP port: %s:%d on 0x%x\n", - source_addr, rtp_end->local_port, endpno); - goto cleanup0; - } - - if (mgcp_create_bind(source_addr, &rtp_end->rtcp, - rtp_end->local_port + 1) != 0) { - LOGP(DLMGCP, LOGL_ERROR, "Failed to create RTCP port: %s:%d on 0x%x\n", - source_addr, rtp_end->local_port + 1, endpno); - goto cleanup1; - } - - mgcp_set_ip_tos(rtp_end->rtp.fd, cfg->endp_dscp); - mgcp_set_ip_tos(rtp_end->rtcp.fd, cfg->endp_dscp); - - rtp_end->rtp.when = BSC_FD_READ; - if (osmo_fd_register(&rtp_end->rtp) != 0) { - LOGP(DLMGCP, LOGL_ERROR, "Failed to register RTP port %d on 0x%x\n", - rtp_end->local_port, endpno); - goto cleanup2; - } - - rtp_end->rtcp.when = BSC_FD_READ; - if (osmo_fd_register(&rtp_end->rtcp) != 0) { - LOGP(DLMGCP, LOGL_ERROR, "Failed to register RTCP port %d on 0x%x\n", - rtp_end->local_port + 1, endpno); - goto cleanup3; - } - - return 0; - -cleanup3: - osmo_fd_unregister(&rtp_end->rtp); -cleanup2: - close(rtp_end->rtcp.fd); - rtp_end->rtcp.fd = -1; -cleanup1: - close(rtp_end->rtp.fd); - rtp_end->rtp.fd = -1; -cleanup0: - return -1; -} - -static int int_bind(const char *port, - struct mgcp_rtp_end *end, int (*cb)(struct osmo_fd *, unsigned), - struct mgcp_endpoint *_endp, - const char *source_addr, int rtp_port) -{ - if (end->rtp.fd != -1 || end->rtcp.fd != -1) { - LOGP(DLMGCP, LOGL_ERROR, "Previous %s was still bound on %d\n", - port, ENDPOINT_NUMBER(_endp)); - mgcp_free_rtp_port(end); - } - - end->local_port = rtp_port; - end->rtp.cb = cb; - end->rtp.data = _endp; - end->rtcp.data = _endp; - end->rtcp.cb = cb; - return bind_rtp(_endp->cfg, source_addr, end, ENDPOINT_NUMBER(_endp)); -} - -int mgcp_bind_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port) -{ - return int_bind("bts-port", &endp->bts_end, - rtp_data_bts, endp, - mgcp_bts_src_addr(endp), rtp_port); -} - -int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port) -{ - return int_bind("net-port", &endp->net_end, - rtp_data_net, endp, - mgcp_net_src_addr(endp), rtp_port); -} - -int mgcp_bind_trans_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port) -{ - return int_bind("trans-net", &endp->trans_net, - rtp_data_trans_net, endp, - endp->cfg->source_addr, rtp_port); -} - -int mgcp_bind_trans_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port) -{ - return int_bind("trans-bts", &endp->trans_bts, - rtp_data_trans_bts, endp, - endp->cfg->source_addr, rtp_port); -} - -int mgcp_free_rtp_port(struct mgcp_rtp_end *end) -{ - if (end->rtp.fd != -1) { - close(end->rtp.fd); - end->rtp.fd = -1; - osmo_fd_unregister(&end->rtp); - } - - if (end->rtcp.fd != -1) { - close(end->rtcp.fd); - end->rtcp.fd = -1; - osmo_fd_unregister(&end->rtcp); - } - - return 0; -} - - -void mgcp_state_calc_loss(struct mgcp_rtp_state *state, - struct mgcp_rtp_end *end, uint32_t *expected, - int *loss) -{ - *expected = state->stats_cycles + state->stats_max_seq; - *expected = *expected - state->stats_base_seq + 1; - - if (!state->stats_initialized) { - *expected = 0; - *loss = 0; - return; - } - - /* - * Make sure the sign is correct and use the biggest - * positive/negative number that fits. - */ - *loss = *expected - end->packets; - if (*expected < end->packets) { - if (*loss > 0) - *loss = INT_MIN; - } else { - if (*loss < 0) - *loss = INT_MAX; - } -} - -uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *state) -{ - if (!state->stats_initialized) - return 0; - return state->stats_jitter >> 4; -} diff --git a/src/libosmo-legacy-mgcp/mgcp_osmux.c b/src/libosmo-legacy-mgcp/mgcp_osmux.c deleted file mode 100644 index b53e2b57b..000000000 --- a/src/libosmo-legacy-mgcp/mgcp_osmux.c +++ /dev/null @@ -1,588 +0,0 @@ -/* - * (C) 2012-2013 by Pablo Neira Ayuso - * (C) 2012-2013 by On Waves ehf - * All rights not specifically granted under this license are reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by the - * Free Software Foundation; either version 3 of the License, or (at your - * option) any later version. - */ - -#include /* for printf */ -#include /* for memcpy */ -#include /* for abs */ -#include /* for PRIu64 */ -#include -#include -#include - -#include -#include - -#include -#include -#include - -static struct osmo_fd osmux_fd; - -static LLIST_HEAD(osmux_handle_list); - -struct osmux_handle { - struct llist_head head; - struct osmux_in_handle *in; - struct in_addr rem_addr; - int rem_port; - int refcnt; -}; - -static void *osmux; - -static void osmux_deliver(struct msgb *batch_msg, void *data) -{ - struct osmux_handle *handle = data; - struct sockaddr_in out = { - .sin_family = AF_INET, - .sin_port = handle->rem_port, - }; - - memcpy(&out.sin_addr, &handle->rem_addr, sizeof(handle->rem_addr)); - sendto(osmux_fd.fd, batch_msg->data, batch_msg->len, 0, - (struct sockaddr *)&out, sizeof(out)); - msgb_free(batch_msg); -} - -static struct osmux_handle * -osmux_handle_find_get(struct in_addr *addr, int rem_port) -{ - struct osmux_handle *h; - - /* Lookup for existing OSMUX handle for this destination address. */ - llist_for_each_entry(h, &osmux_handle_list, head) { - if (memcmp(&h->rem_addr, addr, sizeof(struct in_addr)) == 0 && - h->rem_port == rem_port) { - LOGP(DLMGCP, LOGL_DEBUG, "using existing OSMUX handle " - "for addr=%s:%d\n", - inet_ntoa(*addr), ntohs(rem_port)); - h->refcnt++; - return h; - } - } - - return NULL; -} - -static void osmux_handle_put(struct osmux_in_handle *in) -{ - struct osmux_handle *h; - - /* Lookup for existing OSMUX handle for this destination address. */ - llist_for_each_entry(h, &osmux_handle_list, head) { - if (h->in == in) { - if (--h->refcnt == 0) { - LOGP(DLMGCP, LOGL_INFO, - "Releasing unused osmux handle for %s:%d\n", - inet_ntoa(h->rem_addr), - ntohs(h->rem_port)); - LOGP(DLMGCP, LOGL_INFO, "Stats: " - "input RTP msgs: %u bytes: %"PRIu64" " - "output osmux msgs: %u bytes: %"PRIu64"\n", - in->stats.input_rtp_msgs, - in->stats.input_rtp_bytes, - in->stats.output_osmux_msgs, - in->stats.output_osmux_bytes); - llist_del(&h->head); - osmux_xfrm_input_fini(h->in); - talloc_free(h); - } - return; - } - } - LOGP(DLMGCP, LOGL_ERROR, "cannot find Osmux input handle %p\n", in); -} - -static struct osmux_handle * -osmux_handle_alloc(struct mgcp_config *cfg, struct in_addr *addr, int rem_port) -{ - struct osmux_handle *h; - - h = talloc_zero(osmux, struct osmux_handle); - if (!h) - return NULL; - h->rem_addr = *addr; - h->rem_port = rem_port; - h->refcnt++; - - h->in = talloc_zero(h, struct osmux_in_handle); - if (!h->in) { - talloc_free(h); - return NULL; - } - - h->in->osmux_seq = 0; /* sequence number to start OSmux message from */ - h->in->batch_factor = cfg->osmux_batch; - /* If batch size is zero, the library defaults to 1470 bytes. */ - h->in->batch_size = cfg->osmux_batch_size; - h->in->deliver = osmux_deliver; - osmux_xfrm_input_init(h->in); - h->in->data = h; - - llist_add(&h->head, &osmux_handle_list); - - LOGP(DLMGCP, LOGL_DEBUG, "created new OSMUX handle for addr=%s:%d\n", - inet_ntoa(*addr), ntohs(rem_port)); - - return h; -} - -static struct osmux_in_handle * -osmux_handle_lookup(struct mgcp_config *cfg, struct in_addr *addr, int rem_port) -{ - struct osmux_handle *h; - - h = osmux_handle_find_get(addr, rem_port); - if (h != NULL) - return h->in; - - h = osmux_handle_alloc(cfg, addr, rem_port); - if (h == NULL) - return NULL; - - return h->in; -} - -int osmux_xfrm_to_osmux(int type, char *buf, int rc, struct mgcp_endpoint *endp) -{ - int ret; - struct msgb *msg; - - msg = msgb_alloc(4096, "RTP"); - if (!msg) - return 0; - - memcpy(msg->data, buf, rc); - msgb_put(msg, rc); - - while ((ret = osmux_xfrm_input(endp->osmux.in, msg, endp->osmux.cid)) > 0) { - /* batch full, build and deliver it */ - osmux_xfrm_input_deliver(endp->osmux.in); - } - return 0; -} - -static struct mgcp_endpoint * -endpoint_lookup(struct mgcp_config *cfg, int cid, - struct in_addr *from_addr, int type) -{ - struct mgcp_endpoint *tmp = NULL; - int i; - - /* Lookup for the endpoint that corresponds to this port */ - for (i=0; itrunk.number_endpoints; i++) { - struct in_addr *this; - - tmp = &cfg->trunk.endpoints[i]; - - if (!tmp->allocated) - continue; - - switch(type) { - case MGCP_DEST_NET: - this = &tmp->net_end.addr; - break; - case MGCP_DEST_BTS: - this = &tmp->bts_end.addr; - break; - default: - /* Should not ever happen */ - LOGP(DLMGCP, LOGL_ERROR, "Bad type %d. Fix your code.\n", type); - return NULL; - } - - if (tmp->osmux.cid == cid && this->s_addr == from_addr->s_addr) - return tmp; - } - - LOGP(DLMGCP, LOGL_ERROR, "Cannot find endpoint with cid=%d\n", cid); - - return NULL; -} - -static void scheduled_tx_net_cb(struct msgb *msg, void *data) -{ - struct mgcp_endpoint *endp = data; - struct sockaddr_in addr = { - .sin_addr = endp->net_end.addr, - .sin_port = endp->net_end.rtp_port, - }; - - endp->bts_end.octets += msg->len; - endp->bts_end.packets++; - - mgcp_send(endp, MGCP_DEST_NET, 1, &addr, (char *)msg->data, msg->len); - msgb_free(msg); -} - -static void scheduled_tx_bts_cb(struct msgb *msg, void *data) -{ - struct mgcp_endpoint *endp = data; - struct sockaddr_in addr = { - .sin_addr = endp->bts_end.addr, - .sin_port = endp->bts_end.rtp_port, - }; - - endp->net_end.octets += msg->len; - endp->net_end.packets++; - - mgcp_send(endp, MGCP_DEST_BTS, 1, &addr, (char *)msg->data, msg->len); - msgb_free(msg); -} - -static struct msgb *osmux_recv(struct osmo_fd *ofd, struct sockaddr_in *addr) -{ - struct msgb *msg; - socklen_t slen = sizeof(*addr); - int ret; - - msg = msgb_alloc(4096, "OSMUX"); - if (!msg) { - LOGP(DLMGCP, LOGL_ERROR, "cannot allocate message\n"); - return NULL; - } - ret = recvfrom(ofd->fd, msg->data, msg->data_len, 0, - (struct sockaddr *)addr, &slen); - if (ret <= 0) { - msgb_free(msg); - LOGP(DLMGCP, LOGL_ERROR, "cannot receive message\n"); - return NULL; - } - msgb_put(msg, ret); - - return msg; -} - -#define osmux_chunk_length(msg, rem) (rem - msg->len); - -int osmux_read_from_bsc_nat_cb(struct osmo_fd *ofd, unsigned int what) -{ - struct msgb *msg; - struct osmux_hdr *osmuxh; - struct sockaddr_in addr; - struct mgcp_config *cfg = ofd->data; - uint32_t rem; - - msg = osmux_recv(ofd, &addr); - if (!msg) - return -1; - - /* not any further processing dummy messages */ - if (msg->data[0] == MGCP_DUMMY_LOAD) - goto out; - - rem = msg->len; - while((osmuxh = osmux_xfrm_output_pull(msg)) != NULL) { - struct mgcp_endpoint *endp; - - /* Yes, we use MGCP_DEST_NET to locate the origin */ - endp = endpoint_lookup(cfg, osmuxh->circuit_id, - &addr.sin_addr, MGCP_DEST_NET); - if (!endp) { - LOGP(DLMGCP, LOGL_ERROR, - "Cannot find an endpoint for circuit_id=%d\n", - osmuxh->circuit_id); - goto out; - } - endp->osmux.stats.octets += osmux_chunk_length(msg, rem); - endp->osmux.stats.chunks++; - rem = msg->len; - - osmux_xfrm_output_sched(&endp->osmux.out, osmuxh); - } -out: - msgb_free(msg); - return 0; -} - -/* This is called from the bsc-nat */ -static int osmux_handle_dummy(struct mgcp_config *cfg, struct sockaddr_in *addr, - struct msgb *msg) -{ - struct mgcp_endpoint *endp; - uint8_t osmux_cid; - - if (msg->len < 1 + sizeof(osmux_cid)) { - LOGP(DLMGCP, LOGL_ERROR, - "Discarding truncated Osmux dummy load\n"); - goto out; - } - - LOGP(DLMGCP, LOGL_DEBUG, "Received Osmux dummy load from %s\n", - inet_ntoa(addr->sin_addr)); - - if (!cfg->osmux) { - LOGP(DLMGCP, LOGL_ERROR, - "bsc wants to use Osmux but bsc-nat did not request it\n"); - goto out; - } - - /* extract the osmux CID from the dummy message */ - memcpy(&osmux_cid, &msg->data[1], sizeof(osmux_cid)); - - endp = endpoint_lookup(cfg, osmux_cid, &addr->sin_addr, MGCP_DEST_BTS); - if (!endp) { - LOGP(DLMGCP, LOGL_ERROR, - "Cannot find endpoint for Osmux CID %d\n", osmux_cid); - goto out; - } - - if (endp->osmux.state == OSMUX_STATE_ENABLED) - goto out; - - if (osmux_enable_endpoint(endp, &addr->sin_addr, addr->sin_port) < 0 ) { - LOGP(DLMGCP, LOGL_ERROR, - "Could not enable osmux in endpoint %d\n", - ENDPOINT_NUMBER(endp)); - goto out; - } - - LOGP(DLMGCP, LOGL_INFO, "Enabling osmux in endpoint %d for %s:%u\n", - ENDPOINT_NUMBER(endp), inet_ntoa(addr->sin_addr), - ntohs(addr->sin_port)); -out: - msgb_free(msg); - return 0; -} - -int osmux_read_from_bsc_cb(struct osmo_fd *ofd, unsigned int what) -{ - struct msgb *msg; - struct osmux_hdr *osmuxh; - struct sockaddr_in addr; - struct mgcp_config *cfg = ofd->data; - uint32_t rem; - - msg = osmux_recv(ofd, &addr); - if (!msg) - return -1; - - /* not any further processing dummy messages */ - if (msg->data[0] == MGCP_DUMMY_LOAD) - return osmux_handle_dummy(cfg, &addr, msg); - - rem = msg->len; - while((osmuxh = osmux_xfrm_output_pull(msg)) != NULL) { - struct mgcp_endpoint *endp; - - /* Yes, we use MGCP_DEST_BTS to locate the origin */ - endp = endpoint_lookup(cfg, osmuxh->circuit_id, - &addr.sin_addr, MGCP_DEST_BTS); - if (!endp) { - LOGP(DLMGCP, LOGL_ERROR, - "Cannot find an endpoint for circuit_id=%d\n", - osmuxh->circuit_id); - goto out; - } - endp->osmux.stats.octets += osmux_chunk_length(msg, rem); - endp->osmux.stats.chunks++; - rem = msg->len; - - osmux_xfrm_output_sched(&endp->osmux.out, osmuxh); - } -out: - msgb_free(msg); - return 0; -} - -int osmux_init(int role, struct mgcp_config *cfg) -{ - int ret; - - switch(role) { - case OSMUX_ROLE_BSC: - osmux_fd.cb = osmux_read_from_bsc_nat_cb; - break; - case OSMUX_ROLE_BSC_NAT: - osmux_fd.cb = osmux_read_from_bsc_cb; - break; - default: - LOGP(DLMGCP, LOGL_ERROR, "wrong role for OSMUX\n"); - return -1; - } - osmux_fd.data = cfg; - - ret = mgcp_create_bind(cfg->osmux_addr, &osmux_fd, cfg->osmux_port); - if (ret < 0) { - LOGP(DLMGCP, LOGL_ERROR, "cannot bind OSMUX socket\n"); - return ret; - } - mgcp_set_ip_tos(osmux_fd.fd, cfg->endp_dscp); - osmux_fd.when |= BSC_FD_READ; - - ret = osmo_fd_register(&osmux_fd); - if (ret < 0) { - LOGP(DLMGCP, LOGL_ERROR, "cannot register OSMUX socket\n"); - return ret; - } - cfg->osmux_init = 1; - - return 0; -} - -int osmux_enable_endpoint(struct mgcp_endpoint *endp, struct in_addr *addr, uint16_t port) -{ - /* If osmux is enabled, initialize the output handler. This handler is - * used to reconstruct the RTP flow from osmux. The RTP SSRC is - * allocated based on the circuit ID (endp->osmux.cid), which is unique - * in the local scope to the BSC/BSC-NAT. We use it to divide the RTP - * SSRC space (2^32) by the 256 possible circuit IDs, then randomly - * select one value from that window. Thus, we have no chance to have - * overlapping RTP SSRC traveling to the BTSes behind the BSC, - * similarly, for flows traveling to the MSC. - */ - static const uint32_t rtp_ssrc_winlen = UINT32_MAX / 256; - - if (endp->osmux.state == OSMUX_STATE_DISABLED) { - LOGP(DLMGCP, LOGL_ERROR, "Endpoint %u didn't request Osmux\n", - ENDPOINT_NUMBER(endp)); - return -1; - } - - osmux_xfrm_output_init(&endp->osmux.out, - (endp->osmux.cid * rtp_ssrc_winlen) + - (random() % rtp_ssrc_winlen)); - - endp->osmux.in = osmux_handle_lookup(endp->cfg, addr, port); - if (!endp->osmux.in) { - LOGP(DLMGCP, LOGL_ERROR, "Cannot allocate input osmux handle\n"); - return -1; - } - if (!osmux_xfrm_input_open_circuit(endp->osmux.in, endp->osmux.cid, - endp->cfg->osmux_dummy)) { - LOGP(DLMGCP, LOGL_ERROR, "Cannot open osmux circuit %u\n", - endp->osmux.cid); - return -1; - } - - switch (endp->cfg->role) { - case MGCP_BSC_NAT: - endp->type = MGCP_OSMUX_BSC_NAT; - osmux_xfrm_output_set_tx_cb(&endp->osmux.out, - scheduled_tx_net_cb, endp); - break; - case MGCP_BSC: - endp->type = MGCP_OSMUX_BSC; - osmux_xfrm_output_set_tx_cb(&endp->osmux.out, - scheduled_tx_bts_cb, endp); - break; - } - endp->osmux.state = OSMUX_STATE_ENABLED; - - return 0; -} - -void osmux_disable_endpoint(struct mgcp_endpoint *endp) -{ - LOGP(DLMGCP, LOGL_INFO, "Releasing endpoint %u using Osmux CID %u\n", - ENDPOINT_NUMBER(endp), endp->osmux.cid); - - /* We are closing, we don't need pending RTP packets to be transmitted */ - osmux_xfrm_output_set_tx_cb(&endp->osmux.out, NULL, NULL); - osmux_xfrm_output_flush(&endp->osmux.out); - - osmux_xfrm_input_close_circuit(endp->osmux.in, endp->osmux.cid); - endp->osmux.state = OSMUX_STATE_DISABLED; - endp->osmux.cid = -1; - osmux_handle_put(endp->osmux.in); -} - -void osmux_release_cid(struct mgcp_endpoint *endp) -{ - if (endp->osmux.allocated_cid >= 0) - osmux_put_cid(endp->osmux.allocated_cid); - endp->osmux.allocated_cid = -1; -} - -void osmux_allocate_cid(struct mgcp_endpoint *endp) -{ - osmux_release_cid(endp); - endp->osmux.allocated_cid = osmux_get_cid(); -} - -/* We don't need to send the dummy load for osmux so often as another endpoint - * may have already punched the hole in the firewall. This approach is simple - * though. - */ -int osmux_send_dummy(struct mgcp_endpoint *endp) -{ - char buf[1 + sizeof(uint8_t)]; - struct in_addr addr_unset = {}; - - buf[0] = MGCP_DUMMY_LOAD; - memcpy(&buf[1], &endp->osmux.cid, sizeof(endp->osmux.cid)); - - /* Wait until we have the connection information from MDCX */ - if (memcmp(&endp->net_end.addr, &addr_unset, sizeof(addr_unset)) == 0) - return 0; - - if (endp->osmux.state == OSMUX_STATE_ACTIVATING) { - if (osmux_enable_endpoint(endp, &endp->net_end.addr, - htons(endp->cfg->osmux_port)) < 0) { - LOGP(DLMGCP, LOGL_ERROR, - "Could not activate osmux in endpoint %d\n", - ENDPOINT_NUMBER(endp)); - } - LOGP(DLMGCP, LOGL_ERROR, - "Osmux CID %u for %s:%u is now enabled\n", - endp->osmux.cid, inet_ntoa(endp->net_end.addr), - endp->cfg->osmux_port); - } - LOGP(DLMGCP, LOGL_DEBUG, - "sending OSMUX dummy load to %s CID %u\n", - inet_ntoa(endp->net_end.addr), endp->osmux.cid); - - return mgcp_udp_send(osmux_fd.fd, &endp->net_end.addr, - htons(endp->cfg->osmux_port), buf, sizeof(buf)); -} - -/* bsc-nat allocates/releases the Osmux circuit ID */ -static uint8_t osmux_cid_bitmap[(OSMUX_CID_MAX + 1) / 8]; - -int osmux_used_cid(void) -{ - int i, j, used = 0; - - for (i = 0; i < sizeof(osmux_cid_bitmap); i++) { - for (j = 0; j < 8; j++) { - if (osmux_cid_bitmap[i] & (1 << j)) - used += 1; - } - } - - return used; -} - -int osmux_get_cid(void) -{ - int i, j; - - for (i = 0; i < sizeof(osmux_cid_bitmap); i++) { - for (j = 0; j < 8; j++) { - if (osmux_cid_bitmap[i] & (1 << j)) - continue; - - osmux_cid_bitmap[i] |= (1 << j); - LOGP(DLMGCP, LOGL_DEBUG, - "Allocating Osmux CID %u from pool\n", (i * 8) + j); - return (i * 8) + j; - } - } - - LOGP(DLMGCP, LOGL_ERROR, "All Osmux circuits are in use!\n"); - return -1; -} - -void osmux_put_cid(uint8_t osmux_cid) -{ - LOGP(DLMGCP, LOGL_DEBUG, "Osmux CID %u is back to the pool\n", osmux_cid); - osmux_cid_bitmap[osmux_cid / 8] &= ~(1 << (osmux_cid % 8)); -} diff --git a/src/libosmo-legacy-mgcp/mgcp_protocol.c b/src/libosmo-legacy-mgcp/mgcp_protocol.c deleted file mode 100644 index 854b4baa5..000000000 --- a/src/libosmo-legacy-mgcp/mgcp_protocol.c +++ /dev/null @@ -1,1665 +0,0 @@ -/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */ -/* The protocol implementation */ - -/* - * (C) 2009-2012 by Holger Hans Peter Freyther - * (C) 2009-2012 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#define for_each_non_empty_line(line, save) \ - for (line = strtok_r(NULL, "\r\n", &save); line;\ - line = strtok_r(NULL, "\r\n", &save)) - - -static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end); - -struct mgcp_request { - char *name; - struct msgb *(*handle_request) (struct mgcp_parse_data *data); - char *debug_name; -}; - -#define MGCP_REQUEST(NAME, REQ, DEBUG_NAME) \ - { .name = NAME, .handle_request = REQ, .debug_name = DEBUG_NAME }, - -static struct msgb *handle_audit_endpoint(struct mgcp_parse_data *data); -static struct msgb *handle_create_con(struct mgcp_parse_data *data); -static struct msgb *handle_delete_con(struct mgcp_parse_data *data); -static struct msgb *handle_modify_con(struct mgcp_parse_data *data); -static struct msgb *handle_rsip(struct mgcp_parse_data *data); -static struct msgb *handle_noti_req(struct mgcp_parse_data *data); - -static void create_transcoder(struct mgcp_endpoint *endp); -static void delete_transcoder(struct mgcp_endpoint *endp); - -static int setup_rtp_processing(struct mgcp_endpoint *endp); - -static int mgcp_analyze_header(struct mgcp_parse_data *parse, char *data); - -/* Display an mgcp message on the log output */ -void display_mgcp_message(unsigned char *message, unsigned int len, - char *preamble) -{ - unsigned char line[80]; - unsigned char *ptr; - unsigned int consumed = 0; - unsigned int consumed_line = 0; - unsigned int line_count = 0; - - if (!log_check_level(DLMGCP, LOGL_DEBUG)) - return; - - while (1) { - memset(line, 0, sizeof(line)); - ptr = line; - consumed_line = 0; - do { - if (*message != '\n' && *message != '\r') { - *ptr = *message; - ptr++; - } - message++; - consumed++; - consumed_line++; - } while (*message != '\n' && consumed < len - && consumed_line < sizeof(line)); - - if (strlen((const char *)line)) { - LOGP(DLMGCP, LOGL_DEBUG, "%s: line #%02u: %s\n", - preamble, line_count, line); - line_count++; - } - - if (consumed >= len) - return; - } -} - -static int mgcp_check_param(const struct mgcp_endpoint *endp, const char *line) -{ - const size_t line_len = strlen(line); - if (line[0] != '\0' && line_len < 2) { - LOGP(DLMGCP, LOGL_ERROR, - "Wrong MGCP option format: '%s' on 0x%x\n", - line, ENDPOINT_NUMBER(endp)); - return 0; - } - - return 1; -} - -static uint32_t generate_call_id(struct mgcp_config *cfg) -{ - int i; - - /* use the call id */ - ++cfg->last_call_id; - - /* handle wrap around */ - if (cfg->last_call_id == CI_UNUSED) - ++cfg->last_call_id; - - /* callstack can only be of size number_of_endpoints */ - /* verify that the call id is free, e.g. in case of overrun */ - for (i = 1; i < cfg->trunk.number_endpoints; ++i) - if (cfg->trunk.endpoints[i].ci == cfg->last_call_id) - return generate_call_id(cfg); - - return cfg->last_call_id; -} - -/* - * array of function pointers for handling various - * messages. In the future this might be binary sorted - * for performance reasons. - */ -static const struct mgcp_request mgcp_requests [] = { - MGCP_REQUEST("AUEP", handle_audit_endpoint, "AuditEndpoint") - MGCP_REQUEST("CRCX", handle_create_con, "CreateConnection") - MGCP_REQUEST("DLCX", handle_delete_con, "DeleteConnection") - MGCP_REQUEST("MDCX", handle_modify_con, "ModifiyConnection") - MGCP_REQUEST("RQNT", handle_noti_req, "NotificationRequest") - - /* SPEC extension */ - MGCP_REQUEST("RSIP", handle_rsip, "ReSetInProgress") -}; - -static struct msgb *mgcp_msgb_alloc(void) -{ - struct msgb *msg; - msg = msgb_alloc_headroom(4096, 128, "MGCP msg"); - if (!msg) - LOGP(DLMGCP, LOGL_ERROR, "Failed to msgb for MGCP data.\n"); - - return msg; -} - -static struct msgb *do_retransmission(const struct mgcp_endpoint *endp) -{ - struct msgb *msg = mgcp_msgb_alloc(); - if (!msg) - return NULL; - - msg->l2h = msgb_put(msg, strlen(endp->last_response)); - memcpy(msg->l2h, endp->last_response, msgb_l2len(msg)); - display_mgcp_message(msg->l2h, msgb_l2len(msg), "Retransmitted response"); - return msg; -} - -static struct msgb *create_resp(struct mgcp_endpoint *endp, int code, - const char *txt, const char *msg, - const char *trans, const char *param, - const char *sdp) -{ - int len; - struct msgb *res; - - res = mgcp_msgb_alloc(); - if (!res) - return NULL; - - len = snprintf((char *) res->data, 2048, "%d %s%s%s\r\n%s", - code, trans, txt, param ? param : "", sdp ? sdp : ""); - if (len < 0) { - LOGP(DLMGCP, LOGL_ERROR, "Failed to sprintf MGCP response.\n"); - msgb_free(res); - return NULL; - } - - res->l2h = msgb_put(res, len); - LOGP(DLMGCP, LOGL_DEBUG, "Generated response: code=%d\n", code); - display_mgcp_message(res->l2h, msgb_l2len(res), "Generated response"); - - /* - * Remember the last transmission per endpoint. - */ - if (endp) { - struct mgcp_trunk_config *tcfg = endp->tcfg; - talloc_free(endp->last_response); - talloc_free(endp->last_trans); - endp->last_trans = talloc_strdup(tcfg->endpoints, trans); - endp->last_response = talloc_strndup(tcfg->endpoints, - (const char *) res->l2h, - msgb_l2len(res)); - } - - return res; -} - -static struct msgb *create_ok_resp_with_param(struct mgcp_endpoint *endp, - int code, const char *msg, - const char *trans, const char *param) -{ - return create_resp(endp, code, " OK", msg, trans, param, NULL); -} - -static struct msgb *create_ok_response(struct mgcp_endpoint *endp, - int code, const char *msg, const char *trans) -{ - return create_ok_resp_with_param(endp, code, msg, trans, NULL); -} - -static struct msgb *create_err_response(struct mgcp_endpoint *endp, - int code, const char *msg, const char *trans) -{ - return create_resp(endp, code, " FAIL", msg, trans, NULL, NULL); -} - -static int write_response_sdp(struct mgcp_endpoint *endp, - char *sdp_record, size_t size, const char *addr) -{ - const char *fmtp_extra; - const char *audio_name; - int payload_type; - int len; - int nchars; - - endp->cfg->get_net_downlink_format_cb(endp, &payload_type, - &audio_name, &fmtp_extra); - - len = snprintf(sdp_record, size, - "v=0\r\n" - "o=- %u 23 IN IP4 %s\r\n" - "s=-\r\n" - "c=IN IP4 %s\r\n" - "t=0 0\r\n", - endp->ci, addr, addr); - - if (len < 0 || len >= size) - goto buffer_too_small; - - if (payload_type >= 0) { - nchars = snprintf(sdp_record + len, size - len, - "m=audio %d RTP/AVP %d\r\n", - endp->net_end.local_port, payload_type); - if (nchars < 0 || nchars >= size - len) - goto buffer_too_small; - - len += nchars; - - if (audio_name && endp->tcfg->audio_send_name) { - nchars = snprintf(sdp_record + len, size - len, - "a=rtpmap:%d %s\r\n", - payload_type, audio_name); - - if (nchars < 0 || nchars >= size - len) - goto buffer_too_small; - - len += nchars; - } - - if (fmtp_extra) { - nchars = snprintf(sdp_record + len, size - len, - "%s\r\n", fmtp_extra); - - if (nchars < 0 || nchars >= size - len) - goto buffer_too_small; - - len += nchars; - } - } - if (endp->bts_end.packet_duration_ms > 0 && endp->tcfg->audio_send_ptime) { - nchars = snprintf(sdp_record + len, size - len, - "a=ptime:%d\r\n", - endp->bts_end.packet_duration_ms); - if (nchars < 0 || nchars >= size - len) - goto buffer_too_small; - - len += nchars; - } - - return len; - -buffer_too_small: - LOGP(DLMGCP, LOGL_ERROR, "SDP buffer too small: %zu (needed %d)\n", - size, len); - return -1; -} - -static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp, - const char *msg, const char *trans_id) -{ - const char *addr = endp->cfg->local_ip; - char sdp_record[4096]; - int len; - int nchars; - char osmux_extension[strlen("\nX-Osmux: 255") + 1]; - - if (!addr) - addr = mgcp_net_src_addr(endp); - - if (endp->osmux.state == OSMUX_STATE_NEGOTIATING) { - sprintf(osmux_extension, "\nX-Osmux: %u", endp->osmux.cid); - endp->osmux.state = OSMUX_STATE_ACTIVATING; - } else { - osmux_extension[0] = '\0'; - } - - len = snprintf(sdp_record, sizeof(sdp_record), - "I: %u%s\n\n", endp->ci, osmux_extension); - if (len < 0) - return NULL; - - nchars = write_response_sdp(endp, sdp_record + len, - sizeof(sdp_record) - len - 1, addr); - if (nchars < 0) - return NULL; - - len += nchars; - - sdp_record[sizeof(sdp_record) - 1] = '\0'; - - return create_resp(endp, 200, " OK", msg, trans_id, NULL, sdp_record); -} - -static void send_dummy(struct mgcp_endpoint *endp) -{ - if (endp->osmux.state != OSMUX_STATE_DISABLED) - osmux_send_dummy(endp); - else - mgcp_send_dummy(endp); -} - -/* - * handle incoming messages: - * - this can be a command (four letters, space, transaction id) - * - or a response (three numbers, space, transaction id) - */ -struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg) -{ - struct mgcp_parse_data pdata; - int i, code, handled = 0; - struct msgb *resp = NULL; - char *data; - - if (msgb_l2len(msg) < 4) { - LOGP(DLMGCP, LOGL_ERROR, "msg too short: %d\n", msg->len); - return NULL; - } - - if (mgcp_msg_terminate_nul(msg)) - return NULL; - - display_mgcp_message(msg->l2h, msgb_l2len(msg), "Received message"); - - /* attempt to treat it as a response */ - if (sscanf((const char *)&msg->l2h[0], "%3d %*s", &code) == 1) { - LOGP(DLMGCP, LOGL_DEBUG, "Response: Code: %d\n", code); - return NULL; - } - - msg->l3h = &msg->l2h[4]; - - - /* - * Check for a duplicate message and respond. - */ - memset(&pdata, 0, sizeof(pdata)); - pdata.cfg = cfg; - data = strline_r((char *) msg->l3h, &pdata.save); - pdata.found = mgcp_analyze_header(&pdata, data); - if (pdata.endp && pdata.trans - && pdata.endp->last_trans - && strcmp(pdata.endp->last_trans, pdata.trans) == 0) { - return do_retransmission(pdata.endp); - } - - for (i = 0; i < ARRAY_SIZE(mgcp_requests); ++i) { - if (strncmp(mgcp_requests[i].name, (const char *) &msg->l2h[0], 4) == 0) { - handled = 1; - resp = mgcp_requests[i].handle_request(&pdata); - break; - } - } - - if (!handled) - LOGP(DLMGCP, LOGL_NOTICE, "MSG with type: '%.4s' not handled\n", &msg->l2h[0]); - - return resp; -} - -/** - * We have a null terminated string with the endpoint name here. We only - * support two kinds. Simple ones as seen on the BSC level and the ones - * seen on the trunk side. - */ -static struct mgcp_endpoint *find_e1_endpoint(struct mgcp_config *cfg, - const char *mgcp) -{ - char *rest = NULL; - struct mgcp_trunk_config *tcfg; - int trunk, endp; - - trunk = strtoul(mgcp + 6, &rest, 10); - if (rest == NULL || rest[0] != '/' || trunk < 1) { - LOGP(DLMGCP, LOGL_ERROR, "Wrong trunk name '%s'\n", mgcp); - return NULL; - } - - endp = strtoul(rest + 1, &rest, 10); - if (rest == NULL || rest[0] != '@') { - LOGP(DLMGCP, LOGL_ERROR, "Wrong endpoint name '%s'\n", mgcp); - return NULL; - } - - /* signalling is on timeslot 1 */ - if (endp == 1) - return NULL; - - tcfg = mgcp_trunk_num(cfg, trunk); - if (!tcfg) { - LOGP(DLMGCP, LOGL_ERROR, "The trunk %d is not declared.\n", trunk); - return NULL; - } - - if (!tcfg->endpoints) { - LOGP(DLMGCP, LOGL_ERROR, "Endpoints of trunk %d not allocated.\n", trunk); - return NULL; - } - - if (endp < 1 || endp >= tcfg->number_endpoints) { - LOGP(DLMGCP, LOGL_ERROR, "Failed to find endpoint '%s'\n", mgcp); - return NULL; - } - - return &tcfg->endpoints[endp]; -} - -static struct mgcp_endpoint *find_endpoint(struct mgcp_config *cfg, const char *mgcp) -{ - char *endptr = NULL; - unsigned int gw = INT_MAX; - - if (strncmp(mgcp, "ds/e1", 5) == 0) - return find_e1_endpoint(cfg, mgcp); - - gw = strtoul(mgcp, &endptr, 16); - if (gw > 0 && gw < cfg->trunk.number_endpoints && endptr[0] == '@') - return &cfg->trunk.endpoints[gw]; - - LOGP(DLMGCP, LOGL_ERROR, "Not able to find the endpoint: '%s'\n", mgcp); - return NULL; -} - -/** - * @returns 0 when the status line was complete and transaction_id and - * endp out parameters are set. - */ -static int mgcp_analyze_header(struct mgcp_parse_data *pdata, char *data) -{ - int i = 0; - char *elem, *save = NULL; - - OSMO_ASSERT(data); - pdata->trans = "000000"; - - for (elem = strtok_r(data, " ", &save); elem; - elem = strtok_r(NULL, " ", &save)) { - switch (i) { - case 0: - pdata->trans = elem; - break; - case 1: - pdata->endp = find_endpoint(pdata->cfg, elem); - if (!pdata->endp) { - LOGP(DLMGCP, LOGL_ERROR, - "Unable to find Endpoint `%s'\n", elem); - return -1; - } - break; - case 2: - if (strcmp("MGCP", elem)) { - LOGP(DLMGCP, LOGL_ERROR, - "MGCP header parsing error\n"); - return -1; - } - break; - case 3: - if (strcmp("1.0", elem)) { - LOGP(DLMGCP, LOGL_ERROR, "MGCP version `%s' " - "not supported\n", elem); - return -1; - } - break; - } - i++; - } - - if (i != 4) { - LOGP(DLMGCP, LOGL_ERROR, "MGCP status line too short.\n"); - pdata->trans = "000000"; - pdata->endp = NULL; - return -1; - } - - return 0; -} - -static int verify_call_id(const struct mgcp_endpoint *endp, - const char *callid) -{ - if (strcmp(endp->callid, callid) != 0) { - LOGP(DLMGCP, LOGL_ERROR, "CallIDs does not match on 0x%x. '%s' != '%s'\n", - ENDPOINT_NUMBER(endp), endp->callid, callid); - return -1; - } - - return 0; -} - -static int verify_ci(const struct mgcp_endpoint *endp, - const char *_ci) -{ - uint32_t ci = strtoul(_ci, NULL, 10); - - if (ci != endp->ci) { - LOGP(DLMGCP, LOGL_ERROR, "ConnectionIdentifiers do not match on 0x%x. %u != %s\n", - ENDPOINT_NUMBER(endp), endp->ci, _ci); - return -1; - } - - return 0; -} - -static struct msgb *handle_audit_endpoint(struct mgcp_parse_data *p) -{ - if (p->found != 0) - return create_err_response(NULL, 500, "AUEP", p->trans); - else - return create_ok_response(p->endp, 200, "AUEP", p->trans); -} - -static int parse_conn_mode(const char *msg, struct mgcp_endpoint *endp) -{ - int ret = 0; - if (strcmp(msg, "recvonly") == 0) - endp->conn_mode = MGCP_CONN_RECV_ONLY; - else if (strcmp(msg, "sendrecv") == 0) - endp->conn_mode = MGCP_CONN_RECV_SEND; - else if (strcmp(msg, "sendonly") == 0) - endp->conn_mode = MGCP_CONN_SEND_ONLY; - else if (strcmp(msg, "loopback") == 0) - endp->conn_mode = MGCP_CONN_LOOPBACK; - else { - LOGP(DLMGCP, LOGL_ERROR, "Unknown connection mode: '%s'\n", msg); - ret = -1; - } - - endp->net_end.output_enabled = - endp->conn_mode & MGCP_CONN_SEND_ONLY ? 1 : 0; - endp->bts_end.output_enabled = - endp->conn_mode & MGCP_CONN_RECV_ONLY ? 1 : 0; - - LOGP(DLMGCP, LOGL_DEBUG, "endpoint %x connection mode '%s' %d output_enabled net %d bts %d\n", - ENDPOINT_NUMBER(endp), - msg, endp->conn_mode, endp->net_end.output_enabled, - endp->bts_end.output_enabled); - - return ret; -} - -static int allocate_port(struct mgcp_endpoint *endp, struct mgcp_rtp_end *end, - struct mgcp_port_range *range, - int (*alloc)(struct mgcp_endpoint *endp, int port)) -{ - int i; - - if (range->mode == PORT_ALLOC_STATIC) { - end->local_alloc = PORT_ALLOC_STATIC; - return 0; - } - - /* attempt to find a port */ - for (i = 0; i < 200; ++i) { - int rc; - - if (range->last_port >= range->range_end) - range->last_port = range->range_start; - - rc = alloc(endp, range->last_port); - - range->last_port += 2; - if (rc == 0) { - end->local_alloc = PORT_ALLOC_DYNAMIC; - return 0; - } - - } - - LOGP(DLMGCP, LOGL_ERROR, "Allocating a RTP/RTCP port failed 200 times 0x%x.\n", - ENDPOINT_NUMBER(endp)); - return -1; -} - -static int allocate_ports(struct mgcp_endpoint *endp) -{ - if (allocate_port(endp, &endp->net_end, &endp->cfg->net_ports, - mgcp_bind_net_rtp_port) != 0) - return -1; - - if (allocate_port(endp, &endp->bts_end, &endp->cfg->bts_ports, - mgcp_bind_bts_rtp_port) != 0) { - mgcp_rtp_end_reset(&endp->net_end); - return -1; - } - - if (endp->cfg->transcoder_ip && endp->tcfg->trunk_type == MGCP_TRUNK_VIRTUAL) { - if (allocate_port(endp, &endp->trans_net, - &endp->cfg->transcoder_ports, - mgcp_bind_trans_net_rtp_port) != 0) { - mgcp_rtp_end_reset(&endp->net_end); - mgcp_rtp_end_reset(&endp->bts_end); - return -1; - } - - if (allocate_port(endp, &endp->trans_bts, - &endp->cfg->transcoder_ports, - mgcp_bind_trans_bts_rtp_port) != 0) { - mgcp_rtp_end_reset(&endp->net_end); - mgcp_rtp_end_reset(&endp->bts_end); - mgcp_rtp_end_reset(&endp->trans_net); - return -1; - } - - /* remember that we have set up transcoding */ - endp->type = MGCP_RTP_TRANSCODED; - } - - return 0; -} - -/* Set the LCO from a string (see RFC 3435). - * The string is stored in the 'string' field. A NULL string is handled excatly - * like an empty string, the 'string' field is never NULL after this function - * has been called. */ -static void set_local_cx_options(void *ctx, struct mgcp_lco *lco, - const char *options) -{ - char *p_opt, *a_opt; - char codec[9]; - - talloc_free(lco->string); - talloc_free(lco->codec); - lco->codec = NULL; - lco->pkt_period_min = lco->pkt_period_max = 0; - lco->string = talloc_strdup(ctx, options ? options : ""); - - p_opt = strstr(lco->string, "p:"); - if (p_opt && sscanf(p_opt, "p:%d-%d", - &lco->pkt_period_min, &lco->pkt_period_max) == 1) - lco->pkt_period_max = lco->pkt_period_min; - - a_opt = strstr(lco->string, "a:"); - if (a_opt && sscanf(a_opt, "a:%8[^,]", codec) == 1) - lco->codec = talloc_strdup(ctx, codec); -} - -void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change, - struct mgcp_rtp_end *rtp) -{ - struct mgcp_trunk_config *tcfg = endp->tcfg; - - int patch_ssrc = expect_ssrc_change && tcfg->force_constant_ssrc; - - rtp->force_aligned_timing = tcfg->force_aligned_timing; - rtp->force_constant_ssrc = patch_ssrc ? 1 : 0; - - LOGP(DLMGCP, LOGL_DEBUG, - "Configuring RTP endpoint: local port %d%s%s\n", - ntohs(rtp->rtp_port), - rtp->force_aligned_timing ? ", force constant timing" : "", - rtp->force_constant_ssrc ? ", force constant ssrc" : ""); -} - -uint32_t mgcp_rtp_packet_duration(struct mgcp_endpoint *endp, - struct mgcp_rtp_end *rtp) -{ - int f = 0; - - /* Get the number of frames per channel and packet */ - if (rtp->frames_per_packet) - f = rtp->frames_per_packet; - else if (rtp->packet_duration_ms && rtp->codec.frame_duration_num) { - int den = 1000 * rtp->codec.frame_duration_num; - f = (rtp->packet_duration_ms * rtp->codec.frame_duration_den + den/2) - / den; - } - - return rtp->codec.rate * f * rtp->codec.frame_duration_num / rtp->codec.frame_duration_den; -} - -static int mgcp_parse_osmux_cid(const char *line) -{ - int osmux_cid; - - if (sscanf(line + 2, "Osmux: %u", &osmux_cid) != 1) - return -1; - - if (osmux_cid > OSMUX_CID_MAX) { - LOGP(DLMGCP, LOGL_ERROR, "Osmux ID too large: %u > %u\n", - osmux_cid, OSMUX_CID_MAX); - return -1; - } - LOGP(DLMGCP, LOGL_DEBUG, "bsc-nat offered Osmux CID %u\n", osmux_cid); - - return osmux_cid; -} - -static int mgcp_osmux_setup(struct mgcp_endpoint *endp, const char *line) -{ - if (!endp->cfg->osmux_init) { - if (osmux_init(OSMUX_ROLE_BSC, endp->cfg) < 0) { - LOGP(DLMGCP, LOGL_ERROR, "Cannot init OSMUX\n"); - return -1; - } - LOGP(DLMGCP, LOGL_NOTICE, "OSMUX socket has been set up\n"); - } - - return mgcp_parse_osmux_cid(line); -} - -static struct msgb *handle_create_con(struct mgcp_parse_data *p) -{ - struct mgcp_trunk_config *tcfg; - struct mgcp_endpoint *endp = p->endp; - int error_code = 400; - - const char *local_options = NULL; - const char *callid = NULL; - const char *mode = NULL; - char *line; - int have_sdp = 0, osmux_cid = -1; - - if (p->found != 0) - return create_err_response(NULL, 510, "CRCX", p->trans); - - /* parse CallID C: and LocalParameters L: */ - for_each_line(line, p->save) { - if (!mgcp_check_param(endp, line)) - continue; - - switch (line[0]) { - case 'L': - local_options = (const char *) line + 3; - break; - case 'C': - callid = (const char *) line + 3; - break; - case 'M': - mode = (const char *) line + 3; - break; - case 'X': - /* Osmux is not enabled in this bsc, ignore it so the - * bsc-nat knows that we don't want to use Osmux. - */ - if (!p->endp->cfg->osmux) - break; - - if (strncmp("Osmux: ", line + 2, strlen("Osmux: ")) == 0) - osmux_cid = mgcp_osmux_setup(endp, line); - break; - case '\0': - have_sdp = 1; - goto mgcp_header_done; - default: - LOGP(DLMGCP, LOGL_NOTICE, "Unhandled option: '%c'/%d on 0x%x\n", - *line, *line, ENDPOINT_NUMBER(endp)); - break; - } - } - -mgcp_header_done: - tcfg = p->endp->tcfg; - - /* Check required data */ - if (!callid || !mode) { - LOGP(DLMGCP, LOGL_ERROR, "Missing callid and mode in CRCX on 0x%x\n", - ENDPOINT_NUMBER(endp)); - return create_err_response(endp, 400, "CRCX", p->trans); - } - - if (endp->allocated) { - if (tcfg->force_realloc) { - LOGP(DLMGCP, LOGL_NOTICE, "Endpoint 0x%x already allocated. Forcing realloc.\n", - ENDPOINT_NUMBER(endp)); - mgcp_release_endp(endp); - if (p->cfg->realloc_cb) - p->cfg->realloc_cb(tcfg, ENDPOINT_NUMBER(endp)); - } else { - LOGP(DLMGCP, LOGL_ERROR, "Endpoint is already used. 0x%x\n", - ENDPOINT_NUMBER(endp)); - return create_err_response(endp, 400, "CRCX", p->trans); - } - } - - /* copy some parameters */ - endp->callid = talloc_strdup(tcfg->endpoints, callid); - - set_local_cx_options(endp->tcfg->endpoints, &endp->local_options, - local_options); - - if (parse_conn_mode(mode, endp) != 0) { - error_code = 517; - goto error2; - } - - /* initialize */ - endp->net_end.rtp_port = endp->net_end.rtcp_port = endp->bts_end.rtp_port = endp->bts_end.rtcp_port = 0; - mgcp_rtp_end_config(endp, 0, &endp->net_end); - mgcp_rtp_end_config(endp, 0, &endp->bts_end); - - /* set to zero until we get the info */ - memset(&endp->net_end.addr, 0, sizeof(endp->net_end.addr)); - - /* bind to the port now */ - if (allocate_ports(endp) != 0) - goto error2; - - /* assign a local call identifier or fail */ - endp->ci = generate_call_id(p->cfg); - if (endp->ci == CI_UNUSED) - goto error2; - - /* Annotate Osmux circuit ID and set it to negotiating state until this - * is fully set up from the dummy load. - */ - endp->osmux.state = OSMUX_STATE_DISABLED; - if (osmux_cid >= 0) { - endp->osmux.cid = osmux_cid; - endp->osmux.state = OSMUX_STATE_NEGOTIATING; - } else if (endp->cfg->osmux == OSMUX_USAGE_ONLY) { - LOGP(DLMGCP, LOGL_ERROR, - "Osmux only and no osmux offered on 0x%x\n", ENDPOINT_NUMBER(endp)); - goto error2; - } - - /* Apply Jiter buffer settings for this endpoint, they can be overriden by CRCX policy later */ - endp->bts_use_jibuf = endp->cfg->bts_use_jibuf; - endp->bts_jitter_delay_min = endp->cfg->bts_jitter_delay_min; - endp->bts_jitter_delay_max = endp->cfg->bts_jitter_delay_max; - - endp->allocated = 1; - - /* set up RTP media parameters */ - mgcp_set_audio_info(p->cfg, &endp->bts_end.codec, tcfg->audio_payload, tcfg->audio_name); - endp->bts_end.fmtp_extra = talloc_strdup(tcfg->endpoints, - tcfg->audio_fmtp_extra); - if (have_sdp) - mgcp_parse_sdp_data(endp, &endp->net_end, p); - else if (endp->local_options.codec) - mgcp_set_audio_info(p->cfg, &endp->net_end.codec, - PTYPE_UNDEFINED, endp->local_options.codec); - - if (p->cfg->bts_force_ptime) { - endp->bts_end.packet_duration_ms = p->cfg->bts_force_ptime; - endp->bts_end.force_output_ptime = 1; - } - - if (setup_rtp_processing(endp) != 0) - goto error2; - - /* policy CB */ - if (p->cfg->policy_cb) { - int rc; - rc = p->cfg->policy_cb(tcfg, ENDPOINT_NUMBER(endp), - MGCP_ENDP_CRCX, p->trans); - switch (rc) { - case MGCP_POLICY_REJECT: - LOGP(DLMGCP, LOGL_NOTICE, "CRCX rejected by policy on 0x%x\n", - ENDPOINT_NUMBER(endp)); - mgcp_release_endp(endp); - return create_err_response(endp, 400, "CRCX", p->trans); - break; - case MGCP_POLICY_DEFER: - /* stop processing */ - create_transcoder(endp); - /* Set up jitter buffer if required after policy has updated jibuf endp values */ - if (endp->bts_use_jibuf) { - endp->bts_jb = osmo_jibuf_alloc(tcfg->endpoints); - osmo_jibuf_set_min_delay(endp->bts_jb, endp->bts_jitter_delay_min); - osmo_jibuf_set_max_delay(endp->bts_jb, endp->bts_jitter_delay_max); - osmo_jibuf_set_dequeue_cb(endp->bts_jb, mgcp_dejitter_udp_send, &endp->net_end); - } - return NULL; - break; - case MGCP_POLICY_CONT: - /* just continue */ - break; - } - } - - /* Set up jitter buffer if required after policy has updated jibuf endp values */ - if (endp->bts_use_jibuf) { - endp->bts_jb = osmo_jibuf_alloc(tcfg->endpoints); - osmo_jibuf_set_min_delay(endp->bts_jb, endp->bts_jitter_delay_min); - osmo_jibuf_set_max_delay(endp->bts_jb, endp->bts_jitter_delay_max); - osmo_jibuf_set_dequeue_cb(endp->bts_jb, mgcp_dejitter_udp_send, &endp->net_end); - } - - LOGP(DLMGCP, LOGL_DEBUG, "Creating endpoint on: 0x%x CI: %u port: %u/%u\n", - ENDPOINT_NUMBER(endp), endp->ci, - endp->net_end.local_port, endp->bts_end.local_port); - if (p->cfg->change_cb) - p->cfg->change_cb(tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_CRCX); - - if (endp->conn_mode & MGCP_CONN_RECV_ONLY && tcfg->keepalive_interval != 0) { - send_dummy(endp); - } - - create_transcoder(endp); - return create_response_with_sdp(endp, "CRCX", p->trans); -error2: - mgcp_release_endp(endp); - LOGP(DLMGCP, LOGL_NOTICE, "Resource error on 0x%x\n", ENDPOINT_NUMBER(endp)); - return create_err_response(endp, error_code, "CRCX", p->trans); -} - -static struct msgb *handle_modify_con(struct mgcp_parse_data *p) -{ - struct mgcp_endpoint *endp = p->endp; - int error_code = 500; - int silent = 0; - int have_sdp = 0; - char *line; - const char *local_options = NULL; - - if (p->found != 0) - return create_err_response(NULL, 510, "MDCX", p->trans); - - if (endp->ci == CI_UNUSED) { - LOGP(DLMGCP, LOGL_ERROR, "Endpoint is not " - "holding a connection. 0x%x\n", ENDPOINT_NUMBER(endp)); - return create_err_response(endp, 400, "MDCX", p->trans); - } - - for_each_line(line, p->save) { - if (!mgcp_check_param(endp, line)) - continue; - - switch (line[0]) { - case 'C': { - if (verify_call_id(endp, line + 3) != 0) - goto error3; - break; - } - case 'I': { - if (verify_ci(endp, line + 3) != 0) - goto error3; - break; - } - case 'L': - local_options = (const char *) line + 3; - break; - case 'M': - if (parse_conn_mode(line + 3, endp) != 0) { - error_code = 517; - goto error3; - } - endp->orig_mode = endp->conn_mode; - break; - case 'Z': - silent = strcmp("noanswer", line + 3) == 0; - break; - case '\0': - /* SDP file begins */ - have_sdp = 1; - mgcp_parse_sdp_data(endp, &endp->net_end, p); - /* This will exhaust p->save, so the loop will - * terminate next time. - */ - break; - default: - LOGP(DLMGCP, LOGL_NOTICE, "Unhandled MGCP option: '%c'/%d on 0x%x\n", - line[0], line[0], ENDPOINT_NUMBER(endp)); - break; - } - } - - set_local_cx_options(endp->tcfg->endpoints, &endp->local_options, - local_options); - - if (!have_sdp && endp->local_options.codec) - mgcp_set_audio_info(p->cfg, &endp->net_end.codec, - PTYPE_UNDEFINED, endp->local_options.codec); - - if (setup_rtp_processing(endp) != 0) - goto error3; - - /* policy CB */ - if (p->cfg->policy_cb) { - int rc; - rc = p->cfg->policy_cb(endp->tcfg, ENDPOINT_NUMBER(endp), - MGCP_ENDP_MDCX, p->trans); - switch (rc) { - case MGCP_POLICY_REJECT: - LOGP(DLMGCP, LOGL_NOTICE, "MDCX rejected by policy on 0x%x\n", - ENDPOINT_NUMBER(endp)); - if (silent) - goto out_silent; - return create_err_response(endp, 400, "MDCX", p->trans); - break; - case MGCP_POLICY_DEFER: - /* stop processing */ - LOGP(DLMGCP, LOGL_DEBUG, "endp %x MDCX defer\n", - ENDPOINT_NUMBER(endp)); - return NULL; - break; - case MGCP_POLICY_CONT: - /* just continue */ - break; - } - } - - mgcp_rtp_end_config(endp, 1, &endp->net_end); - mgcp_rtp_end_config(endp, 1, &endp->bts_end); - - /* modify */ - LOGP(DLMGCP, LOGL_DEBUG, "Modified endpoint on: 0x%x Server: %s:%u\n", - ENDPOINT_NUMBER(endp), inet_ntoa(endp->net_end.addr), ntohs(endp->net_end.rtp_port)); - if (p->cfg->change_cb) - p->cfg->change_cb(endp->tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_MDCX); - - if (endp->conn_mode & MGCP_CONN_RECV_ONLY && - endp->tcfg->keepalive_interval != 0) - send_dummy(endp); - - if (silent) - goto out_silent; - - return create_response_with_sdp(endp, "MDCX", p->trans); - -error3: - return create_err_response(endp, error_code, "MDCX", p->trans); - - -out_silent: - LOGP(DLMGCP, LOGL_DEBUG, "endp %x Modify endpoint: silent exit\n", - ENDPOINT_NUMBER(endp)); - return NULL; -} - -static struct msgb *handle_delete_con(struct mgcp_parse_data *p) -{ - struct mgcp_endpoint *endp = p->endp; - int error_code = 400; - int silent = 0; - char *line; - char stats[1048]; - - if (p->found != 0) - return create_err_response(NULL, error_code, "DLCX", p->trans); - - if (!p->endp->allocated) { - LOGP(DLMGCP, LOGL_ERROR, "Endpoint is not used. 0x%x\n", - ENDPOINT_NUMBER(endp)); - return create_err_response(endp, 400, "DLCX", p->trans); - } - - for_each_line(line, p->save) { - if (!mgcp_check_param(endp, line)) - continue; - - switch (line[0]) { - case 'C': - if (verify_call_id(endp, line + 3) != 0) - goto error3; - break; - case 'I': - if (verify_ci(endp, line + 3) != 0) - goto error3; - break; - case 'Z': - silent = strcmp("noanswer", line + 3) == 0; - break; - default: - LOGP(DLMGCP, LOGL_NOTICE, "Unhandled option: '%c'/%d on 0x%x\n", - line[0], line[0], ENDPOINT_NUMBER(endp)); - break; - } - } - - /* policy CB */ - if (p->cfg->policy_cb) { - int rc; - rc = p->cfg->policy_cb(endp->tcfg, ENDPOINT_NUMBER(endp), - MGCP_ENDP_DLCX, p->trans); - switch (rc) { - case MGCP_POLICY_REJECT: - LOGP(DLMGCP, LOGL_NOTICE, "DLCX rejected by policy on 0x%x\n", - ENDPOINT_NUMBER(endp)); - if (silent) - goto out_silent; - return create_err_response(endp, 400, "DLCX", p->trans); - break; - case MGCP_POLICY_DEFER: - /* stop processing */ - delete_transcoder(endp); - return NULL; - break; - case MGCP_POLICY_CONT: - /* just continue */ - break; - } - } - - /* free the connection */ - LOGP(DLMGCP, LOGL_DEBUG, "Deleted endpoint on: 0x%x Server: %s:%u\n", - ENDPOINT_NUMBER(endp), inet_ntoa(endp->net_end.addr), ntohs(endp->net_end.rtp_port)); - - /* save the statistics of the current call */ - mgcp_format_stats(endp, stats, sizeof(stats)); - - delete_transcoder(endp); - mgcp_release_endp(endp); - if (p->cfg->change_cb) - p->cfg->change_cb(endp->tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_DLCX); - - if (silent) - goto out_silent; - return create_ok_resp_with_param(endp, 250, "DLCX", p->trans, stats); - -error3: - return create_err_response(endp, error_code, "DLCX", p->trans); - -out_silent: - return NULL; -} - -static struct msgb *handle_rsip(struct mgcp_parse_data *p) -{ - if (p->found != 0) { - LOGP(DLMGCP, LOGL_ERROR, "Failed to find the endpoint.\n"); - return NULL; - } - - if (p->cfg->reset_cb) - p->cfg->reset_cb(p->endp->tcfg); - return NULL; -} - -static char extract_tone(const char *line) -{ - const char *str = strstr(line, "D/"); - if (!str) - return CHAR_MAX; - - return str[2]; -} - -/* - * This can request like DTMF detection and forward, fax detection... it - * can also request when the notification should be send and such. We don't - * do this right now. - */ -static struct msgb *handle_noti_req(struct mgcp_parse_data *p) -{ - int res = 0; - char *line; - char tone = CHAR_MAX; - - if (p->found != 0) - return create_err_response(NULL, 400, "RQNT", p->trans); - - for_each_line(line, p->save) { - switch (line[0]) { - case 'S': - tone = extract_tone(line); - break; - } - } - - /* we didn't see a signal request with a tone */ - if (tone == CHAR_MAX) - return create_ok_response(p->endp, 200, "RQNT", p->trans); - - if (p->cfg->rqnt_cb) - res = p->cfg->rqnt_cb(p->endp, tone); - - return res == 0 ? - create_ok_response(p->endp, 200, "RQNT", p->trans) : - create_err_response(p->endp, res, "RQNT", p->trans); -} - -static void mgcp_keepalive_timer_cb(void *_tcfg) -{ - struct mgcp_trunk_config *tcfg = _tcfg; - int i; - LOGP(DLMGCP, LOGL_DEBUG, "Triggered trunk %d keepalive timer.\n", - tcfg->trunk_nr); - - if (tcfg->keepalive_interval <= 0) - return; - - for (i = 1; i < tcfg->number_endpoints; ++i) { - struct mgcp_endpoint *endp = &tcfg->endpoints[i]; - if (endp->conn_mode == MGCP_CONN_RECV_ONLY) - send_dummy(endp); - } - - LOGP(DLMGCP, LOGL_DEBUG, "Rescheduling trunk %d keepalive timer.\n", - tcfg->trunk_nr); - osmo_timer_schedule(&tcfg->keepalive_timer, tcfg->keepalive_interval, 0); -} - -void mgcp_trunk_set_keepalive(struct mgcp_trunk_config *tcfg, int interval) -{ - tcfg->keepalive_interval = interval; - osmo_timer_setup(&tcfg->keepalive_timer, mgcp_keepalive_timer_cb, tcfg); - - if (interval <= 0) - osmo_timer_del(&tcfg->keepalive_timer); - else - osmo_timer_schedule(&tcfg->keepalive_timer, - tcfg->keepalive_interval, 0); -} - -struct mgcp_config *mgcp_config_alloc(void) -{ - struct mgcp_config *cfg; - - cfg = talloc_zero(NULL, struct mgcp_config); - if (!cfg) { - LOGP(DLMGCP, LOGL_FATAL, "Failed to allocate config.\n"); - return NULL; - } - - cfg->source_port = 2427; - cfg->source_addr = talloc_strdup(cfg, "0.0.0.0"); - cfg->osmux_addr = talloc_strdup(cfg, "0.0.0.0"); - - cfg->transcoder_remote_base = 4000; - - cfg->bts_ports.base_port = RTP_PORT_DEFAULT; - cfg->net_ports.base_port = RTP_PORT_NET_DEFAULT; - - cfg->rtp_processing_cb = &mgcp_rtp_processing_default; - cfg->setup_rtp_processing_cb = &mgcp_setup_rtp_processing_default; - - cfg->get_net_downlink_format_cb = &mgcp_get_net_downlink_format_default; - - /* default trunk handling */ - cfg->trunk.cfg = cfg; - cfg->trunk.trunk_nr = 0; - cfg->trunk.trunk_type = MGCP_TRUNK_VIRTUAL; - cfg->trunk.audio_name = talloc_strdup(cfg, "AMR/8000"); - cfg->trunk.audio_payload = 126; - cfg->trunk.audio_send_ptime = 1; - cfg->trunk.audio_send_name = 1; - cfg->trunk.omit_rtcp = 0; - mgcp_trunk_set_keepalive(&cfg->trunk, MGCP_KEEPALIVE_ONCE); - - INIT_LLIST_HEAD(&cfg->trunks); - - return cfg; -} - -struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int nr) -{ - struct mgcp_trunk_config *trunk; - - trunk = talloc_zero(cfg, struct mgcp_trunk_config); - if (!trunk) { - LOGP(DLMGCP, LOGL_ERROR, "Failed to allocate.\n"); - return NULL; - } - - trunk->cfg = cfg; - trunk->trunk_type = MGCP_TRUNK_E1; - trunk->trunk_nr = nr; - trunk->audio_name = talloc_strdup(cfg, "AMR/8000"); - trunk->audio_payload = 126; - trunk->audio_send_ptime = 1; - trunk->audio_send_name = 1; - trunk->number_endpoints = 33; - trunk->omit_rtcp = 0; - mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE); - llist_add_tail(&trunk->entry, &cfg->trunks); - return trunk; -} - -struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index) -{ - struct mgcp_trunk_config *trunk; - - llist_for_each_entry(trunk, &cfg->trunks, entry) - if (trunk->trunk_nr == index) - return trunk; - - return NULL; -} - -static void mgcp_rtp_codec_reset(struct mgcp_rtp_codec *codec) -{ - codec->payload_type = -1; - talloc_free(codec->subtype_name); - codec->subtype_name = NULL; - talloc_free(codec->audio_name); - codec->audio_name = NULL; - codec->frame_duration_num = DEFAULT_RTP_AUDIO_FRAME_DUR_NUM; - codec->frame_duration_den = DEFAULT_RTP_AUDIO_FRAME_DUR_DEN; - codec->rate = DEFAULT_RTP_AUDIO_DEFAULT_RATE; - codec->channels = DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS; -} - -static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end) -{ - if (end->local_alloc == PORT_ALLOC_DYNAMIC) { - mgcp_free_rtp_port(end); - end->local_port = 0; - } - - end->packets = 0; - end->octets = 0; - end->dropped_packets = 0; - memset(&end->addr, 0, sizeof(end->addr)); - end->rtp_port = end->rtcp_port = 0; - end->local_alloc = -1; - talloc_free(end->fmtp_extra); - end->fmtp_extra = NULL; - talloc_free(end->rtp_process_data); - end->rtp_process_data = NULL; - - /* Set default values */ - end->frames_per_packet = 0; /* unknown */ - end->packet_duration_ms = DEFAULT_RTP_AUDIO_PACKET_DURATION_MS; - end->output_enabled = 0; - - mgcp_rtp_codec_reset(&end->codec); - mgcp_rtp_codec_reset(&end->alt_codec); -} - -static void mgcp_rtp_end_init(struct mgcp_rtp_end *end) -{ - mgcp_rtp_end_reset(end); - end->rtp.fd = -1; - end->rtcp.fd = -1; -} - -int mgcp_endpoints_allocate(struct mgcp_trunk_config *tcfg) -{ - int i; - - /* Initialize all endpoints */ - tcfg->endpoints = _talloc_zero_array(tcfg->cfg, - sizeof(struct mgcp_endpoint), - tcfg->number_endpoints, "endpoints"); - if (!tcfg->endpoints) - return -1; - - for (i = 0; i < tcfg->number_endpoints; ++i) { - tcfg->endpoints[i].osmux.allocated_cid = -1; - tcfg->endpoints[i].ci = CI_UNUSED; - tcfg->endpoints[i].cfg = tcfg->cfg; - tcfg->endpoints[i].tcfg = tcfg; - mgcp_rtp_end_init(&tcfg->endpoints[i].net_end); - mgcp_rtp_end_init(&tcfg->endpoints[i].bts_end); - mgcp_rtp_end_init(&tcfg->endpoints[i].trans_net); - mgcp_rtp_end_init(&tcfg->endpoints[i].trans_bts); - } - - return 0; -} - -void mgcp_release_endp(struct mgcp_endpoint *endp) -{ - LOGP(DLMGCP, LOGL_DEBUG, "Releasing endpoint on: 0x%x\n", ENDPOINT_NUMBER(endp)); - if (endp->bts_jb) - osmo_jibuf_delete(endp->bts_jb); - endp->bts_jb = NULL; - endp->ci = CI_UNUSED; - endp->allocated = 0; - - talloc_free(endp->callid); - endp->callid = NULL; - - talloc_free(endp->local_options.string); - endp->local_options.string = NULL; - talloc_free(endp->local_options.codec); - endp->local_options.codec = NULL; - - mgcp_rtp_end_reset(&endp->bts_end); - mgcp_rtp_end_reset(&endp->net_end); - mgcp_rtp_end_reset(&endp->trans_net); - mgcp_rtp_end_reset(&endp->trans_bts); - endp->type = MGCP_RTP_DEFAULT; - - memset(&endp->net_state, 0, sizeof(endp->net_state)); - memset(&endp->bts_state, 0, sizeof(endp->bts_state)); - - endp->conn_mode = endp->orig_mode = MGCP_CONN_NONE; - - if (endp->osmux.state == OSMUX_STATE_ENABLED) - osmux_disable_endpoint(endp); - - /* release the circuit ID if it had been allocated */ - osmux_release_cid(endp); - - memset(&endp->taps, 0, sizeof(endp->taps)); -} - -void mgcp_initialize_endp(struct mgcp_endpoint *endp) -{ - return mgcp_release_endp(endp); -} - -static int send_trans(struct mgcp_config *cfg, const char *buf, int len) -{ - struct sockaddr_in addr; - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr = cfg->transcoder_in; - addr.sin_port = htons(2427); - return sendto(cfg->gw_fd.bfd.fd, buf, len, 0, - (struct sockaddr *) &addr, sizeof(addr)); -} - -static void send_msg(struct mgcp_endpoint *endp, int endpoint, int port, - const char *msg, const char *mode) -{ - char buf[2096]; - int len; - int nchars; - - /* hardcoded to AMR right now, we do not know the real type at this point */ - len = snprintf(buf, sizeof(buf), - "%s 42 %x@mgw MGCP 1.0\r\n" - "C: 4256\r\n" - "M: %s\r\n" - "\r\n", - msg, endpoint, mode); - - if (len < 0) - return; - - nchars = write_response_sdp(endp, buf + len, sizeof(buf) + len - 1, NULL); - if (nchars < 0) - return; - - len += nchars; - - buf[sizeof(buf) - 1] = '\0'; - - send_trans(endp->cfg, buf, len); -} - -static void send_dlcx(struct mgcp_endpoint *endp, int endpoint) -{ - char buf[2096]; - int len; - - len = snprintf(buf, sizeof(buf), - "DLCX 43 %x@mgw MGCP 1.0\r\n" - "C: 4256\r\n" - , endpoint); - - if (len < 0) - return; - - buf[sizeof(buf) - 1] = '\0'; - - send_trans(endp->cfg, buf, len); -} - -static int send_agent(struct mgcp_config *cfg, const char *buf, int len) -{ - return write(cfg->gw_fd.bfd.fd, buf, len); -} - -int mgcp_send_reset_all(struct mgcp_config *cfg) -{ - static const char mgcp_reset[] = { - "RSIP 1 *@mgw MGCP 1.0\r\n" - }; - - return send_agent(cfg, mgcp_reset, sizeof mgcp_reset -1); -} - -int mgcp_send_reset_ep(struct mgcp_endpoint *endp, int endpoint) -{ - char buf[128]; - int len; - - len = snprintf(buf, sizeof(buf), - "RSIP 39 %x@mgw MGCP 1.0\r\n" - , endpoint); - if (len < 0) - return len; - - buf[sizeof(buf) - 1] = '\0'; - - return send_agent(endp->cfg, buf, len); -} - -static int setup_rtp_processing(struct mgcp_endpoint *endp) -{ - int rc = 0; - struct mgcp_config *cfg = endp->cfg; - - if (endp->type != MGCP_RTP_DEFAULT) - return 0; - - if (endp->conn_mode == MGCP_CONN_LOOPBACK) - return 0; - - if (endp->conn_mode & MGCP_CONN_SEND_ONLY) - rc |= cfg->setup_rtp_processing_cb(endp, &endp->net_end, &endp->bts_end); - else - rc |= cfg->setup_rtp_processing_cb(endp, &endp->net_end, NULL); - - if (endp->conn_mode & MGCP_CONN_RECV_ONLY) - rc |= cfg->setup_rtp_processing_cb(endp, &endp->bts_end, &endp->net_end); - else - rc |= cfg->setup_rtp_processing_cb(endp, &endp->bts_end, NULL); - return rc; -} - -static void create_transcoder(struct mgcp_endpoint *endp) -{ - int port; - int in_endp = ENDPOINT_NUMBER(endp); - int out_endp = endp_back_channel(in_endp); - - if (endp->type != MGCP_RTP_TRANSCODED) - return; - - send_msg(endp, in_endp, endp->trans_bts.local_port, "CRCX", "sendrecv"); - send_msg(endp, in_endp, endp->trans_bts.local_port, "MDCX", "sendrecv"); - send_msg(endp, out_endp, endp->trans_net.local_port, "CRCX", "sendrecv"); - send_msg(endp, out_endp, endp->trans_net.local_port, "MDCX", "sendrecv"); - - port = rtp_calculate_port(in_endp, endp->cfg->transcoder_remote_base); - endp->trans_bts.rtp_port = htons(port); - endp->trans_bts.rtcp_port = htons(port + 1); - - port = rtp_calculate_port(out_endp, endp->cfg->transcoder_remote_base); - endp->trans_net.rtp_port = htons(port); - endp->trans_net.rtcp_port = htons(port + 1); -} - -static void delete_transcoder(struct mgcp_endpoint *endp) -{ - int in_endp = ENDPOINT_NUMBER(endp); - int out_endp = endp_back_channel(in_endp); - - if (endp->type != MGCP_RTP_TRANSCODED) - return; - - send_dlcx(endp, in_endp); - send_dlcx(endp, out_endp); -} - -int mgcp_reset_transcoder(struct mgcp_config *cfg) -{ - if (!cfg->transcoder_ip) - return 0; - - static const char mgcp_reset[] = { - "RSIP 1 13@mgw MGCP 1.0\r\n" - }; - - return send_trans(cfg, mgcp_reset, sizeof mgcp_reset -1); -} - -void mgcp_format_stats(struct mgcp_endpoint *endp, char *msg, size_t size) -{ - uint32_t expected, jitter; - int ploss; - int nchars; - mgcp_state_calc_loss(&endp->net_state, &endp->net_end, - &expected, &ploss); - jitter = mgcp_state_calc_jitter(&endp->net_state); - - nchars = snprintf(msg, size, - "\r\nP: PS=%u, OS=%u, PR=%u, OR=%u, PL=%d, JI=%u", - endp->bts_end.packets, endp->bts_end.octets, - endp->net_end.packets, endp->net_end.octets, - ploss, jitter); - if (nchars < 0 || nchars >= size) - goto truncate; - - msg += nchars; - size -= nchars; - - if (endp->cfg->osmux != OSMUX_USAGE_OFF) { - /* Error Counter */ - nchars = snprintf(msg, size, - "\r\nX-Osmo-CP: EC TIS=%u, TOS=%u, TIR=%u, TOR=%u", - endp->net_state.in_stream.err_ts_counter, - endp->net_state.out_stream.err_ts_counter, - endp->bts_state.in_stream.err_ts_counter, - endp->bts_state.out_stream.err_ts_counter); - if (nchars < 0 || nchars >= size) - goto truncate; - - msg += nchars; - size -= nchars; - - if (endp->osmux.state == OSMUX_STATE_ENABLED) { - snprintf(msg, size, - "\r\nX-Osmux-ST: CR=%u, BR=%u", - endp->osmux.stats.chunks, - endp->osmux.stats.octets); - } - } -truncate: - msg[size - 1] = '\0'; -} - -int mgcp_parse_stats(struct msgb *msg, uint32_t *ps, uint32_t *os, - uint32_t *pr, uint32_t *_or, int *loss, uint32_t *jitter) -{ - char *line, *save; - int rc; - - /* initialize with bad values */ - *ps = *os = *pr = *_or = *jitter = UINT_MAX; - *loss = INT_MAX; - - - line = strtok_r((char *) msg->l2h, "\r\n", &save); - if (!line) - return -1; - - /* this can only parse the message that is created above... */ - for_each_non_empty_line(line, save) { - switch (line[0]) { - case 'P': - rc = sscanf(line, "P: PS=%u, OS=%u, PR=%u, OR=%u, PL=%d, JI=%u", - ps, os, pr, _or, loss, jitter); - return rc == 6 ? 0 : -1; - } - } - - return -1; -} diff --git a/src/libosmo-legacy-mgcp/mgcp_sdp.c b/src/libosmo-legacy-mgcp/mgcp_sdp.c deleted file mode 100644 index 055e1af6c..000000000 --- a/src/libosmo-legacy-mgcp/mgcp_sdp.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Some SDP file parsing... - * - * (C) 2009-2015 by Holger Hans Peter Freyther - * (C) 2009-2014 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - -#include -#include - -#include - -struct sdp_rtp_map { - /* the type */ - int payload_type; - /* null, static or later dynamic codec name */ - char *codec_name; - /* A pointer to the original line for later parsing */ - char *map_line; - - int rate; - int channels; -}; - -int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec, - int payload_type, const char *audio_name) -{ - int rate = codec->rate; - int channels = codec->channels; - char audio_codec[64]; - - talloc_free(codec->subtype_name); - codec->subtype_name = NULL; - talloc_free(codec->audio_name); - codec->audio_name = NULL; - - if (payload_type != PTYPE_UNDEFINED) - codec->payload_type = payload_type; - - if (!audio_name) { - switch (payload_type) { - case 0: audio_name = "PCMU/8000/1"; break; - case 3: audio_name = "GSM/8000/1"; break; - case 8: audio_name = "PCMA/8000/1"; break; - case 18: audio_name = "G729/8000/1"; break; - default: - /* Payload type is unknown, don't change rate and - * channels. */ - /* TODO: return value? */ - return 0; - } - } - - if (sscanf(audio_name, "%63[^/]/%d/%d", - audio_codec, &rate, &channels) < 1) - return -EINVAL; - - codec->rate = rate; - codec->channels = channels; - codec->subtype_name = talloc_strdup(ctx, audio_codec); - codec->audio_name = talloc_strdup(ctx, audio_name); - - if (!strcmp(audio_codec, "G729")) { - codec->frame_duration_num = 10; - codec->frame_duration_den = 1000; - } else { - codec->frame_duration_num = DEFAULT_RTP_AUDIO_FRAME_DUR_NUM; - codec->frame_duration_den = DEFAULT_RTP_AUDIO_FRAME_DUR_DEN; - } - - if (payload_type < 0) { - payload_type = 96; - if (rate == 8000 && channels == 1) { - if (!strcmp(audio_codec, "GSM")) - payload_type = 3; - else if (!strcmp(audio_codec, "PCMA")) - payload_type = 8; - else if (!strcmp(audio_codec, "PCMU")) - payload_type = 0; - else if (!strcmp(audio_codec, "G729")) - payload_type = 18; - } - - codec->payload_type = payload_type; - } - - if (channels != 1) - LOGP(DLMGCP, LOGL_NOTICE, - "Channels != 1 in SDP: '%s'\n", audio_name); - - return 0; -} - -void codecs_initialize(void *ctx, struct sdp_rtp_map *codecs, int used) -{ - int i; - - for (i = 0; i < used; ++i) { - switch (codecs[i].payload_type) { - case 0: - codecs[i].codec_name = "PCMU"; - codecs[i].rate = 8000; - codecs[i].channels = 1; - break; - case 3: - codecs[i].codec_name = "GSM"; - codecs[i].rate = 8000; - codecs[i].channels = 1; - break; - case 8: - codecs[i].codec_name = "PCMA"; - codecs[i].rate = 8000; - codecs[i].channels = 1; - break; - case 18: - codecs[i].codec_name = "G729"; - codecs[i].rate = 8000; - codecs[i].channels = 1; - break; - } - } -} - -void codecs_update(void *ctx, struct sdp_rtp_map *codecs, int used, int payload, char *audio_name) -{ - int i; - - for (i = 0; i < used; ++i) { - char audio_codec[64]; - int rate = -1; - int channels = -1; - if (codecs[i].payload_type != payload) - continue; - if (sscanf(audio_name, "%63[^/]/%d/%d", - audio_codec, &rate, &channels) < 1) { - LOGP(DLMGCP, LOGL_ERROR, "Failed to parse '%s'\n", audio_name); - continue; - } - - codecs[i].map_line = talloc_strdup(ctx, audio_name); - codecs[i].codec_name = talloc_strdup(ctx, audio_codec); - codecs[i].rate = rate; - codecs[i].channels = channels; - return; - } - - LOGP(DLMGCP, LOGL_ERROR, "Unconfigured PT(%d) with %s\n", payload, audio_name); -} - -int is_codec_compatible(struct mgcp_endpoint *endp, struct sdp_rtp_map *codec) -{ - char *bts_codec; - char audio_codec[64]; - - if (!codec->codec_name) - return 0; - - /* - * GSM, GSM/8000 and GSM/8000/1 should all be compatible.. let's go - * by name first. - */ - bts_codec = endp->tcfg->audio_name; - if (sscanf(bts_codec, "%63[^/]/%*d/%*d", audio_codec) < 1) - return 0; - - return strcasecmp(audio_codec, codec->codec_name) == 0; -} - -int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p) -{ - struct sdp_rtp_map codecs[10]; - int codecs_used = 0; - char *line; - int maxptime = -1; - int i; - int codecs_assigned = 0; - void *tmp_ctx = talloc_new(NULL); - - memset(&codecs, 0, sizeof(codecs)); - - for_each_line(line, p->save) { - switch (line[0]) { - case 'o': - case 's': - case 't': - case 'v': - /* skip these SDP attributes */ - break; - case 'a': { - int payload; - int ptime, ptime2 = 0; - char audio_name[64]; - - - if (sscanf(line, "a=rtpmap:%d %63s", - &payload, audio_name) == 2) { - codecs_update(tmp_ctx, codecs, codecs_used, payload, audio_name); - } else if (sscanf(line, "a=ptime:%d-%d", - &ptime, &ptime2) >= 1) { - if (ptime2 > 0 && ptime2 != ptime) - rtp->packet_duration_ms = 0; - else - rtp->packet_duration_ms = ptime; - } else if (sscanf(line, "a=maxptime:%d", &ptime2) == 1) { - maxptime = ptime2; - } - break; - } - case 'm': { - int port, rc; - - rc = sscanf(line, "m=audio %d RTP/AVP %d %d %d %d %d %d %d %d %d %d", - &port, - &codecs[0].payload_type, - &codecs[1].payload_type, - &codecs[2].payload_type, - &codecs[3].payload_type, - &codecs[4].payload_type, - &codecs[5].payload_type, - &codecs[6].payload_type, - &codecs[7].payload_type, - &codecs[8].payload_type, - &codecs[9].payload_type); - if (rc >= 2) { - rtp->rtp_port = htons(port); - rtp->rtcp_port = htons(port + 1); - codecs_used = rc - 1; - codecs_initialize(tmp_ctx, codecs, codecs_used); - } - break; - } - case 'c': { - char ipv4[16]; - - if (sscanf(line, "c=IN IP4 %15s", ipv4) == 1) { - inet_aton(ipv4, &rtp->addr); - } - break; - } - default: - if (p->endp) - LOGP(DLMGCP, LOGL_NOTICE, - "Unhandled SDP option: '%c'/%d on 0x%x\n", - line[0], line[0], ENDPOINT_NUMBER(p->endp)); - else - LOGP(DLMGCP, LOGL_NOTICE, - "Unhandled SDP option: '%c'/%d\n", - line[0], line[0]); - break; - } - } - - /* Now select the primary and alt_codec */ - for (i = 0; i < codecs_used && codecs_assigned < 2; ++i) { - struct mgcp_rtp_codec *codec = codecs_assigned == 0 ? - &rtp->codec : &rtp->alt_codec; - - if (endp->tcfg->no_audio_transcoding && - !is_codec_compatible(endp, &codecs[i])) { - LOGP(DLMGCP, LOGL_NOTICE, "Skipping codec %s\n", - codecs[i].codec_name); - continue; - } - - mgcp_set_audio_info(p->cfg, codec, - codecs[i].payload_type, - codecs[i].map_line); - codecs_assigned += 1; - } - - if (codecs_assigned > 0) { - /* TODO/XXX: Store this per codec and derive it on use */ - if (maxptime >= 0 && maxptime * rtp->codec.frame_duration_den > - rtp->codec.frame_duration_num * 1500) { - /* more than 1 frame */ - rtp->packet_duration_ms = 0; - } - - LOGP(DLMGCP, LOGL_NOTICE, - "Got media info via SDP: port %d, payload %d (%s), " - "duration %d, addr %s\n", - ntohs(rtp->rtp_port), rtp->codec.payload_type, - rtp->codec.subtype_name ? rtp->codec.subtype_name : "unknown", - rtp->packet_duration_ms, inet_ntoa(rtp->addr)); - } - - talloc_free(tmp_ctx); - return codecs_assigned > 0; -} - diff --git a/src/libosmo-legacy-mgcp/mgcp_transcode.c b/src/libosmo-legacy-mgcp/mgcp_transcode.c deleted file mode 100644 index cbabdd1fa..000000000 --- a/src/libosmo-legacy-mgcp/mgcp_transcode.c +++ /dev/null @@ -1,611 +0,0 @@ -/* - * (C) 2014 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - -#include -#include -#include - - -#include "g711common.h" - -#include -#include -#include - -#include -#include - -int mgcp_transcoding_get_frame_size(void *state_, int nsamples, int dst) -{ - struct mgcp_process_rtp_state *state = state_; - if (dst) - return (nsamples >= 0 ? - nsamples / state->dst_samples_per_frame : - 1) * state->dst_frame_size; - else - return (nsamples >= 0 ? - nsamples / state->src_samples_per_frame : - 1) * state->src_frame_size; -} - -static enum audio_format get_audio_format(const struct mgcp_rtp_codec *codec) -{ - if (codec->subtype_name) { - if (!strcasecmp("GSM", codec->subtype_name)) - return AF_GSM; - if (!strcasecmp("PCMA", codec->subtype_name)) - return AF_PCMA; - if (!strcasecmp("PCMU", codec->subtype_name)) - return AF_PCMU; -#ifdef HAVE_BCG729 - if (!strcasecmp("G729", codec->subtype_name)) - return AF_G729; -#endif - if (!strcasecmp("L16", codec->subtype_name)) - return AF_L16; - } - - switch (codec->payload_type) { - case 0 /* PCMU */: - return AF_PCMU; - case 3 /* GSM */: - return AF_GSM; - case 8 /* PCMA */: - return AF_PCMA; -#ifdef HAVE_BCG729 - case 18 /* G.729 */: - return AF_G729; -#endif - case 11 /* L16 */: - return AF_L16; - default: - return AF_INVALID; - } -} - -static void l16_encode(short *sample, unsigned char *buf, size_t n) -{ - for (; n > 0; --n, ++sample, buf += 2) { - buf[0] = sample[0] >> 8; - buf[1] = sample[0] & 0xff; - } -} - -static void l16_decode(unsigned char *buf, short *sample, size_t n) -{ - for (; n > 0; --n, ++sample, buf += 2) - sample[0] = ((short)buf[0] << 8) | buf[1]; -} - -static void alaw_encode(short *sample, unsigned char *buf, size_t n) -{ - for (; n > 0; --n) - *(buf++) = s16_to_alaw(*(sample++)); -} - -static void alaw_decode(unsigned char *buf, short *sample, size_t n) -{ - for (; n > 0; --n) - *(sample++) = alaw_to_s16(*(buf++)); -} - -static void ulaw_encode(short *sample, unsigned char *buf, size_t n) -{ - for (; n > 0; --n) - *(buf++) = s16_to_ulaw(*(sample++)); -} - -static void ulaw_decode(unsigned char *buf, short *sample, size_t n) -{ - for (; n > 0; --n) - *(sample++) = ulaw_to_s16(*(buf++)); -} - -static int processing_state_destructor(struct mgcp_process_rtp_state *state) -{ - switch (state->src_fmt) { - case AF_GSM: - if (state->src.gsm_handle) - gsm_destroy(state->src.gsm_handle); - break; -#ifdef HAVE_BCG729 - case AF_G729: - if (state->src.g729_dec) - closeBcg729DecoderChannel(state->src.g729_dec); - break; -#endif - default: - break; - } - switch (state->dst_fmt) { - case AF_GSM: - if (state->dst.gsm_handle) - gsm_destroy(state->dst.gsm_handle); - break; -#ifdef HAVE_BCG729 - case AF_G729: - if (state->dst.g729_enc) - closeBcg729EncoderChannel(state->dst.g729_enc); - break; -#endif - default: - break; - } - return 0; -} - -int mgcp_transcoding_setup(struct mgcp_endpoint *endp, - struct mgcp_rtp_end *dst_end, - struct mgcp_rtp_end *src_end) -{ - struct mgcp_process_rtp_state *state; - enum audio_format src_fmt, dst_fmt; - const struct mgcp_rtp_codec *dst_codec = &dst_end->codec; - - /* cleanup first */ - if (dst_end->rtp_process_data) { - talloc_free(dst_end->rtp_process_data); - dst_end->rtp_process_data = NULL; - } - - if (!src_end) - return 0; - - const struct mgcp_rtp_codec *src_codec = &src_end->codec; - - if (endp->tcfg->no_audio_transcoding) { - LOGP(DLMGCP, LOGL_NOTICE, - "Transcoding disabled on endpoint 0x%x\n", - ENDPOINT_NUMBER(endp)); - return 0; - } - - src_fmt = get_audio_format(src_codec); - dst_fmt = get_audio_format(dst_codec); - - LOGP(DLMGCP, LOGL_ERROR, - "Checking transcoding: %s (%d) -> %s (%d)\n", - src_codec->subtype_name, src_codec->payload_type, - dst_codec->subtype_name, dst_codec->payload_type); - - if (src_fmt == AF_INVALID || dst_fmt == AF_INVALID) { - if (!src_codec->subtype_name || !dst_codec->subtype_name) - /* Not enough info, do nothing */ - return 0; - - if (strcasecmp(src_codec->subtype_name, dst_codec->subtype_name) == 0) - /* Nothing to do */ - return 0; - - LOGP(DLMGCP, LOGL_ERROR, - "Cannot transcode: %s codec not supported (%s -> %s).\n", - src_fmt != AF_INVALID ? "destination" : "source", - src_codec->audio_name, dst_codec->audio_name); - return -EINVAL; - } - - if (src_codec->rate && dst_codec->rate && src_codec->rate != dst_codec->rate) { - LOGP(DLMGCP, LOGL_ERROR, - "Cannot transcode: rate conversion (%d -> %d) not supported.\n", - src_codec->rate, dst_codec->rate); - return -EINVAL; - } - - state = talloc_zero(endp->tcfg->cfg, struct mgcp_process_rtp_state); - talloc_set_destructor(state, processing_state_destructor); - dst_end->rtp_process_data = state; - - state->src_fmt = src_fmt; - - switch (state->src_fmt) { - case AF_L16: - case AF_S16: - state->src_frame_size = 80 * sizeof(short); - state->src_samples_per_frame = 80; - break; - case AF_GSM: - state->src_frame_size = sizeof(gsm_frame); - state->src_samples_per_frame = 160; - state->src.gsm_handle = gsm_create(); - if (!state->src.gsm_handle) { - LOGP(DLMGCP, LOGL_ERROR, - "Failed to initialize GSM decoder.\n"); - return -EINVAL; - } - break; -#ifdef HAVE_BCG729 - case AF_G729: - state->src_frame_size = 10; - state->src_samples_per_frame = 80; - state->src.g729_dec = initBcg729DecoderChannel(); - if (!state->src.g729_dec) { - LOGP(DLMGCP, LOGL_ERROR, - "Failed to initialize G.729 decoder.\n"); - return -EINVAL; - } - break; -#endif - case AF_PCMU: - case AF_PCMA: - state->src_frame_size = 80; - state->src_samples_per_frame = 80; - break; - default: - break; - } - - state->dst_fmt = dst_fmt; - - switch (state->dst_fmt) { - case AF_L16: - case AF_S16: - state->dst_frame_size = 80*sizeof(short); - state->dst_samples_per_frame = 80; - break; - case AF_GSM: - state->dst_frame_size = sizeof(gsm_frame); - state->dst_samples_per_frame = 160; - state->dst.gsm_handle = gsm_create(); - if (!state->dst.gsm_handle) { - LOGP(DLMGCP, LOGL_ERROR, - "Failed to initialize GSM encoder.\n"); - return -EINVAL; - } - break; -#ifdef HAVE_BCG729 - case AF_G729: - state->dst_frame_size = 10; - state->dst_samples_per_frame = 80; - state->dst.g729_enc = initBcg729EncoderChannel(); - if (!state->dst.g729_enc) { - LOGP(DLMGCP, LOGL_ERROR, - "Failed to initialize G.729 decoder.\n"); - return -EINVAL; - } - break; -#endif - case AF_PCMU: - case AF_PCMA: - state->dst_frame_size = 80; - state->dst_samples_per_frame = 80; - break; - default: - break; - } - - if (dst_end->force_output_ptime) - state->dst_packet_duration = mgcp_rtp_packet_duration(endp, dst_end); - - LOGP(DLMGCP, LOGL_INFO, - "Initialized RTP processing on: 0x%x " - "conv: %d (%d, %d, %s) -> %d (%d, %d, %s)\n", - ENDPOINT_NUMBER(endp), - src_fmt, src_codec->payload_type, src_codec->rate, src_end->fmtp_extra, - dst_fmt, dst_codec->payload_type, dst_codec->rate, dst_end->fmtp_extra); - - return 0; -} - -void mgcp_transcoding_net_downlink_format(struct mgcp_endpoint *endp, - int *payload_type, - const char**audio_name, - const char**fmtp_extra) -{ - struct mgcp_process_rtp_state *state = endp->net_end.rtp_process_data; - struct mgcp_rtp_codec *net_codec = &endp->net_end.codec; - struct mgcp_rtp_codec *bts_codec = &endp->bts_end.codec; - - if (!state || net_codec->payload_type < 0) { - *payload_type = bts_codec->payload_type; - *audio_name = bts_codec->audio_name; - *fmtp_extra = endp->bts_end.fmtp_extra; - return; - } - - *payload_type = net_codec->payload_type; - *audio_name = net_codec->audio_name; - *fmtp_extra = endp->net_end.fmtp_extra; -} - -static int decode_audio(struct mgcp_process_rtp_state *state, - uint8_t **src, size_t *nbytes) -{ - while (*nbytes >= state->src_frame_size) { - if (state->sample_cnt + state->src_samples_per_frame > ARRAY_SIZE(state->samples)) { - LOGP(DLMGCP, LOGL_ERROR, - "Sample buffer too small: %zu > %zu.\n", - state->sample_cnt + state->src_samples_per_frame, - ARRAY_SIZE(state->samples)); - return -ENOSPC; - } - switch (state->src_fmt) { - case AF_GSM: - if (gsm_decode(state->src.gsm_handle, - (gsm_byte *)*src, state->samples + state->sample_cnt) < 0) { - LOGP(DLMGCP, LOGL_ERROR, - "Failed to decode GSM.\n"); - return -EINVAL; - } - break; -#ifdef HAVE_BCG729 - case AF_G729: - bcg729Decoder(state->src.g729_dec, *src, 0, state->samples + state->sample_cnt); - break; -#endif - case AF_PCMU: - ulaw_decode(*src, state->samples + state->sample_cnt, - state->src_samples_per_frame); - break; - case AF_PCMA: - alaw_decode(*src, state->samples + state->sample_cnt, - state->src_samples_per_frame); - break; - case AF_S16: - memmove(state->samples + state->sample_cnt, *src, - state->src_frame_size); - break; - case AF_L16: - l16_decode(*src, state->samples + state->sample_cnt, - state->src_samples_per_frame); - break; - default: - break; - } - *src += state->src_frame_size; - *nbytes -= state->src_frame_size; - state->sample_cnt += state->src_samples_per_frame; - } - return 0; -} - -static int encode_audio(struct mgcp_process_rtp_state *state, - uint8_t *dst, size_t buf_size, size_t max_samples) -{ - int nbytes = 0; - size_t nsamples = 0; - /* Encode samples into dst */ - while (nsamples + state->dst_samples_per_frame <= max_samples) { - if (nbytes + state->dst_frame_size > buf_size) { - if (nbytes > 0) - break; - - /* Not even one frame fits into the buffer */ - LOGP(DLMGCP, LOGL_INFO, - "Encoding (RTP) buffer too small: %zu > %zu.\n", - nbytes + state->dst_frame_size, buf_size); - return -ENOSPC; - } - switch (state->dst_fmt) { - case AF_GSM: - gsm_encode(state->dst.gsm_handle, - state->samples + state->sample_offs, dst); - break; -#ifdef HAVE_BCG729 - case AF_G729: - bcg729Encoder(state->dst.g729_enc, - state->samples + state->sample_offs, dst); - break; -#endif - case AF_PCMU: - ulaw_encode(state->samples + state->sample_offs, dst, - state->src_samples_per_frame); - break; - case AF_PCMA: - alaw_encode(state->samples + state->sample_offs, dst, - state->src_samples_per_frame); - break; - case AF_S16: - memmove(dst, state->samples + state->sample_offs, - state->dst_frame_size); - break; - case AF_L16: - l16_encode(state->samples + state->sample_offs, dst, - state->src_samples_per_frame); - break; - default: - break; - } - dst += state->dst_frame_size; - nbytes += state->dst_frame_size; - state->sample_offs += state->dst_samples_per_frame; - nsamples += state->dst_samples_per_frame; - } - state->sample_cnt -= nsamples; - return nbytes; -} - -static struct mgcp_rtp_end *source_for_dest(struct mgcp_endpoint *endp, - struct mgcp_rtp_end *dst_end) -{ - if (&endp->bts_end == dst_end) - return &endp->net_end; - else if (&endp->net_end == dst_end) - return &endp->bts_end; - OSMO_ASSERT(0); -} - -/* - * With some modems we get offered multiple codecs - * and we have selected one of them. It might not - * be the right one and we need to detect this with - * the first audio packets. One difficulty is that - * we patch the rtp payload type in place, so we - * need to discuss this. - */ -struct mgcp_process_rtp_state *check_transcode_state( - struct mgcp_endpoint *endp, - struct mgcp_rtp_end *dst_end, - struct rtp_hdr *rtp_hdr) -{ - struct mgcp_rtp_end *src_end; - - /* Only deal with messages from net to bts */ - if (&endp->bts_end != dst_end) - goto done; - - src_end = source_for_dest(endp, dst_end); - - /* Already patched */ - if (rtp_hdr->payload_type == dst_end->codec.payload_type) - goto done; - /* The payload we expect */ - if (rtp_hdr->payload_type == src_end->codec.payload_type) - goto done; - /* The matching alternate payload type? Then switch */ - if (rtp_hdr->payload_type == src_end->alt_codec.payload_type) { - struct mgcp_config *cfg = endp->cfg; - struct mgcp_rtp_codec tmp_codec = src_end->alt_codec; - src_end->alt_codec = src_end->codec; - src_end->codec = tmp_codec; - cfg->setup_rtp_processing_cb(endp, &endp->net_end, &endp->bts_end); - cfg->setup_rtp_processing_cb(endp, &endp->bts_end, &endp->net_end); - } - -done: - return dst_end->rtp_process_data; -} - -int mgcp_transcoding_process_rtp(struct mgcp_endpoint *endp, - struct mgcp_rtp_end *dst_end, - char *data, int *len, int buf_size) -{ - struct mgcp_process_rtp_state *state; - const size_t rtp_hdr_size = sizeof(struct rtp_hdr); - struct rtp_hdr *rtp_hdr = (struct rtp_hdr *) data; - char *payload_data = (char *) &rtp_hdr->data[0]; - int payload_len = *len - rtp_hdr_size; - uint8_t *src = (uint8_t *)payload_data; - uint8_t *dst = (uint8_t *)payload_data; - size_t nbytes = payload_len; - size_t nsamples; - size_t max_samples; - uint32_t ts_no; - int rc; - - state = check_transcode_state(endp, dst_end, rtp_hdr); - if (!state) - return 0; - - if (state->src_fmt == state->dst_fmt) { - if (!state->dst_packet_duration) - return 0; - - /* TODO: repackage without transcoding */ - } - - /* If the remaining samples do not fit into a fixed ptime, - * a) discard them, if the next packet is much later - * b) add silence and * send it, if the current packet is not - * yet too late - * c) append the sample data, if the timestamp matches exactly - */ - - /* TODO: check payload type (-> G.711 comfort noise) */ - - if (payload_len > 0) { - ts_no = ntohl(rtp_hdr->timestamp); - if (!state->is_running) { - state->next_seq = ntohs(rtp_hdr->sequence); - state->next_time = ts_no; - state->is_running = 1; - } - - - if (state->sample_cnt > 0) { - int32_t delta = ts_no - state->next_time; - /* TODO: check sequence? reordering? packet loss? */ - - if (delta > state->sample_cnt) { - /* There is a time gap between the last packet - * and the current one. Just discard the - * partial data that is left in the buffer. - * TODO: This can be improved by adding silence - * instead if the delta is small enough. - */ - LOGP(DLMGCP, LOGL_NOTICE, - "0x%x dropping sample buffer due delta=%d sample_cnt=%zu\n", - ENDPOINT_NUMBER(endp), delta, state->sample_cnt); - state->sample_cnt = 0; - state->next_time = ts_no; - } else if (delta < 0) { - LOGP(DLMGCP, LOGL_NOTICE, - "RTP time jumps backwards, delta = %d, " - "discarding buffered samples\n", - delta); - state->sample_cnt = 0; - state->sample_offs = 0; - return -EAGAIN; - } - - /* Make sure the samples start without offset */ - if (state->sample_offs && state->sample_cnt) - memmove(&state->samples[0], - &state->samples[state->sample_offs], - state->sample_cnt * - sizeof(state->samples[0])); - } - - state->sample_offs = 0; - - /* Append decoded audio to samples */ - decode_audio(state, &src, &nbytes); - - if (nbytes > 0) - LOGP(DLMGCP, LOGL_NOTICE, - "Skipped audio frame in RTP packet: %zu octets\n", - nbytes); - } else - ts_no = state->next_time; - - if (state->sample_cnt < state->dst_packet_duration) - return -EAGAIN; - - max_samples = - state->dst_packet_duration ? - state->dst_packet_duration : state->sample_cnt; - - nsamples = state->sample_cnt; - - rc = encode_audio(state, dst, buf_size, max_samples); - /* - * There were no samples to encode? - * TODO: how does this work for comfort noise? - */ - if (rc == 0) - return -ENOMSG; - /* Any other error during the encoding */ - if (rc < 0) - return rc; - - nsamples -= state->sample_cnt; - - *len = rtp_hdr_size + rc; - rtp_hdr->sequence = htons(state->next_seq); - rtp_hdr->timestamp = htonl(ts_no); - - state->next_seq += 1; - state->next_time = ts_no + nsamples; - - /* - * XXX: At this point we should always have consumed - * samples. So doing OSMO_ASSERT(nsamples > 0) and returning - * rtp_hdr_size should be fine. - */ - return nsamples ? rtp_hdr_size : 0; -} diff --git a/src/libosmo-legacy-mgcp/mgcp_vty.c b/src/libosmo-legacy-mgcp/mgcp_vty.c deleted file mode 100644 index 420333dbf..000000000 --- a/src/libosmo-legacy-mgcp/mgcp_vty.c +++ /dev/null @@ -1,1627 +0,0 @@ -/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */ -/* The protocol implementation */ - -/* - * (C) 2009-2014 by Holger Hans Peter Freyther - * (C) 2009-2011 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - - -#include - -#include -#include -#include - -#include -#include - -#define RTCP_OMIT_STR "Drop RTCP packets in both directions\n" -#define RTP_PATCH_STR "Modify RTP packet header in both directions\n" -#define RTP_KEEPALIVE_STR "Send dummy UDP packet to net RTP destination\n" - -static struct mgcp_config *g_cfg = NULL; - -static struct mgcp_trunk_config *find_trunk(struct mgcp_config *cfg, int nr) -{ - struct mgcp_trunk_config *trunk; - - if (nr == 0) - trunk = &cfg->trunk; - else - trunk = mgcp_trunk_num(cfg, nr); - - return trunk; -} - -/* - * vty code for mgcp below - */ -struct cmd_node mgcp_node = { - MGCP_NODE, - "%s(config-mgcp)# ", - 1, -}; - -struct cmd_node trunk_node = { - TRUNK_NODE, - "%s(config-mgcp-trunk)# ", - 1, -}; - -static int config_write_mgcp(struct vty *vty) -{ - vty_out(vty, "mgcp%s", VTY_NEWLINE); - if (g_cfg->local_ip) - vty_out(vty, " local ip %s%s", g_cfg->local_ip, VTY_NEWLINE); - if (g_cfg->bts_ip && strlen(g_cfg->bts_ip) != 0) - vty_out(vty, " bts ip %s%s", g_cfg->bts_ip, VTY_NEWLINE); - vty_out(vty, " bind ip %s%s", g_cfg->source_addr, VTY_NEWLINE); - vty_out(vty, " bind port %u%s", g_cfg->source_port, VTY_NEWLINE); - - if (g_cfg->bts_ports.mode == PORT_ALLOC_STATIC) - vty_out(vty, " rtp bts-base %u%s", g_cfg->bts_ports.base_port, VTY_NEWLINE); - else - vty_out(vty, " rtp bts-range %u %u%s", - g_cfg->bts_ports.range_start, g_cfg->bts_ports.range_end, VTY_NEWLINE); - if (g_cfg->bts_ports.bind_addr) - vty_out(vty, " rtp bts-bind-ip %s%s", g_cfg->bts_ports.bind_addr, VTY_NEWLINE); - - if (g_cfg->net_ports.mode == PORT_ALLOC_STATIC) - vty_out(vty, " rtp net-base %u%s", g_cfg->net_ports.base_port, VTY_NEWLINE); - else - vty_out(vty, " rtp net-range %u %u%s", - g_cfg->net_ports.range_start, g_cfg->net_ports.range_end, VTY_NEWLINE); - if (g_cfg->net_ports.bind_addr) - vty_out(vty, " rtp net-bind-ip %s%s", g_cfg->net_ports.bind_addr, VTY_NEWLINE); - - vty_out(vty, " rtp ip-dscp %d%s", g_cfg->endp_dscp, VTY_NEWLINE); - if (g_cfg->trunk.keepalive_interval == MGCP_KEEPALIVE_ONCE) - vty_out(vty, " rtp keep-alive once%s", VTY_NEWLINE); - else if (g_cfg->trunk.keepalive_interval) - vty_out(vty, " rtp keep-alive %d%s", - g_cfg->trunk.keepalive_interval, VTY_NEWLINE); - else - vty_out(vty, " no rtp keep-alive%s", VTY_NEWLINE); - - if (g_cfg->trunk.omit_rtcp) - vty_out(vty, " rtcp-omit%s", VTY_NEWLINE); - else - vty_out(vty, " no rtcp-omit%s", VTY_NEWLINE); - if (g_cfg->trunk.force_constant_ssrc || g_cfg->trunk.force_aligned_timing) { - vty_out(vty, " %srtp-patch ssrc%s", - g_cfg->trunk.force_constant_ssrc ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %srtp-patch timestamp%s", - g_cfg->trunk.force_aligned_timing ? "" : "no ", VTY_NEWLINE); - } else - vty_out(vty, " no rtp-patch%s", VTY_NEWLINE); - if (g_cfg->trunk.audio_payload != -1) - vty_out(vty, " sdp audio-payload number %d%s", - g_cfg->trunk.audio_payload, VTY_NEWLINE); - if (g_cfg->trunk.audio_name) - vty_out(vty, " sdp audio-payload name %s%s", - g_cfg->trunk.audio_name, VTY_NEWLINE); - if (g_cfg->trunk.audio_fmtp_extra) - vty_out(vty, " sdp audio fmtp-extra %s%s", - g_cfg->trunk.audio_fmtp_extra, VTY_NEWLINE); - vty_out(vty, " %ssdp audio-payload send-ptime%s", - g_cfg->trunk.audio_send_ptime ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %ssdp audio-payload send-name%s", - g_cfg->trunk.audio_send_name ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " loop %u%s", !!g_cfg->trunk.audio_loop, VTY_NEWLINE); - vty_out(vty, " number endpoints %u%s", g_cfg->trunk.number_endpoints - 1, VTY_NEWLINE); - vty_out(vty, " %sallow-transcoding%s", - g_cfg->trunk.no_audio_transcoding ? "no " : "", VTY_NEWLINE); - if (g_cfg->call_agent_addr) - vty_out(vty, " call-agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE); - if (g_cfg->transcoder_ip) - vty_out(vty, " transcoder-mgw %s%s", g_cfg->transcoder_ip, VTY_NEWLINE); - - if (g_cfg->transcoder_ports.mode == PORT_ALLOC_STATIC) - vty_out(vty, " rtp transcoder-base %u%s", g_cfg->transcoder_ports.base_port, VTY_NEWLINE); - else - vty_out(vty, " rtp transcoder-range %u %u%s", - g_cfg->transcoder_ports.range_start, g_cfg->transcoder_ports.range_end, VTY_NEWLINE); - if (g_cfg->bts_force_ptime > 0) - vty_out(vty, " rtp force-ptime %d%s", g_cfg->bts_force_ptime, VTY_NEWLINE); - vty_out(vty, " transcoder-remote-base %u%s", g_cfg->transcoder_remote_base, VTY_NEWLINE); - - switch (g_cfg->osmux) { - case OSMUX_USAGE_ON: - vty_out(vty, " osmux on%s", VTY_NEWLINE); - break; - case OSMUX_USAGE_ONLY: - vty_out(vty, " osmux only%s", VTY_NEWLINE); - break; - case OSMUX_USAGE_OFF: - default: - vty_out(vty, " osmux off%s", VTY_NEWLINE); - break; - } - if (g_cfg->osmux) { - vty_out(vty, " osmux bind-ip %s%s", - g_cfg->osmux_addr, VTY_NEWLINE); - vty_out(vty, " osmux batch-factor %d%s", - g_cfg->osmux_batch, VTY_NEWLINE); - vty_out(vty, " osmux batch-size %u%s", - g_cfg->osmux_batch_size, VTY_NEWLINE); - vty_out(vty, " osmux port %u%s", - g_cfg->osmux_port, VTY_NEWLINE); - vty_out(vty, " osmux dummy %s%s", - g_cfg->osmux_dummy ? "on" : "off", VTY_NEWLINE); - } - if (g_cfg->bts_use_jibuf) - vty_out(vty, " bts-jitter-buffer%s", VTY_NEWLINE); - if (g_cfg->bts_jitter_delay_min) - vty_out(vty, " bts-jitter-buffer-delay-min %"PRIu32"%s", g_cfg->bts_jitter_delay_min, VTY_NEWLINE); - if (g_cfg->bts_jitter_delay_max) - vty_out(vty, " bts-jitter-buffer-delay-max %"PRIu32"%s", g_cfg->bts_jitter_delay_max, VTY_NEWLINE); - - return CMD_SUCCESS; -} - -static void dump_rtp_end(const char *end_name, struct vty *vty, - struct mgcp_rtp_state *state, struct mgcp_rtp_end *end) -{ - struct mgcp_rtp_codec *codec = &end->codec; - - vty_out(vty, - " %s%s" - " Timestamp Errs: %d->%d%s" - " Dropped Packets: %d%s" - " Payload Type: %d Rate: %u Channels: %d %s" - " Frame Duration: %u Frame Denominator: %u%s" - " FPP: %d Packet Duration: %u%s" - " FMTP-Extra: %s Audio-Name: %s Sub-Type: %s%s" - " Output-Enabled: %d Force-PTIME: %d%s", - end_name, VTY_NEWLINE, - state->in_stream.err_ts_counter, - state->out_stream.err_ts_counter, VTY_NEWLINE, - end->dropped_packets, VTY_NEWLINE, - codec->payload_type, codec->rate, codec->channels, VTY_NEWLINE, - codec->frame_duration_num, codec->frame_duration_den, VTY_NEWLINE, - end->frames_per_packet, end->packet_duration_ms, VTY_NEWLINE, - end->fmtp_extra, codec->audio_name, codec->subtype_name, VTY_NEWLINE, - end->output_enabled, end->force_output_ptime, VTY_NEWLINE); -} - -static void dump_trunk(struct vty *vty, struct mgcp_trunk_config *cfg, int verbose) -{ - int i; - - vty_out(vty, "%s trunk nr %d with %d endpoints:%s", - cfg->trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1", - cfg->trunk_nr, cfg->number_endpoints - 1, VTY_NEWLINE); - - if (!cfg->endpoints) { - vty_out(vty, "No endpoints allocated yet.%s", VTY_NEWLINE); - return; - } - - for (i = 1; i < cfg->number_endpoints; ++i) { - struct mgcp_endpoint *endp = &cfg->endpoints[i]; - vty_out(vty, - " Endpoint 0x%.2x: CI: %d net: %u/%u bts: %u/%u on %s " - "traffic received bts: %u remote: %u transcoder: %u/%u%s", - i, endp->ci, - ntohs(endp->net_end.rtp_port), ntohs(endp->net_end.rtcp_port), - ntohs(endp->bts_end.rtp_port), ntohs(endp->bts_end.rtcp_port), - inet_ntoa(endp->bts_end.addr), - endp->bts_end.packets, endp->net_end.packets, - endp->trans_net.packets, endp->trans_bts.packets, - VTY_NEWLINE); - - if (verbose && endp->allocated) { - dump_rtp_end("Net->BTS", vty, &endp->bts_state, &endp->bts_end); - dump_rtp_end("BTS->Net", vty, &endp->net_state, &endp->net_end); - } - } -} - -DEFUN(show_mcgp, show_mgcp_cmd, - "show mgcp [stats]", - SHOW_STR - "Display information about the MGCP Media Gateway\n" - "Include Statistics\n") -{ - struct mgcp_trunk_config *trunk; - int show_stats = argc >= 1; - - dump_trunk(vty, &g_cfg->trunk, show_stats); - - llist_for_each_entry(trunk, &g_cfg->trunks, entry) - dump_trunk(vty, trunk, show_stats); - - if (g_cfg->osmux) - vty_out(vty, "Osmux used CID: %d%s", osmux_used_cid(), VTY_NEWLINE); - vty_out(vty, "Jitter Buffer by default on Uplink : %s%s", - g_cfg->bts_use_jibuf ? "on" : "off", VTY_NEWLINE); - if (g_cfg->bts_use_jibuf) - vty_out(vty, "Jitter Buffer delays: min=%"PRIu32" max=%"PRIu32"%s", - g_cfg->bts_jitter_delay_min, g_cfg->bts_jitter_delay_max, VTY_NEWLINE); - - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp, - cfg_mgcp_cmd, - "mgcp", - "Configure the MGCP") -{ - vty->node = MGCP_NODE; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_local_ip, - cfg_mgcp_local_ip_cmd, - "local ip A.B.C.D", - "Local options for the SDP record\n" - IP_STR - "IPv4 Address to use in SDP record\n") -{ - osmo_talloc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_bts_ip, - cfg_mgcp_bts_ip_cmd, - "bts ip A.B.C.D", - "BTS Audio source/destination options\n" - IP_STR - "IPv4 Address of the BTS\n") -{ - osmo_talloc_replace_string(g_cfg, &g_cfg->bts_ip, argv[0]); - inet_aton(g_cfg->bts_ip, &g_cfg->bts_in); - return CMD_SUCCESS; -} - -#define BIND_STR "Listen/Bind related socket option\n" -DEFUN(cfg_mgcp_bind_ip, - cfg_mgcp_bind_ip_cmd, - "bind ip A.B.C.D", - BIND_STR - IP_STR - "IPv4 Address to bind to\n") -{ - osmo_talloc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_bind_port, - cfg_mgcp_bind_port_cmd, - "bind port <0-65534>", - BIND_STR - "Port information\n" - "UDP port to listen for MGCP messages\n") -{ - unsigned int port = atoi(argv[0]); - g_cfg->source_port = port; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_bind_early, - cfg_mgcp_bind_early_cmd, - "bind early (0|1)", - BIND_STR - "Bind local ports on start up\n" - "Bind on demand\n" "Bind on startup\n") -{ - vty_out(vty, "bind early is deprecated, remove it from the config.\n"); - return CMD_WARNING; -} - -static void parse_base(struct mgcp_port_range *range, const char **argv) -{ - unsigned int port = atoi(argv[0]); - range->mode = PORT_ALLOC_STATIC; - range->base_port = port; -} - -static void parse_range(struct mgcp_port_range *range, const char **argv) -{ - range->mode = PORT_ALLOC_DYNAMIC; - range->range_start = atoi(argv[0]); - range->range_end = atoi(argv[1]); - range->last_port = g_cfg->bts_ports.range_start; -} - - -#define RTP_STR "RTP configuration\n" -#define BTS_START_STR "First UDP port allocated for the BTS side\n" -#define NET_START_STR "First UDP port allocated for the NET side\n" -#define UDP_PORT_STR "UDP Port number\n" -DEFUN(cfg_mgcp_rtp_bts_base_port, - cfg_mgcp_rtp_bts_base_port_cmd, - "rtp bts-base <0-65534>", - RTP_STR - BTS_START_STR - UDP_PORT_STR) -{ - parse_base(&g_cfg->bts_ports, argv); - return CMD_SUCCESS; -} - -#define RANGE_START_STR "Start of the range of ports\n" -#define RANGE_END_STR "End of the range of ports\n" -DEFUN(cfg_mgcp_rtp_bts_range, - cfg_mgcp_rtp_bts_range_cmd, - "rtp bts-range <0-65534> <0-65534>", - RTP_STR "Range of ports to use for the BTS side\n" - RANGE_START_STR RANGE_END_STR) -{ - parse_range(&g_cfg->bts_ports, argv); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_rtp_net_range, - cfg_mgcp_rtp_net_range_cmd, - "rtp net-range <0-65534> <0-65534>", - RTP_STR "Range of ports to use for the NET side\n" - RANGE_START_STR RANGE_END_STR) -{ - parse_range(&g_cfg->net_ports, argv); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_rtp_net_base_port, - cfg_mgcp_rtp_net_base_port_cmd, - "rtp net-base <0-65534>", - RTP_STR NET_START_STR UDP_PORT_STR) -{ - parse_base(&g_cfg->net_ports, argv); - return CMD_SUCCESS; -} - -ALIAS_DEPRECATED(cfg_mgcp_rtp_bts_base_port, cfg_mgcp_rtp_base_port_cmd, - "rtp base <0-65534>", - RTP_STR BTS_START_STR UDP_PORT_STR) - -DEFUN(cfg_mgcp_rtp_transcoder_range, - cfg_mgcp_rtp_transcoder_range_cmd, - "rtp transcoder-range <0-65534> <0-65534>", - RTP_STR "Range of ports to use for the Transcoder\n" - RANGE_START_STR RANGE_END_STR) -{ - parse_range(&g_cfg->transcoder_ports, argv); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_rtp_transcoder_base, - cfg_mgcp_rtp_transcoder_base_cmd, - "rtp transcoder-base <0-65534>", - RTP_STR "First UDP port allocated for the Transcoder side\n" - UDP_PORT_STR) -{ - parse_base(&g_cfg->transcoder_ports, argv); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_rtp_bts_bind_ip, - cfg_mgcp_rtp_bts_bind_ip_cmd, - "rtp bts-bind-ip A.B.C.D", - RTP_STR "Bind endpoints facing the BTS\n" "Address to bind to\n") -{ - osmo_talloc_replace_string(g_cfg, &g_cfg->bts_ports.bind_addr, argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_rtp_no_bts_bind_ip, - cfg_mgcp_rtp_no_bts_bind_ip_cmd, - "no rtp bts-bind-ip", - NO_STR RTP_STR "Bind endpoints facing the BTS\n" "Address to bind to\n") -{ - talloc_free(g_cfg->bts_ports.bind_addr); - g_cfg->bts_ports.bind_addr = NULL; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_rtp_net_bind_ip, - cfg_mgcp_rtp_net_bind_ip_cmd, - "rtp net-bind-ip A.B.C.D", - RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n") -{ - osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr, argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_rtp_no_net_bind_ip, - cfg_mgcp_rtp_no_net_bind_ip_cmd, - "no rtp net-bind-ip", - NO_STR RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n") -{ - talloc_free(g_cfg->net_ports.bind_addr); - g_cfg->net_ports.bind_addr = NULL; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_rtp_ip_dscp, - cfg_mgcp_rtp_ip_dscp_cmd, - "rtp ip-dscp <0-255>", - RTP_STR - "Apply IP_TOS to the audio stream (including Osmux)\n" "The DSCP value\n") -{ - int dscp = atoi(argv[0]); - g_cfg->endp_dscp = dscp; - return CMD_SUCCESS; -} - -ALIAS_DEPRECATED(cfg_mgcp_rtp_ip_dscp, cfg_mgcp_rtp_ip_tos_cmd, - "rtp ip-tos <0-255>", - RTP_STR - "Apply IP_TOS to the audio stream\n" "The DSCP value\n") - -#define FORCE_PTIME_STR "Force a fixed ptime for packets sent to the BTS" -DEFUN(cfg_mgcp_rtp_force_ptime, - cfg_mgcp_rtp_force_ptime_cmd, - "rtp force-ptime (10|20|40)", - RTP_STR FORCE_PTIME_STR - "The required ptime (packet duration) in ms\n" - "10 ms\n20 ms\n40 ms\n") -{ - g_cfg->bts_force_ptime = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_no_rtp_force_ptime, - cfg_mgcp_no_rtp_force_ptime_cmd, - "no rtp force-ptime", - NO_STR RTP_STR FORCE_PTIME_STR) -{ - g_cfg->bts_force_ptime = 0; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_sdp_fmtp_extra, - cfg_mgcp_sdp_fmtp_extra_cmd, - "sdp audio fmtp-extra .NAME", - "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n" - "Extra Information\n") -{ - char *txt = argv_concat(argv, argc, 0); - if (!txt) - return CMD_WARNING; - - osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_fmtp_extra, txt); - talloc_free(txt); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_allow_transcoding, - cfg_mgcp_allow_transcoding_cmd, - "allow-transcoding", - "Allow transcoding\n") -{ - g_cfg->trunk.no_audio_transcoding = 0; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_no_allow_transcoding, - cfg_mgcp_no_allow_transcoding_cmd, - "no allow-transcoding", - NO_STR "Allow transcoding\n") -{ - g_cfg->trunk.no_audio_transcoding = 1; - return CMD_SUCCESS; -} - -#define SDP_STR "SDP File related options\n" -#define AUDIO_STR "Audio payload options\n" -DEFUN(cfg_mgcp_sdp_payload_number, - cfg_mgcp_sdp_payload_number_cmd, - "sdp audio-payload number <0-255>", - SDP_STR AUDIO_STR - "Number\n" "Payload number\n") -{ - unsigned int payload = atoi(argv[0]); - g_cfg->trunk.audio_payload = payload; - return CMD_SUCCESS; -} - -ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_number, cfg_mgcp_sdp_payload_number_cmd_old, - "sdp audio payload number <0-255>", - SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload number\n") - - -DEFUN(cfg_mgcp_sdp_payload_name, - cfg_mgcp_sdp_payload_name_cmd, - "sdp audio-payload name NAME", - SDP_STR AUDIO_STR "Name\n" "Payload name\n") -{ - osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_name, argv[0]); - return CMD_SUCCESS; -} - -ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_name, cfg_mgcp_sdp_payload_name_cmd_old, - "sdp audio payload name NAME", - SDP_STR AUDIO_STR AUDIO_STR "Name\n" "Payload name\n") - -DEFUN(cfg_mgcp_sdp_payload_send_ptime, - cfg_mgcp_sdp_payload_send_ptime_cmd, - "sdp audio-payload send-ptime", - SDP_STR AUDIO_STR - "Send SDP ptime (packet duration) attribute\n") -{ - g_cfg->trunk.audio_send_ptime = 1; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_no_sdp_payload_send_ptime, - cfg_mgcp_no_sdp_payload_send_ptime_cmd, - "no sdp audio-payload send-ptime", - NO_STR SDP_STR AUDIO_STR - "Send SDP ptime (packet duration) attribute\n") -{ - g_cfg->trunk.audio_send_ptime = 0; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_sdp_payload_send_name, - cfg_mgcp_sdp_payload_send_name_cmd, - "sdp audio-payload send-name", - SDP_STR AUDIO_STR - "Send SDP rtpmap with the audio name\n") -{ - g_cfg->trunk.audio_send_name = 1; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_no_sdp_payload_send_name, - cfg_mgcp_no_sdp_payload_send_name_cmd, - "no sdp audio-payload send-name", - NO_STR SDP_STR AUDIO_STR - "Send SDP rtpmap with the audio name\n") -{ - g_cfg->trunk.audio_send_name = 0; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_loop, - cfg_mgcp_loop_cmd, - "loop (0|1)", - "Loop audio for all endpoints on main trunk\n" - "Don't Loop\n" "Loop\n") -{ - if (g_cfg->osmux) { - vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE); - return CMD_WARNING; - } - g_cfg->trunk.audio_loop = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_force_realloc, - cfg_mgcp_force_realloc_cmd, - "force-realloc (0|1)", - "Force endpoint reallocation when the endpoint is still seized\n" - "Don't force reallocation\n" "force reallocation\n") -{ - g_cfg->trunk.force_realloc = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_number_endp, - cfg_mgcp_number_endp_cmd, - "number endpoints <0-65534>", - "Number options\n" "Endpoints available\n" "Number endpoints\n") -{ - /* + 1 as we start counting at one */ - g_cfg->trunk.number_endpoints = atoi(argv[0]) + 1; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_omit_rtcp, - cfg_mgcp_omit_rtcp_cmd, - "rtcp-omit", - RTCP_OMIT_STR) -{ - g_cfg->trunk.omit_rtcp = 1; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_no_omit_rtcp, - cfg_mgcp_no_omit_rtcp_cmd, - "no rtcp-omit", - NO_STR RTCP_OMIT_STR) -{ - g_cfg->trunk.omit_rtcp = 0; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_patch_rtp_ssrc, - cfg_mgcp_patch_rtp_ssrc_cmd, - "rtp-patch ssrc", - RTP_PATCH_STR - "Force a fixed SSRC\n" - ) -{ - g_cfg->trunk.force_constant_ssrc = 1; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_no_patch_rtp_ssrc, - cfg_mgcp_no_patch_rtp_ssrc_cmd, - "no rtp-patch ssrc", - NO_STR RTP_PATCH_STR - "Force a fixed SSRC\n" - ) -{ - g_cfg->trunk.force_constant_ssrc = 0; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_patch_rtp_ts, - cfg_mgcp_patch_rtp_ts_cmd, - "rtp-patch timestamp", - RTP_PATCH_STR - "Adjust RTP timestamp\n" - ) -{ - g_cfg->trunk.force_aligned_timing = 1; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_no_patch_rtp_ts, - cfg_mgcp_no_patch_rtp_ts_cmd, - "no rtp-patch timestamp", - NO_STR RTP_PATCH_STR - "Adjust RTP timestamp\n" - ) -{ - g_cfg->trunk.force_aligned_timing = 0; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_no_patch_rtp, - cfg_mgcp_no_patch_rtp_cmd, - "no rtp-patch", - NO_STR RTP_PATCH_STR) -{ - g_cfg->trunk.force_constant_ssrc = 0; - g_cfg->trunk.force_aligned_timing = 0; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_rtp_keepalive, - cfg_mgcp_rtp_keepalive_cmd, - "rtp keep-alive <1-120>", - RTP_STR RTP_KEEPALIVE_STR - "Keep alive interval in secs\n" - ) -{ - mgcp_trunk_set_keepalive(&g_cfg->trunk, atoi(argv[0])); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_rtp_keepalive_once, - cfg_mgcp_rtp_keepalive_once_cmd, - "rtp keep-alive once", - RTP_STR RTP_KEEPALIVE_STR - "Send dummy packet only once after CRCX/MDCX\n" - ) -{ - mgcp_trunk_set_keepalive(&g_cfg->trunk, MGCP_KEEPALIVE_ONCE); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_no_rtp_keepalive, - cfg_mgcp_no_rtp_keepalive_cmd, - "no rtp keep-alive", - NO_STR RTP_STR RTP_KEEPALIVE_STR - ) -{ - mgcp_trunk_set_keepalive(&g_cfg->trunk, 0); - return CMD_SUCCESS; -} - - - -#define CALL_AGENT_STR "Callagent information\n" -DEFUN(cfg_mgcp_agent_addr, - cfg_mgcp_agent_addr_cmd, - "call-agent ip A.B.C.D", - CALL_AGENT_STR IP_STR - "IPv4 Address of the callagent\n") -{ - osmo_talloc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]); - return CMD_SUCCESS; -} - -ALIAS_DEPRECATED(cfg_mgcp_agent_addr, cfg_mgcp_agent_addr_cmd_old, - "call agent ip A.B.C.D", - CALL_AGENT_STR CALL_AGENT_STR IP_STR - "IPv4 Address of the callagent\n") - - -DEFUN(cfg_mgcp_transcoder, - cfg_mgcp_transcoder_cmd, - "transcoder-mgw A.B.C.D", - "Use a MGW to detranscoder RTP\n" - "The IP address of the MGW") -{ - osmo_talloc_replace_string(g_cfg, &g_cfg->transcoder_ip, argv[0]); - inet_aton(g_cfg->transcoder_ip, &g_cfg->transcoder_in); - - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_no_transcoder, - cfg_mgcp_no_transcoder_cmd, - "no transcoder-mgw", - NO_STR "Disable the transcoding\n") -{ - if (g_cfg->transcoder_ip) { - LOGP(DLMGCP, LOGL_NOTICE, "Disabling transcoding on future calls.\n"); - talloc_free(g_cfg->transcoder_ip); - g_cfg->transcoder_ip = NULL; - } - - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_transcoder_remote_base, - cfg_mgcp_transcoder_remote_base_cmd, - "transcoder-remote-base <0-65534>", - "Set the base port for the transcoder\n" "The RTP base port on the transcoder") -{ - g_cfg->transcoder_remote_base = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd, - "trunk <1-64>", - "Configure a SS7 trunk\n" "Trunk Nr\n") -{ - struct mgcp_trunk_config *trunk; - int index = atoi(argv[0]); - - trunk = mgcp_trunk_num(g_cfg, index); - if (!trunk) - trunk = mgcp_trunk_alloc(g_cfg, index); - - if (!trunk) { - vty_out(vty, "%%Unable to allocate trunk %u.%s", - index, VTY_NEWLINE); - return CMD_WARNING; - } - - vty->node = TRUNK_NODE; - vty->index = trunk; - return CMD_SUCCESS; -} - -static int config_write_trunk(struct vty *vty) -{ - struct mgcp_trunk_config *trunk; - - llist_for_each_entry(trunk, &g_cfg->trunks, entry) { - vty_out(vty, " trunk %d%s", trunk->trunk_nr, VTY_NEWLINE); - vty_out(vty, " sdp audio-payload number %d%s", - trunk->audio_payload, VTY_NEWLINE); - vty_out(vty, " sdp audio-payload name %s%s", - trunk->audio_name, VTY_NEWLINE); - vty_out(vty, " %ssdp audio-payload send-ptime%s", - trunk->audio_send_ptime ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %ssdp audio-payload send-name%s", - trunk->audio_send_name ? "" : "no ", VTY_NEWLINE); - - if (trunk->keepalive_interval == MGCP_KEEPALIVE_ONCE) - vty_out(vty, " rtp keep-alive once%s", VTY_NEWLINE); - else if (trunk->keepalive_interval) - vty_out(vty, " rtp keep-alive %d%s", - trunk->keepalive_interval, VTY_NEWLINE); - else - vty_out(vty, " no rtp keep-alive%s", VTY_NEWLINE); - vty_out(vty, " loop %d%s", - trunk->audio_loop, VTY_NEWLINE); - vty_out(vty, " force-realloc %d%s", - trunk->force_realloc, VTY_NEWLINE); - if (trunk->omit_rtcp) - vty_out(vty, " rtcp-omit%s", VTY_NEWLINE); - else - vty_out(vty, " no rtcp-omit%s", VTY_NEWLINE); - if (trunk->force_constant_ssrc || trunk->force_aligned_timing) { - vty_out(vty, " %srtp-patch ssrc%s", - trunk->force_constant_ssrc ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %srtp-patch timestamp%s", - trunk->force_aligned_timing ? "" : "no ", VTY_NEWLINE); - } else - vty_out(vty, " no rtp-patch%s", VTY_NEWLINE); - if (trunk->audio_fmtp_extra) - vty_out(vty, " sdp audio fmtp-extra %s%s", - trunk->audio_fmtp_extra, VTY_NEWLINE); - vty_out(vty, " %sallow-transcoding%s", - trunk->no_audio_transcoding ? "no " : "", VTY_NEWLINE); - } - - return CMD_SUCCESS; -} - -DEFUN(cfg_trunk_sdp_fmtp_extra, - cfg_trunk_sdp_fmtp_extra_cmd, - "sdp audio fmtp-extra .NAME", - "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n" - "Extra Information\n") -{ - struct mgcp_trunk_config *trunk = vty->index; - char *txt = argv_concat(argv, argc, 0); - if (!txt) - return CMD_WARNING; - - osmo_talloc_replace_string(g_cfg, &trunk->audio_fmtp_extra, txt); - talloc_free(txt); - return CMD_SUCCESS; -} - -DEFUN(cfg_trunk_payload_number, - cfg_trunk_payload_number_cmd, - "sdp audio-payload number <0-255>", - SDP_STR AUDIO_STR "Number\n" "Payload Number\n") -{ - struct mgcp_trunk_config *trunk = vty->index; - unsigned int payload = atoi(argv[0]); - - trunk->audio_payload = payload; - return CMD_SUCCESS; -} - -ALIAS_DEPRECATED(cfg_trunk_payload_number, cfg_trunk_payload_number_cmd_old, - "sdp audio payload number <0-255>", - SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload Number\n") - -DEFUN(cfg_trunk_payload_name, - cfg_trunk_payload_name_cmd, - "sdp audio-payload name NAME", - SDP_STR AUDIO_STR "Payload\n" "Payload Name\n") -{ - struct mgcp_trunk_config *trunk = vty->index; - - osmo_talloc_replace_string(g_cfg, &trunk->audio_name, argv[0]); - return CMD_SUCCESS; -} - -ALIAS_DEPRECATED(cfg_trunk_payload_name, cfg_trunk_payload_name_cmd_old, - "sdp audio payload name NAME", - SDP_STR AUDIO_STR AUDIO_STR "Payload\n" "Payload Name\n") - - -DEFUN(cfg_trunk_loop, - cfg_trunk_loop_cmd, - "loop (0|1)", - "Loop audio for all endpoints on this trunk\n" - "Don't Loop\n" "Loop\n") -{ - struct mgcp_trunk_config *trunk = vty->index; - - if (g_cfg->osmux) { - vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE); - return CMD_WARNING; - } - trunk->audio_loop = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_trunk_sdp_payload_send_ptime, - cfg_trunk_sdp_payload_send_ptime_cmd, - "sdp audio-payload send-ptime", - SDP_STR AUDIO_STR - "Send SDP ptime (packet duration) attribute\n") -{ - struct mgcp_trunk_config *trunk = vty->index; - trunk->audio_send_ptime = 1; - return CMD_SUCCESS; -} - -DEFUN(cfg_trunk_no_sdp_payload_send_ptime, - cfg_trunk_no_sdp_payload_send_ptime_cmd, - "no sdp audio-payload send-ptime", - NO_STR SDP_STR AUDIO_STR - "Send SDP ptime (packet duration) attribute\n") -{ - struct mgcp_trunk_config *trunk = vty->index; - trunk->audio_send_ptime = 0; - return CMD_SUCCESS; -} - -DEFUN(cfg_trunk_sdp_payload_send_name, - cfg_trunk_sdp_payload_send_name_cmd, - "sdp audio-payload send-name", - SDP_STR AUDIO_STR - "Send SDP rtpmap with the audio name\n") -{ - struct mgcp_trunk_config *trunk = vty->index; - trunk->audio_send_name = 1; - return CMD_SUCCESS; -} - -DEFUN(cfg_trunk_no_sdp_payload_send_name, - cfg_trunk_no_sdp_payload_send_name_cmd, - "no sdp audio-payload send-name", - NO_STR SDP_STR AUDIO_STR - "Send SDP rtpmap with the audio name\n") -{ - struct mgcp_trunk_config *trunk = vty->index; - trunk->audio_send_name = 0; - return CMD_SUCCESS; -} - -DEFUN(cfg_trunk_omit_rtcp, - cfg_trunk_omit_rtcp_cmd, - "rtcp-omit", - RTCP_OMIT_STR) -{ - struct mgcp_trunk_config *trunk = vty->index; - trunk->omit_rtcp = 1; - return CMD_SUCCESS; -} - -DEFUN(cfg_trunk_no_omit_rtcp, - cfg_trunk_no_omit_rtcp_cmd, - "no rtcp-omit", - NO_STR RTCP_OMIT_STR) -{ - struct mgcp_trunk_config *trunk = vty->index; - trunk->omit_rtcp = 0; - return CMD_SUCCESS; -} - -DEFUN(cfg_trunk_patch_rtp_ssrc, - cfg_trunk_patch_rtp_ssrc_cmd, - "rtp-patch ssrc", - RTP_PATCH_STR - "Force a fixed SSRC\n" - ) -{ - struct mgcp_trunk_config *trunk = vty->index; - trunk->force_constant_ssrc = 1; - return CMD_SUCCESS; -} - -DEFUN(cfg_trunk_no_patch_rtp_ssrc, - cfg_trunk_no_patch_rtp_ssrc_cmd, - "no rtp-patch ssrc", - NO_STR RTP_PATCH_STR - "Force a fixed SSRC\n" - ) -{ - struct mgcp_trunk_config *trunk = vty->index; - trunk->force_constant_ssrc = 0; - return CMD_SUCCESS; -} - -DEFUN(cfg_trunk_patch_rtp_ts, - cfg_trunk_patch_rtp_ts_cmd, - "rtp-patch timestamp", - RTP_PATCH_STR - "Adjust RTP timestamp\n" - ) -{ - struct mgcp_trunk_config *trunk = vty->index; - trunk->force_aligned_timing = 1; - return CMD_SUCCESS; -} - -DEFUN(cfg_trunk_no_patch_rtp_ts, - cfg_trunk_no_patch_rtp_ts_cmd, - "no rtp-patch timestamp", - NO_STR RTP_PATCH_STR - "Adjust RTP timestamp\n" - ) -{ - struct mgcp_trunk_config *trunk = vty->index; - trunk->force_aligned_timing = 0; - return CMD_SUCCESS; -} - -DEFUN(cfg_trunk_no_patch_rtp, - cfg_trunk_no_patch_rtp_cmd, - "no rtp-patch", - NO_STR RTP_PATCH_STR) -{ - struct mgcp_trunk_config *trunk = vty->index; - trunk->force_constant_ssrc = 0; - trunk->force_aligned_timing = 0; - return CMD_SUCCESS; -} - -DEFUN(cfg_trunk_rtp_keepalive, - cfg_trunk_rtp_keepalive_cmd, - "rtp keep-alive <1-120>", - RTP_STR RTP_KEEPALIVE_STR - "Keep-alive interval in secs\n" - ) -{ - struct mgcp_trunk_config *trunk = vty->index; - mgcp_trunk_set_keepalive(trunk, atoi(argv[0])); - return CMD_SUCCESS; -} - -DEFUN(cfg_trunk_rtp_keepalive_once, - cfg_trunk_rtp_keepalive_once_cmd, - "rtp keep-alive once", - RTP_STR RTP_KEEPALIVE_STR - "Send dummy packet only once after CRCX/MDCX\n" - ) -{ - struct mgcp_trunk_config *trunk = vty->index; - mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE); - return CMD_SUCCESS; -} - -DEFUN(cfg_trunk_no_rtp_keepalive, - cfg_trunk_no_rtp_keepalive_cmd, - "no rtp keep-alive", - NO_STR RTP_STR RTP_KEEPALIVE_STR - ) -{ - struct mgcp_trunk_config *trunk = vty->index; - mgcp_trunk_set_keepalive(trunk, 0); - return CMD_SUCCESS; -} - -DEFUN(cfg_trunk_allow_transcoding, - cfg_trunk_allow_transcoding_cmd, - "allow-transcoding", - "Allow transcoding\n") -{ - struct mgcp_trunk_config *trunk = vty->index; - trunk->no_audio_transcoding = 0; - return CMD_SUCCESS; -} - -DEFUN(cfg_trunk_no_allow_transcoding, - cfg_trunk_no_allow_transcoding_cmd, - "no allow-transcoding", - NO_STR "Allow transcoding\n") -{ - struct mgcp_trunk_config *trunk = vty->index; - trunk->no_audio_transcoding = 1; - return CMD_SUCCESS; -} - -DEFUN(loop_endp, - loop_endp_cmd, - "loop-endpoint <0-64> NAME (0|1)", - "Loop a given endpoint\n" "Trunk number\n" - "The name in hex of the endpoint\n" "Disable the loop\n" "Enable the loop\n") -{ - struct mgcp_trunk_config *trunk; - struct mgcp_endpoint *endp; - - trunk = find_trunk(g_cfg, atoi(argv[0])); - if (!trunk) { - vty_out(vty, "%%Trunk %d not found in the config.%s", - atoi(argv[0]), VTY_NEWLINE); - return CMD_WARNING; - } - - if (!trunk->endpoints) { - vty_out(vty, "%%Trunk %d has no endpoints allocated.%s", - trunk->trunk_nr, VTY_NEWLINE); - return CMD_WARNING; - } - - int endp_no = strtoul(argv[1], NULL, 16); - if (endp_no < 1 || endp_no >= trunk->number_endpoints) { - vty_out(vty, "Loopback number %s/%d is invalid.%s", - argv[1], endp_no, VTY_NEWLINE); - return CMD_WARNING; - } - - - endp = &trunk->endpoints[endp_no]; - int loop = atoi(argv[2]); - - if (loop) - endp->conn_mode = MGCP_CONN_LOOPBACK; - else - endp->conn_mode = endp->orig_mode; - - /* Handle it like a MDCX, switch on SSRC patching if enabled */ - mgcp_rtp_end_config(endp, 1, &endp->bts_end); - mgcp_rtp_end_config(endp, 1, &endp->net_end); - - return CMD_SUCCESS; -} - -DEFUN(tap_call, - tap_call_cmd, - "tap-call <0-64> ENDPOINT (bts-in|bts-out|net-in|net-out) A.B.C.D <0-65534>", - "Forward data on endpoint to a different system\n" "Trunk number\n" - "The endpoint in hex\n" - "Forward the data coming from the bts\n" - "Forward the data coming from the bts leaving to the network\n" - "Forward the data coming from the net\n" - "Forward the data coming from the net leaving to the bts\n" - "destination IP of the data\n" "destination port\n") -{ - struct mgcp_rtp_tap *tap; - struct mgcp_trunk_config *trunk; - struct mgcp_endpoint *endp; - int port = 0; - - trunk = find_trunk(g_cfg, atoi(argv[0])); - if (!trunk) { - vty_out(vty, "%%Trunk %d not found in the config.%s", - atoi(argv[0]), VTY_NEWLINE); - return CMD_WARNING; - } - - if (!trunk->endpoints) { - vty_out(vty, "%%Trunk %d has no endpoints allocated.%s", - trunk->trunk_nr, VTY_NEWLINE); - return CMD_WARNING; - } - - int endp_no = strtoul(argv[1], NULL, 16); - if (endp_no < 1 || endp_no >= trunk->number_endpoints) { - vty_out(vty, "Endpoint number %s/%d is invalid.%s", - argv[1], endp_no, VTY_NEWLINE); - return CMD_WARNING; - } - - endp = &trunk->endpoints[endp_no]; - - if (strcmp(argv[2], "bts-in") == 0) { - port = MGCP_TAP_BTS_IN; - } else if (strcmp(argv[2], "bts-out") == 0) { - port = MGCP_TAP_BTS_OUT; - } else if (strcmp(argv[2], "net-in") == 0) { - port = MGCP_TAP_NET_IN; - } else if (strcmp(argv[2], "net-out") == 0) { - port = MGCP_TAP_NET_OUT; - } else { - vty_out(vty, "Unknown mode... tricked vty?%s", VTY_NEWLINE); - return CMD_WARNING; - } - - tap = &endp->taps[port]; - memset(&tap->forward, 0, sizeof(tap->forward)); - inet_aton(argv[3], &tap->forward.sin_addr); - tap->forward.sin_port = htons(atoi(argv[4])); - tap->enabled = 1; - return CMD_SUCCESS; -} - -DEFUN(free_endp, free_endp_cmd, - "free-endpoint <0-64> NUMBER", - "Free the given endpoint\n" "Trunk number\n" - "Endpoint number in hex.\n") -{ - struct mgcp_trunk_config *trunk; - struct mgcp_endpoint *endp; - - trunk = find_trunk(g_cfg, atoi(argv[0])); - if (!trunk) { - vty_out(vty, "%%Trunk %d not found in the config.%s", - atoi(argv[0]), VTY_NEWLINE); - return CMD_WARNING; - } - - if (!trunk->endpoints) { - vty_out(vty, "%%Trunk %d has no endpoints allocated.%s", - trunk->trunk_nr, VTY_NEWLINE); - return CMD_WARNING; - } - - int endp_no = strtoul(argv[1], NULL, 16); - if (endp_no < 1 || endp_no >= trunk->number_endpoints) { - vty_out(vty, "Endpoint number %s/%d is invalid.%s", - argv[1], endp_no, VTY_NEWLINE); - return CMD_WARNING; - } - - endp = &trunk->endpoints[endp_no]; - mgcp_release_endp(endp); - return CMD_SUCCESS; -} - -DEFUN(reset_endp, reset_endp_cmd, - "reset-endpoint <0-64> NUMBER", - "Reset the given endpoint\n" "Trunk number\n" - "Endpoint number in hex.\n") -{ - struct mgcp_trunk_config *trunk; - struct mgcp_endpoint *endp; - int endp_no, rc; - - trunk = find_trunk(g_cfg, atoi(argv[0])); - if (!trunk) { - vty_out(vty, "%%Trunk %d not found in the config.%s", - atoi(argv[0]), VTY_NEWLINE); - return CMD_WARNING; - } - - if (!trunk->endpoints) { - vty_out(vty, "%%Trunk %d has no endpoints allocated.%s", - trunk->trunk_nr, VTY_NEWLINE); - return CMD_WARNING; - } - - endp_no = strtoul(argv[1], NULL, 16); - if (endp_no < 1 || endp_no >= trunk->number_endpoints) { - vty_out(vty, "Endpoint number %s/%d is invalid.%s", - argv[1], endp_no, VTY_NEWLINE); - return CMD_WARNING; - } - - endp = &trunk->endpoints[endp_no]; - rc = mgcp_send_reset_ep(endp, ENDPOINT_NUMBER(endp)); - if (rc < 0) { - vty_out(vty, "Error %d sending reset.%s", rc, VTY_NEWLINE); - return CMD_WARNING; - } - return CMD_SUCCESS; -} - -DEFUN(reset_all_endp, reset_all_endp_cmd, - "reset-all-endpoints", - "Reset all endpoints\n") -{ - int rc; - - rc = mgcp_send_reset_all(g_cfg); - if (rc < 0) { - vty_out(vty, "Error %d during endpoint reset.%s", - rc, VTY_NEWLINE); - return CMD_WARNING; - } - return CMD_SUCCESS; -} - -#define OSMUX_STR "RTP multiplexing\n" -DEFUN(cfg_mgcp_osmux, - cfg_mgcp_osmux_cmd, - "osmux (on|off|only)", - OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n") -{ - if (strcmp(argv[0], "off") == 0) { - g_cfg->osmux = OSMUX_USAGE_OFF; - return CMD_SUCCESS; - } - - if (strcmp(argv[0], "on") == 0) - g_cfg->osmux = OSMUX_USAGE_ON; - else if (strcmp(argv[0], "only") == 0) - g_cfg->osmux = OSMUX_USAGE_ONLY; - - if (g_cfg->trunk.audio_loop) { - vty_out(vty, "Cannot use `loop' with `osmux'.%s", - VTY_NEWLINE); - return CMD_WARNING; - } - - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_osmux_ip, - cfg_mgcp_osmux_ip_cmd, - "osmux bind-ip A.B.C.D", - OSMUX_STR IP_STR "IPv4 Address to bind to\n") -{ - osmo_talloc_replace_string(g_cfg, &g_cfg->osmux_addr, argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_osmux_batch_factor, - cfg_mgcp_osmux_batch_factor_cmd, - "osmux batch-factor <1-8>", - OSMUX_STR "Batching factor\n" "Number of messages in the batch\n") -{ - g_cfg->osmux_batch = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_osmux_batch_size, - cfg_mgcp_osmux_batch_size_cmd, - "osmux batch-size <1-65535>", - OSMUX_STR "batch size\n" "Batch size in bytes\n") -{ - g_cfg->osmux_batch_size = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_osmux_port, - cfg_mgcp_osmux_port_cmd, - "osmux port <1-65535>", - OSMUX_STR "port\n" "UDP port\n") -{ - g_cfg->osmux_port = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_osmux_dummy, - cfg_mgcp_osmux_dummy_cmd, - "osmux dummy (on|off)", - OSMUX_STR "Dummy padding\n" "Enable dummy padding\n" "Disable dummy padding\n") -{ - if (strcmp(argv[0], "on") == 0) - g_cfg->osmux_dummy = 1; - else if (strcmp(argv[0], "off") == 0) - g_cfg->osmux_dummy = 0; - - return CMD_SUCCESS; -} - -#define DEJITTER_STR "Uplink Jitter Buffer" -DEFUN(cfg_mgcp_bts_use_jibuf, - cfg_mgcp_bts_use_jibuf_cmd, - "bts-jitter-buffer", - DEJITTER_STR "\n") -{ - g_cfg->bts_use_jibuf = true; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_no_bts_use_jibuf, - cfg_mgcp_no_bts_use_jibuf_cmd, - "no bts-jitter-buffer", - NO_STR DEJITTER_STR "\n") -{ - g_cfg->bts_use_jibuf = false; - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_bts_jitter_delay_min, - cfg_mgcp_bts_jitter_delay_min_cmd, - "bts-jitter-buffer-delay-min <1-65535>", - DEJITTER_STR " Minimum Delay in ms\n" "Minimum Delay in ms\n") -{ - g_cfg->bts_jitter_delay_min = atoi(argv[0]); - if (!g_cfg->bts_jitter_delay_min) { - vty_out(vty, "bts-jitter-buffer-delay-min cannot be zero.%s", VTY_NEWLINE); - return CMD_WARNING; - } - if (g_cfg->bts_jitter_delay_min && g_cfg->bts_jitter_delay_max && - g_cfg->bts_jitter_delay_min > g_cfg->bts_jitter_delay_max) { - vty_out(vty, "bts-jitter-buffer-delay-min cannot be bigger than " \ - "bts-jitter-buffer-delay-max.%s", VTY_NEWLINE); - return CMD_WARNING; - } - return CMD_SUCCESS; -} - -DEFUN(cfg_mgcp_bts_jitter_delay_max, - cfg_mgcp_bts_jitter_delay_max_cmd, - "bts-jitter-buffer-delay-max <1-65535>", - DEJITTER_STR " Maximum Delay in ms\n" "Maximum Delay in ms\n") -{ - g_cfg->bts_jitter_delay_max = atoi(argv[0]); - if (!g_cfg->bts_jitter_delay_max) { - vty_out(vty, "bts-jitter-buffer-delay-max cannot be zero.%s", VTY_NEWLINE); - return CMD_WARNING; - } - if (g_cfg->bts_jitter_delay_min && g_cfg->bts_jitter_delay_max && - g_cfg->bts_jitter_delay_min > g_cfg->bts_jitter_delay_max) { - vty_out(vty, "bts-jitter-buffer-delay-max cannot be smaller than " \ - "bts-jitter-buffer-delay-min.%s", VTY_NEWLINE); - return CMD_WARNING; - } - return CMD_SUCCESS; -} - -int mgcp_vty_init(void) -{ - install_element_ve(&show_mgcp_cmd); - install_element(ENABLE_NODE, &loop_endp_cmd); - install_element(ENABLE_NODE, &tap_call_cmd); - install_element(ENABLE_NODE, &free_endp_cmd); - install_element(ENABLE_NODE, &reset_endp_cmd); - install_element(ENABLE_NODE, &reset_all_endp_cmd); - - install_element(CONFIG_NODE, &cfg_mgcp_cmd); - install_node(&mgcp_node, config_write_mgcp); - - install_element(MGCP_NODE, &cfg_mgcp_local_ip_cmd); - install_element(MGCP_NODE, &cfg_mgcp_bts_ip_cmd); - install_element(MGCP_NODE, &cfg_mgcp_bind_ip_cmd); - install_element(MGCP_NODE, &cfg_mgcp_bind_port_cmd); - install_element(MGCP_NODE, &cfg_mgcp_bind_early_cmd); - install_element(MGCP_NODE, &cfg_mgcp_rtp_base_port_cmd); - install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_base_port_cmd); - install_element(MGCP_NODE, &cfg_mgcp_rtp_net_base_port_cmd); - install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_range_cmd); - install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_bind_ip_cmd); - install_element(MGCP_NODE, &cfg_mgcp_rtp_no_bts_bind_ip_cmd); - install_element(MGCP_NODE, &cfg_mgcp_rtp_net_range_cmd); - install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_cmd); - install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_cmd); - install_element(MGCP_NODE, &cfg_mgcp_rtp_transcoder_range_cmd); - install_element(MGCP_NODE, &cfg_mgcp_rtp_transcoder_base_cmd); - install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd); - install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_tos_cmd); - install_element(MGCP_NODE, &cfg_mgcp_rtp_force_ptime_cmd); - install_element(MGCP_NODE, &cfg_mgcp_no_rtp_force_ptime_cmd); - install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_cmd); - install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_once_cmd); - install_element(MGCP_NODE, &cfg_mgcp_no_rtp_keepalive_cmd); - install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd); - install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd_old); - install_element(MGCP_NODE, &cfg_mgcp_transcoder_cmd); - install_element(MGCP_NODE, &cfg_mgcp_no_transcoder_cmd); - install_element(MGCP_NODE, &cfg_mgcp_transcoder_remote_base_cmd); - install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd); - install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd); - install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd_old); - install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd_old); - install_element(MGCP_NODE, &cfg_mgcp_loop_cmd); - install_element(MGCP_NODE, &cfg_mgcp_force_realloc_cmd); - install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd); - install_element(MGCP_NODE, &cfg_mgcp_omit_rtcp_cmd); - install_element(MGCP_NODE, &cfg_mgcp_no_omit_rtcp_cmd); - install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ssrc_cmd); - install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ssrc_cmd); - install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ts_cmd); - install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ts_cmd); - install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_cmd); - install_element(MGCP_NODE, &cfg_mgcp_sdp_fmtp_extra_cmd); - install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_ptime_cmd); - install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_ptime_cmd); - install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_name_cmd); - install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_name_cmd); - install_element(MGCP_NODE, &cfg_mgcp_osmux_cmd); - install_element(MGCP_NODE, &cfg_mgcp_osmux_ip_cmd); - install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_factor_cmd); - install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_size_cmd); - install_element(MGCP_NODE, &cfg_mgcp_osmux_port_cmd); - install_element(MGCP_NODE, &cfg_mgcp_osmux_dummy_cmd); - install_element(MGCP_NODE, &cfg_mgcp_allow_transcoding_cmd); - install_element(MGCP_NODE, &cfg_mgcp_no_allow_transcoding_cmd); - install_element(MGCP_NODE, &cfg_mgcp_bts_use_jibuf_cmd); - install_element(MGCP_NODE, &cfg_mgcp_no_bts_use_jibuf_cmd); - install_element(MGCP_NODE, &cfg_mgcp_bts_jitter_delay_min_cmd); - install_element(MGCP_NODE, &cfg_mgcp_bts_jitter_delay_max_cmd); - - - install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd); - install_node(&trunk_node, config_write_trunk); - install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_cmd); - install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_once_cmd); - install_element(TRUNK_NODE, &cfg_trunk_no_rtp_keepalive_cmd); - install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd); - install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd); - install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd_old); - install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd_old); - install_element(TRUNK_NODE, &cfg_trunk_loop_cmd); - install_element(TRUNK_NODE, &cfg_trunk_omit_rtcp_cmd); - install_element(TRUNK_NODE, &cfg_trunk_no_omit_rtcp_cmd); - install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ssrc_cmd); - install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ssrc_cmd); - install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ts_cmd); - install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ts_cmd); - install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_cmd); - install_element(TRUNK_NODE, &cfg_trunk_sdp_fmtp_extra_cmd); - install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_ptime_cmd); - install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_ptime_cmd); - install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_name_cmd); - install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_name_cmd); - install_element(TRUNK_NODE, &cfg_trunk_allow_transcoding_cmd); - install_element(TRUNK_NODE, &cfg_trunk_no_allow_transcoding_cmd); - - return 0; -} - -static int allocate_trunk(struct mgcp_trunk_config *trunk) -{ - int i; - struct mgcp_config *cfg = trunk->cfg; - - if (mgcp_endpoints_allocate(trunk) != 0) { - LOGP(DLMGCP, LOGL_ERROR, - "Failed to allocate %d endpoints on trunk %d.\n", - trunk->number_endpoints, trunk->trunk_nr); - return -1; - } - - /* early bind */ - for (i = 1; i < trunk->number_endpoints; ++i) { - struct mgcp_endpoint *endp = &trunk->endpoints[i]; - - if (cfg->bts_ports.mode == PORT_ALLOC_STATIC) { - cfg->last_bts_port += 2; - if (mgcp_bind_bts_rtp_port(endp, cfg->last_bts_port) != 0) { - LOGP(DLMGCP, LOGL_FATAL, - "Failed to bind: %d\n", cfg->last_bts_port); - return -1; - } - endp->bts_end.local_alloc = PORT_ALLOC_STATIC; - } - - if (cfg->net_ports.mode == PORT_ALLOC_STATIC) { - cfg->last_net_port += 2; - if (mgcp_bind_net_rtp_port(endp, cfg->last_net_port) != 0) { - LOGP(DLMGCP, LOGL_FATAL, - "Failed to bind: %d\n", cfg->last_net_port); - return -1; - } - endp->net_end.local_alloc = PORT_ALLOC_STATIC; - } - - if (trunk->trunk_type == MGCP_TRUNK_VIRTUAL && - cfg->transcoder_ip && cfg->transcoder_ports.mode == PORT_ALLOC_STATIC) { - int rtp_port; - - /* network side */ - rtp_port = rtp_calculate_port(ENDPOINT_NUMBER(endp), - cfg->transcoder_ports.base_port); - if (mgcp_bind_trans_net_rtp_port(endp, rtp_port) != 0) { - LOGP(DLMGCP, LOGL_FATAL, "Failed to bind: %d\n", rtp_port); - return -1; - } - endp->trans_net.local_alloc = PORT_ALLOC_STATIC; - - /* bts side */ - rtp_port = rtp_calculate_port(endp_back_channel(ENDPOINT_NUMBER(endp)), - cfg->transcoder_ports.base_port); - if (mgcp_bind_trans_bts_rtp_port(endp, rtp_port) != 0) { - LOGP(DLMGCP, LOGL_FATAL, "Failed to bind: %d\n", rtp_port); - return -1; - } - endp->trans_bts.local_alloc = PORT_ALLOC_STATIC; - } - } - - return 0; -} - -int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg, - enum mgcp_role role) -{ - int rc; - struct mgcp_trunk_config *trunk; - - cfg->osmux_port = OSMUX_PORT; - cfg->osmux_batch = 4; - cfg->osmux_batch_size = OSMUX_BATCH_DEFAULT_MAX; - - g_cfg = cfg; - rc = vty_read_config_file(config_file, NULL); - if (rc < 0) { - fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file); - return rc; - } - - - if (!g_cfg->bts_ip) - fprintf(stderr, "No BTS ip address specified. This will allow everyone to connect.\n"); - - if (!g_cfg->source_addr) { - fprintf(stderr, "You need to specify a bind address.\n"); - return -1; - } - - /* initialize the last ports */ - g_cfg->last_bts_port = rtp_calculate_port(0, g_cfg->bts_ports.base_port); - g_cfg->last_net_port = rtp_calculate_port(0, g_cfg->net_ports.base_port); - - if (allocate_trunk(&g_cfg->trunk) != 0) { - LOGP(DLMGCP, LOGL_ERROR, "Failed to initialize the virtual trunk.\n"); - return -1; - } - - llist_for_each_entry(trunk, &g_cfg->trunks, entry) { - if (allocate_trunk(trunk) != 0) { - LOGP(DLMGCP, LOGL_ERROR, - "Failed to initialize E1 trunk %d.\n", trunk->trunk_nr); - return -1; - } - } - cfg->role = role; - - return 0; -} - diff --git a/src/osmo-bsc_mgcp/Makefile.am b/src/osmo-bsc_mgcp/Makefile.am deleted file mode 100644 index e8a6f468c..000000000 --- a/src/osmo-bsc_mgcp/Makefile.am +++ /dev/null @@ -1,31 +0,0 @@ -AM_CPPFLAGS = \ - $(all_includes) \ - -I$(top_srcdir)/include \ - -I$(top_builddir) \ - $(NULL) - -AM_CFLAGS = \ - -Wall \ - $(LIBOSMOCORE_CFLAGS) \ - $(LIBOSMOVTY_CFLAGS) \ - $(LIBOSMONETIF_CFLAGS) \ - $(LIBBCG729_CFLAGS) \ - $(COVERAGE_CFLAGS) \ - $(NULL) - -bin_PROGRAMS = \ - osmo-bsc_mgcp \ - $(NULL) - -osmo_bsc_mgcp_SOURCES = \ - mgcp_main.c \ - $(NULL) - -osmo_bsc_mgcp_LDADD = \ - $(top_builddir)/src/libosmo-legacy-mgcp/libosmo-legacy-mgcp.la \ - $(LIBOSMOCORE_LIBS) \ - $(LIBOSMOVTY_LIBS) \ - $(LIBOSMONETIF_LIBS) \ - $(LIBBCG729_LIBS) \ - $(LIBRARY_GSM) \ - $(NULL) diff --git a/src/osmo-bsc_mgcp/mgcp_main.c b/src/osmo-bsc_mgcp/mgcp_main.c deleted file mode 100644 index edb19a61f..000000000 --- a/src/osmo-bsc_mgcp/mgcp_main.c +++ /dev/null @@ -1,351 +0,0 @@ -/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */ -/* The main method to drive it as a standalone process */ - -/* - * (C) 2009-2011 by Holger Hans Peter Freyther - * (C) 2009-2011 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../../bscconfig.h" - -#ifdef BUILD_MGCP_TRANSCODING -#include -#endif - -#define _GNU_SOURCE -#include - -#warning "Make use of the rtp proxy code" - -static struct mgcp_config *cfg; -static struct mgcp_trunk_config *reset_trunk; -static int reset_endpoints = 0; -static int daemonize = 0; - -const char *openbsc_copyright = - "Copyright (C) 2009-2010 Holger Freyther and On-Waves\r\n" - "Contributions by Daniel Willmann, Jan Lübbe, Stefan Schmidt\r\n" - "Dieter Spaar, Andreas Eversberg, Harald Welte\r\n\r\n" - "License AGPLv3+: GNU AGPL version 3 or later \r\n" - "This is free software: you are free to change and redistribute it.\r\n" - "There is NO WARRANTY, to the extent permitted by law.\r\n"; - -static char *config_file = "mgcp.cfg"; - -/* used by msgb and mgcp */ -void *tall_bsc_ctx = NULL; - -static void print_help() -{ - printf("Some useful help...\n"); - printf(" -h --help is printing this text.\n"); - printf(" -c --config-file filename The config file to use.\n"); - printf(" -s --disable-color\n"); - printf(" -D --daemonize Fork the process into a background daemon\n"); - printf(" -V --version Print the version number\n"); -} - -static void handle_options(int argc, char **argv) -{ - while (1) { - int option_index = 0, c; - static struct option long_options[] = { - {"help", 0, 0, 'h'}, - {"config-file", 1, 0, 'c'}, - {"daemonize", 0, 0, 'D'}, - {"version", 0, 0, 'V'}, - {"disable-color", 0, 0, 's'}, - {0, 0, 0, 0}, - }; - - c = getopt_long(argc, argv, "hc:VD", long_options, &option_index); - - if (c == -1) - break; - - switch(c) { - case 'h': - print_help(); - exit(0); - break; - case 'c': - config_file = talloc_strdup(tall_bsc_ctx, optarg); - break; - case 's': - log_set_use_color(osmo_stderr_target, 0); - break; - case 'V': - print_version(1); - exit(0); - break; - case 'D': - daemonize = 1; - break; - default: - /* ignore */ - break; - }; - } -} - -/* simply remember this */ -static int mgcp_rsip_cb(struct mgcp_trunk_config *tcfg) -{ - reset_endpoints = 1; - reset_trunk = tcfg; - - return 0; -} - -static int read_call_agent(struct osmo_fd *fd, unsigned int what) -{ - struct sockaddr_in addr; - socklen_t slen = sizeof(addr); - struct msgb *msg; - struct msgb *resp; - int i; - - msg = (struct msgb *) fd->data; - - /* read one less so we can use it as a \0 */ - int rc = recvfrom(cfg->gw_fd.bfd.fd, msg->data, msg->data_len - 1, 0, - (struct sockaddr *) &addr, &slen); - if (rc < 0) { - perror("Gateway failed to read"); - return -1; - } else if (slen > sizeof(addr)) { - fprintf(stderr, "Gateway received message from outerspace: %zu %zu\n", - (size_t) slen, sizeof(addr)); - return -1; - } - - /* handle message now */ - msg->l2h = msgb_put(msg, rc); - resp = mgcp_handle_message(cfg, msg); - msgb_reset(msg); - - if (resp) { - sendto(cfg->gw_fd.bfd.fd, resp->l2h, msgb_l2len(resp), 0, (struct sockaddr *) &addr, sizeof(addr)); - msgb_free(resp); - } - - if (reset_endpoints) { - LOGP(DLMGCP, LOGL_NOTICE, - "Asked to reset endpoints: %d/%d\n", - reset_trunk->trunk_nr, reset_trunk->trunk_type); - reset_endpoints = 0; - - /* is checking in_addr.s_addr == INADDR_LOOPBACK making it more secure? */ - for (i = 1; i < reset_trunk->number_endpoints; ++i) - mgcp_release_endp(&reset_trunk->endpoints[i]); - } - - return 0; -} - -int mgcp_vty_is_config_node(struct vty *vty, int node) -{ - switch (node) { - case CONFIG_NODE: - return 0; - - default: - return 1; - } -} - -int mgcp_vty_go_parent(struct vty *vty) -{ - switch (vty->node) { - case TRUNK_NODE: - vty->node = MGCP_NODE; - vty->index = NULL; - break; - case MGCP_NODE: - default: - if (mgcp_vty_is_config_node(vty, vty->node)) - vty->node = CONFIG_NODE; - else - vty->node = ENABLE_NODE; - - vty->index = NULL; - } - - return vty->node; -} - - -static struct vty_app_info vty_info = { - .name = "OpenBSC MGCP", - .version = PACKAGE_VERSION, - .go_parent_cb = mgcp_vty_go_parent, - .is_config_node = mgcp_vty_is_config_node, -}; - -static const struct log_info_cat log_categories[] = { - /* DLMGCP is provided by the MGCP library */ -}; - -const struct log_info log_info = { - .cat = log_categories, - .num_cat = ARRAY_SIZE(log_categories), -}; - -int main(int argc, char **argv) -{ - struct sockaddr_in addr; - int on = 1, rc; - - tall_bsc_ctx = talloc_named_const(NULL, 1, "mgcp-callagent"); - msgb_talloc_ctx_init(tall_bsc_ctx, 0); - - osmo_init_ignore_signals(); - osmo_init_logging2(tall_bsc_ctx, &log_info); - - cfg = mgcp_config_alloc(); - if (!cfg) - return -1; - -#ifdef BUILD_MGCP_TRANSCODING - cfg->setup_rtp_processing_cb = &mgcp_transcoding_setup; - cfg->rtp_processing_cb = &mgcp_transcoding_process_rtp; - cfg->get_net_downlink_format_cb = &mgcp_transcoding_net_downlink_format; -#endif - - cfg->trunk.force_realloc = 1; - - vty_info.copyright = openbsc_copyright; - vty_init(&vty_info); - logging_vty_add_cmds(NULL); - osmo_stats_vty_add_cmds(&log_info); - mgcp_vty_init(); - - handle_options(argc, argv); - - rate_ctr_init(tall_bsc_ctx); - osmo_stats_init(tall_bsc_ctx); - - rc = mgcp_parse_config(config_file, cfg, MGCP_BSC); - if (rc < 0) - return rc; - - /* start telnet after reading config for vty_get_bind_addr() */ - rc = telnet_init_dynif(tall_bsc_ctx, NULL, - vty_get_bind_addr(), OSMO_VTY_PORT_BSC_MGCP); - if (rc < 0) - return rc; - - /* set some callbacks */ - cfg->reset_cb = mgcp_rsip_cb; - - /* we need to bind a socket */ - if (rc == 0) { - cfg->gw_fd.bfd.when = BSC_FD_READ; - cfg->gw_fd.bfd.cb = read_call_agent; - cfg->gw_fd.bfd.fd = socket(AF_INET, SOCK_DGRAM, 0); - if (cfg->gw_fd.bfd.fd < 0) { - perror("Gateway failed to listen"); - return -1; - } - - setsockopt(cfg->gw_fd.bfd.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(cfg->source_port); - inet_aton(cfg->source_addr, &addr.sin_addr); - - if (bind(cfg->gw_fd.bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("Gateway failed to bind"); - return -1; - } - - cfg->gw_fd.bfd.data = msgb_alloc(4096, "mgcp-msg"); - if (!cfg->gw_fd.bfd.data) { - fprintf(stderr, "Gateway memory error.\n"); - return -1; - } - - if (cfg->call_agent_addr) { - addr.sin_port = htons(2727); - inet_aton(cfg->call_agent_addr, &addr.sin_addr); - if (connect(cfg->gw_fd.bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - LOGP(DLMGCP, LOGL_ERROR, "Failed to connect to: '%s'. errno: %d\n", - cfg->call_agent_addr, errno); - close(cfg->gw_fd.bfd.fd); - cfg->gw_fd.bfd.fd = -1; - return -1; - } - } - - if (osmo_fd_register(&cfg->gw_fd.bfd) != 0) { - LOGP(DLMGCP, LOGL_FATAL, "Failed to register the fd\n"); - return -1; - } - - LOGP(DLMGCP, LOGL_NOTICE, "Configured for MGCP.\n"); - } - - /* initialisation */ - srand(time(NULL)); - - if (daemonize) { - rc = osmo_daemonize(); - if (rc < 0) { - perror("Error during daemonize"); - exit(1); - } - } - - /* main loop */ - while (1) { - osmo_select_main(0); - } - - - return 0; -} diff --git a/tests/Makefile.am b/tests/Makefile.am index 2eed271ef..49a659fc8 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,5 +1,4 @@ SUBDIRS = \ - legacy_mgcp \ mgcp_client \ mgcp \ $(NULL) @@ -26,7 +25,6 @@ EXTRA_DIST = \ testsuite.at \ $(srcdir)/package.m4 \ $(TESTSUITE) \ - vty_test_runner.py \ $(NULL) TESTSUITE = $(srcdir)/testsuite @@ -39,7 +37,6 @@ if ENABLE_EXT_TESTS python-tests: $(BUILT_SOURCES) osmotestvty.py -p $(abs_top_srcdir) -w $(abs_top_builddir) -v osmotestconfig.py -p $(abs_top_srcdir) -w $(abs_top_builddir) -v - $(PYTHON) $(srcdir)/vty_test_runner.py -w $(abs_top_builddir) -v else python-tests: $(BUILT_SOURCES) echo "Not running python-based tests (determined at configure-time)" diff --git a/tests/atlocal.in b/tests/atlocal.in index 362bfa9df..1d2ebee93 100644 --- a/tests/atlocal.in +++ b/tests/atlocal.in @@ -1,7 +1,6 @@ enable_nat_test='@osmo_ac_build_nat@' enable_smpp_test='@osmo_ac_build_smpp@' enable_bsc_test='@osmo_ac_build_bsc@' -enable_mgcp_transcoding_test='@osmo_ac_mgcp_transcoding@' enable_sgsn_test='@found_libgtp_and_libcares@' enable_oap_test='@found_libgtp_and_libcares@' enable_gtphub_test='@found_libgtp_and_libcares@' diff --git a/tests/legacy_mgcp/Makefile.am b/tests/legacy_mgcp/Makefile.am deleted file mode 100644 index f04312486..000000000 --- a/tests/legacy_mgcp/Makefile.am +++ /dev/null @@ -1,61 +0,0 @@ -AM_CPPFLAGS = \ - $(all_includes) \ - -I$(top_srcdir)/include \ - -I$(top_srcdir) \ - $(NULL) - -AM_CFLAGS = \ - -Wall \ - -ggdb3 \ - $(LIBOSMOCORE_CFLAGS) \ - $(LIBOSMONETIF_CFLAGS) \ - $(LIBBCG729_CFLAGS) \ - $(COVERAGE_CFLAGS) \ - $(NULL) - -AM_LDFLAGS = \ - $(COVERAGE_LDFLAGS) \ - $(NULL) - -EXTRA_DIST = \ - mgcp_test.ok \ - mgcp_transcoding_test.ok \ - $(NULL) - -noinst_PROGRAMS = \ - mgcp_test \ - $(NULL) -if BUILD_MGCP_TRANSCODING -noinst_PROGRAMS += \ - mgcp_transcoding_test \ - $(NULL) -endif - -mgcp_test_SOURCES = \ - mgcp_test.c \ - $(NULL) - -mgcp_test_LDADD = \ - $(top_builddir)/src/libosmo-legacy-mgcp/libosmo-legacy-mgcp.la \ - $(LIBOSMOCORE_LIBS) \ - $(LIBOSMOVTY_LIBS) \ - $(LIBRARY_DL) \ - $(LIBOSMONETIF_LIBS) \ - $(LIBRARY_GSM) \ - -lm \ - $(NULL) - -mgcp_transcoding_test_SOURCES = \ - mgcp_transcoding_test.c \ - $(NULL) - -mgcp_transcoding_test_LDADD = \ - $(top_builddir)/src/libosmo-legacy-mgcp/libosmo-legacy-mgcp.la \ - $(LIBOSMOCORE_LIBS) \ - $(LIBOSMOVTY_LIBS) \ - $(LIBBCG729_LIBS) \ - $(LIBRARY_DL) \ - $(LIBOSMONETIF_LIBS) \ - $(LIBRARY_GSM) \ - -lm \ - $(NULL) diff --git a/tests/legacy_mgcp/mgcp_test.c b/tests/legacy_mgcp/mgcp_test.c deleted file mode 100644 index 39400d4ad..000000000 --- a/tests/legacy_mgcp/mgcp_test.c +++ /dev/null @@ -1,1242 +0,0 @@ -/* - * (C) 2011-2012,2014 by Holger Hans Peter Freyther - * (C) 2011-2012,2014 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -#undef _GNU_SOURCE -#define _GNU_SOURCE - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -char *strline_r(char *str, char **saveptr); - -const char *strline_test_data = - "one CR\r" - "two CR\r" - "\r" - "one CRLF\r\n" - "two CRLF\r\n" - "\r\n" - "one LF\n" - "two LF\n" - "\n" - "mixed (4 lines)\r\r\n\n\r\n"; - -#define EXPECTED_NUMBER_OF_LINES 13 - -static void test_strline(void) -{ - char *save = NULL; - char *line; - char buf[2048]; - int counter = 0; - - osmo_strlcpy(buf, strline_test_data, sizeof(buf)); - - for (line = strline_r(buf, &save); line; - line = strline_r(NULL, &save)) { - printf("line: '%s'\n", line); - counter++; - } - - OSMO_ASSERT(counter == EXPECTED_NUMBER_OF_LINES); -} - -#define AUEP1 "AUEP 158663169 ds/e1-1/2@172.16.6.66 MGCP 1.0\r\n" -#define AUEP1_RET "200 158663169 OK\r\n" -#define AUEP2 "AUEP 18983213 ds/e1-2/1@172.16.6.66 MGCP 1.0\r\n" -#define AUEP2_RET "500 18983213 FAIL\r\n" -#define EMPTY "\r\n" -#define EMPTY_RET NULL -#define SHORT "CRCX \r\n" -#define SHORT_RET "510 000000 FAIL\r\n" - -#define MDCX_WRONG_EP "MDCX 18983213 ds/e1-3/1@172.16.6.66 MGCP 1.0\r\n" -#define MDCX_ERR_RET "510 18983213 FAIL\r\n" -#define MDCX_UNALLOCATED "MDCX 18983214 ds/e1-1/2@172.16.6.66 MGCP 1.0\r\n" -#define MDCX_RET "400 18983214 FAIL\r\n" -#define MDCX3 "MDCX 18983215 1@mgw MGCP 1.0\r\n" -#define MDCX3_RET "200 18983215 OK\r\n" \ - "I: 1\n" \ - "\n" \ - "v=0\r\n" \ - "o=- 1 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 0 RTP/AVP 126\r\n" \ - "a=rtpmap:126 AMR/8000\r\n" \ - "a=ptime:20\r\n" -#define MDCX3_FMTP_RET "200 18983215 OK\r\n" \ - "I: 3\n" \ - "\n" \ - "v=0\r\n" \ - "o=- 3 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 0 RTP/AVP 126\r\n" \ - "a=rtpmap:126 AMR/8000\r\n" \ - "a=fmtp:126 0/1/2\r\n" \ - "a=ptime:20\r\n" -#define MDCX4 "MDCX 18983216 1@mgw MGCP 1.0\r\n" \ - "M: sendrecv\r" \ - "C: 2\r\n" \ - "I: 1\r\n" \ - "L: p:20, a:AMR, nt:IN\r\n" \ - "\n" \ - "v=0\r\n" \ - "o=- 1 23 IN IP4 0.0.0.0\r\n" \ - "c=IN IP4 0.0.0.0\r\n" \ - "t=0 0\r\n" \ - "m=audio 4441 RTP/AVP 99\r\n" \ - "a=rtpmap:99 AMR/8000\r\n" \ - "a=ptime:40\r\n" -#define MDCX4_RET(Ident) "200 " Ident " OK\r\n" \ - "I: 1\n" \ - "\n" \ - "v=0\r\n" \ - "o=- 1 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 0 RTP/AVP 126\r\n" \ - "a=rtpmap:126 AMR/8000\r\n" \ - "a=ptime:20\r\n" - -#define MDCX4_PT1 "MDCX 18983217 1@mgw MGCP 1.0\r\n" \ - "M: sendrecv\r" \ - "C: 2\r\n" \ - "I: 1\r\n" \ - "L: p:20-40, a:AMR, nt:IN\r\n" \ - "\n" \ - "v=0\r\n" \ - "o=- 1 23 IN IP4 0.0.0.0\r\n" \ - "c=IN IP4 0.0.0.0\r\n" \ - "t=0 0\r\n" \ - "m=audio 4441 RTP/AVP 99\r\n" \ - "a=rtpmap:99 AMR/8000\r\n" \ - "a=ptime:40\r\n" - -#define MDCX4_PT2 "MDCX 18983218 1@mgw MGCP 1.0\r\n" \ - "M: sendrecv\r" \ - "C: 2\r\n" \ - "I: 1\r\n" \ - "L: p:20-20, a:AMR, nt:IN\r\n" \ - "\n" \ - "v=0\r\n" \ - "o=- 1 23 IN IP4 0.0.0.0\r\n" \ - "c=IN IP4 0.0.0.0\r\n" \ - "t=0 0\r\n" \ - "m=audio 4441 RTP/AVP 99\r\n" \ - "a=rtpmap:99 AMR/8000\r\n" \ - "a=ptime:40\r\n" - -#define MDCX4_PT3 "MDCX 18983219 1@mgw MGCP 1.0\r\n" \ - "M: sendrecv\r" \ - "C: 2\r\n" \ - "I: 1\r\n" \ - "L: a:AMR, nt:IN\r\n" \ - "\n" \ - "v=0\r\n" \ - "o=- 1 23 IN IP4 0.0.0.0\r\n" \ - "c=IN IP4 0.0.0.0\r\n" \ - "t=0 0\r\n" \ - "m=audio 4441 RTP/AVP 99\r\n" \ - "a=rtpmap:99 AMR/8000\r\n" \ - "a=ptime:40\r\n" - -#define MDCX4_SO "MDCX 18983220 1@mgw MGCP 1.0\r\n" \ - "M: sendonly\r" \ - "C: 2\r\n" \ - "I: 1\r\n" \ - "L: p:20, a:AMR, nt:IN\r\n" \ - "\n" \ - "v=0\r\n" \ - "o=- 1 23 IN IP4 0.0.0.0\r\n" \ - "c=IN IP4 0.0.0.0\r\n" \ - "t=0 0\r\n" \ - "m=audio 4441 RTP/AVP 99\r\n" \ - "a=rtpmap:99 AMR/8000\r\n" \ - "a=ptime:40\r\n" - -#define MDCX4_RO "MDCX 18983221 1@mgw MGCP 1.0\r\n" \ - "M: recvonly\r" \ - "C: 2\r\n" \ - "I: 1\r\n" \ - "L: p:20, a:AMR, nt:IN\r\n" - -#define SHORT2 "CRCX 1" -#define SHORT2_RET "510 000000 FAIL\r\n" -#define SHORT3 "CRCX 1 1@mgw" -#define SHORT4 "CRCX 1 1@mgw MGCP" -#define SHORT5 "CRCX 1 1@mgw MGCP 1.0" - -#define CRCX "CRCX 2 1@mgw MGCP 1.0\r\n" \ - "M: recvonly\r\n" \ - "C: 2\r\n" \ - "X\r\n" \ - "L: p:20\r\n" \ - "\r\n" \ - "v=0\r\n" \ - "c=IN IP4 123.12.12.123\r\n" \ - "m=audio 5904 RTP/AVP 97\r\n" \ - "a=rtpmap:97 GSM-EFR/8000\r\n" \ - "a=ptime:40\r\n" - -#define CRCX_RET "200 2 OK\r\n" \ - "I: 1\n" \ - "\n" \ - "v=0\r\n" \ - "o=- 1 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 0 RTP/AVP 126\r\n" \ - "a=rtpmap:126 AMR/8000\r\n" \ - "a=ptime:20\r\n" - -#define CRCX_RET_NO_RTPMAP "200 2 OK\r\n" \ - "I: 1\n" \ - "\n" \ - "v=0\r\n" \ - "o=- 1 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 0 RTP/AVP 126\r\n" \ - "a=ptime:20\r\n" - -#define CRCX_FMTP_RET "200 2 OK\r\n" \ - "I: 3\n" \ - "\n" \ - "v=0\r\n" \ - "o=- 3 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 0 RTP/AVP 126\r\n" \ - "a=rtpmap:126 AMR/8000\r\n" \ - "a=fmtp:126 0/1/2\r\n" \ - "a=ptime:20\r\n" - -#define CRCX_ZYN "CRCX 2 1@mgw MGCP 1.0\r" \ - "M: recvonly\r" \ - "C: 2\r\r" \ - "v=0\r" \ - "c=IN IP4 123.12.12.123\r" \ - "m=audio 5904 RTP/AVP 97\r" \ - "a=rtpmap:97 GSM-EFR/8000\r" - -#define CRCX_ZYN_RET "200 2 OK\r\n" \ - "I: 2\n" \ - "\n" \ - "v=0\r\n" \ - "o=- 2 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 0 RTP/AVP 126\r\n" \ - "a=rtpmap:126 AMR/8000\r\n" \ - "a=ptime:20\r\n" - -#define DLCX "DLCX 7 1@mgw MGCP 1.0\r\n" \ - "C: 2\r\n" - -#define DLCX_RET "250 7 OK\r\n" \ - "P: PS=0, OS=0, PR=0, OR=0, PL=0, JI=0\r\n" - - #define DLCX_RET_OSMUX DLCX_RET \ - "X-Osmo-CP: EC TIS=0, TOS=0, TIR=0, TOR=0\r\n" - -#define RQNT "RQNT 186908780 1@mgw MGCP 1.0\r\n" \ - "X: B244F267488\r\n" \ - "S: D/9\r\n" - -#define RQNT2 "RQNT 186908781 1@mgw MGCP 1.0\r\n" \ - "X: ADD4F26746F\r\n" \ - "R: D/[0-9#*](N), G/ft, fxr/t38\r\n" - -#define RQNT1_RET "200 186908780 OK\r\n" -#define RQNT2_RET "200 186908781 OK\r\n" - -#define PTYPE_IGNORE 0 /* == default initializer */ -#define PTYPE_NONE 128 -#define PTYPE_NYI PTYPE_NONE - -#define CRCX_MULT_1 "CRCX 2 1@mgw MGCP 1.0\r\n" \ - "M: recvonly\r\n" \ - "C: 2\r\n" \ - "X\r\n" \ - "L: p:20\r\n" \ - "\r\n" \ - "v=0\r\n" \ - "c=IN IP4 123.12.12.123\r\n" \ - "m=audio 5904 RTP/AVP 18 97\r\n"\ - "a=rtpmap:18 G729/8000\r\n" \ - "a=rtpmap:97 GSM-EFR/8000\r\n" \ - "a=ptime:40\r\n" - -#define CRCX_MULT_2 "CRCX 2 2@mgw MGCP 1.0\r\n" \ - "M: recvonly\r\n" \ - "C: 2\r\n" \ - "X\r\n" \ - "L: p:20\r\n" \ - "\r\n" \ - "v=0\r\n" \ - "c=IN IP4 123.12.12.123\r\n" \ - "m=audio 5904 RTP/AVP 18 97 101\r\n"\ - "a=rtpmap:18 G729/8000\r\n" \ - "a=rtpmap:97 GSM-EFR/8000\r\n" \ - "a=rtpmap:101 FOO/8000\r\n" \ - "a=ptime:40\r\n" - -#define CRCX_MULT_3 "CRCX 2 3@mgw MGCP 1.0\r\n" \ - "M: recvonly\r\n" \ - "C: 2\r\n" \ - "X\r\n" \ - "L: p:20\r\n" \ - "\r\n" \ - "v=0\r\n" \ - "c=IN IP4 123.12.12.123\r\n" \ - "m=audio 5904 RTP/AVP\r\n" \ - "a=rtpmap:18 G729/8000\r\n" \ - "a=rtpmap:97 GSM-EFR/8000\r\n" \ - "a=rtpmap:101 FOO/8000\r\n" \ - "a=ptime:40\r\n" - -#define CRCX_MULT_4 "CRCX 2 4@mgw MGCP 1.0\r\n" \ - "M: recvonly\r\n" \ - "C: 2\r\n" \ - "X\r\n" \ - "L: p:20\r\n" \ - "\r\n" \ - "v=0\r\n" \ - "c=IN IP4 123.12.12.123\r\n" \ - "m=audio 5904 RTP/AVP 18\r\n" \ - "a=rtpmap:18 G729/8000\r\n" \ - "a=rtpmap:97 GSM-EFR/8000\r\n" \ - "a=rtpmap:101 FOO/8000\r\n" \ - "a=ptime:40\r\n" - -#define CRCX_MULT_GSM_EXACT \ - "CRCX 259260421 5@mgw MGCP 1.0\r\n" \ - "C: 1355c6041e\r\n" \ - "I: 3\r\n" \ - "L: p:20, a:GSM, nt:IN\r\n" \ - "M: recvonly\r\n" \ - "\r\n" \ - "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" \ - "a=rtpmap:0 PCMU/8000\r\n" \ - "a=rtpmap:8 PCMA/8000\r\n" \ - "a=rtpmap:3 gsm/8000\r\n" \ - "a=rtpmap:18 G729/8000\r\n" \ - "a=fmtp:18 annexb=no\r\n" \ - "a=rtpmap:4 G723/8000\r\n" \ - "a=rtpmap:96 iLBC/8000\r\n" \ - "a=fmtp:96 mode=20\r\n" \ - "a=rtpmap:97 iLBC/8000\r\n" \ - "a=fmtp:97 mode=30\r\n" \ - "a=rtpmap:101 telephone-event/8000\r\n" \ - "a=fmtp:101 0-15\r\n" \ - "a=recvonly\r\n" -#define MDCX_NAT_DUMMY \ - "MDCX 23 5@mgw MGCP 1.0\r\n" \ - "C: 1355c6041e\r\n" \ - "\r\n" \ - "c=IN IP4 8.8.8.8\r\n" \ - "m=audio 16434 RTP/AVP 255\r\n" - - -struct mgcp_test { - const char *name; - const char *req; - const char *exp_resp; - int exp_net_ptype; - int exp_bts_ptype; - - const char *extra_fmtp; -}; - -static const struct mgcp_test tests[] = { - { "AUEP1", AUEP1, AUEP1_RET }, - { "AUEP2", AUEP2, AUEP2_RET }, - { "MDCX1", MDCX_WRONG_EP, MDCX_ERR_RET }, - { "MDCX2", MDCX_UNALLOCATED, MDCX_RET }, - { "CRCX", CRCX, CRCX_RET, 97, 126 }, - { "MDCX3", MDCX3, MDCX3_RET, PTYPE_NONE, 126 }, - { "MDCX4", MDCX4, MDCX4_RET("18983216"), 99, 126 }, - { "MDCX4_PT1", MDCX4_PT1, MDCX4_RET("18983217"), 99, 126 }, - { "MDCX4_PT2", MDCX4_PT2, MDCX4_RET("18983218"), 99, 126 }, - { "MDCX4_PT3", MDCX4_PT3, MDCX4_RET("18983219"), 99, 126 }, - { "MDCX4_SO", MDCX4_SO, MDCX4_RET("18983220"), 99, 126 }, - { "MDCX4_RO", MDCX4_RO, MDCX4_RET("18983221"), PTYPE_IGNORE, 126 }, - { "DLCX", DLCX, DLCX_RET, -1, -1 }, - { "CRCX_ZYN", CRCX_ZYN, CRCX_ZYN_RET, 97, 126 }, - { "EMPTY", EMPTY, EMPTY_RET }, - { "SHORT1", SHORT, SHORT_RET }, - { "SHORT2", SHORT2, SHORT2_RET }, - { "SHORT3", SHORT3, SHORT2_RET }, - { "SHORT4", SHORT4, SHORT2_RET }, - { "RQNT1", RQNT, RQNT1_RET }, - { "RQNT2", RQNT2, RQNT2_RET }, - { "DLCX", DLCX, DLCX_RET, -1, -1 }, - { "CRCX", CRCX, CRCX_FMTP_RET, 97, 126, .extra_fmtp = "a=fmtp:126 0/1/2" }, - { "MDCX3", MDCX3, MDCX3_FMTP_RET, PTYPE_NONE, 126 , .extra_fmtp = "a=fmtp:126 0/1/2" }, - { "DLCX", DLCX, DLCX_RET, -1, -1 , .extra_fmtp = "a=fmtp:126 0/1/2" }, -}; - -static const struct mgcp_test retransmit[] = { - { "CRCX", CRCX, CRCX_RET }, - { "RQNT1", RQNT, RQNT1_RET }, - { "RQNT2", RQNT2, RQNT2_RET }, - { "MDCX3", MDCX3, MDCX3_RET }, - { "DLCX", DLCX, DLCX_RET }, -}; - -static struct msgb *create_msg(const char *str) -{ - struct msgb *msg; - - msg = msgb_alloc_headroom(4096, 128, "MGCP msg"); - int len = sprintf((char *)msg->data, "%s", str); - msg->l2h = msgb_put(msg, len); - return msg; -} - -static int last_endpoint = -1; - -static int mgcp_test_policy_cb(struct mgcp_trunk_config *cfg, int endpoint, - int state, const char *transactio_id) -{ - fprintf(stderr, "Policy CB got state %d on endpoint %d\n", - state, endpoint); - last_endpoint = endpoint; - return MGCP_POLICY_CONT; -} - -#define MGCP_DUMMY_LOAD 0x23 -static int dummy_packets = 0; -/* override and forward */ -ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr *dest_addr, socklen_t addrlen) -{ - typedef ssize_t (*sendto_t)(int, const void *, size_t, int, - const struct sockaddr *, socklen_t); - static sendto_t real_sendto = NULL; - uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr); - int dest_port = htons(((struct sockaddr_in *)dest_addr)->sin_port); - - if (!real_sendto) - real_sendto = dlsym(RTLD_NEXT, "sendto"); - - if (len == 1 && ((const char *)buf)[0] == MGCP_DUMMY_LOAD ) { - fprintf(stderr, "Dummy packet to 0x%08x:%d, msg length %zu\n%s\n\n", - dest_host, dest_port, - len, osmo_hexdump(buf, len)); - dummy_packets += 1; - } - - return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen); -} - -static int64_t force_monotonic_time_us = -1; -/* override and forward */ -int clock_gettime(clockid_t clk_id, struct timespec *tp) -{ - typedef int (*clock_gettime_t)(clockid_t clk_id, struct timespec *tp); - static clock_gettime_t real_clock_gettime = NULL; - - if (!real_clock_gettime) - real_clock_gettime = dlsym(RTLD_NEXT, "clock_gettime"); - - if (clk_id == CLOCK_MONOTONIC && force_monotonic_time_us >= 0) { - tp->tv_sec = force_monotonic_time_us / 1000000; - tp->tv_nsec = (force_monotonic_time_us % 1000000) * 1000; - return 0; - } - - return real_clock_gettime(clk_id, tp); -} - -#define CONN_UNMODIFIED (0x1000) - -static void test_values(void) -{ - /* Check that NONE disables all output */ - OSMO_ASSERT((MGCP_CONN_NONE & MGCP_CONN_RECV_SEND) == 0); - - /* Check that LOOPBACK enables all output */ - OSMO_ASSERT((MGCP_CONN_LOOPBACK & MGCP_CONN_RECV_SEND) == - MGCP_CONN_RECV_SEND); -} - - -static void test_messages(void) -{ - struct mgcp_config *cfg; - struct mgcp_endpoint *endp; - int i; - - cfg = mgcp_config_alloc(); - - cfg->trunk.number_endpoints = 64; - mgcp_endpoints_allocate(&cfg->trunk); - - cfg->policy_cb = mgcp_test_policy_cb; - - mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1)); - - /* reset endpoints */ - for (i = 0; i < cfg->trunk.number_endpoints; i++) { - endp = &cfg->trunk.endpoints[i]; - endp->net_end.codec.payload_type = PTYPE_NONE; - endp->net_end.packet_duration_ms = -1; - - OSMO_ASSERT(endp->conn_mode == MGCP_CONN_NONE); - endp->conn_mode |= CONN_UNMODIFIED; - } - - for (i = 0; i < ARRAY_SIZE(tests); i++) { - const struct mgcp_test *t = &tests[i]; - struct msgb *inp; - struct msgb *msg; - - printf("Testing %s\n", t->name); - - last_endpoint = -1; - dummy_packets = 0; - - osmo_talloc_replace_string(cfg, &cfg->trunk.audio_fmtp_extra, t->extra_fmtp); - - inp = create_msg(t->req); - msg = mgcp_handle_message(cfg, inp); - msgb_free(inp); - if (!t->exp_resp) { - if (msg) - printf("%s failed '%s'\n", t->name, (char *) msg->data); - } else if (strcmp((char *) msg->data, t->exp_resp) != 0) - printf("%s failed.\nExpected:\n%s\nGot:\n%s\n", - t->name, t->exp_resp, (char *) msg->data); - msgb_free(msg); - - if (dummy_packets) - printf("Dummy packets: %d\n", dummy_packets); - - if (last_endpoint != -1) { - endp = &cfg->trunk.endpoints[last_endpoint]; - - if (endp->net_end.packet_duration_ms != -1) - printf("Detected packet duration: %d\n", - endp->net_end.packet_duration_ms); - else - printf("Packet duration not set\n"); - if (endp->local_options.pkt_period_min || - endp->local_options.pkt_period_max) - printf("Requested packetetization period: " - "%d-%d\n", - endp->local_options.pkt_period_min, - endp->local_options.pkt_period_max); - else - printf("Requested packetization period not set\n"); - - if ((endp->conn_mode & CONN_UNMODIFIED) == 0) { - printf("Connection mode: %d:%s%s%s%s\n", - endp->conn_mode, - !endp->conn_mode ? " NONE" : "", - endp->conn_mode & MGCP_CONN_SEND_ONLY ? - " SEND" : "", - endp->conn_mode & MGCP_CONN_RECV_ONLY ? - " RECV" : "", - endp->conn_mode & MGCP_CONN_LOOPBACK & - ~MGCP_CONN_RECV_SEND ? - " LOOP" : ""); - fprintf(stderr, - "BTS output %sabled, NET output %sabled\n", - endp->bts_end.output_enabled ? "en" : "dis", - endp->net_end.output_enabled ? "en" : "dis"); - } else - printf("Connection mode not set\n"); - - OSMO_ASSERT(endp->net_end.output_enabled == - (endp->conn_mode & MGCP_CONN_SEND_ONLY ? 1 : 0)); - OSMO_ASSERT(endp->bts_end.output_enabled == - (endp->conn_mode & MGCP_CONN_RECV_ONLY ? 1 : 0)); - - endp->net_end.packet_duration_ms = -1; - endp->local_options.pkt_period_min = 0; - endp->local_options.pkt_period_max = 0; - endp->conn_mode |= CONN_UNMODIFIED; - } - - - /* Check detected payload type */ - if (t->exp_net_ptype != PTYPE_IGNORE || - t->exp_bts_ptype != PTYPE_IGNORE) { - OSMO_ASSERT(last_endpoint != -1); - endp = &cfg->trunk.endpoints[last_endpoint]; - - fprintf(stderr, "endpoint %d: " - "payload type BTS %d (exp %d), NET %d (exp %d)\n", - last_endpoint, - endp->bts_end.codec.payload_type, t->exp_bts_ptype, - endp->net_end.codec.payload_type, t->exp_net_ptype); - - if (t->exp_bts_ptype != PTYPE_IGNORE) - OSMO_ASSERT(endp->bts_end.codec.payload_type == - t->exp_bts_ptype); - if (t->exp_net_ptype != PTYPE_IGNORE) - OSMO_ASSERT(endp->net_end.codec.payload_type == - t->exp_net_ptype); - - /* Reset them again for next test */ - endp->net_end.codec.payload_type = PTYPE_NONE; - } - } - - talloc_free(cfg); -} - -static void test_retransmission(void) -{ - struct mgcp_config *cfg; - int i; - - cfg = mgcp_config_alloc(); - - cfg->trunk.number_endpoints = 64; - mgcp_endpoints_allocate(&cfg->trunk); - - mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1)); - - /* reset endpoints */ - for (i = 0; i < cfg->trunk.number_endpoints; i++) { - struct mgcp_endpoint *endp; - endp = &cfg->trunk.endpoints[i]; - endp->bts_end.packet_duration_ms = 20; - } - - for (i = 0; i < ARRAY_SIZE(retransmit); i++) { - const struct mgcp_test *t = &retransmit[i]; - struct msgb *inp; - struct msgb *msg; - - printf("Testing %s\n", t->name); - - inp = create_msg(t->req); - msg = mgcp_handle_message(cfg, inp); - msgb_free(inp); - if (strcmp((char *) msg->data, t->exp_resp) != 0) - printf("%s failed '%s'\n", t->name, (char *) msg->data); - msgb_free(msg); - - /* Retransmit... */ - printf("Re-transmitting %s\n", t->name); - inp = create_msg(t->req); - msg = mgcp_handle_message(cfg, inp); - msgb_free(inp); - if (strcmp((char *) msg->data, t->exp_resp) != 0) - printf("%s failed '%s'\n", t->name, (char *) msg->data); - msgb_free(msg); - } - - talloc_free(cfg); -} - -static int rqnt_cb(struct mgcp_endpoint *endp, char _tone) -{ - ptrdiff_t tone = _tone; - endp->cfg->data = (void *) tone; - return 0; -} - -static void test_rqnt_cb(void) -{ - struct mgcp_config *cfg; - struct msgb *inp, *msg; - - cfg = mgcp_config_alloc(); - cfg->rqnt_cb = rqnt_cb; - - cfg->trunk.number_endpoints = 64; - mgcp_endpoints_allocate(&cfg->trunk); - - mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1)); - - inp = create_msg(CRCX); - msgb_free(mgcp_handle_message(cfg, inp)); - msgb_free(inp); - - /* send the RQNT and check for the CB */ - inp = create_msg(RQNT); - msg = mgcp_handle_message(cfg, inp); - if (strncmp((const char *) msg->l2h, "200", 3) != 0) { - printf("FAILED: message is not 200. '%s'\n", msg->l2h); - abort(); - } - - if (cfg->data != (void *) '9') { - printf("FAILED: callback not called: %p\n", cfg->data); - abort(); - } - - msgb_free(msg); - msgb_free(inp); - - inp = create_msg(DLCX); - msgb_free(mgcp_handle_message(cfg, inp)); - msgb_free(inp); - talloc_free(cfg); -} - -struct pl_test { - int cycles; - uint16_t base_seq; - uint16_t max_seq; - uint32_t packets; - - uint32_t expected; - int loss; -}; - -static const struct pl_test pl_test_dat[] = { - /* basic.. just one package */ - { .cycles = 0, .base_seq = 0, .max_seq = 0, .packets = 1, .expected = 1, .loss = 0}, - /* some packages and a bit of loss */ - { .cycles = 0, .base_seq = 0, .max_seq = 100, .packets = 100, .expected = 101, .loss = 1}, - /* wrap around */ - { .cycles = 1<<16, .base_seq = 0xffff, .max_seq = 2, .packets = 4, .expected = 4, .loss = 0}, - /* min loss */ - { .cycles = 0, .base_seq = 0, .max_seq = 0, .packets = UINT_MAX, .expected = 1, .loss = INT_MIN }, - /* max loss, with wrap around on expected max */ - { .cycles = INT_MAX, .base_seq = 0, .max_seq = UINT16_MAX, .packets = 0, .expected = ((uint32_t)(INT_MAX) + UINT16_MAX + 1), .loss = INT_MAX }, -}; - -static void test_packet_loss_calc(void) -{ - int i; - printf("Testing packet loss calculation.\n"); - - 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; - - rtp.packets = pl_test_dat[i].packets; - mgcp_state_calc_loss(&state, &rtp, &expected, &loss); - - if (loss != pl_test_dat[i].loss || expected != pl_test_dat[i].expected) { - printf("FAIL: Wrong exp/loss at idx(%d) Loss(%d vs. %d) Exp(%u vs. %u)\n", - i, loss, pl_test_dat[i].loss, - expected, pl_test_dat[i].expected); - } - } -} - -static void test_mgcp_stats(void) -{ - printf("Testing stat parsing\n"); - - uint32_t bps, bos, pr, _or, jitter; - struct msgb *msg; - int loss; - int rc; - - msg = create_msg(DLCX_RET); - rc = mgcp_parse_stats(msg, &bps, &bos, &pr, &_or, &loss, &jitter); - printf("Parsing result: %d\n", rc); - if (bps != 0 || bos != 0 || pr != 0 || _or != 0 || loss != 0 || jitter != 0) - printf("FAIL: Parsing failed1.\n"); - msgb_free(msg); - - msg = create_msg("250 7 OK\r\nP: PS=10, OS=20, PR=30, OR=40, PL=-3, JI=40\r\n"); - rc = mgcp_parse_stats(msg, &bps, &bos, &pr, &_or, &loss, &jitter); - printf("Parsing result: %d\n", rc); - if (bps != 10 || bos != 20 || pr != 30 || _or != 40 || loss != -3 || jitter != 40) - printf("FAIL: Parsing failed2.\n"); - msgb_free(msg); -} - -struct rtp_packet_info { - float txtime; - int len; - char *data; -}; - -struct rtp_packet_info test_rtp_packets1[] = { - /* RTP: SeqNo=0, TS=0 */ - {0.000000, 20, "\x80\x62\x00\x00\x00\x00\x00\x00\x11\x22\x33\x44" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=1, TS=160 */ - {0.020000, 20, "\x80\x62\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=2, TS=320 */ - {0.040000, 20, "\x80\x62\x00\x02\x00\x00\x01\x40\x11\x22\x33\x44" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* Repeat RTP timestamp: */ - /* RTP: SeqNo=3, TS=320 */ - {0.060000, 20, "\x80\x62\x00\x03\x00\x00\x01\x40\x11\x22\x33\x44" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=4, TS=480 */ - {0.080000, 20, "\x80\x62\x00\x04\x00\x00\x01\xE0\x11\x22\x33\x44" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=5, TS=640 */ - {0.100000, 20, "\x80\x62\x00\x05\x00\x00\x02\x80\x11\x22\x33\x44" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* Double skip RTP timestamp (delta = 2*160): */ - /* RTP: SeqNo=6, TS=960 */ - {0.120000, 20, "\x80\x62\x00\x06\x00\x00\x03\xC0\x11\x22\x33\x44" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=7, TS=1120 */ - {0.140000, 20, "\x80\x62\x00\x07\x00\x00\x04\x60\x11\x22\x33\x44" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=8, TS=1280 */ - {0.160000, 20, "\x80\x62\x00\x08\x00\x00\x05\x00\x11\x22\x33\x44" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* Non 20ms RTP timestamp (delta = 120): */ - /* RTP: SeqNo=9, TS=1400 */ - {0.180000, 20, "\x80\x62\x00\x09\x00\x00\x05\x78\x11\x22\x33\x44" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=10, TS=1560 */ - {0.200000, 20, "\x80\x62\x00\x0A\x00\x00\x06\x18\x11\x22\x33\x44" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=11, TS=1720 */ - {0.220000, 20, "\x80\x62\x00\x0B\x00\x00\x06\xB8\x11\x22\x33\x44" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* SSRC changed to 0x10203040, RTP timestamp jump */ - /* RTP: SeqNo=12, TS=34688 */ - {0.240000, 20, "\x80\x62\x00\x0C\x00\x00\x87\x80\x10\x20\x30\x40" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=13, TS=34848 */ - {0.260000, 20, "\x80\x62\x00\x0D\x00\x00\x88\x20\x10\x20\x30\x40" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=14, TS=35008 */ - {0.280000, 20, "\x80\x62\x00\x0E\x00\x00\x88\xC0\x10\x20\x30\x40" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* Non 20ms RTP timestamp (delta = 120): */ - /* RTP: SeqNo=15, TS=35128 */ - {0.300000, 20, "\x80\x62\x00\x0F\x00\x00\x89\x38\x10\x20\x30\x40" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=16, TS=35288 */ - {0.320000, 20, "\x80\x62\x00\x10\x00\x00\x89\xD8\x10\x20\x30\x40" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=17, TS=35448 */ - {0.340000, 20, "\x80\x62\x00\x11\x00\x00\x8A\x78\x10\x20\x30\x40" - "\x01\x23\x45\x67\x8A\xAB\xCD\xEF"}, - /* SeqNo increment by 2, RTP timestamp delta = 320: */ - /* RTP: SeqNo=19, TS=35768 */ - {0.360000, 20, "\x80\x62\x00\x13\x00\x00\x8B\xB8\x10\x20\x30\x40" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=20, TS=35928 */ - {0.380000, 20, "\x80\x62\x00\x14\x00\x00\x8C\x58\x10\x20\x30\x40" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=21, TS=36088 */ - {0.380000, 20, "\x80\x62\x00\x15\x00\x00\x8C\xF8\x10\x20\x30\x40" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* Repeat last packet */ - /* RTP: SeqNo=21, TS=36088 */ - {0.400000, 20, "\x80\x62\x00\x15\x00\x00\x8C\xF8\x10\x20\x30\x40" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=22, TS=36248 */ - {0.420000, 20, "\x80\x62\x00\x16\x00\x00\x8D\x98\x10\x20\x30\x40" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=23, TS=36408 */ - {0.440000, 20, "\x80\x62\x00\x17\x00\x00\x8E\x38\x10\x20\x30\x40" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* Don't increment SeqNo but increment timestamp by 160 */ - /* RTP: SeqNo=23, TS=36568 */ - {0.460000, 20, "\x80\x62\x00\x17\x00\x00\x8E\xD8\x10\x20\x30\x40" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=24, TS=36728 */ - {0.480000, 20, "\x80\x62\x00\x18\x00\x00\x8F\x78\x10\x20\x30\x40" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=25, TS=36888 */ - {0.500000, 20, "\x80\x62\x00\x19\x00\x00\x90\x18\x10\x20\x30\x40" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* SSRC changed to 0x50607080, RTP timestamp jump, Delay of 1.5s, - * SeqNo jump */ - /* RTP: SeqNo=1000, TS=160000 */ - {2.000000, 20, "\x80\x62\x03\xE8\x00\x02\x71\x00\x50\x60\x70\x80" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=1001, TS=160160 */ - {2.020000, 20, "\x80\x62\x03\xE9\x00\x02\x71\xA0\x50\x60\x70\x80" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, - /* RTP: SeqNo=1002, TS=160320 */ - {2.040000, 20, "\x80\x62\x03\xEA\x00\x02\x72\x40\x50\x60\x70\x80" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, -}; - -void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state, - struct mgcp_rtp_end *rtp_end, struct sockaddr_in *addr, - char *data, int len); - -static void test_packet_error_detection(int patch_ssrc, int patch_ts) -{ - int i; - - struct mgcp_trunk_config trunk; - struct mgcp_endpoint endp; - struct mgcp_rtp_state state; - struct mgcp_rtp_end *rtp = &endp.net_end; - struct sockaddr_in addr = {0}; - char buffer[4096]; - 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; - - printf("Testing packet error detection%s%s.\n", - patch_ssrc ? ", patch SSRC" : "", - patch_ts ? ", patch timestamps" : ""); - - memset(&trunk, 0, sizeof(trunk)); - memset(&endp, 0, sizeof(endp)); - memset(&state, 0, sizeof(state)); - - trunk.number_endpoints = 1; - trunk.endpoints = &endp; - trunk.force_constant_ssrc = patch_ssrc; - trunk.force_aligned_timing = patch_ts; - - endp.tcfg = &trunk; - - mgcp_initialize_endp(&endp); - - rtp->codec.payload_type = 98; - - for (i = 0; i < ARRAY_SIZE(test_rtp_packets1); ++i) { - struct rtp_packet_info *info = test_rtp_packets1 + i; - - force_monotonic_time_us = round(1000000.0 * info->txtime); - - OSMO_ASSERT(info->len <= sizeof(buffer)); - OSMO_ASSERT(info->len >= 0); - memmove(buffer, info->data, info->len); - - mgcp_rtp_end_config(&endp, 1, rtp); - - mgcp_patch_and_count(&endp, &state, rtp, &addr, - buffer, info->len); - - if (state.out_stream.ssrc != last_ssrc) { - printf("Output SSRC changed to %08x\n", - state.out_stream.ssrc); - last_ssrc = state.out_stream.ssrc; - } - - printf("In TS: %d, dTS: %d, Seq: %d\n", - state.in_stream.last_timestamp, - 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", - 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); - - printf("Stats: Jitter = %u, Transit = %d\n", - mgcp_state_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_timestamp = state.out_stream.last_timestamp; - last_seqno = state.out_stream.last_seq; - } - - force_monotonic_time_us = -1; -} - -static void test_multilple_codec(void) -{ - struct mgcp_config *cfg; - struct mgcp_endpoint *endp; - struct msgb *inp, *resp; - struct in_addr addr; - - printf("Testing multiple payload types\n"); - - cfg = mgcp_config_alloc(); - cfg->trunk.number_endpoints = 64; - mgcp_endpoints_allocate(&cfg->trunk); - cfg->policy_cb = mgcp_test_policy_cb; - mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1)); - - /* Allocate endpoint 1@mgw with two codecs */ - last_endpoint = -1; - inp = create_msg(CRCX_MULT_1); - resp = mgcp_handle_message(cfg, inp); - msgb_free(inp); - msgb_free(resp); - - OSMO_ASSERT(last_endpoint == 1); - endp = &cfg->trunk.endpoints[last_endpoint]; - OSMO_ASSERT(endp->net_end.codec.payload_type == 18); - OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 97); - - /* Allocate 2@mgw with three codecs, last one ignored */ - last_endpoint = -1; - inp = create_msg(CRCX_MULT_2); - resp = mgcp_handle_message(cfg, inp); - msgb_free(inp); - msgb_free(resp); - - OSMO_ASSERT(last_endpoint == 2); - endp = &cfg->trunk.endpoints[last_endpoint]; - OSMO_ASSERT(endp->net_end.codec.payload_type == 18); - OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 97); - - /* Allocate 3@mgw with no codecs, check for PT == -1 */ - last_endpoint = -1; - inp = create_msg(CRCX_MULT_3); - resp = mgcp_handle_message(cfg, inp); - msgb_free(inp); - msgb_free(resp); - - OSMO_ASSERT(last_endpoint == 3); - endp = &cfg->trunk.endpoints[last_endpoint]; - OSMO_ASSERT(endp->net_end.codec.payload_type == -1); - OSMO_ASSERT(endp->net_end.alt_codec.payload_type == -1); - - /* Allocate 4@mgw with a single codec */ - last_endpoint = -1; - inp = create_msg(CRCX_MULT_4); - resp = mgcp_handle_message(cfg, inp); - msgb_free(inp); - msgb_free(resp); - - OSMO_ASSERT(last_endpoint == 4); - endp = &cfg->trunk.endpoints[last_endpoint]; - OSMO_ASSERT(endp->net_end.codec.payload_type == 18); - OSMO_ASSERT(endp->net_end.alt_codec.payload_type == -1); - - /* Allocate 5@mgw at select GSM.. */ - last_endpoint = -1; - inp = create_msg(CRCX_MULT_GSM_EXACT); - talloc_free(cfg->trunk.audio_name); - cfg->trunk.audio_name = "GSM/8000"; - cfg->trunk.no_audio_transcoding = 1; - resp = mgcp_handle_message(cfg, inp); - msgb_free(inp); - msgb_free(resp); - - OSMO_ASSERT(last_endpoint == 5); - endp = &cfg->trunk.endpoints[last_endpoint]; - OSMO_ASSERT(endp->net_end.codec.payload_type == 3); - OSMO_ASSERT(endp->net_end.alt_codec.payload_type == -1); - - inp = create_msg(MDCX_NAT_DUMMY); - last_endpoint = -1; - resp = mgcp_handle_message(cfg, inp); - msgb_free(inp); - msgb_free(resp); - OSMO_ASSERT(last_endpoint == 5); - endp = &cfg->trunk.endpoints[last_endpoint]; - OSMO_ASSERT(endp->net_end.codec.payload_type == 3); - OSMO_ASSERT(endp->net_end.alt_codec.payload_type == -1); - OSMO_ASSERT(endp->net_end.rtp_port == htons(16434)); - memset(&addr, 0, sizeof(addr)); - inet_aton("8.8.8.8", &addr); - OSMO_ASSERT(endp->net_end.addr.s_addr == addr.s_addr); - - /* Check what happens without that flag */ - - /* Free the previous endpoint and the data ... */ - mgcp_release_endp(endp); - talloc_free(endp->last_response); - talloc_free(endp->last_trans); - endp->last_response = endp->last_trans = NULL; - - last_endpoint = -1; - inp = create_msg(CRCX_MULT_GSM_EXACT); - cfg->trunk.no_audio_transcoding = 0; - resp = mgcp_handle_message(cfg, inp); - msgb_free(inp); - msgb_free(resp); - - OSMO_ASSERT(last_endpoint == 5); - endp = &cfg->trunk.endpoints[last_endpoint]; - OSMO_ASSERT(endp->net_end.codec.payload_type == 255); - OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 0); - - talloc_free(cfg); -} - -static void test_no_cycle(void) -{ - struct mgcp_config *cfg; - struct mgcp_endpoint *endp; - - printf("Testing no sequence flow on initial packet\n"); - - cfg = mgcp_config_alloc(); - cfg->trunk.number_endpoints = 64; - mgcp_endpoints_allocate(&cfg->trunk); - - endp = &cfg->trunk.endpoints[1]; - OSMO_ASSERT(endp->net_state.stats_initialized == 0); - - mgcp_rtp_annex_count(endp, &endp->net_state, 0, 0, 2342); - OSMO_ASSERT(endp->net_state.stats_initialized == 1); - OSMO_ASSERT(endp->net_state.stats_cycles == 0); - OSMO_ASSERT(endp->net_state.stats_max_seq == 0); - - mgcp_rtp_annex_count(endp, &endp->net_state, 1, 0, 2342); - OSMO_ASSERT(endp->net_state.stats_initialized == 1); - OSMO_ASSERT(endp->net_state.stats_cycles == 0); - OSMO_ASSERT(endp->net_state.stats_max_seq == 1); - - /* now jump.. */ - mgcp_rtp_annex_count(endp, &endp->net_state, UINT16_MAX, 0, 2342); - OSMO_ASSERT(endp->net_state.stats_initialized == 1); - OSMO_ASSERT(endp->net_state.stats_cycles == 0); - OSMO_ASSERT(endp->net_state.stats_max_seq == UINT16_MAX); - - /* and wrap */ - mgcp_rtp_annex_count(endp, &endp->net_state, 0, 0, 2342); - OSMO_ASSERT(endp->net_state.stats_initialized == 1); - OSMO_ASSERT(endp->net_state.stats_cycles == UINT16_MAX + 1); - OSMO_ASSERT(endp->net_state.stats_max_seq == 0); - - talloc_free(cfg); -} - -static void test_no_name(void) -{ - struct mgcp_config *cfg; - struct mgcp_endpoint *endp; - struct msgb *inp, *msg; - int i; - - printf("Testing no rtpmap name\n"); - cfg = mgcp_config_alloc(); - - cfg->trunk.number_endpoints = 64; - cfg->trunk.audio_send_name = 0; - mgcp_endpoints_allocate(&cfg->trunk); - - cfg->policy_cb = mgcp_test_policy_cb; - - mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1)); - - /* reset endpoints */ - for (i = 0; i < cfg->trunk.number_endpoints; i++) { - endp = &cfg->trunk.endpoints[i]; - endp->net_end.codec.payload_type = PTYPE_NONE; - endp->net_end.packet_duration_ms = -1; - - OSMO_ASSERT(endp->conn_mode == MGCP_CONN_NONE); - endp->conn_mode |= CONN_UNMODIFIED; - } - - inp = create_msg(CRCX); - msg = mgcp_handle_message(cfg, inp); - if (strcmp((char *) msg->data, CRCX_RET_NO_RTPMAP) != 0) - printf("FAILED: there should not be a RTPMAP: %s\n", - (char *) msg->data); - msgb_free(inp); - msgb_free(msg); - - mgcp_release_endp(&cfg->trunk.endpoints[1]); - talloc_free(cfg); -} - -static void test_osmux_cid(void) -{ - int id, i; - - OSMO_ASSERT(osmux_used_cid() == 0); - id = osmux_get_cid(); - OSMO_ASSERT(id == 0); - OSMO_ASSERT(osmux_used_cid() == 1); - osmux_put_cid(id); - OSMO_ASSERT(osmux_used_cid() == 0); - - for (i = 0; i < 256; ++i) { - id = osmux_get_cid(); - OSMO_ASSERT(id == i); - OSMO_ASSERT(osmux_used_cid() == i + 1); - } - - id = osmux_get_cid(); - OSMO_ASSERT(id == -1); - - for (i = 0; i < 256; ++i) - osmux_put_cid(i); - OSMO_ASSERT(osmux_used_cid() == 0); -} - -static const struct log_info_cat log_categories[] = { -}; - -const struct log_info log_info = { - .cat = log_categories, - .num_cat = ARRAY_SIZE(log_categories), -}; - -int main(int argc, char **argv) -{ - void *ctx = talloc_named_const(NULL, 0, "mgcp_test"); - void *msgb_ctx = msgb_talloc_ctx_init(ctx, 0); - osmo_init_logging2(ctx, &log_info); - - test_strline(); - test_values(); - test_messages(); - test_retransmission(); - test_packet_loss_calc(); - test_rqnt_cb(); - test_mgcp_stats(); - test_packet_error_detection(1, 0); - test_packet_error_detection(0, 0); - test_packet_error_detection(0, 1); - test_packet_error_detection(1, 1); - test_multilple_codec(); - test_no_cycle(); - test_no_name(); - test_osmux_cid(); - - OSMO_ASSERT(talloc_total_size(msgb_ctx) == 0); - OSMO_ASSERT(talloc_total_blocks(msgb_ctx) == 1); - talloc_free(msgb_ctx); - printf("Done\n"); - return EXIT_SUCCESS; -} diff --git a/tests/legacy_mgcp/mgcp_test.ok b/tests/legacy_mgcp/mgcp_test.ok deleted file mode 100644 index 4e27282ee..000000000 --- a/tests/legacy_mgcp/mgcp_test.ok +++ /dev/null @@ -1,480 +0,0 @@ -line: 'one CR' -line: 'two CR' -line: '' -line: 'one CRLF' -line: 'two CRLF' -line: '' -line: 'one LF' -line: 'two LF' -line: '' -line: 'mixed (4 lines)' -line: '' -line: '' -line: '' -Testing AUEP1 -Testing AUEP2 -Testing MDCX1 -Testing MDCX2 -Testing CRCX -Dummy packets: 1 -Detected packet duration: 40 -Requested packetetization period: 20-20 -Connection mode: 1: RECV -Testing MDCX3 -Dummy packets: 1 -Packet duration not set -Requested packetization period not set -Connection mode not set -Testing MDCX4 -Dummy packets: 1 -Detected packet duration: 40 -Requested packetetization period: 20-20 -Connection mode: 3: SEND RECV -Testing MDCX4_PT1 -Dummy packets: 1 -Detected packet duration: 40 -Requested packetetization period: 20-40 -Connection mode: 3: SEND RECV -Testing MDCX4_PT2 -Dummy packets: 1 -Detected packet duration: 40 -Requested packetetization period: 20-20 -Connection mode: 3: SEND RECV -Testing MDCX4_PT3 -Dummy packets: 1 -Detected packet duration: 40 -Requested packetization period not set -Connection mode: 3: SEND RECV -Testing MDCX4_SO -Detected packet duration: 40 -Requested packetetization period: 20-20 -Connection mode: 2: SEND -Testing MDCX4_RO -Dummy packets: 1 -Packet duration not set -Requested packetetization period: 20-20 -Connection mode: 1: RECV -Testing DLCX -Detected packet duration: 20 -Requested packetization period not set -Connection mode: 0: NONE -Testing CRCX_ZYN -Dummy packets: 1 -Packet duration not set -Requested packetization period not set -Connection mode: 1: RECV -Testing EMPTY -Testing SHORT1 -Testing SHORT2 -Testing SHORT3 -Testing SHORT4 -Testing RQNT1 -Testing RQNT2 -Testing DLCX -Detected packet duration: 20 -Requested packetization period not set -Connection mode: 0: NONE -Testing CRCX -Dummy packets: 1 -Detected packet duration: 40 -Requested packetetization period: 20-20 -Connection mode: 1: RECV -Testing MDCX3 -Dummy packets: 1 -Packet duration not set -Requested packetization period not set -Connection mode not set -Testing DLCX -Detected packet duration: 20 -Requested packetization period not set -Connection mode: 0: NONE -Testing CRCX -Re-transmitting CRCX -Testing RQNT1 -Re-transmitting RQNT1 -Testing RQNT2 -Re-transmitting RQNT2 -Testing MDCX3 -Re-transmitting MDCX3 -Testing DLCX -Re-transmitting DLCX -Testing packet loss calculation. -Testing stat parsing -Parsing result: 0 -Parsing result: 0 -Testing packet error detection, patch SSRC. -Output SSRC changed to 11223344 -In TS: 0, dTS: 0, Seq: 0 -Out TS change: 0, dTS: 0, Seq change: 0, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = 0 -In TS: 160, dTS: 160, Seq: 1 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = 0 -In TS: 320, dTS: 160, Seq: 2 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = 0 -In TS: 320, dTS: 160, Seq: 3 -Out TS change: 0, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 10, Transit = 160 -In TS: 480, dTS: 160, Seq: 4 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 9, Transit = 160 -In TS: 640, dTS: 160, Seq: 5 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 8, Transit = 160 -In TS: 960, dTS: 320, Seq: 6 -Out TS change: 320, dTS: 320, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 18, Transit = 0 -In TS: 1120, dTS: 160, Seq: 7 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 17, Transit = 0 -In TS: 1280, dTS: 160, Seq: 8 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 16, Transit = 0 -In TS: 1400, dTS: 120, Seq: 9 -Out TS change: 120, dTS: 120, Seq change: 1, TS Err change: in +1, out +1 -Stats: Jitter = 17, Transit = 40 -In TS: 1560, dTS: 160, Seq: 10 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 16, Transit = 40 -In TS: 1720, dTS: 160, Seq: 11 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 15, Transit = 40 -In TS: 34688, dTS: 0, Seq: 12 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -32768 -In TS: 34848, dTS: 160, Seq: 13 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -32768 -In TS: 35008, dTS: 160, Seq: 14 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -32768 -In TS: 35128, dTS: 120, Seq: 15 -Out TS change: 120, dTS: 120, Seq change: 1, TS Err change: in +1, out +1 -Stats: Jitter = 2, Transit = -32728 -In TS: 35288, dTS: 160, Seq: 16 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 2, Transit = -32728 -In TS: 35448, dTS: 160, Seq: 17 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 2, Transit = -32728 -In TS: 35768, dTS: 160, Seq: 19 -Out TS change: 320, dTS: 160, Seq change: 2, TS Err change: in +0, out +0 -Stats: Jitter = 12, Transit = -32888 -In TS: 35928, dTS: 160, Seq: 20 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 11, Transit = -32888 -In TS: 36088, dTS: 160, Seq: 21 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 20, Transit = -33048 -In TS: 36088, dTS: 160, Seq: 21 -Out TS change: 0, dTS: 160, Seq change: 0, TS Err change: in +0, out +0 -Stats: Jitter = 29, Transit = -32888 -In TS: 36248, dTS: 160, Seq: 22 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 27, Transit = -32888 -In TS: 36408, dTS: 160, Seq: 23 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 25, Transit = -32888 -In TS: 36568, dTS: 160, Seq: 23 -Out TS change: 160, dTS: 160, Seq change: 0, TS Err change: in +1, out +1 -Stats: Jitter = 24, Transit = -32888 -In TS: 36728, dTS: 160, Seq: 24 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 22, Transit = -32888 -In TS: 36888, dTS: 160, Seq: 25 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 21, Transit = -32888 -In TS: 160000, dTS: 0, Seq: 1000 -Out TS change: 12000, dTS: 12000, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -144000 -In TS: 160160, dTS: 160, Seq: 1001 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -144000 -In TS: 160320, dTS: 160, Seq: 1002 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -144000 -Testing packet error detection. -Output SSRC changed to 11223344 -In TS: 0, dTS: 0, Seq: 0 -Out TS change: 0, dTS: 0, Seq change: 0, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = 0 -In TS: 160, dTS: 160, Seq: 1 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = 0 -In TS: 320, dTS: 160, Seq: 2 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = 0 -In TS: 320, dTS: 160, Seq: 3 -Out TS change: 0, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 10, Transit = 160 -In TS: 480, dTS: 160, Seq: 4 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 9, Transit = 160 -In TS: 640, dTS: 160, Seq: 5 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 8, Transit = 160 -In TS: 960, dTS: 320, Seq: 6 -Out TS change: 320, dTS: 320, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 18, Transit = 0 -In TS: 1120, dTS: 160, Seq: 7 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 17, Transit = 0 -In TS: 1280, dTS: 160, Seq: 8 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 16, Transit = 0 -In TS: 1400, dTS: 120, Seq: 9 -Out TS change: 120, dTS: 120, Seq change: 1, TS Err change: in +1, out +1 -Stats: Jitter = 17, Transit = 40 -In TS: 1560, dTS: 160, Seq: 10 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 16, Transit = 40 -In TS: 1720, dTS: 160, Seq: 11 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 15, Transit = 40 -Output SSRC changed to 10203040 -In TS: 34688, dTS: 0, Seq: 12 -Out TS change: 32968, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -32768 -In TS: 34848, dTS: 160, Seq: 13 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -32768 -In TS: 35008, dTS: 160, Seq: 14 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -32768 -In TS: 35128, dTS: 120, Seq: 15 -Out TS change: 120, dTS: 120, Seq change: 1, TS Err change: in +1, out +1 -Stats: Jitter = 2, Transit = -32728 -In TS: 35288, dTS: 160, Seq: 16 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 2, Transit = -32728 -In TS: 35448, dTS: 160, Seq: 17 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 2, Transit = -32728 -In TS: 35768, dTS: 160, Seq: 19 -Out TS change: 320, dTS: 160, Seq change: 2, TS Err change: in +0, out +0 -Stats: Jitter = 12, Transit = -32888 -In TS: 35928, dTS: 160, Seq: 20 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 11, Transit = -32888 -In TS: 36088, dTS: 160, Seq: 21 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 20, Transit = -33048 -In TS: 36088, dTS: 160, Seq: 21 -Out TS change: 0, dTS: 160, Seq change: 0, TS Err change: in +0, out +0 -Stats: Jitter = 29, Transit = -32888 -In TS: 36248, dTS: 160, Seq: 22 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 27, Transit = -32888 -In TS: 36408, dTS: 160, Seq: 23 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 25, Transit = -32888 -In TS: 36568, dTS: 160, Seq: 23 -Out TS change: 160, dTS: 160, Seq change: 0, TS Err change: in +1, out +1 -Stats: Jitter = 24, Transit = -32888 -In TS: 36728, dTS: 160, Seq: 24 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 22, Transit = -32888 -In TS: 36888, dTS: 160, Seq: 25 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 21, Transit = -32888 -Output SSRC changed to 50607080 -In TS: 160000, dTS: 0, Seq: 1000 -Out TS change: 123112, dTS: 160, Seq change: 975, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -144000 -In TS: 160160, dTS: 160, Seq: 1001 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -144000 -In TS: 160320, dTS: 160, Seq: 1002 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -144000 -Testing packet error detection, patch timestamps. -Output SSRC changed to 11223344 -In TS: 0, dTS: 0, Seq: 0 -Out TS change: 0, dTS: 0, Seq change: 0, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = 0 -In TS: 160, dTS: 160, Seq: 1 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = 0 -In TS: 320, dTS: 160, Seq: 2 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = 0 -In TS: 320, dTS: 160, Seq: 3 -Out TS change: 0, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 10, Transit = 160 -In TS: 480, dTS: 160, Seq: 4 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 9, Transit = 160 -In TS: 640, dTS: 160, Seq: 5 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 8, Transit = 160 -In TS: 960, dTS: 320, Seq: 6 -Out TS change: 320, dTS: 320, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 18, Transit = 0 -In TS: 1120, dTS: 160, Seq: 7 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 17, Transit = 0 -In TS: 1280, dTS: 160, Seq: 8 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 16, Transit = 0 -In TS: 1400, dTS: 120, Seq: 9 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +1, out +0 -Stats: Jitter = 17, Transit = 40 -In TS: 1560, dTS: 160, Seq: 10 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 16, Transit = 40 -In TS: 1720, dTS: 160, Seq: 11 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 15, Transit = 40 -Output SSRC changed to 10203040 -In TS: 34688, dTS: 0, Seq: 12 -Out TS change: 32968, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -32768 -In TS: 34848, dTS: 160, Seq: 13 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -32768 -In TS: 35008, dTS: 160, Seq: 14 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -32768 -In TS: 35128, dTS: 120, Seq: 15 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +1, out +0 -Stats: Jitter = 2, Transit = -32728 -In TS: 35288, dTS: 160, Seq: 16 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 2, Transit = -32728 -In TS: 35448, dTS: 160, Seq: 17 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 2, Transit = -32728 -In TS: 35768, dTS: 160, Seq: 19 -Out TS change: 320, dTS: 160, Seq change: 2, TS Err change: in +0, out +0 -Stats: Jitter = 12, Transit = -32888 -In TS: 35928, dTS: 160, Seq: 20 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 11, Transit = -32888 -In TS: 36088, dTS: 160, Seq: 21 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 20, Transit = -33048 -In TS: 36088, dTS: 160, Seq: 21 -Out TS change: 0, dTS: 160, Seq change: 0, TS Err change: in +0, out +0 -Stats: Jitter = 29, Transit = -32888 -In TS: 36248, dTS: 160, Seq: 22 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 27, Transit = -32888 -In TS: 36408, dTS: 160, Seq: 23 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 25, Transit = -32888 -In TS: 36568, dTS: 160, Seq: 23 -Out TS change: 160, dTS: 160, Seq change: 0, TS Err change: in +1, out +1 -Stats: Jitter = 24, Transit = -32888 -In TS: 36728, dTS: 160, Seq: 24 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 22, Transit = -32888 -In TS: 36888, dTS: 160, Seq: 25 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 21, Transit = -32888 -Output SSRC changed to 50607080 -In TS: 160000, dTS: 0, Seq: 1000 -Out TS change: 123112, dTS: 160, Seq change: 975, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -144000 -In TS: 160160, dTS: 160, Seq: 1001 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -144000 -In TS: 160320, dTS: 160, Seq: 1002 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -144000 -Testing packet error detection, patch SSRC, patch timestamps. -Output SSRC changed to 11223344 -In TS: 0, dTS: 0, Seq: 0 -Out TS change: 0, dTS: 0, Seq change: 0, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = 0 -In TS: 160, dTS: 160, Seq: 1 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = 0 -In TS: 320, dTS: 160, Seq: 2 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = 0 -In TS: 320, dTS: 160, Seq: 3 -Out TS change: 0, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 10, Transit = 160 -In TS: 480, dTS: 160, Seq: 4 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 9, Transit = 160 -In TS: 640, dTS: 160, Seq: 5 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 8, Transit = 160 -In TS: 960, dTS: 320, Seq: 6 -Out TS change: 320, dTS: 320, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 18, Transit = 0 -In TS: 1120, dTS: 160, Seq: 7 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 17, Transit = 0 -In TS: 1280, dTS: 160, Seq: 8 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 16, Transit = 0 -In TS: 1400, dTS: 120, Seq: 9 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +1, out +0 -Stats: Jitter = 17, Transit = 40 -In TS: 1560, dTS: 160, Seq: 10 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 16, Transit = 40 -In TS: 1720, dTS: 160, Seq: 11 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 15, Transit = 40 -In TS: 34688, dTS: 0, Seq: 12 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -32768 -In TS: 34848, dTS: 160, Seq: 13 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -32768 -In TS: 35008, dTS: 160, Seq: 14 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -32768 -In TS: 35128, dTS: 120, Seq: 15 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +1, out +0 -Stats: Jitter = 2, Transit = -32728 -In TS: 35288, dTS: 160, Seq: 16 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 2, Transit = -32728 -In TS: 35448, dTS: 160, Seq: 17 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 2, Transit = -32728 -In TS: 35768, dTS: 160, Seq: 19 -Out TS change: 320, dTS: 160, Seq change: 2, TS Err change: in +0, out +0 -Stats: Jitter = 12, Transit = -32888 -In TS: 35928, dTS: 160, Seq: 20 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 11, Transit = -32888 -In TS: 36088, dTS: 160, Seq: 21 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 20, Transit = -33048 -In TS: 36088, dTS: 160, Seq: 21 -Out TS change: 0, dTS: 160, Seq change: 0, TS Err change: in +0, out +0 -Stats: Jitter = 29, Transit = -32888 -In TS: 36248, dTS: 160, Seq: 22 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 27, Transit = -32888 -In TS: 36408, dTS: 160, Seq: 23 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 25, Transit = -32888 -In TS: 36568, dTS: 160, Seq: 23 -Out TS change: 160, dTS: 160, Seq change: 0, TS Err change: in +1, out +1 -Stats: Jitter = 24, Transit = -32888 -In TS: 36728, dTS: 160, Seq: 24 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 22, Transit = -32888 -In TS: 36888, dTS: 160, Seq: 25 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 21, Transit = -32888 -In TS: 160000, dTS: 0, Seq: 1000 -Out TS change: 12000, dTS: 12000, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -144000 -In TS: 160160, dTS: 160, Seq: 1001 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -144000 -In TS: 160320, dTS: 160, Seq: 1002 -Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -144000 -Testing multiple payload types -Testing no sequence flow on initial packet -Testing no rtpmap name -Done diff --git a/tests/legacy_mgcp/mgcp_transcoding_test.c b/tests/legacy_mgcp/mgcp_transcoding_test.c deleted file mode 100644 index d3f94c74e..000000000 --- a/tests/legacy_mgcp/mgcp_transcoding_test.c +++ /dev/null @@ -1,662 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include - -#include "bscconfig.h" -#ifndef BUILD_MGCP_TRANSCODING -#error "Requires MGCP transcoding enabled (see --enable-mgcp-transcoding)" -#endif - -#include - -uint8_t *audio_frame_l16[] = { -}; - -struct rtp_packets { - float t; - int len; - char *data; -}; - -struct rtp_packets audio_packets_l16[] = { - /* RTP: SeqNo=1, TS=160 */ - {0.020000, 332, - "\x80\x0B\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" - }, -}; - -struct rtp_packets audio_packets_gsm[] = { - /* RTP: SeqNo=1, TS=160 */ - {0.020000, 45, - "\x80\x03\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44" - "\xD4\x7C\xE3\xE9\x62\x50\x39\xF0\xF8\xB4\x68\xEA\x6C\x0E\x81\x1B" - "\x56\x2A\xD5\xBC\x69\x9C\xD1\xF0\x66\x7A\xEC\x49\x7A\x33\x3D\x0A" - "\xDE" - }, -}; - -struct rtp_packets audio_packets_gsm_invalid_size[] = { - /* RTP: SeqNo=1, TS=160 */ - {0.020000, 41, - "\x80\x03\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44" - "\xD4\x7C\xE3\xE9\x62\x50\x39\xF0\xF8\xB4\x68\xEA\x6C\x0E\x81\x1B" - "\x56\x2A\xD5\xBC\x69\x9C\xD1\xF0\x66\x7A\xEC\x49\x7A\x33\x3D\x0A" - "\xDE" - }, -}; - -struct rtp_packets audio_packets_gsm_invalid_data[] = { - /* RTP: SeqNo=1, TS=160 */ - {0.020000, 45, - "\x80\x03\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44" - "\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE" - "\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE" - "\xEE" - }, -}; - -struct rtp_packets audio_packets_gsm_invalid_ptype[] = { - /* RTP: SeqNo=1, TS=160 */ - {0.020000, 45, - "\x80\x08\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44" - "\xD4\x7C\xE3\xE9\x62\x50\x39\xF0\xF8\xB4\x68\xEA\x6C\x0E\x81\x1B" - "\x56\x2A\xD5\xBC\x69\x9C\xD1\xF0\x66\x7A\xEC\x49\x7A\x33\x3D\x0A" - "\xDE" - }, -}; - -struct rtp_packets audio_packets_g729[] = { - /* RTP: SeqNo=1, TS=160 */ - {0.020000, 32, - "\x80\x12\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44" - "\xAF\xC2\x81\x40\x00\xFA\xCE\xA4\x21\x7C\xC5\xC3\x4F\xA5\x98\xF5" - "\xB2\x95\xC4\xAD" - }, -}; - -struct rtp_packets audio_packets_pcma[] = { - /* RTP: SeqNo=1, TS=160 */ - {0.020000, 172, - "\x80\x08\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44" - "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" - "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" - "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" - "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" - "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" - "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" - "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" - "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" - "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" - "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" - }, - /* RTP: SeqNo=26527, TS=232640 */ - {0.020000, 92, - "\x80\x08\x67\x9f\x00\x03\x8c\xc0\x04\xaa\x67\x9f\xd5\xd5\xd5\xd5" - "\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5" - "\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5" - "\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5" - "\xd5\xd5\xd5\xd5\xd5\xd5\x55\x55\xd5\xd5\x55\x55\xd5\xd5\x55\x55" - "\xd5\xd5\xd5\x55\x55\xd5\xd5\xd5\x55\x55\xd5\xd5" - }, - /* RTP: SeqNo=26528, TS=232720 */ - {0.020000, 92, - "\x80\x08\x67\xa0\x00\x03\x8d\x10\x04\xaa\x67\x9f\x55\xd5\xd5\x55" - "\xd5\x55\xd5\xd5\xd5\x55\xd5\x55\xd5\xd5\x55\xd5\x55\xd5\x55\xd5" - "\x55\x55\xd5\x55\xd5\xd5\x55\x55\x55\x55\x55\xd5\xd5\x55\xd5\xd5" - "\xd5\x55\xd5\xd5\xd5\x55\x54\x55\xd5\xd5\x55\xd5\xd5\xd5\xd5\x55" - "\x54\x55\xd5\x55\xd5\x55\x55\x55\x55\x55\xd5\xd5\xd5\xd5\xd5\xd4" - "\xd5\x54\x55\xd5\xd4\xd5\x54\xd5\x55\xd5\xd5\xd5" - }, -}; - - - -static int audio_name_to_type(const char *name) -{ - if (!strcasecmp(name, "gsm")) - return 3; -#ifdef HAVE_BCG729 - else if (!strcasecmp(name, "g729")) - return 18; -#endif - else if (!strcasecmp(name, "pcma")) - return 8; - else if (!strcasecmp(name, "l16")) - return 11; - return -1; -} - -int mgcp_get_trans_frame_size(void *state_, int nsamples, int dst); - -static int given_configured_endpoint(int in_samples, int out_samples, - const char *srcfmt, const char *dstfmt, - void **out_ctx, struct mgcp_endpoint **out_endp) -{ - int rc; - struct mgcp_rtp_end *dst_end; - struct mgcp_rtp_end *src_end; - struct mgcp_config *cfg; - struct mgcp_trunk_config *tcfg; - struct mgcp_endpoint *endp; - - cfg = mgcp_config_alloc(); - tcfg = talloc_zero(cfg, struct mgcp_trunk_config); - endp = talloc_zero(tcfg, struct mgcp_endpoint); - - cfg->setup_rtp_processing_cb = mgcp_transcoding_setup; - cfg->rtp_processing_cb = mgcp_transcoding_process_rtp; - cfg->get_net_downlink_format_cb = mgcp_transcoding_net_downlink_format; - - tcfg->endpoints = endp; - tcfg->number_endpoints = 1; - tcfg->cfg = cfg; - endp->tcfg = tcfg; - endp->cfg = cfg; - mgcp_initialize_endp(endp); - - dst_end = &endp->bts_end; - dst_end->codec.payload_type = audio_name_to_type(dstfmt); - - src_end = &endp->net_end; - src_end->codec.payload_type = audio_name_to_type(srcfmt); - - if (out_samples) { - dst_end->codec.frame_duration_den = dst_end->codec.rate; - dst_end->codec.frame_duration_num = out_samples; - dst_end->frames_per_packet = 1; - dst_end->force_output_ptime = 1; - } - - rc = mgcp_transcoding_setup(endp, dst_end, src_end); - if (rc < 0) { - printf("setup failed: %s", strerror(-rc)); - abort(); - } - - *out_ctx = cfg; - *out_endp = endp; - return 0; -} - - -static int transcode_test(const char *srcfmt, const char *dstfmt, - uint8_t *src_pkts, size_t src_pkt_size) -{ - char buf[4096] = {0x80, 0}; - void *ctx; - - struct mgcp_rtp_end *dst_end; - struct mgcp_process_rtp_state *state; - struct mgcp_endpoint *endp; - int in_size; - const int in_samples = 160; - int len, cont; - - printf("== Transcoding test ==\n"); - printf("converting %s -> %s\n", srcfmt, dstfmt); - - given_configured_endpoint(in_samples, 0, srcfmt, dstfmt, &ctx, &endp); - - dst_end = &endp->bts_end; - state = dst_end->rtp_process_data; - OSMO_ASSERT(state != NULL); - - in_size = mgcp_transcoding_get_frame_size(state, in_samples, 0); - OSMO_ASSERT(sizeof(buf) >= in_size + 12); - - memcpy(buf, src_pkts, src_pkt_size); - - len = src_pkt_size; - - cont = mgcp_transcoding_process_rtp(endp, dst_end, - buf, &len, sizeof(buf)); - if (cont < 0) { - printf("Nothing encoded due: %s\n", strerror(-cont)); - talloc_free(ctx); - return -1; - } - - if (len < 24) { - printf("encoded: %s\n", osmo_hexdump((unsigned char *)buf, len)); - } else { - const char *str = osmo_hexdump((unsigned char *)buf, len); - int i = 0; - const int prefix = 4; - const int cutlen = 48; - int nchars = 0; - - printf("encoded:\n"); - do { - nchars = printf("%*s%-.*s", prefix, "", cutlen, str + i); - i += nchars - prefix; - printf("\n"); - } while (nchars - prefix >= cutlen); - } - printf("counted: %d\n", cont); - talloc_free(ctx); - return 0; -} - -static void test_rtp_seq_state(void) -{ - char buf[4096]; - int len; - int cont; - void *ctx; - struct mgcp_endpoint *endp; - struct mgcp_process_rtp_state *state; - struct rtp_hdr *hdr; - uint32_t ts_no; - uint16_t seq_no; - - given_configured_endpoint(160, 0, "pcma", "l16", &ctx, &endp); - state = endp->bts_end.rtp_process_data; - OSMO_ASSERT(!state->is_running); - OSMO_ASSERT(state->next_seq == 0); - OSMO_ASSERT(state->next_time == 0); - - /* initialize packet */ - len = audio_packets_pcma[0].len; - memcpy(buf, audio_packets_pcma[0].data, len); - cont = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, len); - OSMO_ASSERT(cont >= 0); - OSMO_ASSERT(state->is_running); - OSMO_ASSERT(state->next_seq == 2); - OSMO_ASSERT(state->next_time == 240); - - /* verify that the right timestamp was written */ - OSMO_ASSERT(len == audio_packets_pcma[0].len); - hdr = (struct rtp_hdr *) &buf[0]; - - memcpy(&ts_no, &hdr->timestamp, sizeof(ts_no)); - OSMO_ASSERT(htonl(ts_no) == 160); - memcpy(&seq_no, &hdr->sequence, sizeof(seq_no)); - OSMO_ASSERT(htons(seq_no) == 1); - /* Check the right sequence number is written */ - state->next_seq = 1234; - len = audio_packets_pcma[0].len; - memcpy(buf, audio_packets_pcma[0].data, len); - cont = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, len); - OSMO_ASSERT(cont >= 0); - OSMO_ASSERT(len == audio_packets_pcma[0].len); - hdr = (struct rtp_hdr *) &buf[0]; - - memcpy(&seq_no, &hdr->sequence, sizeof(seq_no)); - OSMO_ASSERT(htons(seq_no) == 1234); - - talloc_free(ctx); -} - -static void test_transcode_result(void) -{ - char buf[4096]; - int len, res; - void *ctx; - struct mgcp_endpoint *endp; - struct mgcp_process_rtp_state *state; - - { - /* from GSM to PCMA and same ptime */ - given_configured_endpoint(160, 0, "gsm", "pcma", &ctx, &endp); - state = endp->bts_end.rtp_process_data; - - /* result */ - len = audio_packets_gsm[0].len; - memcpy(buf, audio_packets_gsm[0].data, len); - res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); - OSMO_ASSERT(res == sizeof(struct rtp_hdr)); - OSMO_ASSERT(state->sample_cnt == 0); - - len = res; - res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); - OSMO_ASSERT(res == -ENOMSG); - - talloc_free(ctx); - } - - { - /* from GSM to PCMA and same ptime */ - given_configured_endpoint(160, 160, "gsm", "pcma", &ctx, &endp); - state = endp->bts_end.rtp_process_data; - - /* result */ - len = audio_packets_gsm[0].len; - memcpy(buf, audio_packets_gsm[0].data, len); - res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); - OSMO_ASSERT(res == sizeof(struct rtp_hdr)); - OSMO_ASSERT(state->sample_cnt == 0); - - len = res; - res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); - OSMO_ASSERT(res == -EAGAIN); - - talloc_free(ctx); - } - - { - /* from PCMA to GSM and wrong different ptime */ - given_configured_endpoint(80, 160, "pcma", "gsm", &ctx, &endp); - state = endp->bts_end.rtp_process_data; - - /* Add the first sample */ - len = audio_packets_pcma[1].len; - memcpy(buf, audio_packets_pcma[1].data, len); - res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); - OSMO_ASSERT(state->sample_cnt == 80); - OSMO_ASSERT(state->next_time == 232640); - OSMO_ASSERT(res < 0); - - /* Add the second sample and it should be consumable */ - len = audio_packets_pcma[2].len; - memcpy(buf, audio_packets_pcma[2].data, len); - res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); - OSMO_ASSERT(state->sample_cnt == 0); - OSMO_ASSERT(state->next_time == 232640 + 80 + 160); - OSMO_ASSERT(res == sizeof(struct rtp_hdr)); - - talloc_free(ctx); - } - - { - /* from PCMA to GSM with a big time jump */ - struct rtp_hdr *hdr; - uint32_t ts; - - given_configured_endpoint(80, 160, "pcma", "gsm", &ctx, &endp); - state = endp->bts_end.rtp_process_data; - - /* Add the first sample */ - len = audio_packets_pcma[1].len; - memcpy(buf, audio_packets_pcma[1].data, len); - res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); - OSMO_ASSERT(state->sample_cnt == 80); - OSMO_ASSERT(state->next_time == 232640); - OSMO_ASSERT(state->next_seq == 26527); - OSMO_ASSERT(res < 0); - - /* Add a skip to the packet to force a 'resync' */ - len = audio_packets_pcma[2].len; - memcpy(buf, audio_packets_pcma[2].data, len); - hdr = (struct rtp_hdr *) &buf[0]; - /* jump the time and add alignment error */ - ts = ntohl(hdr->timestamp) + 123 * 80 + 2; - hdr->timestamp = htonl(ts); - res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); - OSMO_ASSERT(res < 0); - OSMO_ASSERT(state->sample_cnt == 80); - OSMO_ASSERT(state->next_time == ts); - OSMO_ASSERT(state->next_seq == 26527); - /* TODO: this can create alignment errors */ - - - /* Now attempt to consume 160 samples */ - len = audio_packets_pcma[2].len; - memcpy(buf, audio_packets_pcma[2].data, len); - hdr = (struct rtp_hdr *) &buf[0]; - ts += 80; - hdr->timestamp = htonl(ts); - res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); - OSMO_ASSERT(res == 12); - OSMO_ASSERT(state->sample_cnt == 0); - OSMO_ASSERT(state->next_time == ts + 160); - OSMO_ASSERT(state->next_seq == 26528); - - talloc_free(ctx); - } -} - -static void test_transcode_change(void) -{ - char buf[4096] = {0x80, 0}; - void *ctx; - - struct mgcp_endpoint *endp; - struct mgcp_process_rtp_state *state; - struct rtp_hdr *hdr; - - int len, res; - - { - /* from GSM to PCMA and same ptime */ - printf("Testing Initial L16->GSM, PCMA->GSM\n"); - given_configured_endpoint(160, 0, "l16", "gsm", &ctx, &endp); - endp->net_end.alt_codec = endp->net_end.codec; - endp->net_end.alt_codec.payload_type = audio_name_to_type("pcma"); - state = endp->bts_end.rtp_process_data; - - /* initial transcoding work */ - OSMO_ASSERT(state->src_fmt == AF_L16); - OSMO_ASSERT(state->dst_fmt == AF_GSM); - OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 8); - OSMO_ASSERT(endp->net_end.codec.payload_type == 11); - - /* result */ - len = audio_packets_pcma[0].len; - memcpy(buf, audio_packets_pcma[0].data, len); - res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); - state = endp->bts_end.rtp_process_data; - OSMO_ASSERT(res == sizeof(struct rtp_hdr)); - OSMO_ASSERT(state->sample_cnt == 0); - OSMO_ASSERT(state->src_fmt == AF_PCMA); - OSMO_ASSERT(state->dst_fmt == AF_GSM); - OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 11); - OSMO_ASSERT(endp->net_end.codec.payload_type == 8); - - len = res; - res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); - OSMO_ASSERT(res == -ENOMSG); - OSMO_ASSERT(state == endp->bts_end.rtp_process_data); - - - /* now check that comfort noise doesn't change anything */ - len = audio_packets_pcma[1].len; - memcpy(buf, audio_packets_pcma[1].data, len); - hdr = (struct rtp_hdr *) buf; - hdr->payload_type = 12; - res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); - OSMO_ASSERT(state == endp->bts_end.rtp_process_data); - OSMO_ASSERT(state->sample_cnt == 80); - OSMO_ASSERT(state->src_fmt == AF_PCMA); - OSMO_ASSERT(state->dst_fmt == AF_GSM); - OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 11); - OSMO_ASSERT(endp->net_end.codec.payload_type == 8); - - talloc_free(ctx); - } -} - -static int test_repacking(int in_samples, int out_samples, int no_transcode) -{ - char buf[4096] = {0x80, 0}; - int cc; - struct mgcp_endpoint *endp; - void *ctx; - - struct mgcp_process_rtp_state *state; - int in_cnt; - int out_size; - int in_size; - uint32_t ts = 0; - uint16_t seq = 0; - const char *srcfmt = "pcma"; - const char *dstfmt = no_transcode ? "pcma" : "l16"; - - printf("== Transcoding test ==\n"); - printf("converting %s -> %s\n", srcfmt, dstfmt); - - given_configured_endpoint(in_samples, out_samples, srcfmt, dstfmt, &ctx, &endp); - - state = endp->bts_end.rtp_process_data; - OSMO_ASSERT(state != NULL); - - in_size = mgcp_transcoding_get_frame_size(state, in_samples, 0); - OSMO_ASSERT(sizeof(buf) >= in_size + 12); - - out_size = mgcp_transcoding_get_frame_size(state, -1, 1); - OSMO_ASSERT(sizeof(buf) >= out_size + 12); - - buf[1] = endp->net_end.codec.payload_type; - *(uint16_t*)(buf+2) = htons(1); - *(uint32_t*)(buf+4) = htonl(0); - *(uint32_t*)(buf+8) = htonl(0xaabbccdd); - - for (in_cnt = 0; in_cnt < 16; in_cnt++) { - int cont; - int len; - - /* fake PCMA data */ - printf("generating %d %s input samples\n", in_samples, srcfmt); - for (cc = 0; cc < in_samples; cc++) - buf[12+cc] = cc; - - *(uint16_t*)(buf+2) = htonl(seq); - *(uint32_t*)(buf+4) = htonl(ts); - - seq += 1; - ts += in_samples; - - cc += 12; /* include RTP header */ - - len = cc; - - do { - cont = mgcp_transcoding_process_rtp(endp, &endp->bts_end, - buf, &len, sizeof(buf)); - if (cont == -EAGAIN) { - fprintf(stderr, "Got EAGAIN\n"); - break; - } - - if (cont < 0) { - printf("processing failed: %s", strerror(-cont)); - abort(); - } - - len -= 12; /* ignore RTP header */ - - printf("got %d %s output frames (%d octets) count=%d\n", - len / out_size, dstfmt, len, cont); - - len = cont; - } while (len > 0); - } - - talloc_free(ctx); - return 0; -} - -static const struct log_info_cat log_categories[] = { -}; - -const struct log_info log_info = { - .cat = log_categories, - .num_cat = ARRAY_SIZE(log_categories), -}; - -int main(int argc, char **argv) -{ - int rc; - void *ctx = talloc_named_const(NULL, 0, "mgcp_transcoding_test"); - osmo_init_logging2(ctx, &log_info); - - printf("=== Transcoding Good Cases ===\n"); - - transcode_test("l16", "l16", - (uint8_t *)audio_packets_l16[0].data, - audio_packets_l16[0].len); - transcode_test("l16", "gsm", - (uint8_t *)audio_packets_l16[0].data, - audio_packets_l16[0].len); - transcode_test("l16", "pcma", - (uint8_t *)audio_packets_l16[0].data, - audio_packets_l16[0].len); - transcode_test("gsm", "l16", - (uint8_t *)audio_packets_gsm[0].data, - audio_packets_gsm[0].len); - transcode_test("gsm", "gsm", - (uint8_t *)audio_packets_gsm[0].data, - audio_packets_gsm[0].len); - transcode_test("gsm", "pcma", - (uint8_t *)audio_packets_gsm[0].data, - audio_packets_gsm[0].len); - transcode_test("pcma", "l16", - (uint8_t *)audio_packets_pcma[0].data, - audio_packets_pcma[0].len); - transcode_test("pcma", "gsm", - (uint8_t *)audio_packets_pcma[0].data, - audio_packets_pcma[0].len); - transcode_test("pcma", "pcma", - (uint8_t *)audio_packets_pcma[0].data, - audio_packets_pcma[0].len); - - printf("=== Transcoding Bad Cases ===\n"); - - printf("Invalid size:\n"); - rc = transcode_test("gsm", "pcma", - (uint8_t *)audio_packets_gsm_invalid_size[0].data, - audio_packets_gsm_invalid_size[0].len); - OSMO_ASSERT(rc < 0); - - printf("Invalid data:\n"); - rc = transcode_test("gsm", "pcma", - (uint8_t *)audio_packets_gsm_invalid_data[0].data, - audio_packets_gsm_invalid_data[0].len); - OSMO_ASSERT(rc < 0); - - printf("Invalid payload type:\n"); - rc = transcode_test("gsm", "pcma", - (uint8_t *)audio_packets_gsm_invalid_ptype[0].data, - audio_packets_gsm_invalid_ptype[0].len); - OSMO_ASSERT(rc == 0); - - printf("=== Repacking ===\n"); - - test_repacking(160, 160, 0); - test_repacking(160, 160, 1); - test_repacking(160, 80, 0); - test_repacking(160, 80, 1); - test_repacking(160, 320, 0); - test_repacking(160, 320, 1); - test_repacking(160, 240, 0); - test_repacking(160, 240, 1); - test_repacking(160, 100, 0); - test_repacking(160, 100, 1); - test_rtp_seq_state(); - test_transcode_result(); - test_transcode_change(); - - return 0; -} - diff --git a/tests/legacy_mgcp/mgcp_transcoding_test.ok b/tests/legacy_mgcp/mgcp_transcoding_test.ok deleted file mode 100644 index 387cfd275..000000000 --- a/tests/legacy_mgcp/mgcp_transcoding_test.ok +++ /dev/null @@ -1,539 +0,0 @@ -=== Transcoding Good Cases === -== Transcoding test == -converting l16 -> l16 -encoded: - 80 0b 00 01 00 00 00 a0 11 22 33 44 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 - 5a 9e 40 13 00 00 bf ed a5 62 bf ed -counted: 0 -== Transcoding test == -converting l16 -> gsm -encoded: - 80 0b 00 01 00 00 00 a0 11 22 33 44 d4 7c e3 e9 - 62 50 39 f0 f8 b4 68 ea 6c 0e 81 1b 56 2a d5 bc - 69 9c d1 f0 66 7a ec 49 7a 33 3d 0a de -counted: 12 -== Transcoding test == -converting l16 -> pcma -encoded: - 80 0b 00 01 00 00 00 a0 11 22 33 44 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 -counted: 12 -== Transcoding test == -converting gsm -> l16 -encoded: - 80 03 00 01 00 00 00 a0 11 22 33 44 00 00 54 00 - 59 f0 34 20 c4 c8 b9 f8 e2 18 f1 e8 f2 28 f0 e0 - 46 08 4f 80 2c a0 a9 c8 80 00 c0 58 3f 80 63 c0 - 24 b8 fa b8 f6 88 0b a0 c8 70 a8 b0 c8 c0 3b a8 - 66 a0 2e 38 d1 f8 98 98 aa 18 e8 30 26 a0 37 40 - 37 e8 17 00 ee 50 b7 80 b1 88 de 28 18 40 45 b0 - 4f 48 21 d8 df 78 ae 68 ab 98 d6 b8 18 18 48 90 - 4e 70 27 40 e8 10 b5 b0 ac 80 d4 60 14 50 48 48 - 50 10 2a 00 ec 08 ba 00 af 58 d1 c0 10 60 45 c8 - 54 10 30 78 f1 a8 bb 18 ad 48 ce 30 0a e8 3f 30 - 4f 10 32 18 f6 18 bf 20 ac 30 cd 80 0b d0 43 d8 - 55 e0 34 a0 f5 78 bc 98 ad 98 cd c8 0a 80 40 58 - 51 c0 35 40 f9 60 c1 68 ac c8 cb 38 08 00 40 98 - 51 e0 34 d8 fa 28 c2 f0 ae 40 c7 70 02 d0 3c a8 - 54 78 38 a0 fc 68 c2 08 ad 50 c7 78 01 60 39 c0 - 51 38 3a e8 00 e8 c6 38 ab d8 c4 00 fe 08 39 18 - 50 30 39 50 01 d8 ca 70 b1 80 c4 c8 fc 58 36 40 - 51 d8 3b 08 02 80 c8 58 b0 60 c5 a8 fb d0 33 e8 - 4e 80 3c e0 06 10 cb 90 ae 48 c2 60 f9 58 34 08 - 4d a0 3a a8 06 48 cf 80 b4 60 c3 e8 f7 90 30 18 - 4d a0 3b 98 07 90 cf 18 b4 68 c4 88 -counted: 12 -== Transcoding test == -converting gsm -> gsm -encoded: - 80 03 00 01 00 00 00 a0 11 22 33 44 d4 7c e3 e9 - 62 50 39 f0 f8 b4 68 ea 6c 0e 81 1b 56 2a d5 bc - 69 9c d1 f0 66 7a ec 49 7a 33 3d 0a de -counted: 0 -== Transcoding test == -converting gsm -> pcma -encoded: - 80 03 00 01 00 00 00 a0 11 22 33 44 d5 a0 a3 bf - 38 24 08 19 1e 1b a4 a6 b3 20 2a 3a ba ad b7 60 - 17 92 3e 20 3e b8 ac b2 32 2c 20 02 b6 be be 82 - 04 27 26 35 8d a4 a6 b5 35 21 20 31 8d a7 a6 b6 - 02 27 21 30 81 a7 a1 b0 06 24 21 32 85 a4 a0 bd - 19 24 21 3d 90 ba a6 bc 16 25 21 3c 92 a5 a0 bf - 10 25 21 3c 90 a5 a1 bf 6f 3a 21 3f 95 a5 a1 bf - 62 3b 21 39 f3 bb a0 b9 79 3b 21 39 c3 b9 a1 b8 - db 39 20 3b 4a b9 a1 b9 c8 3f 26 38 78 be a1 b8 - f1 3e 26 38 65 bc a6 bb ed 3f 21 3b 6f bf a6 b8 - ec 3d 27 3b 15 bd a6 b8 eb 3d 27 38 -counted: 12 -== Transcoding test == -converting pcma -> l16 -encoded: - 80 08 00 01 00 00 00 a0 11 22 33 44 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 - 5a 00 42 00 00 08 be 00 a6 00 be 00 -counted: 12 -== Transcoding test == -converting pcma -> gsm -encoded: - 80 08 00 01 00 00 00 a0 11 22 33 44 d4 b9 f4 5d - d9 50 5a e1 a0 cd 76 ea 52 0e 87 53 ad d4 ea a2 - 0a 63 ca e9 60 79 e2 2a 25 d2 c0 f3 39 -counted: 12 -== Transcoding test == -converting pcma -> pcma -encoded: - 80 08 00 01 00 00 00 a0 11 22 33 44 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 - d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 -counted: 0 -=== Transcoding Bad Cases === -Invalid size: -== Transcoding test == -converting gsm -> pcma -Nothing encoded due: No message of desired type -Invalid data: -== Transcoding test == -converting gsm -> pcma -Nothing encoded due: No message of desired type -Invalid payload type: -== Transcoding test == -converting gsm -> pcma -encoded: - 80 08 00 01 00 00 00 a0 11 22 33 44 d5 a0 a3 bf - 38 24 08 19 1e 1b a4 a6 b3 20 2a 3a ba ad b7 60 - 17 92 3e 20 3e b8 ac b2 32 2c 20 02 b6 be be 82 - 04 27 26 35 8d a4 a6 b5 35 21 20 31 8d a7 a6 b6 - 02 27 21 30 81 a7 a1 b0 06 24 21 32 85 a4 a0 bd - 19 24 21 3d 90 ba a6 bc 16 25 21 3c 92 a5 a0 bf - 10 25 21 3c 90 a5 a1 bf 6f 3a 21 3f 95 a5 a1 bf - 62 3b 21 39 f3 bb a0 b9 79 3b 21 39 c3 b9 a1 b8 - db 39 20 3b 4a b9 a1 b9 c8 3f 26 38 78 be a1 b8 - f1 3e 26 38 65 bc a6 bb ed 3f 21 3b 6f bf a6 b8 - ec 3d 27 3b 15 bd a6 b8 eb 3d 27 38 -counted: 12 -=== Repacking === -== Transcoding test == -converting pcma -> l16 -generating 160 pcma input samples -got 2 l16 output frames (320 octets) count=12 -generating 160 pcma input samples -got 2 l16 output frames (320 octets) count=12 -generating 160 pcma input samples -got 2 l16 output frames (320 octets) count=12 -generating 160 pcma input samples -got 2 l16 output frames (320 octets) count=12 -generating 160 pcma input samples -got 2 l16 output frames (320 octets) count=12 -generating 160 pcma input samples -got 2 l16 output frames (320 octets) count=12 -generating 160 pcma input samples -got 2 l16 output frames (320 octets) count=12 -generating 160 pcma input samples -got 2 l16 output frames (320 octets) count=12 -generating 160 pcma input samples -got 2 l16 output frames (320 octets) count=12 -generating 160 pcma input samples -got 2 l16 output frames (320 octets) count=12 -generating 160 pcma input samples -got 2 l16 output frames (320 octets) count=12 -generating 160 pcma input samples -got 2 l16 output frames (320 octets) count=12 -generating 160 pcma input samples -got 2 l16 output frames (320 octets) count=12 -generating 160 pcma input samples -got 2 l16 output frames (320 octets) count=12 -generating 160 pcma input samples -got 2 l16 output frames (320 octets) count=12 -generating 160 pcma input samples -got 2 l16 output frames (320 octets) count=12 -== Transcoding test == -converting pcma -> pcma -generating 160 pcma input samples -got 2 pcma output frames (160 octets) count=12 -generating 160 pcma input samples -got 2 pcma output frames (160 octets) count=12 -generating 160 pcma input samples -got 2 pcma output frames (160 octets) count=12 -generating 160 pcma input samples -got 2 pcma output frames (160 octets) count=12 -generating 160 pcma input samples -got 2 pcma output frames (160 octets) count=12 -generating 160 pcma input samples -got 2 pcma output frames (160 octets) count=12 -generating 160 pcma input samples -got 2 pcma output frames (160 octets) count=12 -generating 160 pcma input samples -got 2 pcma output frames (160 octets) count=12 -generating 160 pcma input samples -got 2 pcma output frames (160 octets) count=12 -generating 160 pcma input samples -got 2 pcma output frames (160 octets) count=12 -generating 160 pcma input samples -got 2 pcma output frames (160 octets) count=12 -generating 160 pcma input samples -got 2 pcma output frames (160 octets) count=12 -generating 160 pcma input samples -got 2 pcma output frames (160 octets) count=12 -generating 160 pcma input samples -got 2 pcma output frames (160 octets) count=12 -generating 160 pcma input samples -got 2 pcma output frames (160 octets) count=12 -generating 160 pcma input samples -got 2 pcma output frames (160 octets) count=12 -== Transcoding test == -converting pcma -> l16 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -== Transcoding test == -converting pcma -> pcma -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -== Transcoding test == -converting pcma -> l16 -generating 160 pcma input samples -generating 160 pcma input samples -got 4 l16 output frames (640 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 4 l16 output frames (640 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 4 l16 output frames (640 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 4 l16 output frames (640 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 4 l16 output frames (640 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 4 l16 output frames (640 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 4 l16 output frames (640 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 4 l16 output frames (640 octets) count=12 -== Transcoding test == -converting pcma -> pcma -generating 160 pcma input samples -generating 160 pcma input samples -got 4 pcma output frames (320 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 4 pcma output frames (320 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 4 pcma output frames (320 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 4 pcma output frames (320 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 4 pcma output frames (320 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 4 pcma output frames (320 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 4 pcma output frames (320 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 4 pcma output frames (320 octets) count=12 -== Transcoding test == -converting pcma -> l16 -generating 160 pcma input samples -generating 160 pcma input samples -got 3 l16 output frames (480 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 3 l16 output frames (480 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 3 l16 output frames (480 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 3 l16 output frames (480 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 3 l16 output frames (480 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 3 l16 output frames (480 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 3 l16 output frames (480 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 3 l16 output frames (480 octets) count=12 -== Transcoding test == -converting pcma -> pcma -generating 160 pcma input samples -generating 160 pcma input samples -got 3 pcma output frames (240 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 3 pcma output frames (240 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 3 pcma output frames (240 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 3 pcma output frames (240 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 3 pcma output frames (240 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 3 pcma output frames (240 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 3 pcma output frames (240 octets) count=12 -generating 160 pcma input samples -generating 160 pcma input samples -got 3 pcma output frames (240 octets) count=12 -== Transcoding test == -converting pcma -> l16 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -generating 160 pcma input samples -got 1 l16 output frames (160 octets) count=12 -got 1 l16 output frames (160 octets) count=12 -== Transcoding test == -converting pcma -> pcma -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -generating 160 pcma input samples -got 1 pcma output frames (80 octets) count=12 -got 1 pcma output frames (80 octets) count=12 -Testing Initial L16->GSM, PCMA->GSM diff --git a/tests/testsuite.at b/tests/testsuite.at index 03ec4b902..3585bf05c 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -1,19 +1,6 @@ AT_INIT AT_BANNER([Regression tests.]) -AT_SETUP([legacy_mgcp]) -AT_KEYWORDS([legacy_mgcp]) -cat $abs_srcdir/legacy_mgcp/mgcp_test.ok > expout -AT_CHECK([$abs_top_builddir/tests/legacy_mgcp/mgcp_test], [], [expout], [ignore]) -AT_CLEANUP - -AT_SETUP([legacy_mgcp-trans]) -AT_KEYWORDS([legacy_mgcp-trans]) -AT_CHECK([test "$enable_mgcp_transcoding_test" == yes || exit 77]) -cat $abs_srcdir/legacy_mgcp/mgcp_transcoding_test.ok > expout -AT_CHECK([$abs_top_builddir/tests/legacy_mgcp/mgcp_transcoding_test], [], [expout], [ignore]) -AT_CLEANUP - AT_SETUP([mgcp_client]) AT_KEYWORDS([mgcp_client]) cat $abs_srcdir/mgcp_client/mgcp_client_test.ok > expout diff --git a/tests/vty_test_runner.py b/tests/vty_test_runner.py deleted file mode 100644 index 05bc3bf89..000000000 --- a/tests/vty_test_runner.py +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/env python - -# (C) 2013 by Katerina Barone-Adesi -# (C) 2013 by Holger Hans Peter Freyther -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -import os, sys -import time -import unittest -import socket -import subprocess - -import osmopy.obscvty as obscvty -import osmopy.osmoutil as osmoutil - -# add $top_srcdir/contrib to find ipa.py -sys.path.append(os.path.join(sys.path[0], '..', 'contrib')) - -from ipa import IPA - -# to be able to find $top_srcdir/doc/... -confpath = os.path.join(sys.path[0], '..') - -class TestVTYBase(unittest.TestCase): - - def checkForEndAndExit(self): - res = self.vty.command("list") - #print ('looking for "exit"\n') - self.assert_(res.find(' exit\r') > 0) - #print 'found "exit"\nlooking for "end"\n' - self.assert_(res.find(' end\r') > 0) - #print 'found "end"\n' - - def vty_command(self): - raise Exception("Needs to be implemented by a subclass") - - def vty_app(self): - raise Exception("Needs to be implemented by a subclass") - - def setUp(self): - osmo_vty_cmd = self.vty_command()[:] - config_index = osmo_vty_cmd.index('-c') - if config_index: - cfi = config_index + 1 - osmo_vty_cmd[cfi] = os.path.join(confpath, osmo_vty_cmd[cfi]) - - try: - self.proc = osmoutil.popen_devnull(osmo_vty_cmd) - except OSError: - print >> sys.stderr, "Current directory: %s" % os.getcwd() - print >> sys.stderr, "Consider setting -b" - - appstring = self.vty_app()[2] - appport = self.vty_app()[0] - self.vty = obscvty.VTYInteract(appstring, "127.0.0.1", appport) - - def tearDown(self): - if self.vty: - self.vty._close_socket() - self.vty = None - osmoutil.end_proc(self.proc) - -class TestVTYMGCP(TestVTYBase): - def vty_command(self): - return ["./src/osmo-bsc_mgcp/osmo-bsc_mgcp", "-c", - "doc/examples/osmo-bsc_mgcp/mgcp.cfg"] - - def vty_app(self): - return (4243, "./src/osmo-bsc_mgcp/osmo-bsc_mgcp", "OpenBSC MGCP", "mgcp") - - def testForcePtime(self): - self.vty.enable() - res = self.vty.command("show running-config") - self.assert_(res.find(' rtp force-ptime 20\r') > 0) - self.assertEquals(res.find(' no rtp force-ptime\r'), -1) - - self.vty.command("configure terminal") - self.vty.command("mgcp") - self.vty.command("no rtp force-ptime") - res = self.vty.command("show running-config") - self.assertEquals(res.find(' rtp force-ptime 20\r'), -1) - self.assertEquals(res.find(' no rtp force-ptime\r'), -1) - - def testOmitAudio(self): - self.vty.enable() - res = self.vty.command("show running-config") - self.assert_(res.find(' sdp audio-payload send-name\r') > 0) - self.assertEquals(res.find(' no sdp audio-payload send-name\r'), -1) - - self.vty.command("configure terminal") - self.vty.command("mgcp") - self.vty.command("no sdp audio-payload send-name") - res = self.vty.command("show running-config") - self.assertEquals(res.find(' rtp sdp audio-payload send-name\r'), -1) - self.assert_(res.find(' no sdp audio-payload send-name\r') > 0) - - # TODO: test it for the trunk! - - def testBindAddr(self): - self.vty.enable() - - self.vty.command("configure terminal") - self.vty.command("mgcp") - - # enable.. disable bts-bind-ip - self.vty.command("rtp bts-bind-ip 254.253.252.250") - res = self.vty.command("show running-config") - self.assert_(res.find('rtp bts-bind-ip 254.253.252.250') > 0) - self.vty.command("no rtp bts-bind-ip") - res = self.vty.command("show running-config") - self.assertEquals(res.find(' rtp bts-bind-ip'), -1) - - # enable.. disable net-bind-ip - self.vty.command("rtp net-bind-ip 254.253.252.250") - res = self.vty.command("show running-config") - self.assert_(res.find('rtp net-bind-ip 254.253.252.250') > 0) - self.vty.command("no rtp net-bind-ip") - res = self.vty.command("show running-config") - self.assertEquals(res.find(' rtp net-bind-ip'), -1) - - -if __name__ == '__main__': - import argparse - import sys - - workdir = '.' - - parser = argparse.ArgumentParser() - parser.add_argument("-v", "--verbose", dest="verbose", - action="store_true", help="verbose mode") - parser.add_argument("-p", "--pythonconfpath", dest="p", - help="searchpath for config") - parser.add_argument("-w", "--workdir", dest="w", - help="Working directory") - parser.add_argument("test_name", nargs="*", help="(parts of) test names to run, case-insensitive") - args = parser.parse_args() - - verbose_level = 1 - if args.verbose: - verbose_level = 2 - - if args.w: - workdir = args.w - - if args.p: - confpath = args.p - - print "confpath %s, workdir %s" % (confpath, workdir) - os.chdir(workdir) - print "Running tests for specific VTY commands" - suite = unittest.TestSuite() - suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestVTYMGCP)) - - if args.test_name: - osmoutil.pick_tests(suite, *args.test_name) - - res = unittest.TextTestRunner(verbosity=verbose_level, stream=sys.stdout).run(suite) - sys.exit(len(res.errors) + len(res.failures)) - -# vim: shiftwidth=4 expandtab nocin ai