various CC updates:

* correctly lchan_put the second lchan of a call at teardown
* map the RTP streams of ip.access onto each other
* fix bug that prevented a CONNECt message to ever reach the 'B' side
This commit is contained in:
Harald Welte 2009-02-17 15:29:33 +00:00
parent 167df88aae
commit 49f48b8b77
4 changed files with 69 additions and 30 deletions

View File

@ -489,8 +489,7 @@ void gsm0408_set_reject_cause(int cause);
int gsm0408_rcvmsg(struct msgb *msg);
void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
u_int16_t mnc, u_int16_t lac);
int gsm48_cc_tx_setup(struct gsm_lchan *lchan, struct gsm_subscriber *called,
struct gsm_subscriber *calling);
int gsm48_cc_tx_setup(struct gsm_lchan *lchan, struct gsm_subscriber *calling);
enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra);
enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra);

View File

@ -61,14 +61,20 @@ enum gsm_call_state {
GSM_CSTATE_RELEASE_REQ,
};
struct gsm_lchan;
struct gsm_subscriber;
/* One end of a call */
struct gsm_call {
enum gsm_call_type type;
enum gsm_call_state state;
u_int8_t transaction_id; /* 10.3.2 */
/* the 'local' subscriber */
struct gsm_subscriber *subscr;
/* the 'local' channel */
struct gsm_lchan *local_lchan;
/* the 'remote' channel */
struct gsm_lchan *remote_lchan;
/* the 'remote' subscriber */
struct gsm_subscriber *called_subscr;
};

View File

