Initial IuUP support using proper FSMs
Related: OS#1937
Depends: libosmocore Change-Id I63ee780b4aa162ea097410b234e73984000c0965
Change-Id: I6694a21480b25ab8f35d375295be6601ce38e31d
diff --git a/src/libosmo-mgcp/mgcp_network.c b/src/libosmo-mgcp/mgcp_network.c
index f865dfe..0ea8c25 100644
--- a/src/libosmo-mgcp/mgcp_network.c
+++ b/src/libosmo-mgcp/mgcp_network.c
@@ -48,7 +48,7 @@
#include <osmocom/mgcp/debug.h>
#include <osmocom/codec/codec.h>
#include <osmocom/mgcp/mgcp_e1.h>
-
+#include <osmocom/mgcp/mgcp_iuup.h>
#define RTP_SEQ_MOD (1 << 16)
#define RTP_MAX_DROPOUT 3000
@@ -59,7 +59,7 @@
MGCP_PROTO_RTCP,
};
-static void rtpconn_rate_ctr_add(struct mgcp_conn_rtp *conn_rtp, struct mgcp_endpoint *endp,
+void rtpconn_rate_ctr_add(struct mgcp_conn_rtp *conn_rtp, struct mgcp_endpoint *endp,
int id, int inc)
{
struct rate_ctr_group *conn_stats = conn_rtp->rate_ctr_group;
@@ -156,7 +156,7 @@
/* This does not need to be a precision timestamp and
* is allowed to wrap quite fast. The returned value is
* 1/codec_rate seconds. */
-static uint32_t get_current_ts(unsigned codec_rate)
+uint32_t mgcp_get_current_ts(unsigned codec_rate)
{
struct timespec tp;
uint64_t ret;
@@ -529,7 +529,7 @@
rtp_hdr = (struct rtp_hdr *)msgb_data(msg);
seq = ntohs(rtp_hdr->sequence);
timestamp = ntohl(rtp_hdr->timestamp);
- arrival_time = get_current_ts(rtp_end->codec->rate);
+ arrival_time = mgcp_get_current_ts(rtp_end->codec->rate);
ssrc = ntohl(rtp_hdr->ssrc);
marker_bit = !!rtp_hdr->marker;
transit = arrival_time - timestamp;
@@ -789,7 +789,7 @@
/* Forward data to a debug tap. This is debug function that is intended for
* debugging the voice traffic with tools like gstreamer */
-static void forward_data(int fd, struct mgcp_rtp_tap *tap, struct msgb *msg)
+void forward_data_tap(int fd, struct mgcp_rtp_tap *tap, struct msgb *msg)
{
int rc;
@@ -815,7 +815,7 @@
hdr->version = 2;
hdr->payload_type = rtp_end->codec->payload_type;
- hdr->timestamp = osmo_htonl(get_current_ts(rtp_end->codec->rate));
+ hdr->timestamp = osmo_htonl(mgcp_get_current_ts(rtp_end->codec->rate));
hdr->sequence = osmo_htons(state->alt_rtp_tx_sequence);
hdr->ssrc = state->alt_rtp_tx_ssrc;
}
@@ -975,7 +975,7 @@
* the length is because we currently handle IUUP packets as RTP
* packets, so they must pass this check, if we weould be more
* strict here, we would possibly break 3G. (see also FIXME note
- * below */
+ * below.*/
return 0;
}
@@ -1013,6 +1013,19 @@
"endpoint type is MGCP_OSMUX_BSC_NAT, "
"using osmux_xfrm_to_osmux() to forward data through OSMUX\n");
return osmux_xfrm_to_osmux((char*)msgb_data(msg), msgb_length(msg), conn_dst);
+ case MGCP_RTP_IUUP:
+ if (proto == MGCP_PROTO_RTP) {
+ LOGPENDP(endp, DRTP, LOGL_DEBUG,
+ "endpoint type is MGCP_RTP_IUUP, "
+ "using mgcp_conn_iuup_send_rtp() to forward data over IuUP\n");
+ return mgcp_conn_iuup_send_rtp(conn_src, conn_dst, msg);
+ }
+ /* RTCP: we forward as usual for regular RTP connection */
+ LOGPENDP(endp, DRTP, LOGL_DEBUG,
+ "endpoint type is MGCP_RTP_IUUP and proto!=MGCP_PROTO_RTP, "
+ "using mgcp_send() to forward data directly\n");
+ return mgcp_send(endp, false,
+ mc->from_addr, msg, conn_src, conn_dst);
}
/* If the data has not been handled/forwarded until here, it will
@@ -1073,8 +1086,11 @@
if (check_rtp_destin(conn) != 0)
goto failed;
- rc = mgcp_udp_send(conn->end.rtp.fd, &conn->end.addr,
- conn->end.rtp_port, rtp_dummy_payload, sizeof(rtp_dummy_payload));
+ if (mgcp_conn_rtp_is_iuup(conn))
+ rc = mgcp_conn_iuup_send_dummy(conn);
+ else
+ rc = mgcp_udp_send(conn->end.rtp.fd, &conn->end.addr, conn->end.rtp_port,
+ rtp_dummy_payload, sizeof(rtp_dummy_payload));
if (rc == -1)
goto failed;
@@ -1138,7 +1154,7 @@
* course unable to patch the payload type. A situation like this
* should not occur if transcoding is consequently avoided. Until
* we have transcoding support in osmo-mgw we can not resolve this. */
- if (is_rtp) {
+ if (is_rtp && conn_dst->type != MGCP_RTP_IUUP) {
rc = mgcp_patch_pt(conn_src, conn_dst, msg);
if (rc < 0) {
LOGPENDP(endp, DRTP, LOGL_DEBUG,
@@ -1185,7 +1201,9 @@
mgcp_patch_and_count(endp, rtp_state, rtp_end,
addr, msg);
- if (amr_oa_bwe_convert_indicated(conn_dst->end.codec)) {
+ if (mgcp_conn_rtp_is_iuup(conn_dst) || mgcp_conn_rtp_is_iuup(conn_src)) {
+ /* the iuup code will correctly transform to the correct AMR mode */
+ } else if (amr_oa_bwe_convert_indicated(conn_dst->end.codec)) {
rc = amr_oa_bwe_convert(endp, msg,
conn_dst->end.codec->param.amr_octet_aligned);
if (rc < 0) {
@@ -1211,28 +1229,9 @@
);
/* Forward a copy of the RTP data to a debug ip/port */
- forward_data(rtp_end->rtp.fd, &conn_src->tap_out,
+ forward_data_tap(rtp_end->rtp.fd, &conn_src->tap_out,
msg);
- /* 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 (!rtp_state->patched_first_rtp_payload
- && conn_src->conn->mode == MGCP_CONN_LOOPBACK) {
- uint8_t *data = msgb_data(msg) + 12;
- if (data[0] == 0xe0) {
- data[0] = 0xe4;
- data[1] = 0x00;
- data[2] = (0x09 << 2); /* Patch CRC Header to adapt to new header above */
- rtp_state->patched_first_rtp_payload = true;
- LOGPENDP(endp, DRTP, LOGL_DEBUG,
- "Patching over first two bytes"
- " to fake an IuUP Initialization Ack\n");
- }
- }
-
len = mgcp_udp_send(rtp_end->rtp.fd, &rtp_end->addr, rtp_end->rtp_port,
(char *)msgb_data(msg), msgb_length(msg));
@@ -1292,6 +1291,9 @@
* destination connection is known the RTP packet is sent via
* the destination connection. */
+ /* If source is IuUP, we need to handle state, forward it through specific bridge path: */
+ if (mgcp_conn_rtp_is_iuup(conn_src) && mc->proto == MGCP_PROTO_RTP)
+ return mgcp_conn_iuup_dispatch_rtp(msg);
/* Check if the connection is in loopback mode, if yes, just send the
* incoming data back to the origin */
@@ -1507,7 +1509,7 @@
/* FIXME: count RTP and RTCP separately, also count IuUP payload-less separately */
/* Forward a copy of the RTP data to a debug ip/port */
- forward_data(fd->fd, &conn_src->tap_in, msg);
+ forward_data_tap(fd->fd, &conn_src->tap_in, msg);
rc = rx_rtp(msg);