diff options
Diffstat (limited to 'openbsc')
-rw-r--r-- | openbsc/include/openbsc/signal.h | 1 | ||||
-rw-r--r-- | openbsc/src/gsm_04_11.c | 85 |
2 files changed, 64 insertions, 22 deletions
diff --git a/openbsc/include/openbsc/signal.h b/openbsc/include/openbsc/signal.h index dea634462..1af849684 100644 --- a/openbsc/include/openbsc/signal.h +++ b/openbsc/include/openbsc/signal.h @@ -51,6 +51,7 @@ enum signal_sms { S_SMS_SUBMITTED, /* A SMS has been successfully submitted to us */ S_SMS_DELIVERED, /* A SMS has been successfully delivered to a MS */ S_SMS_SMMA, /* A MS tells us it has more space available */ + S_SMS_MEM_EXCEEDED, /* A MS tells us it has no more space available */ }; /* SS_ABISIP signals */ diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c index 20555101a..4ab06ecb9 100644 --- a/openbsc/src/gsm_04_11.c +++ b/openbsc/src/gsm_04_11.c @@ -45,10 +45,13 @@ #include <openbsc/talloc.h> #include <openbsc/transaction.h> #include <openbsc/paging.h> +#include <openbsc/bsc_rll.h> #define GSM411_ALLOC_SIZE 1024 #define GSM411_ALLOC_HEADROOM 128 +#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */ + static void *tall_gsms_ctx; static u_int32_t new_callref = 0x40000001; @@ -84,7 +87,7 @@ static int gsm411_sendmsg(struct msgb *msg) DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len)); - return rsl_data_request(msg, 0); + return rsl_data_request(msg, UM_SAPI_SMS); } /* Prefix msg with a 04.08/04.11 CP header */ @@ -105,6 +108,7 @@ static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans, switch (gh->msg_type) { case GSM411_MT_CP_DATA: /* 5.2.3.1.2: enter MO-wait for CP-ack */ + /* 5.2.3.2.3: enter MT-wait for CP-ACK */ trans->sms.cp_state = GSM411_CPS_WAIT_CP_ACK; break; } @@ -502,6 +506,7 @@ static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans, rpud_len, rp_ud); } +/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans, struct gsm411_rp_hdr *rph) { @@ -511,13 +516,16 @@ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans, * successfully received a SMS. We can now safely mark it as * transmitted */ - /* we need to look-up the transaction based on rph->msg_ref to - * identify which particular RP_DATA/SMS-submit was ACKed */ + if (!trans->sms.is_mt) { + DEBUGP(DSMS, "RX RP-ACK on a MO transfer ?\n"); + return gsm411_send_rp_error(trans, rph->msg_ref, + GSM411_RP_CAUSE_MSG_INCOMP_STATE); + } if (!sms) { - DEBUGP(DSMS, "RX RP-ACK (MT) but no sms in transaction?!?\n"); - put_lchan(trans->lchan); - return -EIO; + DEBUGP(DSMS, "RX RP-ACK but no sms in transaction?!?\n"); + return gsm411_send_rp_error(trans, rph->msg_ref, + GSM411_RP_CAUSE_PROTOCOL_ERR); } /* mark this SMS as sent in database */ @@ -528,7 +536,7 @@ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans, sms_free(sms); trans->sms.sms = NULL; - put_lchan(trans->lchan); + trans_free(trans); return 0; } @@ -546,19 +554,29 @@ static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans, DEBUGP(DSMS, "RX SMS RP-ERROR Cause=0x%02x\n", cause); - /* we need to look-up the transaction based on rph->msg_ref to - * identify which particular RP_DATA/SMS-submit failed */ + if (!trans->sms.is_mt) { + DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n"); + return gsm411_send_rp_error(trans, rph->msg_ref, + GSM411_RP_CAUSE_MSG_INCOMP_STATE); + } if (!sms) { - DEBUGP(DSMS, "RX RP-ERR (MT) but no sms in transaction?!?\n"); - put_lchan(trans->lchan); - return -EIO; + DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n"); + return gsm411_send_rp_error(trans, rph->msg_ref, + GSM411_RP_CAUSE_PROTOCOL_ERR); + } + + if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) { + /* MS has not enough memory to store the message. We need + * to store this in our database and wati for a SMMA message */ + /* FIXME */ + dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr); } sms_free(sms); trans->sms.sms = NULL; - put_lchan(trans->lchan); + trans_free(trans); return 0; } @@ -672,11 +690,11 @@ int gsm0411_rcv_sms(struct msgb *msg) switch(msg_type) { case GSM411_MT_CP_DATA: DEBUGP(DSMS, "RX SMS CP-DATA\n"); - if (!trans->sms.is_mt) { - /* 5.2.3.1.3: MO state exists when SMC has received - * CP-DATA, including sending of the assoc. CP-ACK */ - trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED; - } + /* 5.2.3.1.3: MO state exists when SMC has received + * CP-DATA, including sending of the assoc. CP-ACK */ + /* 5.2.3.2.4: MT state exists when SMC has received + * CP-DATA, including sending of the assoc. CP-ACK */ + trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED; rc = gsm411_rx_cp_data(msg, gh, trans); /* Send CP-ACK or CP-ERORR in response */ @@ -688,10 +706,11 @@ int gsm0411_rcv_sms(struct msgb *msg) case GSM411_MT_CP_ACK: /* previous CP-DATA in this transaction was confirmed */ DEBUGP(DSMS, "RX SMS CP-ACK\n"); + /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */ + /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */ + trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED; + if (!trans->sms.is_mt) { - /* 5.2.3.1.3: MO state exists when SMC has received - * CP-ACK */ - trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED; /* FIXME: we have sont one CP-DATA, which was now * acknowledged. Check if we want to transfer more, * i.e. multi-part message */ @@ -707,6 +726,7 @@ int gsm0411_rcv_sms(struct msgb *msg) default: DEBUGP(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type); rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST); + trans->sms.cp_state = GSM411_CPS_IDLE; trans_free(trans); break; } @@ -793,6 +813,27 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms) /* FIXME: enter 'wait for RP-ACK' state, start TR1N */ } +/* RLL SAPI3 establish callback */ +static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id, + void *_sms, enum bsc_rllr_ind type) +{ + struct gsm_sms *sms = _sms; + + DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n", + lchan, link_id, sms, type); + + switch (type) { + case BSC_RLLR_IND_EST_CONF: + gsm411_send_sms_lchan(lchan, sms); + break; + case BSC_RLLR_IND_REL_IND: + case BSC_RLLR_IND_ERR_IND: + case BSC_RLLR_IND_TIMEOUT: + sms_free(sms); + break; + } +} + /* paging callback */ static int paging_cb_send_sms(unsigned int hooknum, unsigned int event, struct msgb *msg, void *_lchan, void *_sms) @@ -815,7 +856,7 @@ static int paging_cb_send_sms(unsigned int hooknum, unsigned int event, rc = -EIO; break; } - rc = gsm411_send_sms_lchan(lchan, sms); + rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms); break; case GSM_PAGING_EXPIRED: sms_free(sms); |