summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Chemeris <Alexander.Chemeris@gmail.com>2014-03-08 21:57:07 +0100
committerAlexander Chemeris <Alexander.Chemeris@gmail.com>2014-03-12 21:24:49 +0400
commitaf9683a3730ef7396adebf2dbd56d4ec8ca6b906 (patch)
tree4ac410b96189e13d5fe0ecaa1b80ff6c39909079
parent5ab70da57ae8976a9c55e63de95fabdb057470e6 (diff)
sms,db: Update DB scheme to support more features in our SMSC.
Do not store delivered messages in the DB. In a production system we should not store messages longer than needed, as it will quickly bloat our DB. In case one wants to store messages for debug purposes, we could add one of the following capabilities later: - hexdump to a log file - send to an SMPP entry on delivery - send to Wireshark sms,db: Store SMS Message Reference in the DB, since we need it to generate SMS-STATUS-REPORT. 03.40 9.2.3.6TP-Message-Reference (TP-MR) The SMS-STATUS-REPORT also contains a TP-Message-Reference field. The value sent to the MS will be the sameas the TP-Message-Reference value generated by the MS in the earlier SMS-SUBMIT or SMS-COMMAND to whichthe status report relates. sms,db: Add a 'type' filed to gsm_sms structure to be able diffrentiate normal DELIVER/SUBMIT messages from STATUS-REP messages.
-rw-r--r--openbsc/include/openbsc/gsm_data.h8
-rw-r--r--openbsc/src/libmsc/db.c35
-rw-r--r--openbsc/src/libmsc/gsm_04_11.c4
-rw-r--r--openbsc/src/libmsc/smpp_openbsc.c1
-rw-r--r--openbsc/tests/db/db_test.c14
5 files changed, 50 insertions, 12 deletions
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 2ce7727be..b948d370f 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -302,7 +302,13 @@ struct gsm_sms_addr {
char addr[21+1];
};
+enum gsm_sms_type {
+ GSM_SMS_DELIVER = 0, /* SMS-DELIVER or SMS-SUBMIT */
+ GSM_SMS_STATUS_REP = 1, /* SMS-STATUS-REPORT */
+};
+
struct gsm_sms {
+ enum gsm_sms_type type;
unsigned long long id;
struct gsm_subscriber *receiver;
struct gsm_sms_addr src, dst;
@@ -317,6 +323,8 @@ struct gsm_sms {
time_t received_time;
time_t valid_until;
+ time_t delivered_time;
+ uint8_t delivery_status;
uint8_t reply_path_req;
uint8_t status_rep_req;
uint8_t ud_hdr_ind;
diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c
index 4808af7ec..84d5cbd52 100644
--- a/openbsc/src/libmsc/db.c
+++ b/openbsc/src/libmsc/db.c
@@ -115,9 +115,11 @@ static const char *create_stmts[] = {
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"created TIMESTAMP NOT NULL, "
"received TIMESTAMP, "
- "sent TIMESTAMP, "
+ "delivered TIMESTAMP, "
"deliver_attempts INTEGER NOT NULL DEFAULT 0, "
+ "type INTEGER NOT NULL, "
/* data directly copied/derived from SMS */
+ "msg_ref INTEGER NOT NULL, "
"valid_until TIMESTAMP, "
"reply_path_req INTEGER NOT NULL, "
"status_rep_req INTEGER NOT NULL, "
@@ -231,6 +233,9 @@ static struct gsm_sms *sms_from_result_v3(dbi_result result)
if (!sms)
return NULL;
+ /* This is a normal SMS */
+ sms->type = GSM_SMS_DELIVER;
+
sms->id = dbi_result_get_ulonglong(result, "id");
sender_id = dbi_result_get_ulonglong(result, "sender_id");
@@ -1284,6 +1289,7 @@ int db_sms_store(struct gsm_sms *sms)
unsigned char *q_udata;
char received_timestamp[22];
char validity_timestamp[22];
+ char delivered_timestamp[22];
dbi_conn_quote_string_copy(conn, (char *)sms->text, &q_text);
dbi_conn_quote_string_copy(conn, (char *)sms->dst.addr, &q_daddr);
@@ -1294,21 +1300,26 @@ int db_sms_store(struct gsm_sms *sms)
"'%F %T'", gmtime(&sms->received_time));
strftime(validity_timestamp, sizeof(validity_timestamp),
"'%F %T'", gmtime(&sms->valid_until));
+ strftime(delivered_timestamp, sizeof(delivered_timestamp),
+ "'%F %T'", gmtime(&sms->delivered_time));
result = dbi_conn_queryf(conn,
"INSERT INTO SMS "
- "(created, received, valid_until, "
+ "(created, received, msg_ref, valid_until, "
+ "delivered, type, "
"reply_path_req, status_rep_req, protocol_id, "
"data_coding_scheme, ud_hdr_ind, "
"user_data, text, "
"dest_addr, dest_ton, dest_npi, "
"src_addr, src_ton, src_npi) VALUES "
- "(datetime('now'), %s, %s, "
+ "(datetime('now'), %s, %u, %s, "
+ "%s, %u, "
"%u, %u, %u, "
"%u, %u, "
"%s, %s, "
"%s, %u, %u, "
"%s, %u, %u)",
- received_timestamp, validity_timestamp,
+ received_timestamp, sms->msg_ref, validity_timestamp,
+ delivered_timestamp, sms->type,
sms->reply_path_req, sms->status_rep_req, sms->protocol_id,
sms->data_coding_scheme, sms->ud_hdr_ind,
q_udata, q_text,
@@ -1335,6 +1346,7 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul
if (!sms)
return NULL;
+ sms->type = dbi_result_get_uint(result, "type");
sms->id = dbi_result_get_ulonglong(result, "id");
/* FIXME: those should all be get_uchar, but sqlite3 is braindead */
@@ -1346,7 +1358,8 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul
"data_coding_scheme");
sms->received_time = dbi_result_get_datetime(result, "received");
sms->valid_until = dbi_result_get_datetime(result, "valid_until");
- /* sms->msg_ref is temporary and not stored in DB */
+ sms->delivered_time = dbi_result_get_datetime(result, "delivered");
+ sms->msg_ref = dbi_result_get_uint(result, "msg_ref");
sms->dst.npi = dbi_result_get_uint(result, "dest_npi");
sms->dst.ton = dbi_result_get_uint(result, "dest_ton");
@@ -1411,7 +1424,7 @@ struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, unsigned long long mi
"SELECT SMS.* "
"FROM SMS JOIN Subscriber ON "
"SMS.dest_addr = Subscriber.extension "
- "WHERE SMS.id >= %llu AND SMS.sent IS NULL "
+ "WHERE SMS.id >= %llu "
"AND Subscriber.lac > 0 "
"ORDER BY SMS.id LIMIT 1",
min_id);
@@ -1441,7 +1454,7 @@ struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net,
"SELECT SMS.* "
"FROM SMS JOIN Subscriber ON "
"SMS.dest_addr = Subscriber.extension "
- "WHERE Subscriber.id >= %llu AND SMS.sent IS NULL "
+ "WHERE Subscriber.id >= %llu "
"AND Subscriber.lac > 0 AND SMS.deliver_attempts < %u "
"ORDER BY Subscriber.id, SMS.id LIMIT 1",
min_subscr_id, failed);
@@ -1470,7 +1483,7 @@ struct gsm_sms *db_sms_get_unsent_for_subscr(struct gsm_subscriber *subscr)
"SELECT SMS.* "
"FROM SMS JOIN Subscriber ON "
"SMS.dest_addr = Subscriber.extension "
- "WHERE Subscriber.id = %llu AND SMS.sent IS NULL "
+ "WHERE Subscriber.id = %llu "
"AND Subscriber.lac > 0 "
"ORDER BY SMS.id LIMIT 1",
subscr->id);
@@ -1495,11 +1508,9 @@ int db_sms_mark_delivered(struct gsm_sms *sms)
dbi_result result;
result = dbi_conn_queryf(conn,
- "UPDATE SMS "
- "SET sent = datetime('now') "
- "WHERE id = %llu", sms->id);
+ "DELETE FROM SMS WHERE SMS.id = %llu", sms->id);
if (!result) {
- LOGP(DDB, LOGL_ERROR, "Failed to mark SMS %llu as sent.\n", sms->id);
+ LOGP(DDB, LOGL_ERROR, "Failed to remove SMS %llu from DB.\n", sms->id);
return 1;
}
diff --git a/openbsc/src/libmsc/gsm_04_11.c b/openbsc/src/libmsc/gsm_04_11.c
index 8bb650ed2..01cf6951d 100644
--- a/openbsc/src/libmsc/gsm_04_11.c
+++ b/openbsc/src/libmsc/gsm_04_11.c
@@ -92,6 +92,7 @@ struct gsm_sms *sms_from_text(struct gsm_subscriber *receiver,
if (!sms)
return NULL;
+ sms->type = GSM_SMS_DELIVER;
sms->receiver = subscr_get(receiver);
strncpy(sms->text, text, sizeof(sms->text)-1);
@@ -299,6 +300,9 @@ static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *m
if (!gsms)
return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
+ /* This is a normal SMS */
+ gsms->type = GSM_SMS_DELIVER;
+
/* invert those fields where 0 means active/present */
sms_mti = *smsp & 0x03;
sms_mms = !!(*smsp & 0x04);
diff --git a/openbsc/src/libmsc/smpp_openbsc.c b/openbsc/src/libmsc/smpp_openbsc.c
index ec541c271..d960810cd 100644
--- a/openbsc/src/libmsc/smpp_openbsc.c
+++ b/openbsc/src/libmsc/smpp_openbsc.c
@@ -123,6 +123,7 @@ static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net,
}
sms = sms_alloc();
+ sms->type = GSM_SMS_DELIVER;
sms->source = SMS_SOURCE_SMPP;
sms->smpp.sequence_nr = submit->sequence_number;
diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c
index be327aa99..c8b916096 100644
--- a/openbsc/tests/db/db_test.c
+++ b/openbsc/tests/db/db_test.c
@@ -73,10 +73,13 @@ static void test_sms(void)
subscr->net = &dummy_net;
sms = sms_alloc();
+ sms->type = GSM_SMS_DELIVER;
sms->receiver = subscr_get(subscr);
sms->received_time = 12345;
sms->valid_until = 67890;
+ sms->delivered_time = 98765;
+ sms->msg_ref = 123;
sms->src.ton = 0x23;
sms->src.npi = 0x24;
@@ -104,9 +107,12 @@ static void test_sms(void)
/* now query */
sms = db_sms_get_unsent_for_subscr(subscr);
OSMO_ASSERT(sms);
+ OSMO_ASSERT(sms->type == GSM_SMS_DELIVER);
OSMO_ASSERT(sms->receiver == subscr);
OSMO_ASSERT(sms->received_time == 12345);
OSMO_ASSERT(sms->valid_until == 67890);
+ OSMO_ASSERT(sms->delivered_time == 98765);
+ OSMO_ASSERT(sms->msg_ref == 123);
OSMO_ASSERT(sms->reply_path_req == 1);
OSMO_ASSERT(sms->status_rep_req == 2);
OSMO_ASSERT(sms->ud_hdr_ind == 3);
@@ -120,6 +126,14 @@ static void test_sms(void)
OSMO_ASSERT(sms->user_data_len == strlen("UserData123"));
OSMO_ASSERT(strcmp((char *) sms->user_data, "UserData123") == 0);
+ /* mark SMS as delivered in the DB */
+ db_sms_mark_delivered(sms);
+ sms_free(sms);
+
+ /* now query - we should not get anything */
+ sms = db_sms_get_unsent_for_subscr(subscr);
+ OSMO_ASSERT(!sms);
+
subscr_put(subscr);
}