diff options
-rw-r--r-- | openbsc/include/openbsc/rtp_proxy.h | 2 | ||||
-rw-r--r-- | openbsc/src/libtrau/rtp_proxy.c | 30 | ||||
-rw-r--r-- | openbsc/src/libtrau/rtp_proxy_main.c | 33 |
3 files changed, 62 insertions, 3 deletions
diff --git a/openbsc/include/openbsc/rtp_proxy.h b/openbsc/include/openbsc/rtp_proxy.h index 9d8d5832e..f9a55ebb0 100644 --- a/openbsc/include/openbsc/rtp_proxy.h +++ b/openbsc/include/openbsc/rtp_proxy.h @@ -38,6 +38,7 @@ enum rtp_rx_action { RTP_NONE, RTP_PROXY, RTP_RECV_UPSTREAM, + RTP_LOOPBACK }; enum rtp_tx_action { @@ -85,6 +86,7 @@ int rtp_socket_bind(struct rtp_socket *rs, uint32_t ip); int rtp_socket_bind_port(struct rtp_socket *rs, uint32_t ip, uint16_t port); int rtp_socket_connect(struct rtp_socket *rs, uint32_t ip, uint16_t port); int rtp_socket_proxy(struct rtp_socket *this, struct rtp_socket *other); +int rtp_socket_loopback(struct rtp_socket *s); int rtp_socket_upstream(struct rtp_socket *this, struct gsm_network *net, uint32_t callref); int rtp_socket_free(struct rtp_socket *rs); int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame); diff --git a/openbsc/src/libtrau/rtp_proxy.c b/openbsc/src/libtrau/rtp_proxy.c index 693a57a91..f00b1656b 100644 --- a/openbsc/src/libtrau/rtp_proxy.c +++ b/openbsc/src/libtrau/rtp_proxy.c @@ -392,11 +392,15 @@ static int rtp_socket_read(struct rtp_socket *rs, struct rtp_sub_socket *rss) struct msgb *msg = msgb_alloc(RTP_ALLOC_SIZE, "RTP/RTCP"); struct msgb *new_msg; struct rtp_sub_socket *other_rss; + struct sockaddr_in src_addr; + socklen_t src_addrlen; if (!msg) return -ENOMEM; - rc = read(rss->bfd.fd, msg->data, RTP_ALLOC_SIZE); + src_addrlen = sizeof(src_addr); + rc = recvfrom(rss->bfd.fd, msg->data, RTP_ALLOC_SIZE, 0, + (struct sockaddr *)&src_addr, &src_addrlen); if (rc <= 0) { rss->bfd.when &= ~BSC_FD_READ; return rc; @@ -405,6 +409,20 @@ static int rtp_socket_read(struct rtp_socket *rs, struct rtp_sub_socket *rss) msgb_put(msg, rc); switch (rs->rx_action) { + case RTP_LOOPBACK: + /* if this socket is not connected yet to a remote + * address, do so now */ + if (rss->sin_local.sin_addr.s_addr != src_addr.sin_addr.s_addr || + rss->sin_local.sin_port != src_addr.sin_port) { + LOGP(DLMUX, LOGL_INFO, "connecting loopback socket\n"); + rc = rtp_socket_connect(rs, + ntohl(src_addr.sin_addr.s_addr), + ntohs(src_addr.sin_port)); + } + /* FIXME: Do we need RTCP mangling here? */ + msgb_enqueue(&rss->tx_queue, msg); + rss->bfd.when |= BSC_FD_WRITE; + break; case RTP_PROXY: if (!rs->proxy.other_sock) { rc = -EIO; @@ -724,6 +742,16 @@ int rtp_socket_proxy(struct rtp_socket *this, struct rtp_socket *other) return 0; } +/*! \brief put socket into loopback mode, echong back all data + * \param[in] RTP socket to be put in loopback mode + */ +int rtp_socket_loopback(struct rtp_socket *s) +{ + s->rx_action = RTP_LOOPBACK; + + 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() diff --git a/openbsc/src/libtrau/rtp_proxy_main.c b/openbsc/src/libtrau/rtp_proxy_main.c index afb245364..87d6b7723 100644 --- a/openbsc/src/libtrau/rtp_proxy_main.c +++ b/openbsc/src/libtrau/rtp_proxy_main.c @@ -143,6 +143,29 @@ static struct vty_app_info vty_info = { .is_config_node = bsc_vty_is_config_node, }; +static int create_socket_loop(uint16_t port) +{ + struct rtp_socket *s; + int rc; + + s = rtp_socket_create(); + if (!s) + return -EIO; + + rc = rtp_socket_bind_port(s, INADDR_ANY, port); + if (rc < 0) + goto err_free_s; + + rc = rtp_socket_loopback(s); + if (rc < 0) + goto err_free_s; + + return 0; +err_free_s: + rtp_socket_free(s); + return -EIO; +} + static int create_socket_pair(uint16_t port1, uint16_t port2) { struct rtp_socket *a, *b; @@ -225,15 +248,21 @@ int main(int argc, char **argv) osmo_init_ignore_signals(); /* hard-wire map CIC 1->33, 2->33, ... */ - for (i = 1; i <= 4; i++) { + for (i = 1; i <= 8; i++) { uint16_t port1, port2; port1 = PORT_BY_CIC(0, i); port2 = PORT_BY_CIC(1, i); - printf("Creating UDP port mapping %u -> %u\n", port1, port2); + printf("Creating UDP port mapping (%u,%u:%u) -> (%u,%u:%u)\n", + 0,i,1,i,port1, port2); rc = create_socket_pair(port1, port2); if (rc < 0) exit(1); } + printf("Creating loopback CIC (%u,%u:%u)\n", + 0, 16, PORT_BY_CIC(0, 16)); + rc = create_socket_loop(PORT_BY_CIC(0,16)); + if (rc < 0) + exit(1); if (daemonize) { rc = osmo_daemonize(); |