diff options
Diffstat (limited to 'openbsc/src/gsm_04_08.c')
-rw-r--r-- | openbsc/src/gsm_04_08.c | 117 |
1 files changed, 83 insertions, 34 deletions
diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index d59d7d7ca..f36723937 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -1864,12 +1864,16 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, return 0; } +static int tch_recv_mncc(struct gsm_network *net, u_int32_t callref, int enable); + /* 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) { struct gsm_lchan *lchan = signal_data; int rc; + struct gsm_network *net; + struct gsm_trans *trans; if (subsys != SS_ABISIP) return 0; @@ -1896,6 +1900,15 @@ static int handle_abisip_signal(unsigned int subsys, unsigned int signal, lchan->abis_ip.bound_port); if (rc < 0) goto out_err; + /* check if any transactions on this lchan still have + * a tch_recv_mncc request pending */ + net = lchan->ts->trx->bts->network; + llist_for_each_entry(trans, &net->trans_list, entry) { + if (trans->lchan == lchan && trans->tch_recv) { + DEBUGP(DCC, "pending tch_recv_mncc request\n"); + tch_recv_mncc(net, trans->callref, 1); + } + } break; case S_ABISIP_DLCX_IND: /* the BTS tells us a RTP stream has been disconnected */ @@ -1941,7 +1954,8 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n"); return -EINVAL; } - + + // todo: map between different bts types switch (bts->type) { case GSM_BTS_TYPE_NANOBTS: if (!ipacc_rtp_direct) { @@ -1950,6 +1964,7 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) if (rc < 0) return rc; rc = ipacc_connect_proxy_bind(remote_lchan); +#warning do we need a check of rc here? /* connect them with each other */ rtp_socket_proxy(lchan->abis_ip.rtp_socket, @@ -1971,8 +1986,7 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) break; default: DEBUGP(DCC, "Unknown BTS type %u\n", bts->type); - rc = -EINVAL; - break; + return -EINVAL; } return 0; @@ -1994,45 +2008,61 @@ static int tch_bridge(struct gsm_network *net, u_int32_t *refs) return tch_map(trans1->lchan, trans2->lchan); } -/* enable receive of channels to upqueue */ -static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable) +/* enable receive of channels to MNCC upqueue */ +static int tch_recv_mncc(struct gsm_network *net, u_int32_t callref, int enable) { struct gsm_trans *trans; + struct gsm_lchan *lchan; + struct gsm_bts *bts; + int rc; /* Find callref */ - trans = trans_find_by_callref(net, data->callref); + trans = trans_find_by_callref(net, callref); if (!trans) return -EIO; if (!trans->lchan) return 0; + lchan = trans->lchan; + bts = lchan->ts->trx->bts; - // todo IPACCESS - if (enable) - return trau_recv_lchan(trans->lchan, data->callref); - return trau_mux_unmap(NULL, data->callref); -} - -/* send a frame to channel */ -static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame) -{ - struct gsm_trans *trans; - - /* Find callref */ - trans = trans_find_by_callref(net, frame->callref); - if (!trans) - return -EIO; - if (!trans->lchan) - return 0; - if (trans->lchan->type != GSM_LCHAN_TCH_F && - trans->lchan->type != GSM_LCHAN_TCH_H) - return 0; + switch (bts->type) { + case GSM_BTS_TYPE_NANOBTS: + if (ipacc_rtp_direct) { + DEBUGP(DCC, "Error: RTP proxy is disabled\n"); + return -EINVAL; + } + /* in case, we don't have a RTP socket yet, we note this + * in the transaction and try later */ + if (!lchan->abis_ip.rtp_socket) { + trans->tch_recv = enable; + DEBUGP(DCC, "queue tch_recv_mncc request (%d)\n", enable); + return 0; + } + if (enable) { + /* connect the TCH's to our RTP proxy */ + rc = ipacc_connect_proxy_bind(lchan); + if (rc < 0) + return rc; + /* assign socket to application interface */ + rtp_socket_upstream(lchan->abis_ip.rtp_socket, + net, callref); + } else + rtp_socket_upstream(lchan->abis_ip.rtp_socket, + net, 0); + break; + case GSM_BTS_TYPE_BS11: + if (enable) + return trau_recv_lchan(lchan, callref); + return trau_mux_unmap(NULL, callref); + break; + default: + DEBUGP(DCC, "Unknown BTS type %u\n", bts->type); + return -EINVAL; + } - // todo IPACCESS - return trau_send_lchan(trans->lchan, - (struct decoded_trau_frame *)frame->data); + return 0; } - static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg) { DEBUGP(DCC, "-> STATUS ENQ\n"); @@ -3262,11 +3292,30 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg) case MNCC_BRIDGE: return tch_bridge(net, arg); case MNCC_FRAME_DROP: - return tch_recv(net, arg, 0); + return tch_recv_mncc(net, data->callref, 0); case MNCC_FRAME_RECV: - return tch_recv(net, arg, 1); - case GSM_TRAU_FRAME: - return tch_frame(net, arg); + return tch_recv_mncc(net, data->callref, 1); + case GSM_TCHF_FRAME: + /* Find callref */ + trans = trans_find_by_callref(net, data->callref); + if (!trans) + return -EIO; + if (!trans->lchan) + return 0; + if (trans->lchan->type != GSM_LCHAN_TCH_F) + return 0; + bts = trans->lchan->ts->trx->bts; + switch (bts->type) { + case GSM_BTS_TYPE_NANOBTS: + if (!trans->lchan->abis_ip.rtp_socket) + return 0; + return rtp_send_frame(trans->lchan->abis_ip.rtp_socket, arg); + case GSM_BTS_TYPE_BS11: + return trau_send_frame(trans->lchan, arg); + default: + DEBUGP(DCC, "Unknown BTS type %u\n", bts->type); + } + return -EINVAL; } memset(&rel, 0, sizeof(struct gsm_mncc)); |