rtp: Move the RTP Proxy code out of RSL into the BSC/MSC domain

Instead of creating the sockets in the RSL code we will do this
in the CRCX_ACK, MDCX_ACK, DLCX_IND signal handler of gsm_04_08.
Introduce a handover signal so we can repatch the RTP sockets in
the gsm_04_08 as well.
This commit is contained in:
Holger Hans Peter Freyther 2011-01-06 13:31:41 +01:00
parent 04d362f79d
commit 6c4d2443b4
5 changed files with 98 additions and 74 deletions

View File

@ -46,6 +46,7 @@ enum signal_subsystems {
SS_IPAC_NWL,
SS_RF,
SS_MSC,
SS_HO,
};
/* SS_PAGING signals */
@ -211,5 +212,15 @@ struct msc_signal_data {
struct osmo_msc_data *data;
};
/* handover */
enum signal_ho {
S_HANDOVER_ACK,
};
struct ho_signal_data {
struct gsm_lchan *old_lchan;
struct gsm_lchan *new_lchan;
};
#endif

View File

@ -22,7 +22,7 @@ libbsc_a_SOURCES = abis_rsl.c abis_nm.c gsm_data.c gsm_04_08_utils.c \
trau_frame.c trau_mux.c paging.c e1_config.c e1_input.c \
input/misdn.c input/ipaccess.c handover_logic.c \
talloc_ctx.c system_information.c rest_octets.c \
rtp_proxy.c bts_siemens_bs11.c bts_ipaccess_nanobts.c \
bts_siemens_bs11.c bts_ipaccess_nanobts.c \
bts_unknown.c bsc_version.c bsc_api.c bsc_vty.c meas_rep.c gsm_04_80.c
libmsc_a_SOURCES = gsm_subscriber.c db.c \
@ -30,7 +30,7 @@ libmsc_a_SOURCES = gsm_subscriber.c db.c \
gsm_04_08.c gsm_04_11.c transaction.c \
token_auth.c rrlp.c ussd.c silent_call.c \
handover_decision.c auth.c \
osmo_msc.c
osmo_msc.c rtp_proxy.c
libvty_a_SOURCES = common_vty.c

View File

