diff options
author | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-01-28 10:04:13 +0100 |
---|---|---|
committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-01-28 11:59:51 +0100 |
commit | 556008d724c8b5062a02e4ac1ab6c9e62e02cc33 (patch) | |
tree | 82d58dc55825c10aa99281ce7de5ba990a76253c /openbsc/src/bsc_msc_ip.c | |
parent | 0094f84f305bcdbe29478170109639de9737f088 (diff) |
[bsc] Implement early assignment for CC for the MT case.
In case we need to handle speech but we are currently on a SDCCH
we need to assign a new channel and close the old one. This
implementation should have the correct flow of things but we might
need to fix some error situations properly.
It is implemented by keeping a secondary_lchan pointer that will
be swapped into the lchan pointer after the assignment complete
message from the MS. The old lchan will be deactivated (the SACCH
should stay open). We have to manually remove the subscr from the
lchan structure to properly close things down.
Diffstat (limited to 'openbsc/src/bsc_msc_ip.c')
-rw-r--r-- | openbsc/src/bsc_msc_ip.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/openbsc/src/bsc_msc_ip.c b/openbsc/src/bsc_msc_ip.c index 33bdf50c0..54ed96b2a 100644 --- a/openbsc/src/bsc_msc_ip.c +++ b/openbsc/src/bsc_msc_ip.c @@ -298,20 +298,45 @@ static int handle_cipher_m_complete(struct msgb *msg) /* Receive a ASSIGNMENT COMPLETE */ static int handle_ass_compl(struct msgb *msg) { + struct gsm_lchan *old_chan; struct gsm48_hdr *gh = msgb_l3(msg); DEBUGP(DMSC, "ASSIGNMENT COMPLETE from MS, forwarding to MSC\n"); if (!msg->lchan->msc_data) { DEBUGP(DMSC, "No MSC data\n"); + put_lchan(msg->lchan); + return -1; + } + + if (msg->lchan->msc_data->secondary_lchan != msg->lchan) { + LOGP(DMSC, LOGL_NOTICE, "Wrong assignment complete.\n"); + put_lchan(msg->lchan); return -1; } if (msgb_l3len(msg) - sizeof(*gh) != 1) { DEBUGP(DMSC, "assignment failure invalid: %d\n", msgb_l3len(msg) - sizeof(*gh)); + put_lchan(msg->lchan); return -1; } + + /* swap the channels and release the old */ + old_chan = msg->lchan->msc_data->lchan; + msg->lchan->msc_data->lchan = msg->lchan; + msg->lchan->msc_data->secondary_lchan = NULL; + old_chan->msc_data = NULL; + + /* give up the old channel to not do a SACCH deactivate */ + subscr_put(old_chan->subscr); + old_chan->subscr = NULL; + put_lchan(old_chan); + + /* activate audio on it... */ + if (is_ipaccess_bts(msg->lchan->ts->trx->bts) && msg->lchan->tch_mode != GSM48_CMODE_SIGN) + rsl_ipacc_crcx(msg->lchan); + gsm0808_send_assignment_compl(msg->lchan, gh->data[0]); return 1; } @@ -327,12 +352,20 @@ static int handle_ass_fail(struct msgb *msg) DEBUGP(DMSC, "ASSIGNMENT FAILURE from MS, forwarding to MSC\n"); if (!msg->lchan->msc_data) { DEBUGP(DMSC, "No MSC data\n"); + put_lchan(msg->lchan); + return -1; + } + + if (msg->lchan->msc_data->secondary_lchan != msg->lchan) { + LOGP(DMSC, LOGL_NOTICE, "Wrong assignment complete.\n"); + put_lchan(msg->lchan); return -1; } if (msgb_l3len(msg) - sizeof(*gh) != 1) { DEBUGP(DMSC, "assignment failure invalid: %d\n", msgb_l3len(msg) - sizeof(*gh)); + put_lchan(msg->lchan); return -1; } |