hi,
after having solved an LCR issue, i patched rtp_proxy.c the same way,
because it has the same issue.
1. when next_udp_port (in rtp_socket_bind) reaches 0xfffe, the bind
process will fail next time.
2. if rtp_sub_socket_bind of rtp socket succeeds and rtp_sub_socket_bind
of rtcp socket fails, the rtp socket must be re-created, because it
cannot not be bound again to the next higher port.
3. the port range will not wrap arround and start at 0, but at
RTP_PORT_BASE. (after reaching RTP_PORT_MAX)
andreas
diff --git a/openbsc/src/libtrau/rtp_proxy.c b/openbsc/src/libtrau/rtp_proxy.c
index 3d34ac6..8e705e4 100644
--- a/openbsc/src/libtrau/rtp_proxy.c
+++ b/openbsc/src/libtrau/rtp_proxy.c
@@ -560,13 +560,17 @@ struct rtp_socket *rtp_socket_create(void)
return rs;
out_rtcp_bfd:
- osmo_fd_unregister(&rs->rtcp.bfd);
+ if (rs->rtcp.bfd.fd > 0) {
+ osmo_fd_unregister(&rs->rtcp.bfd);
out_rtcp_socket:
- close(rs->rtcp.bfd.fd);
+ close(rs->rtcp.bfd.fd);
+ }
out_rtp_bfd:
- osmo_fd_unregister(&rs->rtp.bfd);
+ if (rs->rtp.bfd.fd > 0) {
+ osmo_fd_unregister(&rs->rtp.bfd);
out_rtp_socket:
- close(rs->rtp.bfd.fd);
+ close(rs->rtp.bfd.fd);
+ }
out_free:
talloc_free(rs);
DEBUGPC(DLMUX, "failed\n");
@@ -595,29 +599,53 @@ static int rtp_sub_socket_bind(struct rtp_sub_socket
*rss, uint32_t ip,
&alen);
}
-#define RTP_PORT_BASE 30000
-static unsigned int next_udp_port = RTP_PORT_BASE;
+#define RTP_PORT_BASE 30000
+#define RTP_PORT_MAX 39998
+static unsigned short next_udp_port = RTP_PORT_BASE;
/* bind a RTP socket to a local address */
int rtp_socket_bind(struct rtp_socket *rs, uint32_t ip)
{
- int rc = -EIO;
+ int rc, rc2;
struct in_addr ia;
+ unsigned short start_port;
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) {
+ start_port = next_udp_port;
+ while (1) {
rc = rtp_sub_socket_bind(&rs->rtp, ip, next_udp_port);
if (rc != 0)
- continue;
+ goto try_next_port;
rc = rtp_sub_socket_bind(&rs->rtcp, ip, next_udp_port+1);
- if (rc == 0)
+ if (rc == 0) {
+ next_udp_port = (next_udp_port + 2 > RTP_PORT_MAX) ?
+ RTP_PORT_BASE : next_udp_port + 2;
+ break;
+ }
+ /* reopen rtp socket and try again with next udp port */
+ osmo_fd_unregister(&rs->rtp.bfd);
+ close(rs->rtp.bfd.fd);
+ rs->rtp.bfd.fd = 0;
+ rc2 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (rc2 < 0)
+ return rc2;
+ init_rss(&rs->rtp, rs, rc2, RTP_PRIV_RTP);
+ rc2 = osmo_fd_register(&rs->rtp.bfd);
+ if (rc2 < 0) {
+ close(rs->rtp.bfd.fd);
+ return rc2;
+ }
+try_next_port:
+ next_udp_port = (next_udp_port + 2 > RTP_PORT_MAX) ?
+ RTP_PORT_BASE : next_udp_port + 2;
+ if (next_udp_port == start_port)
break;
+ /* we must use rc2, in order to preserve rc */
}
if (rc < 0) {
DEBUGPC(DLMUX, "failed\n");