mgcp: Forward data from the BTS-in to the transcoder
Bind a new port for the transcoder, forward data from the BTS to the transcoder, and from the transcoder to the network. Leave BTS-IN where it is, BTS-OUT can now be after the transcoding took place. We send the data from the BTS RTP port. This whole route will be guarded by the transcoder_ip and if it is NULL (current default) it will not go through the transcoder.
This commit is contained in:
parent
54aaa0fbed
commit
218f8564e1
|
@ -98,6 +98,7 @@ struct mgcp_endpoint {
|
|||
/* port status for bts/net */
|
||||
struct mgcp_rtp_end bts_end;
|
||||
struct mgcp_rtp_end net_end;
|
||||
struct mgcp_rtp_end transcoder_end;
|
||||
|
||||
/* sequence bits */
|
||||
struct mgcp_rtp_state net_state;
|
||||
|
@ -123,6 +124,7 @@ int mgcp_analyze_header(struct mgcp_config *cfg, struct msgb *msg,
|
|||
int mgcp_send_dummy(struct mgcp_endpoint *endp);
|
||||
int mgcp_bind_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
|
||||
int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
|
||||
int mgcp_bind_transcoder_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
|
||||
int mgcp_free_rtp_port(struct mgcp_rtp_end *end);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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), 4000);
|
||||
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,51 @@ 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;
|
||||
}
|
||||
|
||||
return send_to(endp, DEST_NETWORK, proto == PROTO_RTP, &addr, &buf[0], rc);
|
||||
}
|
||||
|
||||
|
@ -453,6 +534,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) {
|
||||
|
|
|
@ -373,7 +373,8 @@ static int parse_conn_mode(const char *msg, int *conn_mode)
|
|||
}
|
||||
|
||||
static int allocate_port(struct mgcp_endpoint *endp, struct mgcp_rtp_end *end,
|
||||
struct mgcp_port_range *range, int for_net)
|
||||
struct mgcp_port_range *range,
|
||||
int (*alloc)(struct mgcp_endpoint *endp, int port))
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -390,9 +391,7 @@ static int allocate_port(struct mgcp_endpoint *endp, struct mgcp_rtp_end *end,
|
|||
if (range->last_port >= range->range_end)
|
||||
range->last_port = range->range_start;
|
||||
|
||||
rc = for_net ?
|
||||
mgcp_bind_net_rtp_port(endp, range->last_port) :
|
||||
mgcp_bind_bts_rtp_port(endp, range->last_port);
|
||||
rc = alloc(endp, range->last_port);
|
||||
|
||||
range->last_port += 2;
|
||||
if (rc == 0) {
|
||||
|
@ -402,21 +401,31 @@ static int allocate_port(struct mgcp_endpoint *endp, struct mgcp_rtp_end *end,
|
|||
|
||||
}
|
||||
|
||||
LOGP(DMGCP, LOGL_ERROR, "Allocating a RTP/RTCP port failed 200 times 0x%x net: %d\n",
|
||||
ENDPOINT_NUMBER(endp), for_net);
|
||||
LOGP(DMGCP, LOGL_ERROR, "Allocating a RTP/RTCP port failed 200 times 0x%x.\n",
|
||||
ENDPOINT_NUMBER(endp));
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int allocate_ports(struct mgcp_endpoint *endp)
|
||||
{
|
||||
if (allocate_port(endp, &endp->net_end, &endp->cfg->net_ports, 1) != 0)
|
||||
if (allocate_port(endp, &endp->net_end, &endp->cfg->net_ports,
|
||||
mgcp_bind_net_rtp_port) != 0)
|
||||
return -1;
|
||||
|
||||
if (allocate_port(endp, &endp->bts_end, &endp->cfg->bts_ports, 0) != 0) {
|
||||
if (allocate_port(endp, &endp->bts_end, &endp->cfg->bts_ports,
|
||||
mgcp_bind_bts_rtp_port) != 0) {
|
||||
mgcp_rtp_end_reset(&endp->net_end);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (endp->cfg->transcoder_ip &&
|
||||
allocate_port(endp, &endp->transcoder_end, &endp->cfg->transcoder_ports,
|
||||
mgcp_bind_transcoder_rtp_port) != 0) {
|
||||
mgcp_rtp_end_reset(&endp->net_end);
|
||||
mgcp_rtp_end_reset(&endp->bts_end);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -805,6 +814,7 @@ int mgcp_endpoints_allocate(struct mgcp_config *cfg)
|
|||
cfg->endpoints[i].cfg = cfg;
|
||||
mgcp_rtp_end_init(&cfg->endpoints[i].net_end);
|
||||
mgcp_rtp_end_init(&cfg->endpoints[i].bts_end);
|
||||
mgcp_rtp_end_init(&cfg->endpoints[i].transcoder_end);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -828,6 +838,7 @@ void mgcp_free_endp(struct mgcp_endpoint *endp)
|
|||
|
||||
mgcp_rtp_end_reset(&endp->bts_end);
|
||||
mgcp_rtp_end_reset(&endp->net_end);
|
||||
mgcp_rtp_end_reset(&endp->transcoder_end);
|
||||
|
||||
memset(&endp->net_state, 0, sizeof(endp->net_state));
|
||||
memset(&endp->bts_state, 0, sizeof(endp->bts_state));
|
||||
|
|
|
@ -505,6 +505,16 @@ int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg)
|
|||
}
|
||||
endp->net_end.local_alloc = PORT_ALLOC_STATIC;
|
||||
}
|
||||
|
||||
if (g_cfg->transcoder_ip && g_cfg->transcoder_ports.mode == PORT_ALLOC_STATIC) {
|
||||
rtp_port = rtp_calculate_port(ENDPOINT_NUMBER(endp),
|
||||
g_cfg->transcoder_ports.base_port);
|
||||
if (mgcp_bind_transcoder_rtp_port(endp, rtp_port) != 0) {
|
||||
LOGP(DMGCP, LOGL_FATAL, "Failed to bind: %d\n", rtp_port);
|
||||
return -1;
|
||||
}
|
||||
endp->transcoder_end.local_alloc = PORT_ALLOC_STATIC;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue