SMPP: Implement transaction mode for SUBMIT-SM

WARNING: if the ESME disconnects, osmo_esme gets freed, and
sms->smpp.esme might point to invalid/unallocated memory!
This commit is contained in:
Harald Welte 2012-11-08 19:44:08 +01:00
parent f1033cc752
commit d4bdee79e9
4 changed files with 95 additions and 1 deletions

View File

@ -271,12 +271,29 @@ struct gsm_network {
struct ctrl_handle *ctrl;
};
struct osmo_esme;
enum gsm_sms_source_id {
SMS_SOURCE_UNKNOWN = 0,
SMS_SOURCE_MS, /* received from MS */
SMS_SOURCE_VTY, /* received from VTY */
SMS_SOURCE_SMPP, /* received via SMPP */
};
#define SMS_HDR_SIZE 128
#define SMS_TEXT_SIZE 256
struct gsm_sms {
unsigned long long id;
struct gsm_subscriber *sender;
struct gsm_subscriber *receiver;
enum gsm_sms_source_id source;
struct {
struct osmo_esme *esme;
uint32_t sequence_nr;
int transaction_mode;
char msg_id[16];
} smpp;
unsigned long validity_minutes;
uint8_t reply_path_req;

View File

@ -38,6 +38,8 @@
#include <openbsc/debug.h>
#include <openbsc/db.h>
#include <openbsc/gsm_04_11.h>
#include <openbsc/gsm_data.h>
#include <openbsc/signal.h>
#include "smpp_smsc.h"
@ -111,6 +113,8 @@ static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net,
}
sms = sms_alloc();
sms->source = SMS_SOURCE_SMPP;
sms->smpp.sequence_nr = submit->sequence_number;
sms->receiver = subscr_get(dest);
strncpy(sms->dest_addr, dest->extension, sizeof(sms->dest_addr)-1);
sms->sender = subscr_get_by_id(net, 1);
@ -163,6 +167,7 @@ int handle_smpp_submit(struct osmo_esme *esme, struct submit_sm_t *submit,
submit_r->command_status = rc;
return 0;
}
sms->smpp.esme = esme;
/* FIXME: TP-PID */
switch (submit->esm_class & 3) {
@ -182,13 +187,54 @@ int handle_smpp_submit(struct osmo_esme *esme, struct submit_sm_t *submit,
rc = 0;
break;
case 2: /* forward (i.e. transaction) mode */
/* FIXME */
sms->smpp.transaction_mode = 1;
gsm411_send_sms_subscr(sms->receiver, sms);
rc = 1; /* don't send any response yet */
break;
}
return rc;
}
static int smpp_sms_cb(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
struct gsm_network *network = handler_data;
struct sms_signal_data *sig_sms = signal_data;
struct gsm_sms *sms = sig_sms->sms;
int rc = 0;
if (!sms)
return 0;
if (sms->source != SMS_SOURCE_SMPP)
return 0;
switch (signal) {
case S_SMS_UNKNOWN_ERROR:
if (sms->smpp.transaction_mode) {
/* Send back the SUBMIT-SM response with apropriate error */
LOGP(DSMS, LOGL_INFO, "SMPP SUBMIT-SM: Error\n");
rc = smpp_tx_submit_r(sms->smpp.esme,
sms->smpp.sequence_nr,
ESME_RDELIVERYFAILURE,
sms->smpp.msg_id);
}
break;
case S_SMS_DELIVERED:
/* SMS layer tells us the delivery has been completed */
if (sms->smpp.transaction_mode) {
/* Send back the SUBMIT-SM response */
LOGP(DSMS, LOGL_INFO, "SMPP SUBMIT-SM: Success\n");
rc = smpp_tx_submit_r(sms->smpp.esme,
sms->smpp.sequence_nr,
ESME_ROK, sms->smpp.msg_id);
}
break;
}
return rc;
}
int smpp_openbsc_init(struct gsm_network *net, uint16_t port)
{
@ -201,6 +247,8 @@ int smpp_openbsc_init(struct gsm_network *net, uint16_t port)
if (rc < 0)
talloc_free(smsc);
osmo_signal_register_handler(SS_SMS, smpp_sms_cb, net);
return rc;
}

View File

@ -46,6 +46,17 @@ enum emse_bind {
ESME_BIND_TX = 0x02,
};
static struct osmo_esme *
esme_by_system_id(const struct smsc *smsc, char *system_id)
{
struct osmo_esme *e;
llist_for_each_entry(e, &smsc->esme_list, list) {
if (!strcmp(e->system_id, system_id))
return e;
}
return NULL;
}
#define INIT_RESP(type, resp, req) { \
@ -280,6 +291,21 @@ static int smpp_handle_enq_link(struct osmo_esme *esme, struct msgb *msg)
return PACK_AND_SEND(esme, &enq_r);
}
int smpp_tx_submit_r(struct osmo_esme *esme, uint32_t sequence_nr,
uint32_t command_status, char *msg_id)
{
struct submit_sm_resp_t submit_r;
memset(&submit_r, 0, sizeof(submit_r));
submit_r.command_length = 0;
submit_r.command_id = SUBMIT_SM_RESP;
submit_r.command_status = command_status;
submit_r.sequence_number= sequence_nr;
snprintf(submit_r.message_id, sizeof(submit_r.message_id), "%s", msg_id);
return PACK_AND_SEND(esme, &submit_r);
}
static int smpp_handle_submit(struct osmo_esme *esme, struct msgb *msg)
{
struct submit_sm_t submit;

View File

@ -46,6 +46,9 @@ struct smsc {
int smpp_smsc_init(struct smsc *smsc, uint16_t port);
int smpp_tx_submit_r(struct osmo_esme *esme, uint32_t sequence_nr,
uint32_t command_status, char *msg_id);
int handle_smpp_submit(struct osmo_esme *esme, struct submit_sm_t *submit,
struct submit_sm_resp_t *submit_r);