@ -1768,32 +1768,9 @@ static int abis_rsl_rx_ipacc_crcx_ack(struct msgb *msg)
ipac_parse_rtp(lchan, &tv);
/* in case we don't use direct BTS-to-BTS RTP */
if (!ipacc_rtp_direct) {
int rc;
/* the BTS has successfully bound a TCH to a local ip/port,
* which means we can connect our UDP socket to it */
if (lchan->abis_ip.rtp_socket) {
rtp_socket_free(lchan->abis_ip.rtp_socket);
lchan->abis_ip.rtp_socket = NULL;
}
lchan->abis_ip.rtp_socket = rtp_socket_create();
if (!lchan->abis_ip.rtp_socket)
goto out_err;
rc = rtp_socket_connect(lchan->abis_ip.rtp_socket,
lchan->abis_ip.bound_ip,
lchan->abis_ip.bound_port);
if (rc < 0)
goto out_err;
}
dispatch_signal(SS_ABISIP, S_ABISIP_CRCX_ACK, msg->lchan);
return 0;
out_err:
return -EIO;
}
static int abis_rsl_rx_ipacc_mdcx_ack(struct msgb *msg)
@ -1817,7 +1794,6 @@ static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
{
struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
struct tlv_parsed tv;
struct gsm_lchan *lchan = msg->lchan;
rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
@ -1825,12 +1801,6 @@ static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
print_rsl_cause(LOGL_DEBUG, TLVP_VAL(&tv, RSL_IE_CAUSE),
TLVP_LEN(&tv, RSL_IE_CAUSE));
/* the BTS tells us a RTP stream has been disconnected */
if (lchan->abis_ip.rtp_socket) {
rtp_socket_free(lchan->abis_ip.rtp_socket);
lchan->abis_ip.rtp_socket = NULL;
}
dispatch_signal(SS_ABISIP, S_ABISIP_DLCX_IND, msg->lchan);
return 0;

View File

@ -1452,6 +1452,60 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
static int tch_recv_mncc(struct gsm_network *net, u_int32_t callref, int enable);
/* handle audio path for handover */
static int handle_ho_signal(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
struct rtp_socket *old_rs, *new_rs, *other_rs;
struct ho_signal_data *sig = signal_data;
if (subsys != SS_HO || signal != S_HANDOVER_ACK)
return 0;
if (ipacc_rtp_direct) {
LOGP(DHO, LOGL_ERROR, "unable to handover in direct RTP mode\n");
return 0;
}
/* RTP Proxy mode */
new_rs = sig->new_lchan->abis_ip.rtp_socket;
old_rs = sig->old_lchan->abis_ip.rtp_socket;
if (!new_rs) {
LOGP(DHO, LOGL_ERROR, "no RTP socket for new_lchan\n");
return -EIO;
}
rsl_ipacc_mdcx_to_rtpsock(sig->new_lchan);
if (!old_rs) {
LOGP(DHO, LOGL_ERROR, "no RTP socket for old_lchan\n");
return -EIO;
}
/* copy rx_action and reference to other sock */
new_rs->rx_action = old_rs->rx_action;
new_rs->tx_action = old_rs->tx_action;
new_rs->transmit = old_rs->transmit;
switch (sig->old_lchan->abis_ip.rtp_socket->rx_action) {
case RTP_PROXY:
other_rs = old_rs->proxy.other_sock;
rtp_socket_proxy(new_rs, other_rs);
/* delete reference to other end socket to prevent
* rtp_socket_free() from removing the inverse reference */
old_rs->proxy.other_sock = NULL;
break;
case RTP_RECV_UPSTREAM:
new_rs->receive = old_rs->receive;
break;
case RTP_NONE:
break;
}
return 0;
}
/* some other part of the code sends us a signal */
static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
@ -1470,6 +1524,24 @@ static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
switch (signal) {
case S_ABISIP_CRCX_ACK:
/* in case we don't use direct BTS-to-BTS RTP */
/* the BTS has successfully bound a TCH to a local ip/port,
* which means we can connect our UDP socket to it */
if (lchan->abis_ip.rtp_socket) {
rtp_socket_free(lchan->abis_ip.rtp_socket);
lchan->abis_ip.rtp_socket = NULL;
}
lchan->abis_ip.rtp_socket = rtp_socket_create();
if (!lchan->abis_ip.rtp_socket)
return -EIO;
rc = rtp_socket_connect(lchan->abis_ip.rtp_socket,
lchan->abis_ip.bound_ip,
lchan->abis_ip.bound_port);
if (rc < 0)
return -EIO;
/* check if any transactions on this lchan still have
* a tch_recv_mncc request pending */
net = lchan->ts->trx->bts->network;
@ -1479,6 +1551,14 @@ static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
tch_recv_mncc(net, trans->callref, 1);
}
}
break;
case S_ABISIP_DLCX_IND:
/* the BTS tells us a RTP stream has been disconnected */
if (lchan->abis_ip.rtp_socket) {
rtp_socket_free(lchan->abis_ip.rtp_socket);
lchan->abis_ip.rtp_socket = NULL;
}
break;
}
@ -3226,5 +3306,6 @@ int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg)
*/
static __attribute__((constructor)) void on_dso_load_0408(void)
{
register_signal_handler(SS_HO, handle_ho_signal, NULL);
register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
}

View File

@ -332,7 +332,7 @@ static int ho_rsl_detect(struct gsm_lchan *new_lchan)
static int ho_ipac_crcx_ack(struct gsm_lchan *new_lchan)
{
struct bsc_handover *ho;
struct rtp_socket *old_rs, *new_rs, *other_rs;
struct ho_signal_data sig_ho;
ho = bsc_ho_by_new_lchan(new_lchan);
if (!ho) {
@ -340,47 +340,9 @@ static int ho_ipac_crcx_ack(struct gsm_lchan *new_lchan)
return 0;
}
if (ipacc_rtp_direct) {
LOGP(DHO, LOGL_ERROR, "unable to handover in direct RTP mode\n");
return 0;
}
/* RTP Proxy mode */
new_rs = new_lchan->abis_ip.rtp_socket;
old_rs = ho->old_lchan->abis_ip.rtp_socket;
if (!new_rs) {
LOGP(DHO, LOGL_ERROR, "no RTP socket for new_lchan\n");
return -EIO;
}
rsl_ipacc_mdcx_to_rtpsock(new_lchan);
if (!old_rs) {
LOGP(DHO, LOGL_ERROR, "no RTP socket for old_lchan\n");
return -EIO;
}
/* copy rx_action and reference to other sock */
new_rs->rx_action = old_rs->rx_action;
new_rs->tx_action = old_rs->tx_action;
new_rs->transmit = old_rs->transmit;
switch (ho->old_lchan->abis_ip.rtp_socket->rx_action) {
case RTP_PROXY:
other_rs = old_rs->proxy.other_sock;
rtp_socket_proxy(new_rs, other_rs);
/* delete reference to other end socket to prevent
* rtp_socket_free() from removing the inverse reference */
old_rs->proxy.other_sock = NULL;
break;
case RTP_RECV_UPSTREAM:
new_rs->receive = old_rs->receive;
break;
case RTP_NONE:
break;
}
sig_ho.old_lchan = ho->old_lchan;
sig_ho.new_lchan = new_lchan;
dispatch_signal(SS_HO, S_HANDOVER_ACK, &sig_ho);
return 0;
}