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:
parent
04d362f79d
commit
6c4d2443b4
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue