aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/bsc_msc_ip.c
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-01-28 10:04:13 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-01-28 11:59:51 +0100
commit556008d724c8b5062a02e4ac1ab6c9e62e02cc33 (patch)
tree82d58dc55825c10aa99281ce7de5ba990a76253c /openbsc/src/bsc_msc_ip.c
parent0094f84f305bcdbe29478170109639de9737f088 (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.c33
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;
}