2012-11-08 15:14:37 +00:00
|
|
|
/* OpenBSC SMPP 3.4 interface, SMSC-side implementation */
|
|
|
|
|
2013-03-13 14:29:27 +00:00
|
|
|
/* (C) 2012-2013 by Harald Welte <laforge@gnumonks.org>
|
2012-11-08 15:14:37 +00:00
|
|
|
*
|
2013-07-13 14:35:32 +00:00
|
|
|
* All Rights Reserved
|
2012-11-08 15:14:37 +00:00
|
|
|
*
|
2013-07-13 14:35:32 +00:00
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
2012-11-08 15:14:37 +00:00
|
|
|
*
|
2013-07-13 14:35:32 +00:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Affero General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2012-11-08 15:14:37 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include <smpp34.h>
|
|
|
|
#include <smpp34_structs.h>
|
|
|
|
#include <smpp34_params.h>
|
|
|
|
|
|
|
|
#include <osmocom/core/utils.h>
|
|
|
|
#include <osmocom/core/msgb.h>
|
|
|
|
#include <osmocom/core/logging.h>
|
|
|
|
#include <osmocom/core/talloc.h>
|
|
|
|
#include <osmocom/gsm/protocol/gsm_04_11.h>
|
2013-03-13 14:29:27 +00:00
|
|
|
#include <osmocom/gsm/protocol/smpp34_osmocom.h>
|
2012-11-08 15:14:37 +00:00
|
|
|
|
2017-09-04 13:04:35 +00:00
|
|
|
#include <osmocom/msc/gsm_subscriber.h>
|
|
|
|
#include <osmocom/msc/debug.h>
|
|
|
|
#include <osmocom/msc/db.h>
|
|
|
|
#include <osmocom/msc/gsm_04_11.h>
|
|
|
|
#include <osmocom/msc/gsm_data.h>
|
|
|
|
#include <osmocom/msc/signal.h>
|
|
|
|
#include <osmocom/msc/transaction.h>
|
|
|
|
#include <osmocom/msc/gsm_subscriber.h>
|
|
|
|
#include <osmocom/msc/chan_alloc.h>
|
|
|
|
#include <osmocom/msc/vlr.h>
|
2012-11-08 15:14:37 +00:00
|
|
|
|
|
|
|
#include "smpp_smsc.h"
|
|
|
|
|
2016-06-19 16:06:02 +00:00
|
|
|
/*! \brief find vlr_subscr for a given SMPP NPI/TON/Address */
|
|
|
|
static struct vlr_subscr *subscr_by_dst(struct gsm_network *net,
|
|
|
|
uint8_t npi, uint8_t ton,
|
|
|
|
const char *addr)
|
2012-11-08 15:14:37 +00:00
|
|
|
{
|
2016-06-19 16:06:02 +00:00
|
|
|
struct vlr_subscr *vsub = NULL;
|
2012-11-08 15:14:37 +00:00
|
|
|
|
|
|
|
switch (npi) {
|
|
|
|
case NPI_Land_Mobile_E212:
|
2016-06-19 16:06:02 +00:00
|
|
|
vsub = vlr_subscr_find_by_imsi(net->vlr, addr);
|
2012-11-08 15:14:37 +00:00
|
|
|
break;
|
|
|
|
case NPI_ISDN_E163_E164:
|
|
|
|
case NPI_Private:
|
2016-06-19 16:06:02 +00:00
|
|
|
vsub = vlr_subscr_find_by_msisdn(net->vlr, addr);
|
2012-11-08 15:14:37 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOGP(DSMPP, LOGL_NOTICE, "Unsupported NPI: %u\n", npi);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-06-19 16:06:02 +00:00
|
|
|
log_set_context(LOG_CTX_VLR_SUBSCR, vsub);
|
|
|
|
return vsub;
|
2012-11-08 15:14:37 +00:00
|
|
|
}
|
|
|
|
|
2017-08-11 10:02:12 +00:00
|
|
|
static int smpp34_submit_tlv_msg_payload(const struct tlv_t *t,
|
|
|
|
const struct submit_sm_t *submit,
|
|
|
|
const uint8_t **sms_msg,
|
|
|
|
unsigned int *sms_msg_len)
|
2012-11-08 15:14:37 +00:00
|
|
|
{
|
2017-08-11 10:02:12 +00:00
|
|
|
if (submit->sm_length) {
|
|
|
|
LOGP(DLSMS, LOGL_ERROR,
|
|
|
|
"SMPP cannot have payload in TLV _and_ in the header\n");
|
|
|
|
return -1;
|
2012-11-08 15:14:37 +00:00
|
|
|
}
|
2017-08-11 10:02:12 +00:00
|
|
|
*sms_msg = t->value.octet;
|
|
|
|
*sms_msg_len = t->length;
|
|
|
|
|
|
|
|
return 0;
|
2012-11-08 15:14:37 +00:00
|
|
|
}
|
|
|
|
|
2012-11-08 19:11:05 +00:00
|
|
|
/*! \brief convert from submit_sm_t to gsm_sms */
|
2012-11-08 15:14:37 +00:00
|
|
|
static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net,
|
|
|
|
const struct submit_sm_t *submit)
|
|
|
|
{
|
2017-08-11 10:02:12 +00:00
|
|
|
const uint8_t *sms_msg = NULL;
|
2017-08-14 19:18:41 +00:00
|
|
|
unsigned int sms_msg_len = 0;
|
2016-06-19 16:06:02 +00:00
|
|
|
struct vlr_subscr *dest;
|
2017-08-11 10:02:12 +00:00
|
|
|
uint16_t msg_ref = 0;
|
2012-11-08 15:14:37 +00:00
|
|
|
struct gsm_sms *sms;
|
|
|
|
struct tlv_t *t;
|
2013-05-28 18:37:07 +00:00
|
|
|
int mode;
|
2012-11-08 15:14:37 +00:00
|
|
|
|
|
|
|
dest = subscr_by_dst(net, submit->dest_addr_npi,
|
|
|
|
submit->dest_addr_ton,
|
|
|
|
(const char *)submit->destination_addr);
|
|
|
|
if (!dest) {
|
2012-11-24 10:13:19 +00:00
|
|
|
LOGP(DLSMS, LOGL_NOTICE, "SMPP SUBMIT-SM for unknown subscriber: "
|
2012-11-08 15:14:37 +00:00
|
|
|
"%s (NPI=%u)\n", submit->destination_addr,
|
|
|
|
submit->dest_addr_npi);
|
|
|
|
return ESME_RINVDSTADR;
|
|
|
|
}
|
|
|
|
|
2017-08-11 10:02:12 +00:00
|
|
|
smpp34_tlv_for_each(t, submit->tlv) {
|
|
|
|
switch (t->tag) {
|
|
|
|
case TLVID_message_payload:
|
|
|
|
if (smpp34_submit_tlv_msg_payload(t, submit, &sms_msg,
|
|
|
|
&sms_msg_len) < 0) {
|
|
|
|
vlr_subscr_put(dest);
|
|
|
|
return ESME_ROPTPARNOTALLWD;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TLVID_user_message_reference:
|
2017-08-18 10:26:23 +00:00
|
|
|
msg_ref = t->value.val16;
|
2017-08-11 10:02:12 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!sms_msg) {
|
|
|
|
if (submit->sm_length > 0 && submit->sm_length < 255) {
|
|
|
|
sms_msg = submit->short_message;
|
|
|
|
sms_msg_len = submit->sm_length;
|
|
|
|
} else {
|
|
|
|
LOGP(DLSMS, LOGL_ERROR,
|
|
|
|
"SMPP neither message payload nor valid sm_length.\n");
|
2016-06-19 16:06:02 +00:00
|
|
|
vlr_subscr_put(dest);
|
2017-08-11 10:02:12 +00:00
|
|
|
return ESME_RINVPARLEN;
|
2012-11-08 15:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sms = sms_alloc();
|
2012-11-08 18:44:08 +00:00
|
|
|
sms->source = SMS_SOURCE_SMPP;
|
|
|
|
sms->smpp.sequence_nr = submit->sequence_number;
|
2017-08-07 13:01:18 +00:00
|
|
|
sms->status_rep_req = submit->registered_delivery;
|
2017-08-11 10:02:12 +00:00
|
|
|
sms->msg_ref = msg_ref;
|
2012-11-23 22:35:01 +00:00
|
|
|
|
|
|
|
/* fill in the destination address */
|
2012-11-09 18:48:48 +00:00
|
|
|
sms->receiver = dest;
|
2012-11-23 22:35:01 +00:00
|
|
|
sms->dst.ton = submit->dest_addr_ton;
|
|
|
|
sms->dst.npi = submit->dest_addr_npi;
|
2016-06-19 16:06:02 +00:00
|
|
|
osmo_strlcpy(sms->dst.addr, dest->msisdn, sizeof(sms->dst.addr));
|
2012-11-23 22:35:01 +00:00
|
|
|
|
|
|
|
/* fill in the source address */
|
|
|
|
sms->src.ton = submit->source_addr_ton;
|
|
|
|
sms->src.npi = submit->source_addr_npi;
|
2017-01-13 02:12:08 +00:00
|
|
|
osmo_strlcpy(sms->src.addr, (char *)submit->source_addr,
|
|
|
|
sizeof(sms->src.addr));
|
2012-11-08 15:14:37 +00:00
|
|
|
|
2017-08-11 11:10:48 +00:00
|
|
|
if (submit->esm_class == SMPP34_DELIVERY_ACK)
|
2017-08-07 13:01:40 +00:00
|
|
|
sms->is_report = true;
|
|
|
|
|
2017-08-11 11:10:48 +00:00
|
|
|
if (submit->esm_class & SMPP34_UDHI_IND)
|
2012-11-08 15:14:37 +00:00
|
|
|
sms->ud_hdr_ind = 1;
|
|
|
|
|
2017-08-11 11:10:48 +00:00
|
|
|
if (submit->esm_class & SMPP34_REPLY_PATH) {
|
2012-11-08 15:14:37 +00:00
|
|
|
sms->reply_path_req = 1;
|
|
|
|
#warning Implement reply path
|
|
|
|
}
|
|
|
|
|
2012-11-08 21:15:04 +00:00
|
|
|
if (submit->data_coding == 0x00 || /* SMSC default */
|
2013-05-28 18:37:07 +00:00
|
|
|
submit->data_coding == 0x01) { /* GSM default alphabet */
|
|
|
|
sms->data_coding_scheme = GSM338_DCS_1111_7BIT;
|
|
|
|
mode = MODE_7BIT;
|
|
|
|
} else if ((submit->data_coding & 0xFC) == 0xF0) { /* 03.38 DCS default */
|
|
|
|
/* pass DCS 1:1 through from SMPP to GSM */
|
|
|
|
sms->data_coding_scheme = submit->data_coding;
|
|
|
|
mode = MODE_7BIT;
|
|
|
|
} else if (submit->data_coding == 0x02 ||
|
|
|
|
submit->data_coding == 0x04) {
|
|
|
|
/* 8-bit binary */
|
|
|
|
sms->data_coding_scheme = GSM338_DCS_1111_8BIT_DATA;
|
|
|
|
mode = MODE_8BIT;
|
|
|
|
} else if ((submit->data_coding & 0xFC) == 0xF4) { /* 03.38 DCS 8bit */
|
|
|
|
/* pass DCS 1:1 through from SMPP to GSM */
|
|
|
|
sms->data_coding_scheme = submit->data_coding;
|
|
|
|
mode = MODE_8BIT;
|
2014-02-21 12:21:03 +00:00
|
|
|
} else if (submit->data_coding == 0x08) {
|
2013-05-28 18:37:07 +00:00
|
|
|
/* UCS-2 */
|
|
|
|
sms->data_coding_scheme = (2 << 2);
|
|
|
|
mode = MODE_8BIT;
|
|
|
|
} else {
|
|
|
|
sms_free(sms);
|
|
|
|
LOGP(DLSMS, LOGL_ERROR, "SMPP Unknown Data Coding 0x%02x\n",
|
|
|
|
submit->data_coding);
|
|
|
|
return ESME_RUNKNOWNERR;
|
|
|
|
}
|
|
|
|
|
2013-05-28 18:58:02 +00:00
|
|
|
if (mode == MODE_7BIT) {
|
2012-11-24 00:37:39 +00:00
|
|
|
uint8_t ud_len = 0, padbits = 0;
|
2012-11-08 15:14:37 +00:00
|
|
|
sms->data_coding_scheme = GSM338_DCS_1111_7BIT;
|
2012-11-09 18:43:50 +00:00
|
|
|
if (sms->ud_hdr_ind) {
|
|
|
|
ud_len = *sms_msg + 1;
|
|
|
|
printf("copying %u bytes user data...\n", ud_len);
|
|
|
|
memcpy(sms->user_data, sms_msg,
|
|
|
|
OSMO_MIN(ud_len, sizeof(sms->user_data)));
|
|
|
|
sms_msg += ud_len;
|
|
|
|
sms_msg_len -= ud_len;
|
2012-11-24 00:37:39 +00:00
|
|
|
padbits = 7 - (ud_len % 7);
|
2012-11-09 18:43:50 +00:00
|
|
|
}
|
2012-11-24 00:37:39 +00:00
|
|
|
gsm_septets2octets(sms->user_data+ud_len, sms_msg,
|
|
|
|
sms_msg_len, padbits);
|
|
|
|
sms->user_data_len = (ud_len*8 + padbits)/7 + sms_msg_len;/* SEPTETS */
|
|
|
|
/* FIXME: sms->text */
|
2013-05-28 18:37:07 +00:00
|
|
|
} else {
|
2012-11-08 15:14:37 +00:00
|
|
|
memcpy(sms->user_data, sms_msg, sms_msg_len);
|
|
|
|
sms->user_data_len = sms_msg_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
*psms = sms;
|
|
|
|
return ESME_ROK;
|
|
|
|
}
|
|
|
|
|
2012-11-08 19:11:05 +00:00
|
|
|
/*! \brief handle incoming libsmpp34 ssubmit_sm_t from remote ESME */
|
2012-11-08 15:14:37 +00:00
|
|
|
int handle_smpp_submit(struct osmo_esme *esme, struct submit_sm_t *submit,
|
|
|
|
struct submit_sm_resp_t *submit_r)
|
|
|
|
{
|
|
|
|
struct gsm_sms *sms;
|
2013-01-20 16:43:50 +00:00
|
|
|
struct gsm_network *net = esme->smsc->priv;
|
|
|
|
struct sms_signal_data sig;
|
2012-11-08 15:14:37 +00:00
|
|
|
int rc = -1;
|
|
|
|
|
2013-01-20 16:43:50 +00:00
|
|
|
rc = submit_to_sms(&sms, net, submit);
|
2012-11-08 15:14:37 +00:00
|
|
|
if (rc != ESME_ROK) {
|
|
|
|
submit_r->command_status = rc;
|
|
|
|
return 0;
|
|
|
|
}
|
2012-11-08 19:11:05 +00:00
|
|
|
smpp_esme_get(esme);
|
2012-11-08 18:44:08 +00:00
|
|
|
sms->smpp.esme = esme;
|
2012-11-08 21:15:04 +00:00
|
|
|
sms->protocol_id = submit->protocol_id;
|
2012-11-08 15:14:37 +00:00
|
|
|
|
2017-08-11 11:10:48 +00:00
|
|
|
switch (submit->esm_class & SMPP34_MSG_MODE_MASK) {
|
2012-11-08 15:14:37 +00:00
|
|
|
case 0: /* default */
|
|
|
|
case 1: /* datagram */
|
|
|
|
case 3: /* store-and-forward */
|
|
|
|
rc = db_sms_store(sms);
|
2013-01-20 16:21:31 +00:00
|
|
|
sms_free(sms);
|
|
|
|
sms = NULL;
|
2012-11-08 15:14:37 +00:00
|
|
|
if (rc < 0) {
|
2012-11-24 10:13:19 +00:00
|
|
|
LOGP(DLSMS, LOGL_ERROR, "SMPP SUBMIT-SM: Unable to "
|
2012-11-08 15:14:37 +00:00
|
|
|
"store SMS in database\n");
|
|
|
|
submit_r->command_status = ESME_RSYSERR;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
strcpy((char *)submit_r->message_id, "msg_id_not_implemented");
|
2012-11-24 10:13:19 +00:00
|
|
|
LOGP(DLSMS, LOGL_INFO, "SMPP SUBMIT-SM: Stored in DB\n");
|
2013-01-20 16:43:50 +00:00
|
|
|
|
|
|
|
memset(&sig, 0, sizeof(sig));
|
|
|
|
osmo_signal_dispatch(SS_SMS, S_SMS_SUBMITTED, &sig);
|
2012-11-08 15:14:37 +00:00
|
|
|
rc = 0;
|
|
|
|
break;
|
|
|
|
case 2: /* forward (i.e. transaction) mode */
|
2012-11-24 10:13:19 +00:00
|
|
|
LOGP(DLSMS, LOGL_DEBUG, "SMPP SUBMIT-SM: Forwarding in "
|
2012-11-09 18:43:50 +00:00
|
|
|
"real time (Transaction/Forward mode)\n");
|
2012-11-08 18:44:08 +00:00
|
|
|
sms->smpp.transaction_mode = 1;
|
|
|
|
gsm411_send_sms_subscr(sms->receiver, sms);
|
2012-11-08 15:14:37 +00:00
|
|
|
rc = 1; /* don't send any response yet */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2016-06-19 16:06:02 +00:00
|
|
|
static void alert_all_esme(struct smsc *smsc, struct vlr_subscr *vsub,
|
2013-07-30 15:45:01 +00:00
|
|
|
uint8_t smpp_avail_status)
|
|
|
|
{
|
|
|
|
struct osmo_esme *esme;
|
|
|
|
|
|
|
|
llist_for_each_entry(esme, &smsc->esme_list, list) {
|
|
|
|
/* we currently send an alert notification to each ESME that is
|
|
|
|
* connected, and do not require a (non-existant) delivery
|
|
|
|
* pending flag to be set before, FIXME: make this VTY
|
|
|
|
* configurable */
|
|
|
|
if (esme->acl && esme->acl->deliver_src_imsi) {
|
|
|
|
smpp_tx_alert(esme, TON_Subscriber_Number,
|
|
|
|
NPI_Land_Mobile_E212,
|
2016-06-19 16:06:02 +00:00
|
|
|
vsub->imsi, smpp_avail_status);
|
2013-07-30 15:45:01 +00:00
|
|
|
} else {
|
|
|
|
smpp_tx_alert(esme, TON_Network_Specific,
|
|
|
|
NPI_ISDN_E163_E164,
|
2016-06-19 16:06:02 +00:00
|
|
|
vsub->msisdn, smpp_avail_status);
|
2013-07-30 15:45:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-08 19:11:05 +00:00
|
|
|
/*! \brief signal handler for status of attempted SMS deliveries */
|
2012-11-08 18:44:08 +00:00
|
|
|
static int smpp_sms_cb(unsigned int subsys, unsigned int signal,
|
|
|
|
void *handler_data, void *signal_data)
|
|
|
|
{
|
|
|
|
struct sms_signal_data *sig_sms = signal_data;
|
|
|
|
struct gsm_sms *sms = sig_sms->sms;
|
2013-07-30 15:39:18 +00:00
|
|
|
struct smsc *smsc = handler_data;
|
2012-11-08 18:44:08 +00:00
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
if (!sms)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (sms->source != SMS_SOURCE_SMPP)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (signal) {
|
2013-07-30 14:30:24 +00:00
|
|
|
case S_SMS_MEM_EXCEEDED:
|
|
|
|
/* fall-through: There is no ESME_Rxxx result code to
|
|
|
|
* indicate a MEMORY EXCEEDED in transaction mode back
|
|
|
|
* to the ESME */
|
2012-11-08 18:44:08 +00:00
|
|
|
case S_SMS_UNKNOWN_ERROR:
|
|
|
|
if (sms->smpp.transaction_mode) {
|
|
|
|
/* Send back the SUBMIT-SM response with apropriate error */
|
2012-11-24 10:13:19 +00:00
|
|
|
LOGP(DLSMS, LOGL_INFO, "SMPP SUBMIT-SM: Error\n");
|
2012-11-08 18:44:08 +00:00
|
|
|
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 */
|
2012-11-24 10:13:19 +00:00
|
|
|
LOGP(DLSMS, LOGL_INFO, "SMPP SUBMIT-SM: Success\n");
|
2012-11-08 18:44:08 +00:00
|
|
|
rc = smpp_tx_submit_r(sms->smpp.esme,
|
|
|
|
sms->smpp.sequence_nr,
|
|
|
|
ESME_ROK, sms->smpp.msg_id);
|
|
|
|
}
|
|
|
|
break;
|
2013-07-30 15:39:18 +00:00
|
|
|
case S_SMS_SMMA:
|
2016-06-19 16:06:02 +00:00
|
|
|
if (!sig_sms->trans || !sig_sms->trans->vsub) {
|
2013-07-30 15:39:18 +00:00
|
|
|
/* SMMA without a subscriber? strange... */
|
|
|
|
LOGP(DLSMS, LOGL_NOTICE, "SMMA without subscriber?\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* There's no real 1:1 match for SMMA in SMPP. However,
|
|
|
|
* an ALERT NOTIFICATION seems to be the most logical
|
|
|
|
* choice */
|
2016-06-19 16:06:02 +00:00
|
|
|
alert_all_esme(smsc, sig_sms->trans->vsub, 0);
|
2013-07-30 15:39:18 +00:00
|
|
|
break;
|
2012-11-08 18:44:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2012-11-09 11:51:44 +00:00
|
|
|
/*! \brief signal handler for subscriber related signals */
|
|
|
|
static int smpp_subscr_cb(unsigned int subsys, unsigned int signal,
|
|
|
|
void *handler_data, void *signal_data)
|
|
|
|
{
|
2016-06-19 16:06:02 +00:00
|
|
|
struct vlr_subscr *vsub = signal_data;
|
2012-11-09 11:51:44 +00:00
|
|
|
struct smsc *smsc = handler_data;
|
|
|
|
uint8_t smpp_avail_status;
|
|
|
|
|
|
|
|
/* determine the smpp_avail_status depending on attach/detach */
|
|
|
|
switch (signal) {
|
|
|
|
case S_SUBSCR_ATTACHED:
|
|
|
|
smpp_avail_status = 0;
|
|
|
|
break;
|
|
|
|
case S_SUBSCR_DETACHED:
|
|
|
|
smpp_avail_status = 2;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-06-19 16:06:02 +00:00
|
|
|
alert_all_esme(smsc, vsub, smpp_avail_status);
|
2012-11-09 11:51:44 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-11-24 00:37:39 +00:00
|
|
|
/* GSM 03.38 6.2.1 Character expanding (no decode!) */
|
|
|
|
static int gsm_7bit_expand(char *text, const uint8_t *user_data, uint8_t septet_l, uint8_t ud_hdr_ind)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
int shift = 0;
|
|
|
|
uint8_t c;
|
|
|
|
|
|
|
|
/* skip the user data header */
|
|
|
|
if (ud_hdr_ind) {
|
|
|
|
/* get user data header length + 1 (for the 'user data header length'-field) */
|
|
|
|
shift = ((user_data[0] + 1) * 8) / 7;
|
|
|
|
if ((((user_data[0] + 1) * 8) % 7) != 0)
|
|
|
|
shift++;
|
|
|
|
septet_l = septet_l - shift;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < septet_l; i++) {
|
|
|
|
c =
|
|
|
|
((user_data[((i + shift) * 7 + 7) >> 3] <<
|
|
|
|
(7 - (((i + shift) * 7 + 7) & 7))) |
|
|
|
|
(user_data[((i + shift) * 7) >> 3] >>
|
|
|
|
(((i + shift) * 7) & 7))) & 0x7f;
|
|
|
|
|
|
|
|
*(text++) = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
*text = '\0';
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-03-13 14:29:27 +00:00
|
|
|
/* FIXME: libsmpp34 helpers, they should be part of libsmpp34! */
|
|
|
|
void append_tlv(tlv_t **req_tlv, uint16_t tag,
|
|
|
|
const uint8_t *data, uint16_t len)
|
|
|
|
{
|
|
|
|
tlv_t tlv;
|
|
|
|
|
|
|
|
memset(&tlv, 0, sizeof(tlv));
|
|
|
|
tlv.tag = tag;
|
|
|
|
tlv.length = len;
|
|
|
|
memcpy(tlv.value.octet, data, tlv.length);
|
|
|
|
build_tlv(req_tlv, &tlv);
|
|
|
|
}
|
|
|
|
void append_tlv_u8(tlv_t **req_tlv, uint16_t tag, uint8_t val)
|
|
|
|
{
|
|
|
|
tlv_t tlv;
|
|
|
|
|
|
|
|
memset(&tlv, 0, sizeof(tlv));
|
|
|
|
tlv.tag = tag;
|
|
|
|
tlv.length = 1;
|
|
|
|
tlv.value.val08 = val;
|
|
|
|
build_tlv(req_tlv, &tlv);
|
|
|
|
}
|
|
|
|
void append_tlv_u16(tlv_t **req_tlv, uint16_t tag, uint16_t val)
|
|
|
|
{
|
|
|
|
tlv_t tlv;
|
|
|
|
|
|
|
|
memset(&tlv, 0, sizeof(tlv));
|
|
|
|
tlv.tag = tag;
|
|
|
|
tlv.length = 2;
|
2017-08-18 10:26:23 +00:00
|
|
|
tlv.value.val16 = val;
|
2013-03-13 14:29:27 +00:00
|
|
|
build_tlv(req_tlv, &tlv);
|
|
|
|
}
|
|
|
|
|
mscsplit: various preparations to separate MSC from BSC
Disable large parts of the code that depend on BSC presence. The code sections
disabled by #if BEFORE_MSCSPLIT shall be modified or dropped in the course of
adding the A-interface.
Don't set msg->lchan nor msg->dst.
Don't use lchan in libmsc.
Decouple lac from bts.
Prepare entry/exit point for MSC -> BSC and MSC -> RNC communication:
Add msc_ifaces.[hc], a_iface.c, with a general msc_tx_dtap() to redirect to
different interfaces depending on the actual subscriber connection.
While iu_tx() is going to be functional fairly soon, the a_tx() is going to be
just a dummy for some time (see comment).
Add Iu specific fields in gsm_subscriber_connection: the UE connection pointer
and an indicator for the Integrity Protection status on Iu (to be fully
implemented in later commits).
Add lac member to gsm_subscriber_connection, to allow decoupling from
bts->location_area_code. The conn->lac will actually be set in iu.c in an
upcoming commit ("add iucs.[hc]").
move to libcommon-cs: gsm48_extract_mi(), gsm48_paging_extract_mi().
libmsc: duplicate gsm0808 / gsm48 functions (towards BSC).
In osmo-nitb, libmsc would directly call the functions on the BSC level, not
always via the bsc_api. When separating libmsc from libbsc, some functions are
missing from the linkage.
Hence duplicate these functions to libmsc, add an msc_ prefix for clarity, also
add a _tx to gsm0808_cipher_mode():
* add msc_gsm0808_tx_cipher_mode() (dummy/stub)
* add msc_gsm48_tx_mm_serv_ack()
* add msc_gsm48_tx_mm_serv_rej()
Call these from libmsc instead of
* gsm0808_cipher_mode()
* gsm48_tx_mm_serv_ack()
* gsm48_tx_mm_serv_rej()
Also add a comment related to msc_gsm0808_tx_cipher_mode() in two places.
Remove internal RTP streaming code; OsmoNITB supported that, but for OsmoMSC,
this will be done with an external MGCP gateway.
Remove LCHAN_MODIFY from internal MNCC state machine.
Temporarily disable all paging to be able to link libmsc without libbsc.
Skip the paging part of channel_test because the paging is now disabled.
Employ fake paging shims in order for msc_vlr_tests to still work.
msc_compl_l3(): publish in .h, tweak return value. Use new libmsc enum values
for return val, to avoid dependency on libbsc headers. Make callable from
other scopes: publish in osmo_msc.h and remove 'static' in osmo_msc.c
add gsm_encr to subscr_conn
move subscr_request to gsm_subscriber.h
subscr_request_channel() -> subscr_request_conn()
move to libmsc: osmo_stats_vty_add_cmds()
gsm_04_08: remove apply_codec_restrictions()
gsm0408_test: use NULL for root ctx
move to libbsc: gsm_bts_neighbor()
move to libbsc: lchan_next_meas_rep()
move vty config for t3212 to network level (periodic lu)
remove unneccessary linking from some tests
remove handle_abisip_signal()
abis_rsl.c: don't use libvlr from libbsc
gsm_subscriber_connection: put the LAC here, so that it is available without
accessing conn->bts. In bsc_api.c, place this lac in conn for the sake of
transition: Iu and A will use this new field to pass the LAC around, but in a
completely separate OsmoBSC this is not actually needed. It can be removed
again from osmo-bsc.git when the time has come.
Siemens MRPCI: completely drop sending the MRPCI messages for now, they shall
be added in osmo-bsc once the A-Interface code has settled. See OS#2389.
Related: OS#1845 OS#2257 OS#2389
Change-Id: Id3705236350d5f69e447046b0a764bbabc3d493c
2017-05-08 13:12:20 +00:00
|
|
|
#if BEFORE_MSCSPLIT
|
|
|
|
/* We currently have no lchan information. Re-add after A-interface, see OS#2390. */
|
2013-03-13 14:29:27 +00:00
|
|
|
/* Append the Osmocom vendor-specific additional TLVs to a SMPP msg */
|
|
|
|
static void append_osmo_tlvs(tlv_t **req_tlv, const struct gsm_lchan *lchan)
|
|
|
|
{
|
|
|
|
int idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep),
|
|
|
|
lchan->meas_rep_idx, 1);
|
|
|
|
const struct gsm_meas_rep *mr = &lchan->meas_rep[idx];
|
|
|
|
const struct gsm_meas_rep_unidir *ul_meas = &mr->ul;
|
|
|
|
const struct gsm_meas_rep_unidir *dl_meas = &mr->dl;
|
|
|
|
|
|
|
|
/* Osmocom vendor-specific SMPP34 extensions */
|
|
|
|
append_tlv_u16(req_tlv, TLVID_osmo_arfcn, lchan->ts->trx->arfcn);
|
|
|
|
if (mr->flags & MEAS_REP_F_MS_L1) {
|
|
|
|
uint8_t ms_dbm;
|
|
|
|
append_tlv_u8(req_tlv, TLVID_osmo_ta, mr->ms_l1.ta);
|
|
|
|
ms_dbm = ms_pwr_dbm(lchan->ts->trx->bts->band, mr->ms_l1.pwr);
|
|
|
|
append_tlv_u8(req_tlv, TLVID_osmo_ms_l1_txpwr, ms_dbm);
|
2017-04-20 11:07:58 +00:00
|
|
|
} else if (mr->flags & MEAS_REP_F_MS_TO) /* Save Timing Offset field = MS Timing Offset + 63 */
|
|
|
|
append_tlv_u8(req_tlv, TLVID_osmo_ta, mr->ms_timing_offset + 63);
|
2013-03-13 14:29:27 +00:00
|
|
|
|
|
|
|
append_tlv_u16(req_tlv, TLVID_osmo_rxlev_ul,
|
|
|
|
rxlev2dbm(ul_meas->full.rx_lev));
|
|
|
|
append_tlv_u8(req_tlv, TLVID_osmo_rxqual_ul, ul_meas->full.rx_qual);
|
|
|
|
|
|
|
|
if (mr->flags & MEAS_REP_F_DL_VALID) {
|
|
|
|
append_tlv_u16(req_tlv, TLVID_osmo_rxlev_dl,
|
|
|
|
rxlev2dbm(dl_meas->full.rx_lev));
|
|
|
|
append_tlv_u8(req_tlv, TLVID_osmo_rxqual_dl,
|
|
|
|
dl_meas->full.rx_qual);
|
|
|
|
}
|
|
|
|
|
2016-06-19 16:06:02 +00:00
|
|
|
if (lchan->conn && lchan->conn->vsub) {
|
|
|
|
struct vlr_subscr *vsub = lchan->conn->vsub;
|
|
|
|
size_t imei_len = strlen(vsub->imei);
|
2013-03-13 14:29:27 +00:00
|
|
|
if (imei_len)
|
|
|
|
append_tlv(req_tlv, TLVID_osmo_imei,
|
2016-06-19 16:06:02 +00:00
|
|
|
(uint8_t *)vsub->imei, imei_len+1);
|
2013-03-13 14:29:27 +00:00
|
|
|
}
|
|
|
|
}
|
mscsplit: various preparations to separate MSC from BSC
Disable large parts of the code that depend on BSC presence. The code sections
disabled by #if BEFORE_MSCSPLIT shall be modified or dropped in the course of
adding the A-interface.
Don't set msg->lchan nor msg->dst.
Don't use lchan in libmsc.
Decouple lac from bts.
Prepare entry/exit point for MSC -> BSC and MSC -> RNC communication:
Add msc_ifaces.[hc], a_iface.c, with a general msc_tx_dtap() to redirect to
different interfaces depending on the actual subscriber connection.
While iu_tx() is going to be functional fairly soon, the a_tx() is going to be
just a dummy for some time (see comment).
Add Iu specific fields in gsm_subscriber_connection: the UE connection pointer
and an indicator for the Integrity Protection status on Iu (to be fully
implemented in later commits).
Add lac member to gsm_subscriber_connection, to allow decoupling from
bts->location_area_code. The conn->lac will actually be set in iu.c in an
upcoming commit ("add iucs.[hc]").
move to libcommon-cs: gsm48_extract_mi(), gsm48_paging_extract_mi().
libmsc: duplicate gsm0808 / gsm48 functions (towards BSC).
In osmo-nitb, libmsc would directly call the functions on the BSC level, not
always via the bsc_api. When separating libmsc from libbsc, some functions are
missing from the linkage.
Hence duplicate these functions to libmsc, add an msc_ prefix for clarity, also
add a _tx to gsm0808_cipher_mode():
* add msc_gsm0808_tx_cipher_mode() (dummy/stub)
* add msc_gsm48_tx_mm_serv_ack()
* add msc_gsm48_tx_mm_serv_rej()
Call these from libmsc instead of
* gsm0808_cipher_mode()
* gsm48_tx_mm_serv_ack()
* gsm48_tx_mm_serv_rej()
Also add a comment related to msc_gsm0808_tx_cipher_mode() in two places.
Remove internal RTP streaming code; OsmoNITB supported that, but for OsmoMSC,
this will be done with an external MGCP gateway.
Remove LCHAN_MODIFY from internal MNCC state machine.
Temporarily disable all paging to be able to link libmsc without libbsc.
Skip the paging part of channel_test because the paging is now disabled.
Employ fake paging shims in order for msc_vlr_tests to still work.
msc_compl_l3(): publish in .h, tweak return value. Use new libmsc enum values
for return val, to avoid dependency on libbsc headers. Make callable from
other scopes: publish in osmo_msc.h and remove 'static' in osmo_msc.c
add gsm_encr to subscr_conn
move subscr_request to gsm_subscriber.h
subscr_request_channel() -> subscr_request_conn()
move to libmsc: osmo_stats_vty_add_cmds()
gsm_04_08: remove apply_codec_restrictions()
gsm0408_test: use NULL for root ctx
move to libbsc: gsm_bts_neighbor()
move to libbsc: lchan_next_meas_rep()
move vty config for t3212 to network level (periodic lu)
remove unneccessary linking from some tests
remove handle_abisip_signal()
abis_rsl.c: don't use libvlr from libbsc
gsm_subscriber_connection: put the LAC here, so that it is available without
accessing conn->bts. In bsc_api.c, place this lac in conn for the sake of
transition: Iu and A will use this new field to pass the LAC around, but in a
completely separate OsmoBSC this is not actually needed. It can be removed
again from osmo-bsc.git when the time has come.
Siemens MRPCI: completely drop sending the MRPCI messages for now, they shall
be added in osmo-bsc once the A-Interface code has settled. See OS#2389.
Related: OS#1845 OS#2257 OS#2389
Change-Id: Id3705236350d5f69e447046b0a764bbabc3d493c
2017-05-08 13:12:20 +00:00
|
|
|
#endif
|
2013-03-13 14:29:27 +00:00
|
|
|
|
2017-05-13 21:38:52 +00:00
|
|
|
struct {
|
|
|
|
uint32_t smpp_status_code;
|
|
|
|
uint8_t gsm411_cause;
|
|
|
|
} smpp_to_gsm411_err_array[] = {
|
|
|
|
|
|
|
|
/* Seems like most phones don't care about the failure cause,
|
|
|
|
* although some will display a different notification for
|
|
|
|
* GSM411_RP_CAUSE_MO_NUM_UNASSIGNED
|
|
|
|
* Some provoke a display of "Try again later"
|
|
|
|
* while others a more definitive "Message sending failed"
|
|
|
|
*/
|
|
|
|
|
|
|
|
{ ESME_RSYSERR, GSM411_RP_CAUSE_MO_DEST_OUT_OF_ORDER },
|
|
|
|
{ ESME_RINVDSTADR, GSM411_RP_CAUSE_MO_NUM_UNASSIGNED },
|
|
|
|
{ ESME_RMSGQFUL, GSM411_RP_CAUSE_MO_CONGESTION },
|
|
|
|
{ ESME_RINVSRCADR, GSM411_RP_CAUSE_MO_SMS_REJECTED },
|
|
|
|
{ ESME_RINVMSGID, GSM411_RP_CAUSE_INV_TRANS_REF }
|
|
|
|
};
|
|
|
|
|
|
|
|
static int smpp_to_gsm411_err(uint32_t smpp_status_code, int *gsm411_cause)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(smpp_to_gsm411_err_array); i++) {
|
|
|
|
if (smpp_to_gsm411_err_array[i].smpp_status_code != smpp_status_code)
|
|
|
|
continue;
|
|
|
|
*gsm411_cause = smpp_to_gsm411_err_array[i].gsm411_cause;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
static void smpp_cmd_free(struct osmo_smpp_cmd *cmd)
|
|
|
|
{
|
|
|
|
osmo_timer_del(&cmd->response_timer);
|
|
|
|
llist_del(&cmd->list);
|
2016-06-19 16:06:02 +00:00
|
|
|
vlr_subscr_put(cmd->vsub);
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
talloc_free(cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void smpp_cmd_flush_pending(struct osmo_esme *esme)
|
|
|
|
{
|
|
|
|
struct osmo_smpp_cmd *cmd, *next;
|
|
|
|
|
|
|
|
llist_for_each_entry_safe(cmd, next, &esme->smpp_cmd_list, list)
|
|
|
|
smpp_cmd_free(cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void smpp_cmd_ack(struct osmo_smpp_cmd *cmd)
|
|
|
|
{
|
|
|
|
struct gsm_subscriber_connection *conn;
|
|
|
|
struct gsm_trans *trans;
|
|
|
|
|
2017-08-07 13:01:30 +00:00
|
|
|
if (cmd->is_report)
|
|
|
|
goto out;
|
|
|
|
|
2016-06-19 16:06:02 +00:00
|
|
|
conn = connection_for_subscr(cmd->vsub);
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
if (!conn) {
|
|
|
|
LOGP(DSMPP, LOGL_ERROR, "No connection to subscriber anymore\n");
|
2017-08-07 13:01:01 +00:00
|
|
|
goto out;
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
}
|
|
|
|
|
2017-08-07 13:01:10 +00:00
|
|
|
trans = trans_find_by_id(conn, GSM48_PDISC_SMS, cmd->gsm411_trans_id);
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
if (!trans) {
|
|
|
|
LOGP(DSMPP, LOGL_ERROR, "GSM transaction %u is gone\n",
|
2017-08-07 13:01:10 +00:00
|
|
|
cmd->gsm411_trans_id);
|
2017-08-07 13:01:01 +00:00
|
|
|
goto out;
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
}
|
|
|
|
|
2017-08-07 13:01:10 +00:00
|
|
|
gsm411_send_rp_ack(trans, cmd->gsm411_msg_ref);
|
2017-08-07 13:01:01 +00:00
|
|
|
out:
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
smpp_cmd_free(cmd);
|
|
|
|
}
|
|
|
|
|
2017-05-13 21:38:52 +00:00
|
|
|
void smpp_cmd_err(struct osmo_smpp_cmd *cmd, uint32_t status)
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
{
|
|
|
|
struct gsm_subscriber_connection *conn;
|
|
|
|
struct gsm_trans *trans;
|
2017-05-13 21:38:52 +00:00
|
|
|
int gsm411_cause;
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
|
2017-08-07 13:01:30 +00:00
|
|
|
if (cmd->is_report)
|
|
|
|
goto out;
|
|
|
|
|
2016-06-19 16:06:02 +00:00
|
|
|
conn = connection_for_subscr(cmd->vsub);
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
if (!conn) {
|
|
|
|
LOGP(DSMPP, LOGL_ERROR, "No connection to subscriber anymore\n");
|
2017-08-07 13:01:01 +00:00
|
|
|
goto out;
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
}
|
|
|
|
|
2017-08-07 13:01:10 +00:00
|
|
|
trans = trans_find_by_id(conn, GSM48_PDISC_SMS, cmd->gsm411_trans_id);
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
if (!trans) {
|
|
|
|
LOGP(DSMPP, LOGL_ERROR, "GSM transaction %u is gone\n",
|
2017-08-07 13:01:10 +00:00
|
|
|
cmd->gsm411_trans_id);
|
2017-08-07 13:01:01 +00:00
|
|
|
goto out;
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
}
|
|
|
|
|
2017-05-13 21:38:52 +00:00
|
|
|
if (smpp_to_gsm411_err(status, &gsm411_cause) < 0)
|
|
|
|
gsm411_cause = GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
|
|
|
|
|
2017-08-07 13:01:10 +00:00
|
|
|
gsm411_send_rp_error(trans, cmd->gsm411_msg_ref, gsm411_cause);
|
2017-08-07 13:01:01 +00:00
|
|
|
out:
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
smpp_cmd_free(cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void smpp_deliver_sm_cb(void *data)
|
|
|
|
{
|
2017-05-13 21:38:52 +00:00
|
|
|
smpp_cmd_err(data, ESME_RSYSERR);
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int smpp_cmd_enqueue(struct osmo_esme *esme,
|
2016-06-19 16:06:02 +00:00
|
|
|
struct vlr_subscr *vsub, struct gsm_sms *sms,
|
2017-08-07 13:01:10 +00:00
|
|
|
uint32_t sequence_number)
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
{
|
|
|
|
struct osmo_smpp_cmd *cmd;
|
|
|
|
|
|
|
|
cmd = talloc_zero(esme, struct osmo_smpp_cmd);
|
|
|
|
if (!cmd)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
cmd->sequence_nr = sequence_number;
|
2017-08-07 13:01:30 +00:00
|
|
|
cmd->is_report = sms->is_report;
|
2017-08-07 13:01:10 +00:00
|
|
|
cmd->gsm411_msg_ref = sms->gsm411.msg_ref;
|
|
|
|
cmd->gsm411_trans_id = sms->gsm411.transaction_id;
|
2016-06-19 16:06:02 +00:00
|
|
|
cmd->vsub = vlr_subscr_get(vsub);
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
|
|
|
|
/* FIXME: No predefined value for this response_timer as specified by
|
|
|
|
* SMPP 3.4 specs, section 7.2. Make this configurable? Don't forget
|
|
|
|
* lchan keeps busy until we get a reply to this SMPP command. Too high
|
|
|
|
* value may exhaust resources.
|
|
|
|
*/
|
2017-05-08 18:57:52 +00:00
|
|
|
osmo_timer_setup(&cmd->response_timer, smpp_deliver_sm_cb, cmd);
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
osmo_timer_schedule(&cmd->response_timer, 5, 0);
|
|
|
|
llist_add_tail(&cmd->list, &esme->smpp_cmd_list);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct osmo_smpp_cmd *smpp_cmd_find_by_seqnum(struct osmo_esme *esme,
|
|
|
|
uint32_t sequence_nr)
|
|
|
|
{
|
|
|
|
struct osmo_smpp_cmd *cmd;
|
|
|
|
|
|
|
|
llist_for_each_entry(cmd, &esme->smpp_cmd_list, list) {
|
|
|
|
if (cmd->sequence_nr == sequence_nr)
|
|
|
|
return cmd;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-03-13 14:29:27 +00:00
|
|
|
static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms,
|
2017-08-07 13:01:10 +00:00
|
|
|
struct gsm_subscriber_connection *conn)
|
2012-11-23 18:02:37 +00:00
|
|
|
{
|
|
|
|
struct deliver_sm_t deliver;
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
int mode, ret;
|
2012-11-23 18:02:37 +00:00
|
|
|
uint8_t dcs;
|
|
|
|
|
|
|
|
memset(&deliver, 0, sizeof(deliver));
|
|
|
|
deliver.command_length = 0;
|
|
|
|
deliver.command_id = DELIVER_SM;
|
|
|
|
deliver.command_status = ESME_ROK;
|
|
|
|
|
|
|
|
strcpy((char *)deliver.service_type, "CMT");
|
|
|
|
if (esme->acl && esme->acl->deliver_src_imsi) {
|
|
|
|
deliver.source_addr_ton = TON_Subscriber_Number;
|
|
|
|
deliver.source_addr_npi = NPI_Land_Mobile_E212;
|
|
|
|
snprintf((char *)deliver.source_addr,
|
|
|
|
sizeof(deliver.source_addr), "%s",
|
2016-06-19 16:06:02 +00:00
|
|
|
conn->vsub->imsi);
|
2012-11-23 18:02:37 +00:00
|
|
|
} else {
|
|
|
|
deliver.source_addr_ton = TON_Network_Specific;
|
|
|
|
deliver.source_addr_npi = NPI_ISDN_E163_E164;
|
|
|
|
snprintf((char *)deliver.source_addr,
|
|
|
|
sizeof(deliver.source_addr), "%s",
|
2016-06-19 16:06:02 +00:00
|
|
|
conn->vsub->msisdn);
|
2012-11-23 18:02:37 +00:00
|
|
|
}
|
|
|
|
|
2012-11-23 22:35:01 +00:00
|
|
|
deliver.dest_addr_ton = sms->dst.ton;
|
|
|
|
deliver.dest_addr_npi = sms->dst.npi;
|
|
|
|
memcpy(deliver.destination_addr, sms->dst.addr,
|
2012-11-23 18:02:37 +00:00
|
|
|
sizeof(deliver.destination_addr));
|
|
|
|
|
2017-08-07 13:01:30 +00:00
|
|
|
if (sms->is_report)
|
2017-08-11 11:10:48 +00:00
|
|
|
deliver.esm_class = SMPP34_DELIVERY_RECEIPT;
|
2017-08-07 13:01:30 +00:00
|
|
|
else
|
2017-08-11 11:10:48 +00:00
|
|
|
deliver.esm_class = SMPP34_DATAGRAM_MODE;
|
2017-08-07 13:01:30 +00:00
|
|
|
|
2012-11-23 18:02:37 +00:00
|
|
|
if (sms->ud_hdr_ind)
|
2017-08-11 11:10:48 +00:00
|
|
|
deliver.esm_class |= SMPP34_UDHI_IND;
|
2012-11-23 18:02:37 +00:00
|
|
|
if (sms->reply_path_req)
|
2017-08-11 11:10:48 +00:00
|
|
|
deliver.esm_class |= SMPP34_REPLY_PATH;
|
2012-11-23 18:02:37 +00:00
|
|
|
|
|
|
|
deliver.protocol_id = sms->protocol_id;
|
|
|
|
deliver.priority_flag = 0;
|
2017-08-07 13:01:15 +00:00
|
|
|
if (sms->status_rep_req)
|
2017-08-11 12:36:01 +00:00
|
|
|
deliver.registered_delivery = SMPP34_DELIVERY_RECEIPT_ON;
|
2012-11-23 18:02:37 +00:00
|
|
|
|
2013-05-28 18:58:02 +00:00
|
|
|
/* Figure out SMPP DCS from TP-DCS */
|
2012-11-23 18:02:37 +00:00
|
|
|
dcs = sms->data_coding_scheme;
|
2013-07-13 15:09:56 +00:00
|
|
|
if (smpp_determine_scheme(dcs, &deliver.data_coding, &mode) == -1)
|
2013-05-28 18:58:02 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* Transparently pass on DCS via SMPP if requested */
|
2013-07-14 06:54:07 +00:00
|
|
|
if (esme->acl && esme->acl->dcs_transparent)
|
2013-05-28 18:58:02 +00:00
|
|
|
deliver.data_coding = dcs;
|
|
|
|
|
|
|
|
if (mode == MODE_7BIT) {
|
2012-11-23 18:02:37 +00:00
|
|
|
uint8_t *dst = deliver.short_message;
|
|
|
|
|
|
|
|
/* SMPP has this strange notion of putting 7bit SMS in
|
|
|
|
* an octet-aligned mode */
|
|
|
|
if (sms->ud_hdr_ind) {
|
2012-11-24 00:37:39 +00:00
|
|
|
/* length (bytes) of UDH inside UD */
|
|
|
|
uint8_t udh_len = sms->user_data[0] + 1;
|
|
|
|
|
|
|
|
/* copy over the UDH */
|
|
|
|
memcpy(dst, sms->user_data, udh_len);
|
|
|
|
dst += udh_len;
|
|
|
|
deliver.sm_length = udh_len;
|
2012-11-23 18:02:37 +00:00
|
|
|
}
|
2012-11-24 00:37:39 +00:00
|
|
|
/* add decoded text */
|
|
|
|
deliver.sm_length += gsm_7bit_expand((char *)dst, sms->user_data, sms->user_data_len, sms->ud_hdr_ind);
|
2013-05-28 18:58:02 +00:00
|
|
|
} else {
|
2012-11-23 18:02:37 +00:00
|
|
|
deliver.sm_length = sms->user_data_len;
|
|
|
|
memcpy(deliver.short_message, sms->user_data, deliver.sm_length);
|
|
|
|
}
|
|
|
|
|
mscsplit: various preparations to separate MSC from BSC
Disable large parts of the code that depend on BSC presence. The code sections
disabled by #if BEFORE_MSCSPLIT shall be modified or dropped in the course of
adding the A-interface.
Don't set msg->lchan nor msg->dst.
Don't use lchan in libmsc.
Decouple lac from bts.
Prepare entry/exit point for MSC -> BSC and MSC -> RNC communication:
Add msc_ifaces.[hc], a_iface.c, with a general msc_tx_dtap() to redirect to
different interfaces depending on the actual subscriber connection.
While iu_tx() is going to be functional fairly soon, the a_tx() is going to be
just a dummy for some time (see comment).
Add Iu specific fields in gsm_subscriber_connection: the UE connection pointer
and an indicator for the Integrity Protection status on Iu (to be fully
implemented in later commits).
Add lac member to gsm_subscriber_connection, to allow decoupling from
bts->location_area_code. The conn->lac will actually be set in iu.c in an
upcoming commit ("add iucs.[hc]").
move to libcommon-cs: gsm48_extract_mi(), gsm48_paging_extract_mi().
libmsc: duplicate gsm0808 / gsm48 functions (towards BSC).
In osmo-nitb, libmsc would directly call the functions on the BSC level, not
always via the bsc_api. When separating libmsc from libbsc, some functions are
missing from the linkage.
Hence duplicate these functions to libmsc, add an msc_ prefix for clarity, also
add a _tx to gsm0808_cipher_mode():
* add msc_gsm0808_tx_cipher_mode() (dummy/stub)
* add msc_gsm48_tx_mm_serv_ack()
* add msc_gsm48_tx_mm_serv_rej()
Call these from libmsc instead of
* gsm0808_cipher_mode()
* gsm48_tx_mm_serv_ack()
* gsm48_tx_mm_serv_rej()
Also add a comment related to msc_gsm0808_tx_cipher_mode() in two places.
Remove internal RTP streaming code; OsmoNITB supported that, but for OsmoMSC,
this will be done with an external MGCP gateway.
Remove LCHAN_MODIFY from internal MNCC state machine.
Temporarily disable all paging to be able to link libmsc without libbsc.
Skip the paging part of channel_test because the paging is now disabled.
Employ fake paging shims in order for msc_vlr_tests to still work.
msc_compl_l3(): publish in .h, tweak return value. Use new libmsc enum values
for return val, to avoid dependency on libbsc headers. Make callable from
other scopes: publish in osmo_msc.h and remove 'static' in osmo_msc.c
add gsm_encr to subscr_conn
move subscr_request to gsm_subscriber.h
subscr_request_channel() -> subscr_request_conn()
move to libmsc: osmo_stats_vty_add_cmds()
gsm_04_08: remove apply_codec_restrictions()
gsm0408_test: use NULL for root ctx
move to libbsc: gsm_bts_neighbor()
move to libbsc: lchan_next_meas_rep()
move vty config for t3212 to network level (periodic lu)
remove unneccessary linking from some tests
remove handle_abisip_signal()
abis_rsl.c: don't use libvlr from libbsc
gsm_subscriber_connection: put the LAC here, so that it is available without
accessing conn->bts. In bsc_api.c, place this lac in conn for the sake of
transition: Iu and A will use this new field to pass the LAC around, but in a
completely separate OsmoBSC this is not actually needed. It can be removed
again from osmo-bsc.git when the time has come.
Siemens MRPCI: completely drop sending the MRPCI messages for now, they shall
be added in osmo-bsc once the A-Interface code has settled. See OS#2389.
Related: OS#1845 OS#2257 OS#2389
Change-Id: Id3705236350d5f69e447046b0a764bbabc3d493c
2017-05-08 13:12:20 +00:00
|
|
|
#if BEFORE_MSCSPLIT
|
|
|
|
/* We currently have no lchan information. Re-add after A-interface, see OS#2390. */
|
2015-02-08 08:21:04 +00:00
|
|
|
if (esme->acl && esme->acl->osmocom_ext && conn->lchan)
|
2013-03-13 14:29:27 +00:00
|
|
|
append_osmo_tlvs(&deliver.tlv, conn->lchan);
|
mscsplit: various preparations to separate MSC from BSC
Disable large parts of the code that depend on BSC presence. The code sections
disabled by #if BEFORE_MSCSPLIT shall be modified or dropped in the course of
adding the A-interface.
Don't set msg->lchan nor msg->dst.
Don't use lchan in libmsc.
Decouple lac from bts.
Prepare entry/exit point for MSC -> BSC and MSC -> RNC communication:
Add msc_ifaces.[hc], a_iface.c, with a general msc_tx_dtap() to redirect to
different interfaces depending on the actual subscriber connection.
While iu_tx() is going to be functional fairly soon, the a_tx() is going to be
just a dummy for some time (see comment).
Add Iu specific fields in gsm_subscriber_connection: the UE connection pointer
and an indicator for the Integrity Protection status on Iu (to be fully
implemented in later commits).
Add lac member to gsm_subscriber_connection, to allow decoupling from
bts->location_area_code. The conn->lac will actually be set in iu.c in an
upcoming commit ("add iucs.[hc]").
move to libcommon-cs: gsm48_extract_mi(), gsm48_paging_extract_mi().
libmsc: duplicate gsm0808 / gsm48 functions (towards BSC).
In osmo-nitb, libmsc would directly call the functions on the BSC level, not
always via the bsc_api. When separating libmsc from libbsc, some functions are
missing from the linkage.
Hence duplicate these functions to libmsc, add an msc_ prefix for clarity, also
add a _tx to gsm0808_cipher_mode():
* add msc_gsm0808_tx_cipher_mode() (dummy/stub)
* add msc_gsm48_tx_mm_serv_ack()
* add msc_gsm48_tx_mm_serv_rej()
Call these from libmsc instead of
* gsm0808_cipher_mode()
* gsm48_tx_mm_serv_ack()
* gsm48_tx_mm_serv_rej()
Also add a comment related to msc_gsm0808_tx_cipher_mode() in two places.
Remove internal RTP streaming code; OsmoNITB supported that, but for OsmoMSC,
this will be done with an external MGCP gateway.
Remove LCHAN_MODIFY from internal MNCC state machine.
Temporarily disable all paging to be able to link libmsc without libbsc.
Skip the paging part of channel_test because the paging is now disabled.
Employ fake paging shims in order for msc_vlr_tests to still work.
msc_compl_l3(): publish in .h, tweak return value. Use new libmsc enum values
for return val, to avoid dependency on libbsc headers. Make callable from
other scopes: publish in osmo_msc.h and remove 'static' in osmo_msc.c
add gsm_encr to subscr_conn
move subscr_request to gsm_subscriber.h
subscr_request_channel() -> subscr_request_conn()
move to libmsc: osmo_stats_vty_add_cmds()
gsm_04_08: remove apply_codec_restrictions()
gsm0408_test: use NULL for root ctx
move to libbsc: gsm_bts_neighbor()
move to libbsc: lchan_next_meas_rep()
move vty config for t3212 to network level (periodic lu)
remove unneccessary linking from some tests
remove handle_abisip_signal()
abis_rsl.c: don't use libvlr from libbsc
gsm_subscriber_connection: put the LAC here, so that it is available without
accessing conn->bts. In bsc_api.c, place this lac in conn for the sake of
transition: Iu and A will use this new field to pass the LAC around, but in a
completely separate OsmoBSC this is not actually needed. It can be removed
again from osmo-bsc.git when the time has come.
Siemens MRPCI: completely drop sending the MRPCI messages for now, they shall
be added in osmo-bsc once the A-Interface code has settled. See OS#2389.
Related: OS#1845 OS#2257 OS#2389
Change-Id: Id3705236350d5f69e447046b0a764bbabc3d493c
2017-05-08 13:12:20 +00:00
|
|
|
#endif
|
2013-03-13 14:29:27 +00:00
|
|
|
|
2017-08-07 13:01:30 +00:00
|
|
|
append_tlv_u16(&deliver.tlv, TLVID_user_message_reference,
|
|
|
|
sms->msg_ref);
|
|
|
|
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
ret = smpp_tx_deliver(esme, &deliver);
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
|
2016-06-19 16:06:02 +00:00
|
|
|
return smpp_cmd_enqueue(esme, conn->vsub, sms,
|
2017-08-07 13:01:10 +00:00
|
|
|
deliver.sequence_number);
|
2012-11-23 18:02:37 +00:00
|
|
|
}
|
|
|
|
|
2012-11-20 21:22:04 +00:00
|
|
|
static struct smsc *g_smsc;
|
|
|
|
|
2015-07-06 14:41:30 +00:00
|
|
|
int smpp_route_smpp_first(struct gsm_sms *sms, struct gsm_subscriber_connection *conn)
|
|
|
|
{
|
|
|
|
return g_smsc->smpp_first;
|
|
|
|
}
|
|
|
|
|
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP
Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until
we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we
can route this sms somewhere we can reach indeed.
After this change, the conversation looks like this:
MS GSM 03.40 SMSC SMPP 3.4 ESME
| | |
| SMS-SUBMIT | |
|------------------->| |
| | DELIVER-SM |
| |---------------->|
| | |
| | DELIVER-SM-RESP |
| |<----------------|
| GSM 04.11 RP-ACK | |
|<-------------------| |
| | |
Before this patch, the RP-ACK was sent back straight forward to the MS,
no matter if the sms can be route by the ESME or not. Thus, the user
ends up getting a misleading "message delivered" in their phone screen,
when the message may just be unroutable by the ESME hence silently
dropped.
If we get no reply from the ESME, there is a hardcoded timer that will
expire to send back an RP-ERROR to the MS indicating that network is
out-of-order. Currently this timer is arbitrarily set to 5 seconds. I
found no specific good default value on the SMPP 3.4 specs, section 7.2,
where the response_timer is described. There must be a place that
describes a better default value for this. We could also expose this
timer through VTY for configurability reasons, to be done later.
Given all this needs to happen asyncronously, ie. block the SMSC, this
patch extends the gsm_sms structure with two new fields to annotate
useful information to send the RP-ACK/RP-ERROR back to the MS of origin.
These new fields are:
* the GSM 04.07 transaction id, to look up for the gsm_trans object.
* the GSM 04.11 message reference so the MS of origin can correlate this
response to its original request.
Tested here using python-libsmpp script that replies with
DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see
here on my motorola C155 that message cannot be delivered. I have tested
with the success status code in the SMPP DELIVER_SM_RESP too.
Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
|
|
|
int smpp_try_deliver(struct gsm_sms *sms,
|
2017-08-07 13:01:10 +00:00
|
|
|
struct gsm_subscriber_connection *conn)
|
2012-11-23 18:02:37 +00:00
|
|
|
{
|
|
|
|
struct osmo_esme *esme;
|
|
|
|
struct osmo_smpp_addr dst;
|
2017-07-05 09:46:55 +00:00
|
|
|
int rc;
|
2012-11-23 18:02:37 +00:00
|
|
|
|
|
|
|
memset(&dst, 0, sizeof(dst));
|
2012-11-23 22:35:01 +00:00
|
|
|
dst.ton = sms->dst.ton;
|
|
|
|
dst.npi = sms->dst.npi;
|
|
|
|
memcpy(dst.addr, sms->dst.addr, sizeof(dst.addr));
|
2012-11-23 18:02:37 +00:00
|
|
|
|
2017-07-05 09:46:55 +00:00
|
|
|
rc = smpp_route(g_smsc, &dst, &esme);
|
|
|
|
if (!rc)
|
2017-08-07 13:01:10 +00:00
|
|
|
rc = deliver_to_esme(esme, sms, conn);
|
2012-11-23 18:02:37 +00:00
|
|
|
|
2017-07-05 09:46:55 +00:00
|
|
|
return rc;
|
2012-11-23 18:02:37 +00:00
|
|
|
}
|
|
|
|
|
2012-11-20 21:22:04 +00:00
|
|
|
struct smsc *smsc_from_vty(struct vty *v)
|
|
|
|
{
|
|
|
|
/* FIXME: this is ugly */
|
|
|
|
return g_smsc;
|
|
|
|
}
|
|
|
|
|
smpp: refactor initialization, add bind address
Make the SMPP bind address configurable (used to be harcoded as "0.0.0.0").
Add VTY command
smpp
local-tcp A.B.C.D <1-65535>
while keeping the old command 'local-tcp-port <1-65535>'. Both the old and the
new command immediately change the SMPP listening address and port.
Add a LOGL_NOTICE log when the SMPP listening address and/or port change.
However, to be useful, this patch has to go somewhat further: refactor the
initialization procedure, because it was impossible to run the VTY commands
without an already established connection.
The SMPP initialization procedure was weird. It would first open a connection
on the default port, and a subsequent VTY port reconfiguration while reading
the config file would try to re-establish a connection on a different port. If
that failed, smpp would switch back to the default port instead of failing the
program launch as the user would expect. If anything else ran on port 2775,
SMPP would thus refuse to launch despite the config file having a different
port: the first bind would always happen on 0.0.0.0:2775. Change that.
In the VTY commands, merely store address and port if no fd is established yet.
Introduce several SMPP initialization stages:
* allocate struct and initialize pointers,
* then read config file without immediately starting to listen,
* and once the main program is ready, start listening.
After that, the VTY command behaves as before: try to re-establish the old
connection if the newly supplied address and port don't work out. I'm not
actually sure why this switch-back behavior is needed, but fair enough.
In detail, replace the function
smpp_smsc_init()
with the various steps
smpp_smsc_alloc_init() -- prepare struct for VTY commands
smpp_smsc_conf() -- set addr an port only, for reading the config file
smpp_smsc_start() -- establish a first connection, for main()
smpp_smsc_restart() -- switch running connection, for telnet VTY
smpp_smsc_stop() -- tear down connection, used by _start() twice
And replace
smpp_openbsc_init()
smpp_openbsc_set_net()
with
smpp_openbsc_alloc_init()
smpp_openbsc_start()
I'd have picked function names like "_bind"/"_unbind", but in the SMPP protocol
there is also a bind/unbind process, so instead I chose the names "_start",
"_restart" and "_stop".
The smsc struct used to be talloc'd outside of smpp_smsc_init(). Since the smsc
code internally uses talloc anyway and employs the smsc struct as talloc
context, I decided to enforce talloc allocation within smpp_smsc_alloc_init().
Be stricter about osmo_signal_register_handler() return codes.
2016-02-24 18:15:39 +00:00
|
|
|
/*! \brief Allocate the OpenBSC SMPP interface struct and init VTY. */
|
|
|
|
int smpp_openbsc_alloc_init(void *ctx)
|
|
|
|
{
|
|
|
|
g_smsc = smpp_smsc_alloc_init(ctx);
|
|
|
|
if (!g_smsc) {
|
|
|
|
LOGP(DSMPP, LOGL_FATAL, "Cannot allocate smsc struct\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return smpp_vty_init();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Launch the OpenBSC SMPP interface with the parameters set from VTY.
|
|
|
|
*/
|
|
|
|
int smpp_openbsc_start(struct gsm_network *net)
|
2012-11-08 15:14:37 +00:00
|
|
|
{
|
|
|
|
int rc;
|
smpp: refactor initialization, add bind address
Make the SMPP bind address configurable (used to be harcoded as "0.0.0.0").
Add VTY command
smpp
local-tcp A.B.C.D <1-65535>
while keeping the old command 'local-tcp-port <1-65535>'. Both the old and the
new command immediately change the SMPP listening address and port.
Add a LOGL_NOTICE log when the SMPP listening address and/or port change.
However, to be useful, this patch has to go somewhat further: refactor the
initialization procedure, because it was impossible to run the VTY commands
without an already established connection.
The SMPP initialization procedure was weird. It would first open a connection
on the default port, and a subsequent VTY port reconfiguration while reading
the config file would try to re-establish a connection on a different port. If
that failed, smpp would switch back to the default port instead of failing the
program launch as the user would expect. If anything else ran on port 2775,
SMPP would thus refuse to launch despite the config file having a different
port: the first bind would always happen on 0.0.0.0:2775. Change that.
In the VTY commands, merely store address and port if no fd is established yet.
Introduce several SMPP initialization stages:
* allocate struct and initialize pointers,
* then read config file without immediately starting to listen,
* and once the main program is ready, start listening.
After that, the VTY command behaves as before: try to re-establish the old
connection if the newly supplied address and port don't work out. I'm not
actually sure why this switch-back behavior is needed, but fair enough.
In detail, replace the function
smpp_smsc_init()
with the various steps
smpp_smsc_alloc_init() -- prepare struct for VTY commands
smpp_smsc_conf() -- set addr an port only, for reading the config file
smpp_smsc_start() -- establish a first connection, for main()
smpp_smsc_restart() -- switch running connection, for telnet VTY
smpp_smsc_stop() -- tear down connection, used by _start() twice
And replace
smpp_openbsc_init()
smpp_openbsc_set_net()
with
smpp_openbsc_alloc_init()
smpp_openbsc_start()
I'd have picked function names like "_bind"/"_unbind", but in the SMPP protocol
there is also a bind/unbind process, so instead I chose the names "_start",
"_restart" and "_stop".
The smsc struct used to be talloc'd outside of smpp_smsc_init(). Since the smsc
code internally uses talloc anyway and employs the smsc struct as talloc
context, I decided to enforce talloc allocation within smpp_smsc_alloc_init().
Be stricter about osmo_signal_register_handler() return codes.
2016-02-24 18:15:39 +00:00
|
|
|
g_smsc->priv = net;
|
2012-11-08 15:14:37 +00:00
|
|
|
|
smpp: refactor initialization, add bind address
Make the SMPP bind address configurable (used to be harcoded as "0.0.0.0").
Add VTY command
smpp
local-tcp A.B.C.D <1-65535>
while keeping the old command 'local-tcp-port <1-65535>'. Both the old and the
new command immediately change the SMPP listening address and port.
Add a LOGL_NOTICE log when the SMPP listening address and/or port change.
However, to be useful, this patch has to go somewhat further: refactor the
initialization procedure, because it was impossible to run the VTY commands
without an already established connection.
The SMPP initialization procedure was weird. It would first open a connection
on the default port, and a subsequent VTY port reconfiguration while reading
the config file would try to re-establish a connection on a different port. If
that failed, smpp would switch back to the default port instead of failing the
program launch as the user would expect. If anything else ran on port 2775,
SMPP would thus refuse to launch despite the config file having a different
port: the first bind would always happen on 0.0.0.0:2775. Change that.
In the VTY commands, merely store address and port if no fd is established yet.
Introduce several SMPP initialization stages:
* allocate struct and initialize pointers,
* then read config file without immediately starting to listen,
* and once the main program is ready, start listening.
After that, the VTY command behaves as before: try to re-establish the old
connection if the newly supplied address and port don't work out. I'm not
actually sure why this switch-back behavior is needed, but fair enough.
In detail, replace the function
smpp_smsc_init()
with the various steps
smpp_smsc_alloc_init() -- prepare struct for VTY commands
smpp_smsc_conf() -- set addr an port only, for reading the config file
smpp_smsc_start() -- establish a first connection, for main()
smpp_smsc_restart() -- switch running connection, for telnet VTY
smpp_smsc_stop() -- tear down connection, used by _start() twice
And replace
smpp_openbsc_init()
smpp_openbsc_set_net()
with
smpp_openbsc_alloc_init()
smpp_openbsc_start()
I'd have picked function names like "_bind"/"_unbind", but in the SMPP protocol
there is also a bind/unbind process, so instead I chose the names "_start",
"_restart" and "_stop".
The smsc struct used to be talloc'd outside of smpp_smsc_init(). Since the smsc
code internally uses talloc anyway and employs the smsc struct as talloc
context, I decided to enforce talloc allocation within smpp_smsc_alloc_init().
Be stricter about osmo_signal_register_handler() return codes.
2016-02-24 18:15:39 +00:00
|
|
|
/* If a VTY configuration has taken place, the values have been stored
|
|
|
|
* in the smsc struct. Otherwise, use the defaults (NULL -> any, 0 ->
|
|
|
|
* default SMPP port, see smpp_smsc_bind()). */
|
|
|
|
rc = smpp_smsc_start(g_smsc, g_smsc->bind_addr, g_smsc->listen_port);
|
2012-11-08 15:14:37 +00:00
|
|
|
if (rc < 0)
|
smpp: refactor initialization, add bind address
Make the SMPP bind address configurable (used to be harcoded as "0.0.0.0").
Add VTY command
smpp
local-tcp A.B.C.D <1-65535>
while keeping the old command 'local-tcp-port <1-65535>'. Both the old and the
new command immediately change the SMPP listening address and port.
Add a LOGL_NOTICE log when the SMPP listening address and/or port change.
However, to be useful, this patch has to go somewhat further: refactor the
initialization procedure, because it was impossible to run the VTY commands
without an already established connection.
The SMPP initialization procedure was weird. It would first open a connection
on the default port, and a subsequent VTY port reconfiguration while reading
the config file would try to re-establish a connection on a different port. If
that failed, smpp would switch back to the default port instead of failing the
program launch as the user would expect. If anything else ran on port 2775,
SMPP would thus refuse to launch despite the config file having a different
port: the first bind would always happen on 0.0.0.0:2775. Change that.
In the VTY commands, merely store address and port if no fd is established yet.
Introduce several SMPP initialization stages:
* allocate struct and initialize pointers,
* then read config file without immediately starting to listen,
* and once the main program is ready, start listening.
After that, the VTY command behaves as before: try to re-establish the old
connection if the newly supplied address and port don't work out. I'm not
actually sure why this switch-back behavior is needed, but fair enough.
In detail, replace the function
smpp_smsc_init()
with the various steps
smpp_smsc_alloc_init() -- prepare struct for VTY commands
smpp_smsc_conf() -- set addr an port only, for reading the config file
smpp_smsc_start() -- establish a first connection, for main()
smpp_smsc_restart() -- switch running connection, for telnet VTY
smpp_smsc_stop() -- tear down connection, used by _start() twice
And replace
smpp_openbsc_init()
smpp_openbsc_set_net()
with
smpp_openbsc_alloc_init()
smpp_openbsc_start()
I'd have picked function names like "_bind"/"_unbind", but in the SMPP protocol
there is also a bind/unbind process, so instead I chose the names "_start",
"_restart" and "_stop".
The smsc struct used to be talloc'd outside of smpp_smsc_init(). Since the smsc
code internally uses talloc anyway and employs the smsc struct as talloc
context, I decided to enforce talloc allocation within smpp_smsc_alloc_init().
Be stricter about osmo_signal_register_handler() return codes.
2016-02-24 18:15:39 +00:00
|
|
|
return rc;
|
2012-11-08 18:44:08 +00:00
|
|
|
|
smpp: refactor initialization, add bind address
Make the SMPP bind address configurable (used to be harcoded as "0.0.0.0").
Add VTY command
smpp
local-tcp A.B.C.D <1-65535>
while keeping the old command 'local-tcp-port <1-65535>'. Both the old and the
new command immediately change the SMPP listening address and port.
Add a LOGL_NOTICE log when the SMPP listening address and/or port change.
However, to be useful, this patch has to go somewhat further: refactor the
initialization procedure, because it was impossible to run the VTY commands
without an already established connection.
The SMPP initialization procedure was weird. It would first open a connection
on the default port, and a subsequent VTY port reconfiguration while reading
the config file would try to re-establish a connection on a different port. If
that failed, smpp would switch back to the default port instead of failing the
program launch as the user would expect. If anything else ran on port 2775,
SMPP would thus refuse to launch despite the config file having a different
port: the first bind would always happen on 0.0.0.0:2775. Change that.
In the VTY commands, merely store address and port if no fd is established yet.
Introduce several SMPP initialization stages:
* allocate struct and initialize pointers,
* then read config file without immediately starting to listen,
* and once the main program is ready, start listening.
After that, the VTY command behaves as before: try to re-establish the old
connection if the newly supplied address and port don't work out. I'm not
actually sure why this switch-back behavior is needed, but fair enough.
In detail, replace the function
smpp_smsc_init()
with the various steps
smpp_smsc_alloc_init() -- prepare struct for VTY commands
smpp_smsc_conf() -- set addr an port only, for reading the config file
smpp_smsc_start() -- establish a first connection, for main()
smpp_smsc_restart() -- switch running connection, for telnet VTY
smpp_smsc_stop() -- tear down connection, used by _start() twice
And replace
smpp_openbsc_init()
smpp_openbsc_set_net()
with
smpp_openbsc_alloc_init()
smpp_openbsc_start()
I'd have picked function names like "_bind"/"_unbind", but in the SMPP protocol
there is also a bind/unbind process, so instead I chose the names "_start",
"_restart" and "_stop".
The smsc struct used to be talloc'd outside of smpp_smsc_init(). Since the smsc
code internally uses talloc anyway and employs the smsc struct as talloc
context, I decided to enforce talloc allocation within smpp_smsc_alloc_init().
Be stricter about osmo_signal_register_handler() return codes.
2016-02-24 18:15:39 +00:00
|
|
|
rc = osmo_signal_register_handler(SS_SMS, smpp_sms_cb, g_smsc);
|
|
|
|
if (rc < 0)
|
|
|
|
return rc;
|
|
|
|
rc = osmo_signal_register_handler(SS_SUBSCR, smpp_subscr_cb, g_smsc);
|
|
|
|
if (rc < 0)
|
|
|
|
return rc;
|
2012-11-20 21:22:04 +00:00
|
|
|
|
smpp: refactor initialization, add bind address
Make the SMPP bind address configurable (used to be harcoded as "0.0.0.0").
Add VTY command
smpp
local-tcp A.B.C.D <1-65535>
while keeping the old command 'local-tcp-port <1-65535>'. Both the old and the
new command immediately change the SMPP listening address and port.
Add a LOGL_NOTICE log when the SMPP listening address and/or port change.
However, to be useful, this patch has to go somewhat further: refactor the
initialization procedure, because it was impossible to run the VTY commands
without an already established connection.
The SMPP initialization procedure was weird. It would first open a connection
on the default port, and a subsequent VTY port reconfiguration while reading
the config file would try to re-establish a connection on a different port. If
that failed, smpp would switch back to the default port instead of failing the
program launch as the user would expect. If anything else ran on port 2775,
SMPP would thus refuse to launch despite the config file having a different
port: the first bind would always happen on 0.0.0.0:2775. Change that.
In the VTY commands, merely store address and port if no fd is established yet.
Introduce several SMPP initialization stages:
* allocate struct and initialize pointers,
* then read config file without immediately starting to listen,
* and once the main program is ready, start listening.
After that, the VTY command behaves as before: try to re-establish the old
connection if the newly supplied address and port don't work out. I'm not
actually sure why this switch-back behavior is needed, but fair enough.
In detail, replace the function
smpp_smsc_init()
with the various steps
smpp_smsc_alloc_init() -- prepare struct for VTY commands
smpp_smsc_conf() -- set addr an port only, for reading the config file
smpp_smsc_start() -- establish a first connection, for main()
smpp_smsc_restart() -- switch running connection, for telnet VTY
smpp_smsc_stop() -- tear down connection, used by _start() twice
And replace
smpp_openbsc_init()
smpp_openbsc_set_net()
with
smpp_openbsc_alloc_init()
smpp_openbsc_start()
I'd have picked function names like "_bind"/"_unbind", but in the SMPP protocol
there is also a bind/unbind process, so instead I chose the names "_start",
"_restart" and "_stop".
The smsc struct used to be talloc'd outside of smpp_smsc_init(). Since the smsc
code internally uses talloc anyway and employs the smsc struct as talloc
context, I decided to enforce talloc allocation within smpp_smsc_alloc_init().
Be stricter about osmo_signal_register_handler() return codes.
2016-02-24 18:15:39 +00:00
|
|
|
return 0;
|
2012-11-08 15:14:37 +00:00
|
|
|
}
|
2013-03-13 14:05:26 +00:00
|
|
|
|