aboutsummaryrefslogtreecommitdiffstats
path: root/src/libtrau/rtp_proxy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libtrau/rtp_proxy.c')
-rw-r--r--src/libtrau/rtp_proxy.c764
1 files changed, 0 insertions, 764 deletions
diff --git a/src/libtrau/rtp_proxy.c b/src/libtrau/rtp_proxy.c
deleted file mode 100644
index 6b38ee5fe..000000000
--- a/src/libtrau/rtp_proxy.c
+++ /dev/null
@@ -1,764 +0,0 @@
-/* RTP proxy handling for ip.access nanoBTS */
-
-/* (C) 2009-2013 by Harald Welte <laforge@gnumonks.org>
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <errno.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/time.h> /* gettimeofday() */
-#include <unistd.h> /* get..() */
-#include <time.h> /* clock() */
-#include <sys/utsname.h> /* uname() */
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-#include <openbsc/gsm_data.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/select.h>
-#include <openbsc/debug.h>
-#include <openbsc/rtp_proxy.h>
-#include <openbsc/mncc.h>
-#include <openbsc/trau_upqueue.h>
-
-#include <osmocom/netif/rtp.h>
-
-/* attempt to determine byte order */
-#include <sys/param.h>
-#include <limits.h>
-
-static LLIST_HEAD(rtp_sockets);
-
-/* should we mangle the CNAME inside SDES of RTCP packets? We disable
- * this by default, as it seems to be not needed */
-static int mangle_rtcp_cname = 0;
-
-enum rtp_bfd_priv {
- RTP_PRIV_NONE,
- RTP_PRIV_RTP,
- RTP_PRIV_RTCP
-};
-
-#define RTP_ALLOC_SIZE 1500
-
-#define RTCP_TYPE_SDES 202
-
-#define RTCP_IE_CNAME 1
-
-
-#define RTP_VERSION 2
-
-/* 33 for FR, all other codecs have smaller size */
-#define MAX_RTP_PAYLOAD_LEN 33
-
-/* decode an rtp frame and create a new buffer with payload */
-static int rtp_decode(struct msgb *msg, uint32_t callref, struct msgb **data)
-{
- struct msgb *new_msg;
- struct gsm_data_frame *frame;
- struct rtp_hdr *rtph = (struct rtp_hdr *)msg->data;
- struct rtp_x_hdr *rtpxh;
- uint8_t *payload, *payload_out;
- int payload_len;
- int msg_type;
- int x_len;
-
- if (msg->len < 12) {
- DEBUGPC(DLMUX, "received RTP frame too short (len = %d)\n",
- msg->len);
- return -EINVAL;
- }
- if (rtph->version != RTP_VERSION) {
- DEBUGPC(DLMUX, "received RTP version %d not supported.\n",
- rtph->version);
- return -EINVAL;
- }
- payload = msg->data + sizeof(struct rtp_hdr) + (rtph->csrc_count << 2);
- payload_len = msg->len - sizeof(struct rtp_hdr) - (rtph->csrc_count << 2);
- if (payload_len < 0) {
- DEBUGPC(DLMUX, "received RTP frame too short (len = %d, "
- "csrc count = %d)\n", msg->len, rtph->csrc_count);
- return -EINVAL;
- }
- if (rtph->extension) {
- if (payload_len < sizeof(struct rtp_x_hdr)) {
- DEBUGPC(DLMUX, "received RTP frame too short for "
- "extension header\n");
- return -EINVAL;
- }
- rtpxh = (struct rtp_x_hdr *)payload;
- x_len = ntohs(rtpxh->length) * 4 + sizeof(struct rtp_x_hdr);
- payload += x_len;
- payload_len -= x_len;
- if (payload_len < 0) {
- DEBUGPC(DLMUX, "received RTP frame too short, "
- "extension header exceeds frame length\n");
- return -EINVAL;
- }
- }
- if (rtph->padding) {
- if (payload_len < 1) {
- DEBUGPC(DLMUX, "received RTP frame too short for "
- "padding length\n");
- return -EINVAL;
- }
- payload_len -= payload[payload_len - 1];
- if (payload_len < 0) {
- DEBUGPC(DLMUX, "received RTP frame with padding "
- "greater than payload\n");
- return -EINVAL;
- }
- }
-
- switch (rtph->payload_type) {
- case RTP_PT_GSM_FULL:
- msg_type = GSM_TCHF_FRAME;
- if (payload_len != RTP_LEN_GSM_FULL) {
- DEBUGPC(DLMUX, "received RTP full rate frame with "
- "payload length != %d (len = %d)\n",
- RTP_LEN_GSM_FULL, payload_len);
- return -EINVAL;
- }
- break;
- case RTP_PT_GSM_EFR:
- msg_type = GSM_TCHF_FRAME_EFR;
- if (payload_len != RTP_LEN_GSM_EFR) {
- DEBUGPC(DLMUX, "received RTP extended full rate frame "
- "with payload length != %d (len = %d)\n",
- RTP_LEN_GSM_EFR, payload_len);
- return -EINVAL;
- }
- break;
- case RTP_PT_GSM_HALF:
- msg_type = GSM_TCHH_FRAME;
- if (payload_len != RTP_LEN_GSM_HALF) {
- DEBUGPC(DLMUX, "received RTP half rate frame with "
- "payload length != %d (len = %d)\n",
- RTP_LEN_GSM_HALF, payload_len);
- return -EINVAL;
- }
- break;
- case RTP_PT_AMR:
- msg_type = GSM_TCH_FRAME_AMR;
- break;
- default:
- DEBUGPC(DLMUX, "received RTP frame with unknown payload "
- "type %d\n", rtph->payload_type);
- return -EINVAL;
- }
-
- if (payload_len > MAX_RTP_PAYLOAD_LEN ||
- (rtph->payload_type == RTP_PT_AMR &&
- payload_len > MAX_RTP_PAYLOAD_LEN - 1)) {
- DEBUGPC(DLMUX, "RTP payload too large (%d octets)\n",
- payload_len);
- return -EINVAL;
- }
-
- /* always allocate for the maximum possible size to avoid
- * fragmentation */
- new_msg = msgb_alloc(sizeof(struct gsm_data_frame) +
- MAX_RTP_PAYLOAD_LEN+1, "GSM-DATA (TCH)");
-
- if (!new_msg)
- return -ENOMEM;
- frame = (struct gsm_data_frame *) msgb_put(new_msg, sizeof(struct gsm_data_frame));
- frame->msg_type = msg_type;
- frame->callref = callref;
- if (rtph->payload_type == RTP_PT_AMR) {
- /* for FR/HR/EFR the length is implicit. In AMR, we
- * need to make it explicit by using the first byte of
- * the data[] buffer as length byte */
- uint8_t *data0 = msgb_put(new_msg, 1);
- *data0 = payload_len;
- }
- payload_out = msgb_put(new_msg, payload_len);
- memcpy(payload_out, payload, payload_len);
-
- *data = new_msg;
- return 0;
-}
-
-/*! \brief encode and send a rtp frame
- * \param[in] rs RTP socket through which we shall send
- * \param[in] frame GSM RTP frame to be sent
- */
-int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
-{
- struct rtp_sub_socket *rss = &rs->rtp;
- struct msgb *msg;
- struct rtp_hdr *rtph;
- uint8_t *payload;
- int payload_type;
- int payload_len;
- int duration; /* in samples */
- int is_bfi = 0;
-
- if (rs->tx_action != RTP_SEND_DOWNSTREAM) {
- /* initialize sequences */
- rs->tx_action = RTP_SEND_DOWNSTREAM;
- rs->transmit.ssrc = rand();
- rs->transmit.sequence = random();
- rs->transmit.timestamp = random();
- }
-
- switch (frame->msg_type) {
- case GSM_TCHF_FRAME:
- payload_type = RTP_PT_GSM_FULL;
- payload_len = RTP_LEN_GSM_FULL;
- duration = RTP_GSM_DURATION;
- break;
- case GSM_TCHF_FRAME_EFR:
- payload_type = RTP_PT_GSM_EFR;
- payload_len = RTP_LEN_GSM_EFR;
- duration = RTP_GSM_DURATION;
- break;
- case GSM_TCHH_FRAME:
- payload_type = RTP_PT_GSM_HALF;
- payload_len = RTP_LEN_GSM_HALF;
- duration = RTP_GSM_DURATION;
- break;
- case GSM_TCH_FRAME_AMR:
- payload_type = RTP_PT_AMR;
- payload_len = frame->data[0];
- duration = RTP_GSM_DURATION;
- break;
- case GSM_BAD_FRAME:
- payload_type = 0;
- payload_len = 0;
- duration = RTP_GSM_DURATION;
- is_bfi = 1;
- break;
- default:
- DEBUGPC(DLMUX, "unsupported message type %d\n",
- frame->msg_type);
- return -EINVAL;
- }
-
- if (payload_len > MAX_RTP_PAYLOAD_LEN) {
- DEBUGPC(DLMUX, "RTP payload too large (%d octets)\n",
- payload_len);
- return -EINVAL;
- }
-
- if (is_bfi) {
- /* In case of a bad frame, just count and drop packet. */
- rs->transmit.timestamp += duration;
- rs->transmit.sequence++;
- return 0;
- }
-
- msg = msgb_alloc(sizeof(struct rtp_hdr) + payload_len, "RTP-GSM");
- if (!msg)
- return -ENOMEM;
- rtph = (struct rtp_hdr *) msgb_put(msg, sizeof(struct rtp_hdr));
- rtph->version = RTP_VERSION;
- rtph->padding = 0;
- rtph->extension = 0;
- rtph->csrc_count = 0;
- rtph->marker = 0;
- rtph->payload_type = payload_type;
- rtph->sequence = htons(rs->transmit.sequence++);
- rtph->timestamp = htonl(rs->transmit.timestamp);
- rs->transmit.timestamp += duration;
- rtph->ssrc = htonl(rs->transmit.ssrc);
-
- payload = msgb_put(msg, payload_len);
- if (frame->msg_type == GSM_TCH_FRAME_AMR)
- memcpy(payload, frame->data + 1, payload_len);
- else
- memcpy(payload, frame->data, payload_len);
- msgb_enqueue(&rss->tx_queue, msg);
- rss->bfd.when |= BSC_FD_WRITE;
-
- return 0;
-}
-
-/* iterate over all chunks in one RTCP message, look for CNAME IEs and
- * replace all of those with 'new_cname' */
-static int rtcp_sdes_cname_mangle(struct msgb *msg, struct rtcp_hdr *rh,
- uint16_t *rtcp_len, const char *new_cname)
-{
- uint8_t *rtcp_end;
- uint8_t *cur = (uint8_t *) rh;
- uint8_t tag, len = 0;
-
- rtcp_end = cur + *rtcp_len;
- /* move cur to end of RTP header */
- cur += sizeof(*rh);
-
- /* iterate over Chunks */
- while (cur+4 < rtcp_end) {
- /* skip four bytes SSRC/CSRC */
- cur += 4;
-
- /* iterate over IE's inside the chunk */
- while (cur+1 < rtcp_end) {
- tag = *cur++;
- if (tag == 0) {
- /* end of chunk, skip additional zero */
- while ((*cur++ == 0) && (cur < rtcp_end)) { }
- break;
- }
- len = *cur++;
-
- if (tag == RTCP_IE_CNAME) {
- /* we've found the CNAME, lets mangle it */
- if (len < strlen(new_cname)) {
- /* we need to make more space */
- int increase = strlen(new_cname) - len;
-
- msgb_push(msg, increase);
- memmove(cur+len+increase, cur+len,
- rtcp_end - (cur+len));
- /* FIXME: we have to respect RTCP
- * padding/alignment rules! */
- len += increase;
- *(cur-1) += increase;
- rtcp_end += increase;
- *rtcp_len += increase;
- }
- /* copy new CNAME into message */
- memcpy(cur, new_cname, strlen(new_cname));
- /* FIXME: zero the padding in case new CNAME
- * is smaller than old one !!! */
- }
- cur += len;
- }
- }
-
- return 0;
-}
-
-static int rtcp_mangle(struct msgb *msg, struct rtp_socket *rs)
-{
- struct rtp_sub_socket *rss = &rs->rtcp;
- struct rtcp_hdr *rtph;
- uint16_t old_len;
- int rc;
-
- if (!mangle_rtcp_cname)
- return 0;
-
- printf("RTCP\n");
- /* iterate over list of RTCP messages */
- rtph = (struct rtcp_hdr *)msg->data;
- while ((void *)rtph + sizeof(*rtph) <= (void *)msg->data + msg->len) {
- old_len = (ntohs(rtph->length) + 1) * 4;
- if ((void *)rtph + old_len > (void *)msg->data + msg->len) {
- DEBUGPC(DLMUX, "received RTCP packet too short for "
- "length element\n");
- return -EINVAL;
- }
- if (rtph->type == RTCP_TYPE_SDES) {
- char new_cname[255];
- osmo_strlcpy(new_cname,
- inet_ntoa(rss->sin_local.sin_addr),
- sizeof(new_cname));
- rc = rtcp_sdes_cname_mangle(msg, rtph, &old_len,
- new_cname);
- if (rc < 0)
- return rc;
- }
- rtph = (void *)rtph + old_len;
- }
-
- return 0;
-}
-
-/* read from incoming RTP/RTCP socket */
-static int rtp_socket_read(struct rtp_socket *rs, struct rtp_sub_socket *rss)
-{
- int rc;
- struct msgb *msg = msgb_alloc(RTP_ALLOC_SIZE, "RTP/RTCP");
- struct msgb *new_msg;
- struct rtp_sub_socket *other_rss;
-
- if (!msg)
- return -ENOMEM;
-
- rc = read(rss->bfd.fd, msg->data, RTP_ALLOC_SIZE);
- if (rc == 0) {
- rss->bfd.when &= ~BSC_FD_READ;
- goto out_free;
- } else if (rc < 0) {
- /* Ignore "connection refused". this happens, If we open the
- * socket faster than the remote side. */
- if (errno == ECONNREFUSED)
- goto out_free;
- DEBUGPC(DLMUX, "Read of RTP socket (%p) failed (errno %d, "
- "%s)\n", rs, errno, strerror(errno));
- rss->bfd.when &= ~BSC_FD_READ;
- goto out_free;
- }
-
- msgb_put(msg, rc);
-
- switch (rs->rx_action) {
- case RTP_PROXY:
- if (!rs->proxy.other_sock) {
- rc = -EIO;
- goto out_free;
- }
- if (rss->bfd.priv_nr == RTP_PRIV_RTP)
- other_rss = &rs->proxy.other_sock->rtp;
- else if (rss->bfd.priv_nr == RTP_PRIV_RTCP) {
- other_rss = &rs->proxy.other_sock->rtcp;
- /* modify RTCP SDES CNAME */
- rc = rtcp_mangle(msg, rs);
- if (rc < 0)
- goto out_free;
- } else {
- rc = -EINVAL;
- goto out_free;
- }
- msgb_enqueue(&other_rss->tx_queue, msg);
- other_rss->bfd.when |= BSC_FD_WRITE;
- break;
-
- case RTP_RECV_UPSTREAM:
- if (!rs->receive.callref || !rs->receive.net) {
- rc = -EIO;
- goto out_free;
- }
- if (rss->bfd.priv_nr == RTP_PRIV_RTCP) {
- if (!mangle_rtcp_cname) {
- msgb_free(msg);
- break;
- }
- /* modify RTCP SDES CNAME */
- rc = rtcp_mangle(msg, rs);
- if (rc < 0)
- goto out_free;
- msgb_enqueue(&rss->tx_queue, msg);
- rss->bfd.when |= BSC_FD_WRITE;
- break;
- }
- if (rss->bfd.priv_nr != RTP_PRIV_RTP) {
- rc = -EINVAL;
- goto out_free;
- }
- rc = rtp_decode(msg, rs->receive.callref, &new_msg);
- if (rc < 0)
- goto out_free;
- msgb_free(msg);
- trau_tx_to_mncc(rs->receive.net, new_msg);
- break;
-
- case RTP_NONE: /* if socket exists, but disabled by app */
- msgb_free(msg);
- break;
- }
-
- return 0;
-
-out_free:
- msgb_free(msg);
- return rc;
-}
-
-/* \brief write from tx_queue to RTP/RTCP socket */
-static int rtp_socket_write(struct rtp_socket *rs, struct rtp_sub_socket *rss)
-{
- struct msgb *msg;
- int written;
-
- msg = msgb_dequeue(&rss->tx_queue);
- if (!msg) {
- rss->bfd.when &= ~BSC_FD_WRITE;
- return 0;
- }
-
- written = write(rss->bfd.fd, msg->data, msg->len);
- if (written < msg->len) {
- LOGP(DLMIB, LOGL_ERROR, "short write");
- msgb_free(msg);
- return -EIO;
- }
-
- msgb_free(msg);
-
- return 0;
-}
-
-
-/*! \brief callback for the select.c:bfd_* layer */
-static int rtp_bfd_cb(struct osmo_fd *bfd, unsigned int flags)
-{
- struct rtp_socket *rs = bfd->data;
- struct rtp_sub_socket *rss;
-
- switch (bfd->priv_nr) {
- case RTP_PRIV_RTP:
- rss = &rs->rtp;
- break;
- case RTP_PRIV_RTCP:
- rss = &rs->rtcp;
- break;
- default:
- return -EINVAL;
- }
-
- if (flags & BSC_FD_READ)
- rtp_socket_read(rs, rss);
-
- if (flags & BSC_FD_WRITE)
- rtp_socket_write(rs, rss);
-
- return 0;
-}
-
-/*! \brief initialize one rtp sub-socket */
-static void init_rss(struct rtp_sub_socket *rss,
- struct rtp_socket *rs, int fd, int priv_nr)
-{
- /* initialize bfd */
- rss->bfd.fd = fd;
- rss->bfd.data = rs;
- rss->bfd.priv_nr = priv_nr;
- rss->bfd.cb = rtp_bfd_cb;
-}
-
-/*! \brief create a new RTP/RTCP socket and bind it */
-struct rtp_socket *rtp_socket_create(void)
-{
- int rc;
- struct rtp_socket *rs;
-
- DEBUGP(DLMUX, "rtp_socket_create(): ");
-
- rs = talloc_zero(tall_bsc_ctx, struct rtp_socket);
- if (!rs)
- return NULL;
-
- INIT_LLIST_HEAD(&rs->rtp.tx_queue);
- INIT_LLIST_HEAD(&rs->rtcp.tx_queue);
-
- rc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (rc < 0)
- goto out_free;
-
- init_rss(&rs->rtp, rs, rc, RTP_PRIV_RTP);
- rc = osmo_fd_register(&rs->rtp.bfd);
- if (rc < 0)
- goto out_rtp_socket;
-
- rc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (rc < 0)
- goto out_rtp_bfd;
-
- init_rss(&rs->rtcp, rs, rc, RTP_PRIV_RTCP);
- rc = osmo_fd_register(&rs->rtcp.bfd);
- if (rc < 0)
- goto out_rtcp_socket;
-
- DEBUGPC(DLMUX, "success\n");
-
- rc = rtp_socket_bind(rs, INADDR_ANY);
- if (rc < 0)
- goto out_rtcp_bfd;
-
- return rs;
-
-out_rtcp_bfd:
- osmo_fd_unregister(&rs->rtcp.bfd);
-out_rtcp_socket:
- close(rs->rtcp.bfd.fd);
-out_rtp_bfd:
- osmo_fd_unregister(&rs->rtp.bfd);
-out_rtp_socket:
- close(rs->rtp.bfd.fd);
-out_free:
- talloc_free(rs);
- DEBUGPC(DLMUX, "failed\n");
- return NULL;
-}
-
-static int rtp_sub_socket_bind(struct rtp_sub_socket *rss, uint32_t ip,
- uint16_t port)
-{
- int rc;
- socklen_t alen = sizeof(rss->sin_local);
-
- rss->sin_local.sin_family = AF_INET;
- rss->sin_local.sin_addr.s_addr = htonl(ip);
- rss->sin_local.sin_port = htons(port);
- rss->bfd.when |= BSC_FD_READ;
-
- rc = bind(rss->bfd.fd, (struct sockaddr *)&rss->sin_local,
- sizeof(rss->sin_local));
- if (rc < 0)
- return rc;
-
- /* retrieve the address we actually bound to, in case we
- * passed INADDR_ANY as IP address */
- return getsockname(rss->bfd.fd, (struct sockaddr *)&rss->sin_local,
- &alen);
-}
-
-#define RTP_PORT_BASE 30000
-static unsigned int next_udp_port = RTP_PORT_BASE;
-
-/*! \brief bind a RTP socket to a specific local address
- * \param[in] rs RTP socket to be bound
- * \param[in] ip local IP address to which socket is to be bound
- */
-int rtp_socket_bind(struct rtp_socket *rs, uint32_t ip)
-{
- int rc = -EIO;
- struct in_addr ia;
-
- ia.s_addr = htonl(ip);
- DEBUGP(DLMUX, "rtp_socket_bind(rs=%p, IP=%s): ", rs,
- inet_ntoa(ia));
-
- /* try to bind to a consecutive pair of ports */
- for (next_udp_port = next_udp_port % 0xffff;
- next_udp_port < 0xffff; next_udp_port += 2) {
- rc = rtp_sub_socket_bind(&rs->rtp, ip, next_udp_port);
- if (rc != 0)
- continue;
-
- rc = rtp_sub_socket_bind(&rs->rtcp, ip, next_udp_port+1);
- if (rc == 0)
- break;
- }
- if (rc < 0) {
- DEBUGPC(DLMUX, "failed\n");
- return rc;
- }
-
- ia.s_addr = rs->rtp.sin_local.sin_addr.s_addr;
- DEBUGPC(DLMUX, "BOUND_IP=%s, BOUND_PORT=%u\n",
- inet_ntoa(ia), ntohs(rs->rtp.sin_local.sin_port));
- return ntohs(rs->rtp.sin_local.sin_port);
-}
-
-static int rtp_sub_socket_connect(struct rtp_sub_socket *rss,
- uint32_t ip, uint16_t port)
-{
- int rc;
- socklen_t alen = sizeof(rss->sin_local);
-
- rss->sin_remote.sin_family = AF_INET;
- rss->sin_remote.sin_addr.s_addr = htonl(ip);
- rss->sin_remote.sin_port = htons(port);
-
- rc = connect(rss->bfd.fd, (struct sockaddr *) &rss->sin_remote,
- sizeof(rss->sin_remote));
- if (rc < 0)
- return rc;
-
- return getsockname(rss->bfd.fd, (struct sockaddr *)&rss->sin_local,
- &alen);
-}
-
-/*! \brief 'connect' a RTP socket to a remote peer
- * \param[in] rs RTP socket to be connected
- * \param[in] ip remote IP address to which to connect
- * \param[in] port remote UDP port number to which to connect
- */
-int rtp_socket_connect(struct rtp_socket *rs, uint32_t ip, uint16_t port)
-{
- int rc;
- struct in_addr ia;
-
- ia.s_addr = htonl(ip);
- DEBUGP(DLMUX, "rtp_socket_connect(rs=%p, ip=%s, port=%u)\n",
- rs, inet_ntoa(ia), port);
-
- rc = rtp_sub_socket_connect(&rs->rtp, ip, port);
- if (rc < 0)
- return rc;
-
- return rtp_sub_socket_connect(&rs->rtcp, ip, port+1);
-}
-
-/*! \brief bind two RTP/RTCP sockets together in the proxy
- * \param[in] this First RTP socket
- * \param[in] other Second RTP socket
- */
-int rtp_socket_proxy(struct rtp_socket *this, struct rtp_socket *other)
-{
- DEBUGP(DLMUX, "rtp_socket_proxy(this=%p, other=%p)\n",
- this, other);
-
- this->rx_action = RTP_PROXY;
- this->proxy.other_sock = other;
-
- other->rx_action = RTP_PROXY;
- other->proxy.other_sock = this;
-
- return 0;
-}
-
-/*! \brief bind RTP/RTCP socket to application, disabling proxy
- * \param[in] this RTP socket
- * \param[in] net gsm_network argument to trau_tx_to_mncc()
- * \param[in] callref callref argument to trau_tx_to_mncc()
- */
-int rtp_socket_upstream(struct rtp_socket *this, struct gsm_network *net,
- uint32_t callref)
-{
- DEBUGP(DLMUX, "rtp_socket_proxy(this=%p, callref=%u)\n",
- this, callref);
-
- if (callref) {
- this->rx_action = RTP_RECV_UPSTREAM;
- this->receive.net = net;
- this->receive.callref = callref;
- } else
- this->rx_action = RTP_NONE;
-
- return 0;
-}
-
-static void free_tx_queue(struct rtp_sub_socket *rss)
-{
- struct msgb *msg;
-
- while ((msg = msgb_dequeue(&rss->tx_queue)))
- msgb_free(msg);
-}
-
-/*! \brief Free/release a previously allocated RTP socket
- * \param[in[] rs RTP/RTCP socket to be released
- */
-int rtp_socket_free(struct rtp_socket *rs)
-{
- DEBUGP(DLMUX, "rtp_socket_free(rs=%p)\n", rs);
-
- /* make sure we don't leave references dangling to us */
- if (rs->rx_action == RTP_PROXY &&
- rs->proxy.other_sock)
- rs->proxy.other_sock->proxy.other_sock = NULL;
-
- osmo_fd_unregister(&rs->rtp.bfd);
- close(rs->rtp.bfd.fd);
- free_tx_queue(&rs->rtp);
-
- osmo_fd_unregister(&rs->rtcp.bfd);
- close(rs->rtcp.bfd.fd);
- free_tx_queue(&rs->rtcp);
-
- talloc_free(rs);
-
- return 0;
-}