From e94db496984b072e8bddacd93e3bd25f4e67dadf Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 8 Nov 2012 20:11:05 +0100 Subject: [PATCH] SMPP: Introduce ESME reference coounting In case a ESME disappears after SUBMIT-SM but before the MT-SMS is delivered (transaction mode), we have to make sure the esme structure still exists. --- openbsc/src/libmsc/gsm_04_11.c | 2 + openbsc/src/libmsc/smpp_openbsc.c | 10 +++-- openbsc/src/libmsc/smpp_smsc.c | 65 ++++++++++++++++++++++++------- openbsc/src/libmsc/smpp_smsc.h | 5 +++ 4 files changed, 64 insertions(+), 18 deletions(-) diff --git a/openbsc/src/libmsc/gsm_04_11.c b/openbsc/src/libmsc/gsm_04_11.c index e6956484f..2ed31e37e 100644 --- a/openbsc/src/libmsc/gsm_04_11.c +++ b/openbsc/src/libmsc/gsm_04_11.c @@ -117,6 +117,8 @@ void sms_free(struct gsm_sms *sms) subscr_put(sms->sender); if (sms->receiver) subscr_put(sms->receiver); + if (sms->smpp.esme) + smpp_esme_put(sms->smpp.esme); talloc_free(sms); } diff --git a/openbsc/src/libmsc/smpp_openbsc.c b/openbsc/src/libmsc/smpp_openbsc.c index 32dac61b3..f155e9c6a 100644 --- a/openbsc/src/libmsc/smpp_openbsc.c +++ b/openbsc/src/libmsc/smpp_openbsc.c @@ -43,7 +43,7 @@ #include "smpp_smsc.h" - +/*! \brief find gsm_subscriber for a given SMPP NPI/TON/Address */ static struct gsm_subscriber *subscr_by_dst(struct gsm_network *net, uint8_t npi, uint8_t ton, const char *addr) { @@ -65,6 +65,7 @@ static struct gsm_subscriber *subscr_by_dst(struct gsm_network *net, return subscr; } +/*! \brief find a TLV with given tag in list of libsmpp34 TLVs */ struct tlv_t *find_tlv(struct tlv_t *head, uint16_t tag) { struct tlv_t *t; @@ -76,7 +77,7 @@ struct tlv_t *find_tlv(struct tlv_t *head, uint16_t tag) return NULL; } -/* convert from submit_sm_t to gsm_sms */ +/*! \brief convert from submit_sm_t to gsm_sms */ static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net, const struct submit_sm_t *submit) { @@ -156,6 +157,7 @@ static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net, return ESME_ROK; } +/*! \brief handle incoming libsmpp34 ssubmit_sm_t from remote ESME */ int handle_smpp_submit(struct osmo_esme *esme, struct submit_sm_t *submit, struct submit_sm_resp_t *submit_r) { @@ -167,6 +169,7 @@ int handle_smpp_submit(struct osmo_esme *esme, struct submit_sm_t *submit, submit_r->command_status = rc; return 0; } + smpp_esme_get(esme); sms->smpp.esme = esme; /* FIXME: TP-PID */ @@ -195,6 +198,7 @@ int handle_smpp_submit(struct osmo_esme *esme, struct submit_sm_t *submit, return rc; } +/*! \brief signal handler for status of attempted SMS deliveries */ static int smpp_sms_cb(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data) { @@ -235,7 +239,7 @@ static int smpp_sms_cb(unsigned int subsys, unsigned int signal, return rc; } - +/*! \brief Initialize the OpenBSC SMPP interface */ int smpp_openbsc_init(struct gsm_network *net, uint16_t port) { struct smsc *smsc = talloc_zero(net, struct smsc); diff --git a/openbsc/src/libmsc/smpp_smsc.c b/openbsc/src/libmsc/smpp_smsc.c index dd6a2f9e3..fc38925cb 100644 --- a/openbsc/src/libmsc/smpp_smsc.c +++ b/openbsc/src/libmsc/smpp_smsc.c @@ -46,6 +46,31 @@ enum emse_bind { ESME_BIND_TX = 0x02, }; +/*! \brief increaes the use/reference count */ +void smpp_esme_get(struct osmo_esme *esme) +{ + esme->use++; +} + +static void esme_destroy(struct osmo_esme *esme) +{ + osmo_wqueue_clear(&esme->wqueue); + if (esme->wqueue.bfd.fd >= 0) { + osmo_fd_unregister(&esme->wqueue.bfd); + close(esme->wqueue.bfd.fd); + } + llist_del(&esme->list); + talloc_free(esme); +} + +/*! \brief decrease the use/reference count, free if it is 0 */ +void smpp_esme_put(struct osmo_esme *esme) +{ + esme->use--; + if (esme->use <= 0) + esme_destroy(esme); +} + static struct osmo_esme * esme_by_system_id(const struct smsc *smsc, char *system_id) { @@ -59,6 +84,7 @@ esme_by_system_id(const struct smsc *smsc, char *system_id) } +/*! \brief initialize the libsmpp34 data structure for a response */ #define INIT_RESP(type, resp, req) { \ memset((resp), 0, sizeof(*(resp))); \ (resp)->command_length = 0; \ @@ -67,6 +93,7 @@ esme_by_system_id(const struct smsc *smsc, char *system_id) (resp)->sequence_number = (req)->sequence_number; \ } +/*! \brief pack a libsmpp34 data strcutrure and send it to the ESME */ #define PACK_AND_SEND(esme, ptr) pack_and_send(esme, (ptr)->command_id, ptr) static int pack_and_send(struct osmo_esme *esme, uint32_t type, void *ptr) { @@ -87,6 +114,7 @@ static int pack_and_send(struct osmo_esme *esme, uint32_t type, void *ptr) return osmo_wqueue_enqueue(&esme->wqueue, msg); } +/*! \brief transmit a generic NACK to a remote ESME */ static int smpp_tx_gen_nack(struct osmo_esme *esme, uint32_t seq, uint32_t status) { struct generic_nack_t nack; @@ -99,19 +127,21 @@ static int smpp_tx_gen_nack(struct osmo_esme *esme, uint32_t seq, uint32_t statu return PACK_AND_SEND(esme, &nack); } +/*! \brief retrieve SMPP command ID from a msgb */ static inline uint32_t smpp_msgb_cmdid(struct msgb *msg) { uint8_t *tmp = msgb_data(msg) + 4; return ntohl(*(uint32_t *)tmp); } +/*! \brief retrieve SMPP sequence number from a msgb */ static inline uint32_t smpp_msgb_seq(struct msgb *msg) { uint8_t *tmp = msgb_data(msg); return ntohl(*(uint32_t *)tmp); } - +/*! \brief handle an incoming SMPP generic NACK */ static int smpp_handle_gen_nack(struct osmo_esme *esme, struct msgb *msg) { struct generic_nack_t nack; @@ -129,6 +159,7 @@ static int smpp_handle_gen_nack(struct osmo_esme *esme, struct msgb *msg) return 0; } +/*! \brief handle an incoming SMPP BIND RECEIVER */ static int smpp_handle_bind_rx(struct osmo_esme *esme, struct msgb *msg) { struct bind_receiver_t bind; @@ -165,6 +196,7 @@ err: return 0; } +/*! \brief handle an incoming SMPP BIND TRANSMITTER */ static int smpp_handle_bind_tx(struct osmo_esme *esme, struct msgb *msg) { struct bind_transmitter_t bind; @@ -212,6 +244,7 @@ err: return PACK_AND_SEND(esme, &bind_r); } +/*! \brief handle an incoming SMPP BIND TRANSCEIVER */ static int smpp_handle_bind_trx(struct osmo_esme *esme, struct msgb *msg) { struct bind_transceiver_t bind; @@ -247,6 +280,7 @@ err: return 0; } +/*! \brief handle an incoming SMPP UNBIND */ static int smpp_handle_unbind(struct osmo_esme *esme, struct msgb *msg) { struct unbind_t unbind; @@ -272,7 +306,7 @@ err: return PACK_AND_SEND(esme, &unbind_r); } - +/*! \brief handle an incoming SMPP ENQUIRE LINK */ static int smpp_handle_enq_link(struct osmo_esme *esme, struct msgb *msg) { struct enquire_link_t enq; @@ -291,6 +325,7 @@ static int smpp_handle_enq_link(struct osmo_esme *esme, struct msgb *msg) return PACK_AND_SEND(esme, &enq_r); } +/*! \brief send a SUBMIT-SM RESPONSE to a remote ESME */ int smpp_tx_submit_r(struct osmo_esme *esme, uint32_t sequence_nr, uint32_t command_status, char *msg_id) { @@ -306,6 +341,7 @@ int smpp_tx_submit_r(struct osmo_esme *esme, uint32_t sequence_nr, return PACK_AND_SEND(esme, &submit_r); } +/*! \brief handle an incoming SMPP SUBMIT-SM */ static int smpp_handle_submit(struct osmo_esme *esme, struct msgb *msg) { struct submit_sm_t submit; @@ -336,7 +372,7 @@ static int smpp_handle_submit(struct osmo_esme *esme, struct msgb *msg) return rc; } -/* one complete SMPP PDU from the ESME has been received */ +/*! \brief one complete SMPP PDU from the ESME has been received */ static int smpp_pdu_rx(struct osmo_esme *esme, struct msgb *msg) { uint32_t cmd_id = smpp_msgb_cmdid(msg); @@ -388,16 +424,7 @@ static int smpp_pdu_rx(struct osmo_esme *esme, struct msgb *msg) return rc; } -static void esme_destroy(struct osmo_esme *esme) -{ - osmo_wqueue_clear(&esme->wqueue); - osmo_fd_unregister(&esme->wqueue.bfd); - close(esme->wqueue.bfd.fd); - llist_del(&esme->list); - talloc_free(esme); -} - -/* call-back when per-ESME TCP socket has some data to be read */ +/* !\brief call-back when per-ESME TCP socket has some data to be read */ static int esme_link_read_cb(struct osmo_fd *ofd) { struct osmo_esme *esme = ofd->data; @@ -456,7 +483,10 @@ static int esme_link_read_cb(struct osmo_fd *ofd) return 0; dead_socket: msgb_free(esme->read_msg); - esme_destroy(esme); + osmo_fd_unregister(&esme->wqueue.bfd); + close(esme->wqueue.bfd.fd); + esme->wqueue.bfd.fd = -1; + smpp_esme_put(esme); return 0; } @@ -469,7 +499,10 @@ static void esme_link_write_cb(struct osmo_fd *ofd, struct msgb *msg) rc = write(ofd->fd, msgb_data(msg), msgb_length(msg)); if (rc == 0) { - esme_destroy(esme); + osmo_fd_unregister(&esme->wqueue.bfd); + close(esme->wqueue.bfd.fd); + esme->wqueue.bfd.fd = -1; + smpp_esme_put(esme); } else if (rc < msgb_length(msg)) { LOGP(DSMPP, LOGL_ERROR, "%s: Short write\n", esme->system_id); return; @@ -484,6 +517,7 @@ static int link_accept_cb(struct smsc *smsc, int fd, if (!esme) return -ENOMEM; + smpp_esme_get(esme); esme->smsc = smsc; osmo_wqueue_init(&esme->wqueue, 10); esme->wqueue.bfd.fd = fd; @@ -518,6 +552,7 @@ static int smsc_fd_cb(struct osmo_fd *ofd, unsigned int what) return link_accept_cb(ofd->data, rc, &sa, sa_len); } +/*! \brief Initialize the SMSC-side SMPP implementation */ int smpp_smsc_init(struct smsc *smsc, uint16_t port) { int rc; diff --git a/openbsc/src/libmsc/smpp_smsc.h b/openbsc/src/libmsc/smpp_smsc.h index 8cdd2e7db..e93ae30c2 100644 --- a/openbsc/src/libmsc/smpp_smsc.h +++ b/openbsc/src/libmsc/smpp_smsc.h @@ -21,6 +21,8 @@ struct osmo_esme { struct llist_head list; struct smsc *smsc; + int use; + struct osmo_wqueue wqueue; struct sockaddr_storage sa; socklen_t sa_len; @@ -46,6 +48,9 @@ struct smsc { int smpp_smsc_init(struct smsc *smsc, uint16_t port); +void smpp_esme_get(struct osmo_esme *esme); +void smpp_esme_put(struct osmo_esme *esme); + int smpp_tx_submit_r(struct osmo_esme *esme, uint32_t sequence_nr, uint32_t command_status, char *msg_id);