Compare commits

..

1 Commits

Author SHA1 Message Date
Keith Whyte
4dde3b6873 Don't build docs
Change-Id: Ifb835fb56ef6c85e02d8773b9d6278c4fd145e05
2025-09-04 17:38:03 +01:00
30 changed files with 913 additions and 1087 deletions

2
.gitignore vendored
View File

@@ -8,8 +8,6 @@ Makefile
Makefile.in
bscconfig.h
bscconfig.h.in
include/osmocom/mgcp_client/mgcp_common.h
include/osmocom/mgcp_client/version.h
src/osmo-mgw/osmo-mgw
*.*~
*.sw?

View File

@@ -9,4 +9,3 @@
#library what description / commit summary line
libosmocore bump_dep; workaround Bump libosmocore version dependency after I68328adb952ca8833ba047cb3b49ccc6f8a1f1b5
has been merged to libosmocore.git; then remove my_msgb_copy_c wrapper function.
libosmocodec bump_dep We depend on the additions of I2c510ac62a0786c137115c45eee7a48b9736265f

View File

@@ -45,7 +45,6 @@ AC_SUBST(LIBRARY_DLSYM)
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.11.0)
PKG_CHECK_MODULES(LIBOSMOCODEC, libosmocodec >= 1.11.0)
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.11.0)
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.11.0)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.11.0)

9
debian/control vendored
View File

@@ -9,7 +9,6 @@ Build-Depends: debhelper (>= 10),
libosmocore-dev (>= 1.11.0),
libosmo-netif-dev (>= 1.6.0),
libosmo-abis-dev (>= 2.0.0),
osmo-gsm-manuals-dev (>= 1.6.0)
Standards-Version: 3.9.8
Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw
Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw
@@ -36,11 +35,3 @@ Multi-Arch: same
Depends: libosmo-mgcp-client14 (= ${binary:Version}), ${misc:Depends}
Description: libosmo-mgcp-client: Osmocom's Media Gateway Control Protocol client utilities
Package: osmo-mgw-doc
Architecture: all
Section: doc
Priority: optional
Depends: ${misc:Depends}
Description: ${misc:Package} PDF documentation
Various manuals: user manual, VTY reference manual and/or
protocol/interface manuals.

2
debian/rules vendored
View File

@@ -30,7 +30,7 @@ override_dh_auto_test:
dh_auto_test || (find . -name testsuite.log -exec cat {} \; ; false)
override_dh_auto_configure:
dh_auto_configure -- --with-systemdsystemunitdir=/lib/systemd/system --enable-manuals
dh_auto_configure -- --with-systemdsystemunitdir=/lib/systemd/system
# Don't create .pdf.gz files (barely saves space and they can't be opened directly by most pdf readers)
override_dh_compress:

View File

@@ -70,85 +70,3 @@ a=ptime:40
=== `X-Osmux`
See <<mgcp-extension-osmux>>
=== Non-standard SDP codec parameters
CRCX command message normally includes an SDP block that specifies the RTP
address of the connecting peer and the list of codecs accepted by that entity.
Codec specifications may include optional parameters given via `a=fmtp` lines;
one well-known parameter is `octet-align`, defined for AMR and AMR-WB codecs.
In addition to standard (RFC-defined) codec parameters (of which the
just-mentioned `octet-align` parameter is the only one implemented so far),
OsmoMGW also understands some non-standard (Osmocom-private) codec parameters
as listed below.
These Osmocom-private codec parameters are meaningful only in the context
of OsmoBSC driving an E1 Abis MGW, which may be either OsmoMGW or a specialized
third-party replacement.
The MGCP extension described in this section is meaningful only for E1
endpoints - it has absolutely no effect on `rtpbridge` endpoints!
==== `tw-ts-001` parameter for FR and EFR codecs
GSM Full Rate codec is known in SDP as `GSM`; GSM Enhanced Full Rate codec
is known in SDP as `GSM-EFR`.
When either codec is to be transported in RTP, there is a choice between
two different payload formats: RFC 3551 or TW-TS-001.
RFC 3551 is the standard in non-GSM Internet applications, and it is the
format specified in later 3GPP releases for IP-based transport of
compressed speech - however, it exhibits functional regressions compared
to the original TRAU-UL frame format of GSM 08.60.
TW-TS-001 is an enhanced alternative payload format for the same codecs
that restores the original functionality and semantics of TRAU-UL frames.
In the context of CRCX or MDCX command messages from OsmoBSC to an E1 Abis MGW,
`tw-ts-001` codec parameter (attached to either `GSM` or `GSM-EFR` codec)
instructs the MGW whether or not it should emit the extended payload format
of TW-TS-001 for GSM uplink traffic converted to RTP.
In the absence of this parameter, IETF-standard and 3GPP-standard RFC 3551
format is emitted; if TW-TS-001 output is desired, please specify
`tw-ts-001=1` on the appropriate `a=fmtp` line.
.Example: `CRCX` message requesting EFR codec with TW-TS-001 extensions
----
CRCX 2 ds/e1-0/s-2/su16-2@mgw MGCP 1.0
M: recvonly
C: 2
L: p:20
v=0
c=IN IP4 123.12.12.123
m=audio 1234 RTP/AVP 110
a=rtpmap:110 GSM-EFR/8000/1
a=fmtp:110 tw-ts-001=1
----
==== `tw-ts-002` parameter for HR codec
GSM Half Rate codec is known in SDP as `GSM-HR-08`.
The same dichotomy that exists between RFC 3551 and TW-TS-001 RTP payload
formats for FR and EFR codecs also exists for HR codec, except that
the two opposing alternatives are now RFC 5993 and TW-TS-002.
In the context of CRCX or MDCX command messages from OsmoBSC to an E1 Abis MGW,
`tw-ts-002` codec parameter (attached to `GSM-HR-08` codec)
instructs the MGW whether or not it should emit the extended payload format
of TW-TS-002 for GSM uplink traffic converted to RTP.
In the absence of this parameter, IETF-standard and 3GPP-standard RFC 5993
format is emitted; if TW-TS-002 output is desired, please specify
`tw-ts-002=1` on the appropriate `a=fmtp` line.
.Example: `CRCX` message requesting HR codec with TW-TS-002 extensions
----
CRCX 2 ds/e1-0/s-2/su8-2@mgw MGCP 1.0
M: recvonly
C: 2
L: p:20
v=0
c=IN IP4 123.12.12.123
m=audio 1234 RTP/AVP 111
a=rtpmap:111 GSM-HR-08/8000/1
a=fmtp:111 tw-ts-002=1
----

View File

