aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/mgcp/mgcp_network.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/mgcp/mgcp_network.c')
-rw-r--r--openbsc/src/mgcp/mgcp_network.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/openbsc/src/mgcp/mgcp_network.c b/openbsc/src/mgcp/mgcp_network.c
index 96a186559..5c57bf49a 100644
--- a/openbsc/src/mgcp/mgcp_network.c
+++ b/openbsc/src/mgcp/mgcp_network.c
@@ -159,6 +159,42 @@ static int forward_data(int fd, struct mgcp_rtp_tap *tap, const char *buf, int l
return sendto(fd, buf, len, 0,
(struct sockaddr *)&tap->forward, sizeof(tap->forward));
}
+
+static int send_transcoder(struct mgcp_endpoint *endp, int is_rtp,
+ const char *buf, int len)
+{
+ int rc;
+ int port;
+ struct mgcp_config *cfg = endp->cfg;
+ struct sockaddr_in addr;
+
+ if (endp->transcoder_end.rtp_port == 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Transcoder port not known on 0x%x\n",
+ ENDPOINT_NUMBER(endp));
+ return -1;
+ }
+
+ port = rtp_calculate_port(ENDPOINT_NUMBER(endp), cfg->transcoder_remote_base);
+ if (!is_rtp)
+ port += 1;
+
+ addr.sin_family = AF_INET;
+ addr.sin_addr = cfg->transcoder_in;
+ addr.sin_port = htons(port);
+
+ rc = sendto(is_rtp ?
+ endp->bts_end.rtp.fd :
+ endp->bts_end.rtcp.fd, buf, len, 0,
+ (struct sockaddr *) &addr, sizeof(addr));
+
+ if (rc != len)
+ LOGP(DMGCP, LOGL_ERROR,
+ "Failed to send data to the transcoder: %s\n",
+ strerror(errno));
+
+ return rc;
+}
+
static int send_to(struct mgcp_endpoint *endp, int dest, int is_rtp,
struct sockaddr_in *addr, char *buf, int rc)
{
@@ -339,6 +375,52 @@ static int rtp_data_bts(struct bsc_fd *fd, unsigned int what)
endp->bts_end.packets += 1;
forward_data(fd->fd, &endp->taps[MGCP_TAP_BTS_IN], buf, rc);
+ if (cfg->transcoder_ip)
+ return send_transcoder(endp, proto == PROTO_RTP, &buf[0], rc);
+ else
+ return send_to(endp, DEST_NETWORK, proto == PROTO_RTP, &addr, &buf[0], rc);
+}
+
+static int rtp_data_transcoder(struct bsc_fd *fd, unsigned int what)
+{
+ char buf[4096];
+ struct sockaddr_in addr;
+ struct mgcp_endpoint *endp;
+ struct mgcp_config *cfg;
+ int rc, proto;
+
+ endp = (struct mgcp_endpoint *) fd->data;
+ cfg = endp->cfg;
+
+ rc = recevice_from(endp, fd->fd, &addr, buf, sizeof(buf));
+ if (rc <= 0)
+ return -1;
+
+ proto = fd == &endp->transcoder_end.rtp ? PROTO_RTP : PROTO_RTCP;
+
+ if (memcmp(&addr.sin_addr, &cfg->transcoder_in, sizeof(addr.sin_addr)) != 0) {
+ LOGP(DMGCP, LOGL_ERROR,
+ "Data not coming from transcoder: %s on 0x%x\n",
+ inet_ntoa(addr.sin_addr), ENDPOINT_NUMBER(endp));
+ return -1;
+ }
+
+ if (endp->transcoder_end.rtp_port != addr.sin_port &&
+ endp->transcoder_end.rtcp_port != addr.sin_port) {
+ LOGP(DMGCP, LOGL_ERROR,
+ "Data from wrong transcoder source port %d on 0x%x\n",
+ ntohs(addr.sin_port), ENDPOINT_NUMBER(endp));
+ return -1;
+ }
+
+ /* throw away the dummy message */
+ if (rc == 1 && buf[0] == DUMMY_LOAD) {
+ LOGP(DMGCP, LOGL_NOTICE, "Filtered dummy from transcoder on 0x%x\n",
+ ENDPOINT_NUMBER(endp));
+ return 0;
+ }
+
+ endp->transcoder_end.packets += 1;
return send_to(endp, DEST_NETWORK, proto == PROTO_RTP, &addr, &buf[0], rc);
}
@@ -453,6 +535,22 @@ int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port)
return bind_rtp(endp->cfg, &endp->net_end, ENDPOINT_NUMBER(endp));
}
+int mgcp_bind_transcoder_rtp_port(struct mgcp_endpoint *endp, int rtp_port)
+{
+ if (endp->transcoder_end.rtp.fd != -1 || endp->transcoder_end.rtcp.fd != -1) {
+ LOGP(DMGCP, LOGL_ERROR, "Previous net-port was still bound on %d\n",
+ ENDPOINT_NUMBER(endp));
+ mgcp_free_rtp_port(&endp->transcoder_end);
+ }
+
+ endp->transcoder_end.local_port = rtp_port;
+ endp->transcoder_end.rtp.cb = rtp_data_transcoder;
+ endp->transcoder_end.rtp.data = endp;
+ endp->transcoder_end.rtcp.data = endp;
+ endp->transcoder_end.rtcp.cb = rtp_data_transcoder;
+ return bind_rtp(endp->cfg, &endp->transcoder_end, ENDPOINT_NUMBER(endp));
+}
+
int mgcp_free_rtp_port(struct mgcp_rtp_end *end)
{
if (end->rtp.fd != -1) {