static void handle_release(struct gsm_subscriber_connection *conn, struct bsc_api *bsc, struct gsm_lchan *lchan) { int destruct = 1; if (conn->secondary_lchan == lchan) { osmo_timer_del(&conn->T10); conn->secondary_lchan = NULL; bsc->assign_fail(conn, GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, NULL); } /* clear the connection now */ if (bsc->clear_request) destruct = bsc->clear_request(conn, 0); /* now give up all channels */ if (conn->lchan == lchan) conn->lchan = NULL; if (conn->ho_lchan == lchan) { bsc_clear_handover(conn, 0); conn->ho_lchan = NULL; } lchan->conn = NULL; gsm0808_clear(conn); if (destruct) subscr_con_free(conn); }
/* lchan release handling */ void msc_release_connection(struct gsm_subscriber_connection *conn) { /* skip when we are in release, e.g. due an error */ if (conn->in_release) return; /* skip releasing of silent calls as they have no transaction */ if (conn->silent_call) return; /* check if there is a pending operation */ if (conn->loc_operation || conn->sec_operation || conn->anch_operation) return; if (trans_has_conn(conn)) return; /* no more connections, asking to release the channel */ /* * We had stopped the LU expire timer T3212. Now we are about * to send the MS back to the idle state and this should lead * to restarting the timer. Set the new expiration time. */ if (conn->expire_timer_stopped) subscr_update_expire_lu(conn->subscr, conn->bts); conn->in_release = 1; gsm0808_clear(conn); if (conn->put_channel) { conn->put_channel = 0; subscr_put_channel(conn->subscr); } subscr_con_free(conn); }
/*! \brief RSL has received a DATA INDICATION with L3 from MS */ int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id) { int rc; struct bsc_api *api = msg->lchan->ts->trx->bts->network->bsc_api; struct gsm_lchan *lchan; lchan = msg->lchan; if (lchan->state != LCHAN_S_ACTIVE) { LOGP(DRSL, LOGL_INFO, "Got data in non active state(%s), " "discarding.\n", gsm_lchans_name(lchan->state)); return -1; } if (lchan->conn) { /* if we already have a connection, forward via DTAP to * MSC */ dispatch_dtap(lchan->conn, link_id, msg); } else { /* allocate a new connection */ rc = BSC_API_CONN_POL_REJECT; lchan->conn = subscr_con_allocate(msg->lchan); if (!lchan->conn) { lchan_release(lchan, 1, 0); return -1; } /* fwd via bsc_api to send COMPLETE L3 INFO to MSC */ rc = api->compl_l3(lchan->conn, msg, 0); if (rc != BSC_API_CONN_POL_ACCEPT) { lchan->conn->lchan = NULL; subscr_con_free(lchan->conn); lchan_release(lchan, 1, 0); } } return 0; }
/* * GSM 08.08 § 3.1.9.1 and 3.2.1.21... * release our gsm_subscriber_connection and send message */ static int bssmap_handle_clear_command(struct osmo_bsc_sccp_con *conn, struct msgb *msg, unsigned int payload_length) { struct msgb *resp; /* TODO: handle the cause of this package */ if (conn->conn) { LOGP(DMSC, LOGL_INFO, "Releasing all transactions on %p\n", conn); gsm0808_clear(conn->conn); subscr_con_free(conn->conn); conn->conn = NULL; } /* send the clear complete message */ resp = gsm0808_create_clear_complete(); if (!resp) { LOGP(DMSC, LOGL_ERROR, "Sending clear complete failed.\n"); return -1; } bsc_queue_for_msc(conn, resp); return 0; }