@ -84,6 +84,17 @@ static const struct tlv_definition rsl_att_tlvdef = {
},
};
static inline int is_ipaccess_bts(struct gsm_bts *bts)
{
switch (bts->type) {
case GSM_BTS_TYPE_NANOBTS_900:
case GSM_BTS_TYPE_NANOBTS_1800:
return 1;
default:
break;
}
return 0;
}
static int gsm48_tx_simple(struct gsm_lchan *lchan,
u_int8_t pdisc, u_int8_t msg_type);
@ -943,7 +954,8 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
struct msgb *msg, void *_lchan, void *param)
{
struct gsm_lchan *lchan = _lchan;
struct gsm_call *call = param;
struct gsm_call *remote_call = param;
struct gsm_call *call = &lchan->call;
int rc = 0;
if (hooknum != GSM_HOOK_RR_PAGING)
@ -952,8 +964,12 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
switch (event) {
case GSM_PAGING_SUCCEEDED:
DEBUGP(DCC, "paging succeeded!\n");
remote_call->remote_lchan = lchan;
call->remote_lchan = remote_call->local_lchan;
/* send SETUP request to called party */
rc = gsm48_cc_tx_setup(lchan, call->called_subscr, call->subscr);
rc = gsm48_cc_tx_setup(lchan, call->remote_lchan->subscr);
if (is_ipaccess_bts(lchan->ts->trx->bts))
rsl_ipacc_bind(lchan);
break;
case GSM_PAGING_EXPIRED:
DEBUGP(DCC, "paging expired!\n");
@ -988,6 +1004,7 @@ static int gsm48_cc_rx_setup(struct msgb *msg)
call->type = GSM_CT_MO;
call->state = GSM_CSTATE_INITIATED;
call->local_lchan = msg->lchan;
call->transaction_id = gh->proto_discr & 0xf0;
tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
@ -1010,7 +1027,6 @@ static int gsm48_cc_rx_setup(struct msgb *msg)
}
subscr_get(msg->lchan->subscr);
call->subscr = msg->lchan->subscr;
call->called_subscr = called_subscr;
/* start paging of the receiving end of the call */
@ -1021,6 +1037,9 @@ static int gsm48_cc_rx_setup(struct msgb *msg)
ret = gsm48_tx_simple(msg->lchan, GSM48_PDISC_CC,
GSM48_MT_CC_CALL_PROC);
if (is_ipaccess_bts(msg->trx->bts))
rsl_ipacc_bind(msg->lchan);
/* change TCH/F mode to voice */
return gsm48_tx_chan_mode_modify(msg->lchan, 0x01);
@ -1032,24 +1051,37 @@ err:
static int gsm48_cc_rx_alerting(struct msgb *msg)
{
struct gsm_call *call = &msg->lchan->call;
struct gsm_lchan *other_lchan;
DEBUGP(DCC, "A -> ALERTING\n");
/* forward ALERTING to other party */
other_lchan = lchan_find(msg->trx->bts, call->called_subscr);
if (!other_lchan)
if (!call->remote_lchan)
return -EIO;
DEBUGP(DCC, "B <- ALERTING\n");
return gsm48_tx_simple(other_lchan, GSM48_PDISC_CC,
return gsm48_tx_simple(call->remote_lchan, GSM48_PDISC_CC,
GSM48_MT_CC_ALERTING);
}
/* map two ipaccess RTP streams onto each other */
static int ipacc_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
{
struct gsm_bts_trx_ts *ts;
ts = remote_lchan->ts;
rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip, ts->abis_ip.bound_port,
lchan->ts->abis_ip.attr_f8, ts->abis_ip.attr_fc);
ts = lchan->ts;
rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip, ts->abis_ip.bound_port,
remote_lchan->ts->abis_ip.attr_f8, ts->abis_ip.attr_fc);
return 0;
}
static int gsm48_cc_rx_connect(struct msgb *msg)
{
struct gsm_call *call = &msg->lchan->call;
struct gsm_lchan *other_lchan;
int rc;
DEBUGP(DCC, "A -> CONNECT\n");
@ -1058,20 +1090,21 @@ static int gsm48_cc_rx_connect(struct msgb *msg)
rc = gsm48_tx_simple(msg->lchan, GSM48_PDISC_CC,
GSM48_MT_CC_CONNECT_ACK);
/* forward CONNECT to other party */
other_lchan = lchan_find(msg->trx->bts, call->called_subscr);
if (!other_lchan)
if (!call->remote_lchan)
return -EIO;
if (is_ipaccess_bts(msg->trx->bts))
ipacc_map(msg->lchan, call->remote_lchan);
/* forward CONNECT to other party */
DEBUGP(DCC, "B <- CONNECT\n");
return gsm48_tx_simple(other_lchan, GSM48_PDISC_CC,
return gsm48_tx_simple(call->remote_lchan, GSM48_PDISC_CC,
GSM48_MT_CC_CONNECT);
}
static int gsm48_cc_rx_disconnect(struct msgb *msg)
{
struct gsm_call *call = &msg->lchan->call;
struct gsm_lchan *other_lchan;
int rc;
@ -1086,19 +1119,18 @@ static int gsm48_cc_rx_disconnect(struct msgb *msg)
GSM48_MT_CC_RELEASE);
/* forward DISCONNECT to other party */
other_lchan = lchan_find(msg->trx->bts, call->called_subscr);
if (!other_lchan)
if (!call->remote_lchan)
return -EIO;
DEBUGP(DCC, "B <- DISCONNECT\n");
return gsm48_tx_simple(other_lchan, GSM48_PDISC_CC,
return gsm48_tx_simple(call->remote_lchan, GSM48_PDISC_CC,
GSM48_MT_CC_DISCONNECT);
}
static const u_int8_t calling_bcd[] = { 0xb9, 0x32, 0x24 };
int gsm48_cc_tx_setup(struct gsm_lchan *lchan, struct gsm_subscriber *called_subscr,
struct gsm_subscriber *calling_subscriber)
int gsm48_cc_tx_setup(struct gsm_lchan *lchan,
struct gsm_subscriber *calling_subscr)
{
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh;
@ -1108,24 +1140,23 @@ int gsm48_cc_tx_setup(struct gsm_lchan *lchan, struct gsm_subscriber *called_sub
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
call->type = GSM_CT_MT;
call->subscr = called_subscr;
call->called_subscr = calling_subscriber;
msg->lchan = lchan;
call->local_lchan = msg->lchan = lchan;
use_lchan(lchan);
gh->proto_discr = GSM48_PDISC_CC;
gh->msg_type = GSM48_MT_CC_SETUP;
msgb_tv_put(msg, GSM48_IE_SIGNAL, GSM48_SIGNAL_DIALTONE);
if (calling_subscriber) {
if (calling_subscr) {
encode_bcd_number(bcd_lv, sizeof(bcd_lv), 0xb9,
calling_subscriber->extension);
calling_subscr->extension);
msgb_tlv_put(msg, GSM48_IE_CALLING_BCD,
bcd_lv[0], bcd_lv+1);
}
if (call->subscr) {
if (lchan->subscr) {
encode_bcd_number(bcd_lv, sizeof(bcd_lv), 0xb9,
call->subscr->extension);
lchan->subscr->extension);
msgb_tlv_put(msg, GSM48_IE_CALLED_BCD,
bcd_lv[0], bcd_lv+1);
}
@ -1167,9 +1198,12 @@ static int gsm0408_rcv_cc(struct msgb *msg)
break;
case GSM48_MT_CC_RELEASE:
DEBUGP(DCC, "-> RELEASE\n");
DEBUGP(DCC, "<- RELEASE_COMPLETE\n");
/* need to respond with RELEASE_COMPLETE */
rc = gsm48_tx_simple(msg->lchan, GSM48_PDISC_CC,
GSM48_MT_CC_RELEASE_COMPL);
put_lchan(msg->lchan);
call->state = GSM_CSTATE_NULL;
break;
case GSM48_MT_CC_STATUS_ENQ:
rc = gsm48_cc_rx_status_enq(msg);

View File

@ -229,7 +229,7 @@ void telnet_call(struct telnet_connection *connection, const char* imsi,
return;
/* TODO: add the origin */
gsm48_cc_tx_setup(lchan, NULL, NULL);
gsm48_cc_tx_setup(lchan, NULL);
}
void telnet_send_gsm_48(struct telnet_connection *connection) {