@@ -40,8 +40,6 @@
#include "mgcp_ratectr.h"
extern void *tall_mgw_ctx;
#define RTP_PORT_DEFAULT_RANGE_START 16002
#define RTP_PORT_DEFAULT_RANGE_END RTP_PORT_DEFAULT_RANGE_START + 64
@@ -52,6 +50,11 @@ struct mgcp_endpoint;
struct mgcp_config;
struct mgcp_trunk;
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?
@@ -130,6 +133,10 @@ struct mgcp_config {
char source_addr[INET6_ADDRSTRLEN];
char call_agent_addr[INET6_ADDRSTRLEN];
/* RTP processing */
mgcp_processing rtp_processing_cb;
mgcp_processing_setup setup_rtp_processing_cb;
struct osmo_wqueue gw_fd;
struct mgcp_port_range net_ports;

View File

@@ -63,10 +63,6 @@ enum mgcp_x_osmo_ign {
struct mgcp_codec_param {
bool amr_octet_aligned_present;
bool amr_octet_aligned;
bool fr_efr_twts001_present;
bool fr_efr_twts001;
bool hr_twts002_present;
bool hr_twts002;
};
/* Ensure that the msg->l2h is NUL terminated. */

View File

@@ -22,6 +22,6 @@ static const uint8_t e1_rates[] = { 64, 32, 32, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8
static const uint8_t e1_offsets[] = { 0, 0, 4, 0, 2, 4, 6, 0, 1, 2, 3, 4, 5, 6, 7 };
int mgcp_e1_endp_equip(struct mgcp_endpoint *endp, uint8_t ts, uint8_t ss, uint8_t offs);
int mgcp_e1_endp_update(struct mgcp_endpoint *endp);
void mgcp_e1_endp_update(struct mgcp_endpoint *endp);
void mgcp_e1_endp_release(struct mgcp_endpoint *endp, uint8_t ts);
int mgcp_e1_send_rtp(struct mgcp_endpoint *endp, struct mgcp_rtp_codec *codec, struct msgb *msg);

View File

@@ -124,7 +124,6 @@ struct mgcp_endpoint {
struct osmo_fsm_inst *trau_sync_fi;
struct osmo_trau2rtp_state *trau_rtp_st;
uint8_t last_amr_ft;
uint8_t rtp_extensions;
struct mgcp_rtp_codec *last_codec;
} e1;
@@ -132,7 +131,7 @@ struct mgcp_endpoint {
struct mgcp_endpoint *mgcp_endp_alloc(struct mgcp_trunk *trunk, unsigned int index);
int mgcp_endp_claim(struct mgcp_endpoint *endp, const char *callid);
int mgcp_endp_update(struct mgcp_endpoint *endp, struct mgcp_conn *conn, enum mgcp_verb verb);
void mgcp_endp_update(struct mgcp_endpoint *endp);
bool mgcp_endp_is_wildcarded(const char *epname);
bool mgcp_endp_is_null(const char *epname);
struct mgcp_endpoint *mgcp_endp_by_name_trunk(int *cause, const char *epname,
@@ -150,7 +149,6 @@ void mgcp_endp_strip_name(char *epname_stripped, const char *epname,
const struct mgcp_trunk *trunk);
struct mgcp_endpoint *mgcp_endp_find_specific(const char *epname,
const struct mgcp_trunk *trunk);
void mgcp_endp_update_lco(struct mgcp_endpoint *endp, const struct mgcp_lco *lco);
void mgcp_endp_release(struct mgcp_endpoint *endp);
struct mgcp_conn *mgcp_endp_get_conn(struct mgcp_endpoint *endp, const char *id);

View File

@@ -31,4 +31,3 @@ void mgcp_conn_iuup_cleanup(struct mgcp_conn_rtp *conn_rtp);
int mgcp_conn_iuup_dispatch_rtp(struct msgb *msg);
int mgcp_conn_iuup_send_rtp(struct mgcp_conn_rtp *conn_src_rtp, struct mgcp_conn_rtp *conn_dest_rtp, struct msgb *msg);
int mgcp_conn_iuup_send_dummy(struct mgcp_conn_rtp *conn_rtp);
int mgcp_conn_iuup_event_rx_crcx_mdcx(struct mgcp_conn_rtp *conn_rtp);

View File

@@ -98,6 +98,18 @@ void mgcp_patch_and_count(const struct mgcp_endpoint *endp,
struct osmo_sockaddr *addr, struct msgb *msg);
int mgcp_get_local_addr(char *addr, struct mgcp_conn_rtp *conn);
/* payload processing default functions */
int mgcp_rtp_processing_default(struct mgcp_endpoint *endp, struct mgcp_rtp_end *dst_end, struct msgb *msg);
int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
struct mgcp_conn_rtp *conn_dst,
struct mgcp_conn_rtp *conn_src);
void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
const struct mgcp_rtp_codec **codec,
const char **fmtp_extra,
struct mgcp_conn_rtp *conn);
/* internal RTP Annex A counting */
void mgcp_rtp_annex_count(const struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
const uint16_t seq, const int32_t transit,

View File

@@ -8,18 +8,6 @@
#include <osmocom/mgcp/mgcp_common.h>
#include <osmocom/mgcp/mgcp_codec.h>
enum mgcp_verb {
MGCP_VERB_CRCX,
MGCP_VERB_MDCX,
MGCP_VERB_DLCX,
MGCP_VERB_AUEP,
MGCP_VERB_RQNT,
MGCP_VERB_RSIP,
};
extern const struct value_string mgcp_verb_names[];
static inline const char *mgcp_verb_name(enum mgcp_verb val)
{ return get_value_string(mgcp_verb_names, val); }
#define MGCP_PARSE_SDP_PTIME_UNSET (-1)
#define MGCP_PARSE_SDP_MAXPTIME_UNSET (-1)
@@ -42,26 +30,12 @@ static inline void mgcp_parse_sdp_init(struct mgcp_parse_sdp *sdp)
mgcp_codecset_reset(&sdp->cset);
}
/* Local connection options */
struct mgcp_lco {
bool present;
char *codec; /* talloc-allocated to some parent */
int pkt_period_min; /* time in ms */
int pkt_period_max; /* time in ms */
};
static inline void mgcp_lco_init(struct mgcp_lco *lco)
{
*lco = (struct mgcp_lco){};
}
char *get_lco_identifier(const char *options);
int check_local_cx_options(void *ctx, const char *options);
#define MGCP_PARSE_HDR_PARS_OSMUX_CID_UNSET (-2)
#define MGCP_PARSE_HDR_PARS_OSMUX_CID_WILDCARD (-1)
struct mgcp_parse_hdr_pars {
const char *lco_string;
struct mgcp_lco lco;
const char *local_options;
const char *callid;
const char *connid;
enum mgcp_connection_mode mode;
@@ -73,20 +47,20 @@ struct mgcp_parse_hdr_pars {
static inline void mgcp_parse_hdr_pars_init(struct mgcp_parse_hdr_pars *hpars)
{
hpars->lco_string = NULL;
mgcp_lco_init(&hpars->lco);
hpars->callid = NULL;
hpars->connid = NULL;
hpars->mode = MGCP_CONN_NONE;
hpars->remote_osmux_cid = MGCP_PARSE_HDR_PARS_OSMUX_CID_UNSET;
hpars->have_sdp = false;
hpars->x_osmo_ign = 0;
*hpars = (struct mgcp_parse_hdr_pars){
.local_options = NULL,
.callid = NULL,
.connid = NULL,
.mode = MGCP_CONN_NONE,
.remote_osmux_cid = MGCP_PARSE_HDR_PARS_OSMUX_CID_UNSET,
.have_sdp = false,
.x_osmo_ign = 0,
};
}
/* Internal structure while parsing a request */
struct mgcp_request_data;
struct mgcp_parse_data {
struct mgcp_request_data *rq; /* backpointer to request context */
struct mgcp_config *cfg;
char *save;
/* MGCP Header: */
char *epname;
@@ -96,36 +70,18 @@ struct mgcp_parse_data {
struct mgcp_parse_sdp sdp;
};
/* Request data passed to the request handler */
struct mgcp_request_data {
enum mgcp_verb verb;
/* Verb string (e.g. "MDCX") */
char name[4+1];
/* Global MGW config */
struct mgcp_config *cfg;
/* parsing results from the MGCP header (trans id, endpoint name ...) */
struct mgcp_parse_data *pdata;
/* pointer to endpoint resource (may be NULL for wildcarded requests) */
struct mgcp_endpoint *endp;
/* pointer to trunk resource */
struct mgcp_trunk *trunk;
/* set to true when the request has been classified as wildcarded */
bool wildcarded;
/* Set to true when the request is targeted at the "null" endpoint */
bool null_endp;
/* contains cause code in case of problems during endp/trunk resolution */
int mgcp_cause;
/* Local connection options */
struct mgcp_lco {
char *string;
char *codec;
int pkt_period_min; /* time in ms */
int pkt_period_max; /* time in ms */
};
char *mgcp_debug_get_last_endpoint_name(void);
char *get_lco_identifier(const char *options);
int check_local_cx_options(void *ctx, const char *options);
struct mgcp_rtp_end;
struct mgcp_endpoint;

View File

@@ -43,7 +43,7 @@ enum {
MGCP_MDCX_FAIL_INVALID_MODE,
MGCP_MDCX_FAIL_INVALID_CONN_OPTIONS,
MGCP_MDCX_FAIL_NO_REMOTE_CONN_DESC,
MGCP_MDCX_FAIL_BIND_PORT,
MGCP_MDCX_FAIL_START_RTP,
MGCP_MDCX_FAIL_AVAIL,
};

View File

@@ -1,6 +1,5 @@
BUILT_SOURCES = \
mgcp_common.h \
version.h \
$(NULL)
noinst_HEADERS = \
@@ -12,20 +11,4 @@ mgcp_common.h: $(top_srcdir)/include/osmocom/mgcp/mgcp_common.h
echo -e "/*\n\n DO NOT EDIT THIS FILE!\n THIS IS OVERWRITTEN DURING BUILD\n This is an automatic copy of <osmocom/mgcp/mgcp_common.h>\n\n */" > mgcp_common.h
cat $(top_srcdir)/include/osmocom/mgcp/mgcp_common.h >> mgcp_common.h
version.h: version.h.tpl
$(AM_V_GEN)$(MKDIR_P) $(dir $@)
$(AM_V_GEN)sed \
-e "s/{{VERSION}}/$$(echo '@VERSION@' | cut -d. -f1-3)/g" \
-e "s/{{VERSION_MAJOR}}/$$(echo '@VERSION@' | cut -d. -f1)/g" \
-e "s/{{VERSION_MINOR}}/$$(echo '@VERSION@' | cut -d. -f2)/g" \
-e "s/{{VERSION_PATCH}}/$$(echo '@VERSION@' | cut -d. -f3)/g" \
$< > $@
EXTRA_DIST = \
version.h.tpl \
$(NULL)
CLEANFILES = \
mgcp_common.h \
version.h \
$(NULL)
CLEANFILES = mgcp_common.h

View File

@@ -1,16 +0,0 @@
#pragma once
#define LIBOSMO_MGCP_CLIENT_VERSION {{VERSION}}
#define LIBOSMO_MGCP_CLIENT_VERSION_STR "{{VERSION}}"
#define LIBOSMO_MGCP_CLIENT_VERSION_MAJOR {{VERSION_MAJOR}}
#define LIBOSMO_MGCP_CLIENT_VERSION_MINOR {{VERSION_MINOR}}
#define LIBOSMO_MGCP_CLIENT_VERSION_PATCH {{VERSION_PATCH}}
#define LIBOSMO_MGCP_CLIENT_VERSION_GREATER_EQUAL(major, minor, patch) \
(LIBOSMO_MGCP_CLIENT_VERSION_MAJOR > (major) || \
(LIBOSMO_MGCP_CLIENT_VERSION_MAJOR == (major) && \
LIBOSMO_MGCP_CLIENT_VERSION_MINOR > (minor)) || \
(LIBOSMO_MGCP_CLIENT_VERSION_MAJOR == (major) && \
LIBOSMO_MGCP_CLIENT_VERSION_MINOR == (minor) && \
LIBOSMO_MGCP_CLIENT_VERSION_PATCH >= (patch)))

View File

@@ -1426,32 +1426,15 @@ static int add_sdp(struct msgb *msg, struct mgcp_msg *mgcp_msg, struct mgcp_clie
/* Add optional codec parameters (fmtp) */
if (mgcp_msg->param_present) {
for (i = 0; i < mgcp_msg->ptmap_len; i++) {
/* The following is only applicable for AMR */
if (mgcp_msg->ptmap[i].codec != CODEC_AMR_8000_1
&& mgcp_msg->ptmap[i].codec != CODEC_AMRWB_16000_1)
continue;
pt = mgcp_msg->ptmap[i].pt;
switch (mgcp_msg->ptmap[i].codec) {
case CODEC_AMR_8000_1:
case CODEC_AMRWB_16000_1:
if (!mgcp_msg->param.amr_octet_aligned_present)
break;
MSGB_PRINTF_OR_RET("a=fmtp:%u octet-align=%d\r\n",
pt, (int)mgcp_msg->param.amr_octet_aligned);
break;
case CODEC_GSM_8000_1:
case CODEC_GSMEFR_8000_1:
if (!mgcp_msg->param.fr_efr_twts001_present)
break;
MSGB_PRINTF_OR_RET("a=fmtp:%u tw-ts-001=%d\r\n",
pt, (int)mgcp_msg->param.fr_efr_twts001);
break;
case CODEC_GSMHR_8000_1:
if (!mgcp_msg->param.hr_twts002_present)
break;
MSGB_PRINTF_OR_RET("a=fmtp:%u tw-ts-002=%d\r\n",
pt, (int)mgcp_msg->param.hr_twts002);
break;
default:
/* no parameters for the remaining codecs */
break;
}
if (mgcp_msg->param.amr_octet_aligned_present && mgcp_msg->param.amr_octet_aligned)
MSGB_PRINTF_OR_RET("a=fmtp:%u octet-align=1\r\n", pt);
else if (mgcp_msg->param.amr_octet_aligned_present && !mgcp_msg->param.amr_octet_aligned)
MSGB_PRINTF_OR_RET("a=fmtp:%u octet-align=0\r\n", pt);
}
}

View File

@@ -7,7 +7,6 @@ AM_CPPFLAGS = \
AM_CFLAGS = \
-Wall \
$(LIBOSMOCORE_CFLAGS) \
$(LIBOSMOCODEC_CFLAGS) \
$(LIBOSMOGSM_CFLAGS) \
$(LIBOSMOVTY_CFLAGS) \
$(LIBOSMONETIF_CFLAGS) \

View File

@@ -40,7 +40,6 @@
#include <osmocom/mgcp/debug.h>
#include <osmocom/mgcp/mgcp_e1.h>
#include <osmocom/codec/codec.h>
#include <osmocom/gsm/rtp_extensions.h>
#define DEBUG_BITS_MAX 80
#define DEBUG_BYTES_MAX 40
@@ -57,6 +56,149 @@ static const struct e1inp_line_ops dummy_e1_line_ops = {
.sign_link = NULL,
};
/* The following EFR TRAU-DL frame is a dummy to be transmitted in the absence
* of RTP-derived TRAU-DL frames. The payload bit content here is the decoder
* homing frame (DHF) of TS 46.060 section 8.2 Table 7 - the best we can do
* in the absence of a proper TFO transform for EFR - while the full TRAU-DL
* frame was generated by passing said EFR DHF through osmo_rtp2trau().
*/
static const ubit_t idle_tf_efr[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 0, 1, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 0, 0, 0, 0, 1, 0,
0, 0, 0, 1, 0, 1, 1, 1,
1, 1, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 0, 1, 0,
1, 0, 0, 0, 1, 1, 1, 1,
1, 0, 0, 1, 0, 1, 0, 1,
1, 0, 1, 0, 1, 1, 0, 1,
0, 1, 1, 0, 0, 0, 0, 0,
1, 0, 0, 1, 1, 1, 1, 1,
0, 0, 0, 1, 1, 1, 0, 1,
1, 0, 0, 0, 0, 1, 1, 0,
0, 0, 0, 1, 1, 0, 0, 0,
1, 0, 0, 0, 1, 1, 1, 1,
0, 1, 1, 0, 1, 1, 0, 0,
1, 0, 0, 1, 1, 0, 0, 0,
1, 0, 0, 0, 0, 1, 0, 1,
1, 1, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 1, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0,
1, 0, 1, 0, 1, 0, 1, 0,
1, 1, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 0,
1, 1, 1, 0, 1, 0, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
};
/* The following FRv1 TRAU-DL frame is a dummy to be transmitted in the absence
* of RTP-derived TRAU-DL frames. The payload bit content here is the silence
* frame of TS 46.011 Table 1 - the best we can do without integrating the
* TFO transform for FRv1 from Themyscira libgsmfr2 - while the full TRAU-DL
* frame was generated by passing said FRv1 silence frame through
* osmo_rtp2trau().
*/
static const ubit_t idle_tf_fr[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1,
1, 0, 1, 0, 1, 0, 1, 1,
1, 1, 0, 0, 1, 1, 0, 1,
1, 0, 1, 0, 1, 0, 1, 0,
1, 0, 0, 1, 0, 0, 1, 0,
1, 1, 1, 0, 0, 1, 0, 0,
0, 0, 1, 0, 1, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0,
0, 1, 1, 0, 0, 0, 1, 1,
1, 1, 0, 0, 0, 1, 0, 0,
1, 1, 1, 0, 1, 1, 0, 1,
1, 1, 0, 1, 1, 0, 0, 0,
1, 0, 0, 1, 1, 1, 0, 1,
1, 1, 0, 0, 0, 0, 1, 0,
1, 0, 0, 0, 1, 0, 0, 0,
1, 0, 0, 0, 0, 1, 1, 0,
0, 0, 1, 1, 1, 0, 0, 0,
1, 1, 0, 0, 1, 1, 1, 0,
1, 1, 0, 1, 1, 0, 1, 1,
1, 0, 0, 0, 1, 0, 0, 1,
1, 1, 0, 1, 1, 0, 0, 0,
1, 0, 1, 0, 1, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 0, 0, 0, 1, 1,
1, 0, 0, 0, 1, 0, 0, 1,
1, 1, 1, 0, 1, 1, 0, 1,
1, 0, 1, 1, 0, 0, 0, 1,
1, 0, 0, 1, 1, 1, 0, 1,
1, 0, 0, 0, 0, 1, 0, 1,
1, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 1, 1, 0, 0,
1, 0, 1, 1, 1, 0, 0, 0,
1, 0, 0, 1, 1, 1, 0, 1,
1, 1, 0, 1, 1, 0, 1, 1,
0, 0, 0, 1, 0, 0, 1, 1,
1, 1, 0, 1, 1, 0, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
};
/* Idle speech frame, see also GSM 08.60, chapter 3.4 */
static const ubit_t idle_tf_spch[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 1, 1, 1, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 0,
1, 1, 1, 1, 1, 1, 1, 1,
};
/* If the RTP transmission has dropouts for some reason the I.460 TX-Queue may
* run empty. In order to make sure that the TRAU frame transmission continues
* we generate idle TRAU frames here. */
@@ -65,59 +207,33 @@ static void e1_i460_mux_empty_cb(struct osmo_i460_subchan *schan, void *user_dat
struct mgcp_endpoint *endp = user_data;
struct rate_ctr_group *rate_ctrs = endp->trunk->ratectr.e1_stats;
struct msgb *msg = msgb_alloc_c(endp->trunk, E1_TRAU_BITS_MSGB, "E1-I.460-IDLE-TX-TRAU-frame");
const uint8_t *dummy_fill_pl;
unsigned dummy_fill_pl_len;
struct osmo_trau_frame tf;
int rc;
uint8_t *ptr;
const uint8_t *ptr_ft;
enum osmo_trau_frame_type ft;
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, E1_I460_TRAU_MUX_EMPTY_CTR));
/* choose dummy fill frame payload based on current codec */
switch (endp->e1.trau_rtp_st->type) {
/* Choose an appropiate idle frame type */
ft = endp->e1.trau_rtp_st->type;
switch (ft) {
case OSMO_TRAU16_FT_FR:
dummy_fill_pl = osmo_gsm611_silence_frame;
dummy_fill_pl_len = GSM_FR_BYTES;
ptr_ft = idle_tf_fr;
break;
case OSMO_TRAU16_FT_EFR:
dummy_fill_pl = osmo_gsm660_homing_frame;
dummy_fill_pl_len = GSM_EFR_BYTES;
break;
case OSMO_TRAU16_FT_HR:
case OSMO_TRAU8_SPEECH:
dummy_fill_pl = osmo_gsm620_silence_frame;
dummy_fill_pl_len = GSM_HR_BYTES;
ptr_ft = idle_tf_efr;
break;
default:
LOGPENDP(endp, DE1, LOGL_ERROR, "E1-I.460-IDLE-TX: unsupported frame type\n");
goto skip;
/* FIXME: What about 8k subslots and AMR frames? */
ptr_ft = idle_tf_spch;
}
/* turn it into a TRAU-DL frame */
memset(&tf, 0, sizeof(tf));
tf.dir = OSMO_TRAU_DIR_DL;
rc = osmo_rtp2trau(&tf, dummy_fill_pl, dummy_fill_pl_len, endp->e1.trau_rtp_st);
if (rc < 0) {
LOGPENDP(endp, DE1, LOGL_ERROR,
"E1-I.460-IDLE-TX: error converting dummy fill frame!\n");
goto skip;
}
rc = osmo_trau_frame_encode(msgb_data(msg), msg->data_len, &tf);
if (rc < 0) {
LOGPENDP(endp, DE1, LOGL_ERROR,
"E1-I.460-IDLE-TX: error encoding dummy fill frame!\n");
goto skip;
}
msgb_put(msg, rc);
/* enqueue it into the I.460 multiplexer */
/* Put the replacement into a message buffer and enqueue it into the
* I.460 multiplexer */
ptr = msgb_put(msg, E1_TRAU_BITS);
memcpy(ptr, ptr_ft, E1_TRAU_BITS);
LOGPENDP(endp, DE1, LOGL_DEBUG, "E1-I.460-IDLE-TX: enquing %u trau frame bits: %s...\n", msgb_length(msg),
osmo_ubit_dump(msgb_data(msg), msgb_length(msg) > DEBUG_BITS_MAX ? DEBUG_BITS_MAX : msgb_length(msg)));
osmo_i460_mux_enqueue(endp->e1.schan, msg);
return;
skip:
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, E1_I460_TRAU_TX_FAIL_CTR));
msgb_free(msg);
}
/* called by I.460 de-multiplexer; feed output of I.460 demux into TRAU frame sync */
@@ -178,7 +294,6 @@ static void sync_frame_out_cb(void *user_data, const ubit_t *bits, unsigned int
/* Convert decoded trau frame to RTP frame */
struct osmo_trau2rtp_state t2rs = {
.type = fr.type,
.rtp_extensions = endp->e1.rtp_extensions,
};
rc = osmo_trau2rtp(msgb_data(msg) + rtp_hdr_len, msg->data_len - rtp_hdr_len, &fr, &t2rs);
if (rc <= 0) {
@@ -546,7 +661,7 @@ int mgcp_e1_endp_equip(struct mgcp_endpoint *endp, uint8_t ts, uint8_t ss, uint8
/*! Update E1 related parameters (codec and sync pattern).
* \param[in] endp endpoint to update. */
int mgcp_e1_endp_update(struct mgcp_endpoint *endp)
void mgcp_e1_endp_update(struct mgcp_endpoint *endp)
{
struct mgcp_conn *conn;
struct mgcp_conn_rtp *conn_rtp;
@@ -567,17 +682,9 @@ int mgcp_e1_endp_update(struct mgcp_endpoint *endp)
determine_trau_fr_type(codec->subtype_name, endp->e1.scd.rate, endp->e1.last_amr_ft, endp);
endp->e1.last_codec = codec;
/* possible RTP extensions, codec-associated */
endp->e1.rtp_extensions = 0;
if (codec->param_present && codec->param.fr_efr_twts001)
endp->e1.rtp_extensions |= OSMO_RTP_EXT_TWTS001;
if (codec->param_present && codec->param.hr_twts002)
endp->e1.rtp_extensions |= OSMO_RTP_EXT_TWTS002;
/* Update sync pattern */
sync_pat_id = determine_trau_sync_pat(codec->subtype_name, endp->e1.scd.rate, endp->e1.last_amr_ft, endp);
osmo_trau_sync_set_pat(endp->e1.trau_sync_fi, sync_pat_id);
return 0;
}
/*! Remove E1 resources from endpoint

View File

@@ -24,7 +24,6 @@
#include <osmocom/mgcp/mgcp.h>
#include <osmocom/mgcp/mgcp_protocol.h>
#include <osmocom/mgcp/mgcp_conn.h>
#include <osmocom/mgcp/mgcp_iuup.h>
#include <osmocom/mgcp/mgcp_endp.h>
#include <osmocom/mgcp/mgcp_trunk.h>
@@ -641,85 +640,20 @@ int mgcp_endp_claim(struct mgcp_endpoint *endp, const char *callid)
/*! update endpoint, updates internal endpoint specific data, should be
* after when MDCX or CRCX has been executed successuflly.
* \param[in] endp endpoint to update.
* \returns zero on success, mgcp negative error on failure. */
static int mgcp_endp_update_virtual(struct mgcp_endpoint *endp, struct mgcp_conn *conn, enum mgcp_verb verb)
* \param[in] endp endpoint to update. */
void mgcp_endp_update(struct mgcp_endpoint *endp)
{
OSMO_ASSERT(conn);
OSMO_ASSERT(conn->type == MGCP_CONN_TYPE_RTP);
struct mgcp_conn_rtp *conn_rtp = mgcp_conn_get_conn_rtp(conn);
switch (conn_rtp->type) {
case MGCP_RTP_DEFAULT:
break;
case MGCP_RTP_OSMUX:
if (conn_osmux_event_rx_crcx_mdcx(conn_rtp) < 0) {
LOGPCONN(conn, DLMGCP, LOGL_ERROR, "CRCX: Osmux handling failed!\n");
return -500;
}
break;
case MGCP_RTP_IUUP:
return mgcp_conn_iuup_event_rx_crcx_mdcx(conn_rtp);
default:
return -523;
}
return 0;
}
/*! update endpoint, updates internal endpoint specific data, should be
* after when MDCX or CRCX has been executed successuflly.
* \param[in] endp endpoint to update.
* \returns zero on success, mgcp negative error on failure. */
int mgcp_endp_update(struct mgcp_endpoint *endp, struct mgcp_conn *conn, enum mgcp_verb verb)
{
OSMO_ASSERT(conn);
struct mgcp_trunk *trunk = endp->trunk;
struct mgcp_conn_rtp *conn_rtp = mgcp_conn_get_conn_rtp(conn);
char new_local_addr[INET6_ADDRSTRLEN];
/* CRCX: Find a local address for conn based on policy and initial SDP remote
* information, then find a free port for it.
* MDCX: msg may have provided a new remote address, which means we may need
* to update our announced IP addr and re-bind our local end. This can
* happen for instance if MGW initially provided an IPv4 during CRCX
* ACK, and now MDCX tells us the remote has an IPv6 address.
*/
if (mgcp_get_local_addr(new_local_addr, conn_rtp) < 0)
goto fail_bind_port_ret;
if (strcmp(new_local_addr, conn_rtp->end.local_addr)) {
osmo_strlcpy(conn_rtp->end.local_addr, new_local_addr, sizeof(conn_rtp->end.local_addr));
mgcp_rtp_end_free_port(&conn_rtp->end);
if (mgcp_trunk_allocate_conn_rtp_ports(trunk, conn_rtp) != 0)
goto fail_bind_port_ret;
}
/* Allocate resources */
switch (endp->trunk->trunk_type) {
case MGCP_TRUNK_VIRTUAL:
return mgcp_endp_update_virtual(endp, conn, verb);
/* No updating initaliziation required for virtual endpoints. */
break;
case MGCP_TRUNK_E1:
return mgcp_e1_endp_update(endp);
mgcp_e1_endp_update(endp);
break;
default:
OSMO_ASSERT(false);
}
return 0;
fail_bind_port_ret:
switch (verb) {
case MGCP_VERB_CRCX:
rate_ctr_inc(rate_ctr_group_get_ctr(trunk->ratectr.mgcp_crcx_ctr_group,
MGCP_CRCX_FAIL_BIND_PORT));
break;
case MGCP_VERB_MDCX:
rate_ctr_inc(rate_ctr_group_get_ctr(trunk->ratectr.mgcp_mdcx_ctr_group,
MGCP_MDCX_FAIL_BIND_PORT));
break;
default:
break;
}
return -500;
}
void mgcp_endp_add_conn(struct mgcp_endpoint *endp, struct mgcp_conn *conn)
@@ -830,22 +764,6 @@ struct mgcp_conn_rtp *mgcp_endp_get_conn_rtp(struct mgcp_endpoint *endp,
return NULL;
}
/* Helps assigning a new lco structure, since "codec" is talloc allocated. */
void mgcp_endp_update_lco(struct mgcp_endpoint *endp, const struct mgcp_lco *lco)
{
/* First free old talloc allocated codec string: */
talloc_free(endp->local_options.codec);
endp->local_options.codec = NULL;
if (lco) {
endp->local_options = *lco;
if (lco->codec)
endp->local_options.codec = talloc_strdup(endp, lco->codec);
} else {
endp->local_options = (struct mgcp_lco){0};
}
}
/*! release endpoint, all open connections are closed.
* \param[in] endp endpoint to release */
void mgcp_endp_release(struct mgcp_endpoint *endp)
@@ -867,7 +785,10 @@ void mgcp_endp_release(struct mgcp_endpoint *endp)
/* Reset endpoint parameters and states */
talloc_free(endp->callid);
endp->callid = NULL;
mgcp_endp_update_lco(endp, NULL);
talloc_free(endp->local_options.string);
endp->local_options.string = NULL;
talloc_free(endp->local_options.codec);
endp->local_options.codec = NULL;
if (endp->trunk->trunk_type == MGCP_TRUNK_E1) {
uint8_t ts = e1_ts_nr_from_epname(endp->name);

View File

@@ -753,44 +753,3 @@ int mgcp_conn_iuup_send_dummy(struct mgcp_conn_rtp *conn_rtp)
return 0;
}
/* To be called every time an CRCX/MDCX is received.
* returns: 0 if conn can continue, MGCP negative code if an error ocurred during setup */
int mgcp_conn_iuup_event_rx_crcx_mdcx(struct mgcp_conn_rtp *conn_rtp)
{
struct mgcp_conn *peer_conn;
struct mgcp_conn_rtp *peer_conn_rtp;
OSMO_ASSERT(mgcp_conn_rtp_is_iuup(conn_rtp));
/* keep waiting to receive remote address through CRCX/MDCX */
if (!mgcp_rtp_end_remote_addr_available(&conn_rtp->end))
return 0;
/* Conn already IuUP-configured/initialized, nothing to be done. */
if (conn_rtp->iuup.configured)
return 0;
/* Reached this point, conn_rtp is an IuUP conn which can be configured
* and was not yet configured. If its sister conn in the endpoint was
* already configured as IuUP "passive", then we know this one can be
* configured as IuUP "active" right now. In that case, do so.
* This usually happens on an HNBGW co-located MGW, where during
* RAB-ASS-REQ the RAN-side conn (sister conn here) was already
* configured and then upon rx of RAB-ASS-RESP it sets up (CRCX) the
* CN-side IuUP conn (rt_conn here).
*/
peer_conn = mgcp_find_dst_conn(conn_rtp->conn);
/* No peer conn yet, nothing to be done. */
if (!peer_conn)
return 0;
peer_conn_rtp = mgcp_conn_get_conn_rtp(peer_conn);
if (mgcp_conn_rtp_is_iuup(peer_conn_rtp) &&
peer_conn_rtp->iuup.configured &&
!conn_rtp->iuup.active_init) {
LOG_CONN_RTP(conn_rtp, LOGL_INFO, "Sister IuUP conn in endp configured as passive, init this one as active\n");
OSMO_ASSERT(peer_conn_rtp->iuup.init_ind);
_conn_iuup_configure_as_active(conn_rtp, peer_conn_rtp->iuup.init_ind);
}
return 0;
}

View File

@@ -36,7 +36,7 @@
/* (same fmt as LOGPENDP()) */
#define LOG_MGCP_PDATA(PDATA, LEVEL, FMT, ARGS...) \
LOGP(DLMGCP, LEVEL, "%s: endpoint(%s) " FMT, (PDATA)->rq->name, (PDATA)->epname ? : "null-epname", ##ARGS)
LOGP(DLMGCP, LEVEL, "endpoint:%s " FMT, (PDATA) ? ((PDATA)->epname ? : "null-epname") : "null-pdata", ##ARGS)
/*! Display an mgcp message on the log output.
* \param[in] message mgcp message string
@@ -101,197 +101,6 @@ enum mgcp_connection_mode mgcp_parse_conn_mode(const char *mode)
return MGCP_CONN_NONE;
}
/*! Helper function for check_local_cx_options() to get a pointer of the next
* lco option identifier
* \param[in] lco string
* \returns pointer to the beginning of the LCO identifier, NULL on failure */
char *get_lco_identifier(const char *options)
{
char *ptr;
unsigned int count = 0;
/* Jump to the end of the lco identifier */
ptr = strstr(options, ":");
if (!ptr)
return NULL;
/* Walk backwards until the pointer points to the beginning of the
* lco identifier. We know that we stand at the beginning when we
* are either at the beginning of the memory or see a space or
* comma. (this is tolerant, it will accept a:10, b:11 as well as
* a:10,b:11) */
while (1) {
/* Endless loop protection */
if (count > 10000)
return NULL;
else if (ptr < options || *ptr == ' ' || *ptr == ',') {
ptr++;
break;
}
ptr--;
count++;
}
/* Check if we got any result */
if (*ptr == ':')
return NULL;
return ptr;
}
/*! Check the LCO option. This function checks for multiple appearance of LCO
* options, which is illegal
* \param[in] ctx talloc context
* \param[in] lco string
* \returns 0 on success, -1 on failure */
int check_local_cx_options(void *ctx, const char *options)
{
int i;
char *options_copy;
char *lco_identifier;
char *lco_identifier_end;
char *next_lco_identifier;
char **lco_seen;
unsigned int lco_seen_n = 0;
if (!options)
return -1;
lco_seen =
(char **)talloc_zero_size(ctx, strlen(options) * sizeof(char *));
options_copy = talloc_strdup(ctx, options);
lco_identifier = options_copy;
do {
/* Move the lco_identifier pointer to the beginning of the
* current lco option identifier */
lco_identifier = get_lco_identifier(lco_identifier);
if (!lco_identifier)
goto error;
/* Look ahead to the next LCO option early, since we
* will parse destructively */
next_lco_identifier = strstr(lco_identifier + 1, ",");
/* Pinch off the end of the lco field identifier name
* and see if we still got something, also check if
* there is some value after the colon. */
lco_identifier_end = strstr(lco_identifier, ":");
if (!lco_identifier_end)
goto error;
if (*(lco_identifier_end + 1) == ' '
|| *(lco_identifier_end + 1) == ','
|| *(lco_identifier_end + 1) == '\0')
goto error;
*lco_identifier_end = '\0';
if (strlen(lco_identifier) == 0)
goto error;
/* Check if we have already seen the current field identifier
* before. If yes, we must bail, an LCO must only appear once
* in the LCO string */
for (i = 0; i < lco_seen_n; i++) {
if (strcasecmp(lco_seen[i], lco_identifier) == 0)
goto error;
}
lco_seen[lco_seen_n] = lco_identifier;
lco_seen_n++;
/* The first identifier must always be found at the beginnning
* of the LCO string */
if (lco_seen[0] != options_copy)
goto error;
/* Go to the next lco option */
lco_identifier = next_lco_identifier;
} while (lco_identifier);
talloc_free(lco_seen);
talloc_free(options_copy);
return 0;
error:
talloc_free(lco_seen);
talloc_free(options_copy);
return -1;
}
/* Set the LCO from a string (see RFC 3435).
* The string is stored in the 'string' field. A NULL string is handled exactly
* like an empty string, the 'string' field is never NULL after this function
* has been called. */
static int mgcp_parse_lco(void *ctx, struct mgcp_lco *lco, const char *options)
{
const char *lco_id;
char codec[17];
char nt[17];
int len;
if (!options)
return 0;
if (strlen(options) == 0)
return 0;
lco->present = true;
/* Make sure the encoding of the LCO is consistent before we proceed */
if (check_local_cx_options(ctx, options) != 0) {
LOGP(DLMGCP, LOGL_ERROR,
"local CX options: Internal inconsistency in Local Connection Options!\n");
return -524;
}
lco_id = options;
while ((lco_id = get_lco_identifier(lco_id))) {
switch (tolower(lco_id[0])) {
case 'p':
if (sscanf(lco_id + 1, ":%d-%d",
&lco->pkt_period_min, &lco->pkt_period_max) == 1)
lco->pkt_period_max = lco->pkt_period_min;
break;
case 'a':
/* FIXME: LCO also supports the negotiation of more than one codec.
* (e.g. a:PCMU;G726-32) But this implementation only supports a single
* codec only. Ignoring all but the first codec. */
if (sscanf(lco_id + 1, ":%16[^,;]", codec) == 1) {
talloc_free(lco->codec);
/* MGCP header is case insensive, and we'll need
codec in uppercase when using it later: */
len = strlen(codec);
lco->codec = talloc_size(ctx, len + 1);
osmo_str_toupper_buf(lco->codec, len + 1, codec);
}
break;
case 'n':
if (lco_id[1] == 't' && sscanf(lco_id + 2, ":%16[^,]", nt) == 1)
break;
/* else: fall through to print notice log */
default:
LOGP(DLMGCP, LOGL_NOTICE,
"LCO: unhandled option: '%c'/%d in \"%s\"\n",
*lco_id, *lco_id, options);
break;
}
lco_id = strchr(lco_id, ',');
if (!lco_id)
break;
}
LOGP(DLMGCP, LOGL_DEBUG,
"local CX options: lco->pkt_period_max: %d, lco->codec: %s\n",
lco->pkt_period_max, lco->codec);
/* Check if the packetization fits the 20ms raster */
if (lco->pkt_period_min % 20 && lco->pkt_period_max % 20) {
LOGP(DLMGCP, LOGL_ERROR,
"local CX options: packetization interval is not a multiple of 20ms!\n");
return -535;
}
return 0;
}
/*! Analyze and parse the the hader of an MGCP messeage string.
* \param[out] pdata caller provided memory to store the parsing results.
* \param[in] data mgcp message string.
@@ -368,7 +177,6 @@ int mgcp_parse_hdr_pars(struct mgcp_parse_data *pdata)
{
struct mgcp_parse_hdr_pars *hp = &pdata->hpars;
char *line;
int rc;
mgcp_parse_hdr_pars_init(hp);
@@ -380,24 +188,7 @@ int mgcp_parse_hdr_pars(struct mgcp_parse_data *pdata)
switch (toupper(line[0])) {
case 'L':
hp->lco_string = (const char *)line + 3;
rc = mgcp_parse_lco(pdata, &hp->lco, hp->lco_string);
if (rc < 0) {
LOG_MGCP_PDATA(pdata, LOGL_NOTICE, "Invalid LocalConnectionOptions line: '%s'", line);
switch (pdata->rq->verb) {
case MGCP_VERB_CRCX:
rate_ctr_inc(rate_ctr_group_get_ctr(pdata->rq->trunk->ratectr.mgcp_crcx_ctr_group,
MGCP_CRCX_FAIL_INVALID_CONN_OPTIONS));
break;
case MGCP_VERB_MDCX:
rate_ctr_inc(rate_ctr_group_get_ctr(pdata->rq->trunk->ratectr.mgcp_mdcx_ctr_group,
MGCP_MDCX_FAIL_INVALID_CONN_OPTIONS));
break;
default:
break;
}
return rc;
}
hp->local_options = (const char *)line + 3;
break;
case 'C':
hp->callid = (const char *)line + 3;
@@ -421,23 +212,7 @@ int mgcp_parse_hdr_pars(struct mgcp_parse_data *pdata)
hp->have_sdp = true;
goto mgcp_header_done;
default:
LOG_MGCP_PDATA(pdata, LOGL_NOTICE, "unhandled option: '%c'/%d\n", *line, *line);
switch (pdata->rq->verb) {
case MGCP_VERB_CRCX:
rate_ctr_inc(rate_ctr_group_get_ctr(pdata->rq->trunk->ratectr.mgcp_crcx_ctr_group,
MGCP_CRCX_FAIL_UNHANDLED_PARAM));
break;
case MGCP_VERB_MDCX:
rate_ctr_inc(rate_ctr_group_get_ctr(pdata->rq->trunk->ratectr.mgcp_mdcx_ctr_group,
MGCP_MDCX_FAIL_UNHANDLED_PARAM));
break;
case MGCP_VERB_DLCX:
rate_ctr_inc(rate_ctr_group_get_ctr(pdata->rq->trunk->ratectr.mgcp_dlcx_ctr_group,
MGCP_DLCX_FAIL_UNHANDLED_PARAM));
break;
default:
break;
}
LOG_MGCP_PDATA(pdata, LOGL_NOTICE, "CRCX: unhandled option: '%c'/%d\n", *line, *line);
return -539;
}
}
@@ -501,6 +276,10 @@ int mgcp_verify_call_id(struct mgcp_endpoint *endp, const char *callid)
if (!endp)
return -1;
/* Accept any CallID for "X-Osmo-IGN: C" */
if (endp->x_osmo_ign & MGCP_X_OSMO_IGN_CALLID)
return 0;
if (!callid)
return -1;
if (!endp->callid)

View File

@@ -408,6 +408,31 @@ static int align_rtp_timestamp_offset(const struct mgcp_endpoint *endp,
return ts_error;
}
/*! dummy callback to disable transcoding (see also cfg->rtp_processing_cb).
* \param[in] associated endpoint.
* \param[in] destination RTP end.
* \param[in,out] msg message bufffer containing data. Function might change length.
* \returns ignores input parameters, return always 0. */
int mgcp_rtp_processing_default(struct mgcp_endpoint *endp,
struct mgcp_rtp_end *dst_end,
struct msgb *msg)
{
return 0;
}
/*! dummy callback to disable transcoding (see also cfg->setup_rtp_processing_cb).
* \param[in] associated endpoint.
* \param[in] destination RTP connnection.
* \param[in] source RTP connection.
* \returns ignores input parameters, return always 0. */
int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
struct mgcp_conn_rtp *conn_dst,
struct mgcp_conn_rtp *conn_src)
{
LOGPENDP(endp, DRTP, LOGL_DEBUG, "transcoding disabled\n");
return 0;
}
void mgcp_rtp_annex_count(const struct mgcp_endpoint *endp,
struct mgcp_rtp_state *state, const uint16_t seq,
const int32_t transit, const uint32_t ssrc,
@@ -1162,7 +1187,13 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct osmo_sockaddr *addr
* header is present, we will generate one. */
gen_rtp_header(msg, rtp_end, rtp_state);
/* TODO: Run transcoder */
/* Run transcoder */
rc = endp->trunk->cfg->rtp_processing_cb(endp, rtp_end, msg);
if (rc < 0) {
LOGPENDP(endp, DRTP, LOGL_ERROR, "Error %d during transcoding\n", rc);
msgb_free(msg);
return rc;
}
if (addr)
mgcp_patch_and_count(endp, rtp_state, rtp_end, addr, msg);

View File

@@ -211,7 +211,6 @@ osmux_handle_find_or_create(const struct mgcp_trunk *trunk, const struct osmo_so
int conn_osmux_send_rtp(struct mgcp_conn_rtp *conn, struct msgb *msg)
{
int ret;
size_t msg_len;
if (!conn->end.output_enabled) {
rtpconn_osmux_rate_ctr_inc(conn, OSMUX_RTP_PACKETS_TX_DROPPED_CTR);
@@ -235,17 +234,15 @@ int conn_osmux_send_rtp(struct mgcp_conn_rtp *conn, struct msgb *msg)
return -1;
}
msg_len = msgb_length(msg);
while ((ret = osmux_xfrm_input(conn->osmux.in, msg, conn->osmux.remote_cid)) > 0) {
/* batch full, build and deliver it */
osmux_xfrm_input_deliver(conn->osmux.in);
}
/* NOTE: At this point msg is now owned by osmux subsystem and may have been potentially freed. */
if (ret < 0) {
rtpconn_osmux_rate_ctr_inc(conn, OSMUX_RTP_PACKETS_TX_DROPPED_CTR);
} else {
rtpconn_osmux_rate_ctr_inc(conn, OSMUX_RTP_PACKETS_TX_CTR);
rtpconn_osmux_rate_ctr_add(conn, OSMUX_AMR_OCTETS_TX_CTR, msg_len - sizeof(struct rtp_hdr));
rtpconn_osmux_rate_ctr_add(conn, OSMUX_AMR_OCTETS_TX_CTR, msgb_length(msg) - sizeof(struct rtp_hdr));
}
return 0;
}
@@ -498,9 +495,6 @@ int osmux_init(struct mgcp_trunk *trunk)
int ret, fd;
struct mgcp_config *cfg = trunk->cfg;
if (cfg->osmux.initialized)
return 0;
/* So far we only support running on one trunk: */
OSMO_ASSERT(trunk == mgcp_trunk_by_num(cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID));
@@ -513,19 +507,19 @@ int osmux_init(struct mgcp_trunk *trunk)
ret = mgcp_create_bind(cfg->osmux.local_addr_v4, cfg->osmux.local_port,
cfg->endp_dscp, cfg->endp_priority);
if (ret < 0) {
LOGPTRUNK(trunk, DOSMUX, LOGL_ERROR, "Cannot bind OSMUX IPv4 socket to %s:%u\n",
cfg->osmux.local_addr_v4, cfg->osmux.local_port);
LOGP(DOSMUX, LOGL_ERROR, "Cannot bind OSMUX IPv4 socket to %s:%u\n",
cfg->osmux.local_addr_v4, cfg->osmux.local_port);
goto out_free_v4;
}
fd = ret;
ret = osmo_iofd_register(osmux_fd_v4, fd);
if (ret < 0) {
LOGPTRUNK(trunk, DOSMUX, LOGL_ERROR, "Cannot register OSMUX IPv4 socket %s\n", osmo_sock_get_name2(fd));
LOGP(DOSMUX, LOGL_ERROR, "Cannot register OSMUX IPv4 socket %s\n", osmo_sock_get_name2(fd));
close(fd);
goto out_free_v4;
}
LOGPTRUNK(trunk, DOSMUX, LOGL_INFO, "OSMUX IPv4 socket listening on %s\n", osmo_sock_get_name2(fd));
LOGP(DOSMUX, LOGL_INFO, "OSMUX IPv4 socket listening on %s\n", osmo_sock_get_name2(fd));
}
osmux_fd_v6 = osmo_iofd_setup(trunk, -1, "osmux_fd_v6", OSMO_IO_FD_MODE_RECVFROM_SENDTO, &osmux_ioops, trunk);
@@ -537,8 +531,8 @@ int osmux_init(struct mgcp_trunk *trunk)
ret = mgcp_create_bind(cfg->osmux.local_addr_v6, cfg->osmux.local_port,
cfg->endp_dscp, cfg->endp_priority);
if (ret < 0) {
LOGPTRUNK(trunk, DOSMUX, LOGL_ERROR, "Cannot bind OSMUX IPv6 socket to [%s]:%u\n",
cfg->osmux.local_addr_v6, cfg->osmux.local_port);
LOGP(DOSMUX, LOGL_ERROR, "Cannot bind OSMUX IPv6 socket to [%s]:%u\n",
cfg->osmux.local_addr_v6, cfg->osmux.local_port);
goto out_free_v6;
}
fd = ret;
@@ -549,10 +543,9 @@ int osmux_init(struct mgcp_trunk *trunk)
close(fd);
goto out_free_v6;
}
LOGPTRUNK(trunk, DOSMUX, LOGL_INFO, "OSMUX IPv6 socket listening on %s\n", osmo_sock_get_name2(fd));
LOGP(DOSMUX, LOGL_INFO, "OSMUX IPv6 socket listening on %s\n", osmo_sock_get_name2(fd));
}
cfg->osmux.initialized = true;
LOGPTRUNK(trunk, DOSMUX, LOGL_NOTICE, "OSMUX socket has been set up\n");
return 0;
out_free_v6:
@@ -564,7 +557,6 @@ out_free_v4:
osmo_iofd_free(osmux_fd_v4);
osmux_fd_v4 = NULL;
out:
LOGPTRUNK(trunk, DOSMUX, LOGL_ERROR, "Cannot init OSMUX\n");
return -1;
}

File diff suppressed because it is too large Load Diff

View File

@@ -93,7 +93,7 @@ static const struct rate_ctr_desc mgcp_mdcx_ctr_desc[] = {
[MGCP_MDCX_FAIL_INVALID_CONN_OPTIONS] = { "mdcx:conn_opt", "connection options invalid." },
[MGCP_MDCX_FAIL_NO_REMOTE_CONN_DESC] =
{ "mdcx:no_remote_conn_desc", "no opposite end specified for connection." },
[MGCP_MDCX_FAIL_BIND_PORT] = { "mdcx:bind_port", "port bind failure." },
[MGCP_MDCX_FAIL_START_RTP] = { "mdcx:start_rtp_failure", "failure to start RTP processing." },
[MGCP_MDCX_FAIL_AVAIL] = { "mdcx:unavailable", "endpoint unavailable." },
};

View File

@@ -199,7 +199,7 @@ static int fmtp_from_sdp(void *ctx, struct sdp_fmtp_param *fmtp_param, char *sdp
unsigned int pt;
unsigned int count = 0;
char delimiter;
unsigned int param_val;
unsigned int amr_octet_aligned;
memset(fmtp_param, 0, sizeof(*fmtp_param));
@@ -239,30 +239,12 @@ static int fmtp_from_sdp(void *ctx, struct sdp_fmtp_param *fmtp_param, char *sdp
if (delimiter == ';' || delimiter == ',')
str_ptr[strlen(str_ptr) - 1] = '\0';
/* We support the following codec parameters:
*
* AMR: octet-align parameter of RFC 4867 section 8.3;
* FR & EFR: tw-ts-001 parameter, Osmocom private;
* HR: tw-ts-002 parameter, Osmocom private.
*
* tw-ts-001 and tw-ts-002 Osmocom-private parameters are used
* only in the context of OsmoBSC driving an E1 MGW endpoint.
*/
if (sscanf(param_str, "octet-align=%d", &param_val) == 1) {
/* AMR octet aligned parameter (see also RFC 3267, section 8.3) */
if (sscanf(param_str, "octet-align=%d", &amr_octet_aligned) == 1) {
fmtp_param->param.amr_octet_aligned_present = true;
fmtp_param->param.amr_octet_aligned = false;
if (param_val == 1)
if (amr_octet_aligned == 1)
fmtp_param->param.amr_octet_aligned = true;
} else if (sscanf(param_str, "tw-ts-001=%d", &param_val) == 1) {
fmtp_param->param.fr_efr_twts001_present = true;
fmtp_param->param.fr_efr_twts001 = false;
if (param_val == 1)
fmtp_param->param.fr_efr_twts001 = true;
} else if (sscanf(param_str, "tw-ts-002=%d", &param_val) == 1) {
fmtp_param->param.hr_twts002_present = true;
fmtp_param->param.hr_twts002 = false;
if (param_val == 1)
fmtp_param->param.hr_twts002 = true;
}
param_str = strtok(NULL, " ");
@@ -577,23 +559,7 @@ int mgcp_write_response_sdp(const struct mgcp_endpoint *endp,
goto buffer_too_small;
}
/* Include a=fmtp line in MGCP response only for AMR
* octet-align parameter, not for tw-ts-* parameters.
* Rationale:
*
* - tw-ts-* parameters exist meaningfully only for E1
* endpoints driven by OsmoBSC, not in any other
* context. libosmo-mgcp-client used by OsmoBSC
* completely ignores all fmtp lines, has no code
* to parse them at all.
*
* - The SDP we return is supposed to indicate what
* _we_ accept, conceptually independent from what
* the remote accepts. And we always accept TW-TS-001
* and TW-TS-002 RTP formats going to E1 DL, whether
* or not we send them in UL per client request.
*/
if (codec->param_present && codec->param.amr_octet_aligned_present) {
if (codec->param_present) {
fmtp_param.payload_type = payload_type;
fmtp_param.param = codec->param;
fmtp_params[0] = fmtp_param;

View File

@@ -27,7 +27,6 @@ osmo_mgw_SOURCES = \
osmo_mgw_LDADD = \
$(top_builddir)/src/libosmo-mgcp/libosmo-mgcp.a \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOCODEC_LIBS) \
$(LIBOSMOVTY_LIBS) \
$(LIBOSMOGSM_LIBS) \
$(LIBOSMOCTRL_LIBS) \

View File

@@ -36,7 +36,6 @@ mgcp_test_SOURCES = \
mgcp_test_LDADD = \
$(top_builddir)/src/libosmo-mgcp/libosmo-mgcp.a \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOCODEC_LIBS) \
$(LIBOSMOVTY_LIBS) \
$(LIBOSMOGSM_LIBS) \
$(LIBOSMOABIS_LIBS) \

View File

@@ -43,8 +43,6 @@
#include <math.h>
#include <ctype.h>
void *tall_mgw_ctx;
char *strline_r(char *str, char **saveptr);
const char *strline_test_data =
@@ -2325,7 +2323,7 @@ void test_conn_id_matching(void)
INIT_LLIST_HEAD(&endp.conns);
conn = talloc_zero(tall_mgw_ctx, struct mgcp_conn);
conn = talloc_zero(NULL, struct mgcp_conn);
OSMO_ASSERT(conn);
osmo_strlcpy(conn->id, conn_id_generated, sizeof(conn->id));
llist_add(&conn->entry, &endp.conns);