diff options
author | Holger Hans Peter Freyther <holger@moiji-mobile.com> | 2014-04-30 15:32:41 +0200 |
---|---|---|
committer | Holger Hans Peter Freyther <holger@moiji-mobile.com> | 2014-04-30 15:32:41 +0200 |
commit | edfdc9829cc2cc6f05a9cd9015e22210e442a259 (patch) | |
tree | 99272bb5e327734193efdac665a7b81c92a0f664 | |
parent | 1b148ec1009c32faea269331836e366cfff7d18e (diff) | |
parent | 6114401b9bce9322fb2826fe41393d03d0981ab2 (diff) |
Merge branch 'zecke/features/sms-db-changes'
This branch allows a SMPP user to fully specify the sender id. It
requires a change in schema, database migration code and exposed
some issues in the libdbi and the sqlite3 driver.
-rw-r--r-- | openbsc/include/openbsc/gsm_data.h | 1 | ||||
-rw-r--r-- | openbsc/src/libbsc/gsm_subscriber_base.c | 6 | ||||
-rw-r--r-- | openbsc/src/libmsc/db.c | 298 | ||||
-rw-r--r-- | openbsc/src/libmsc/gsm_04_11.c | 9 | ||||
-rw-r--r-- | openbsc/src/libmsc/smpp_openbsc.c | 5 | ||||
-rw-r--r-- | openbsc/tests/db/Makefile.am | 2 | ||||
-rw-r--r-- | openbsc/tests/db/db_test.c | 95 | ||||
-rw-r--r-- | openbsc/tests/db/db_test.err | 2 | ||||
-rw-r--r-- | openbsc/tests/db/hlr.sqlite3 | bin | 0 -> 29696 bytes | |||
-rw-r--r-- | openbsc/tests/testsuite.at | 4 |
10 files changed, 351 insertions, 71 deletions
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 8f24d4fd1..4338cd60c 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -304,7 +304,6 @@ struct gsm_sms_addr { struct gsm_sms { unsigned long long id; - struct gsm_subscriber *sender; struct gsm_subscriber *receiver; struct gsm_sms_addr src, dst; enum gsm_sms_source_id source; diff --git a/openbsc/src/libbsc/gsm_subscriber_base.c b/openbsc/src/libbsc/gsm_subscriber_base.c index 5755687a1..5e00443c2 100644 --- a/openbsc/src/libbsc/gsm_subscriber_base.c +++ b/openbsc/src/libbsc/gsm_subscriber_base.c @@ -72,6 +72,12 @@ static void subscr_free(struct gsm_subscriber *subscr) talloc_free(subscr); } +void subscr_direct_free(struct gsm_subscriber *subscr) +{ + OSMO_ASSERT(subscr->use_count == 1); + subscr_free(subscr); +} + struct gsm_subscriber *subscr_get(struct gsm_subscriber *subscr) { subscr->use_count++; diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index bfa4e75a0..1580acd91 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -38,23 +38,42 @@ #include <osmocom/core/statistics.h> #include <osmocom/core/rate_ctr.h> +/* Semi-Private-Interface (SPI) for the subscriber code */ +void subscr_direct_free(struct gsm_subscriber *subscr); + static char *db_basename = NULL; static char *db_dirname = NULL; static dbi_conn conn; -#define SCHEMA_REVISION "3" +#define SCHEMA_REVISION "4" + +enum { + SCHEMA_META, + INSERT_META, + SCHEMA_SUBSCRIBER, + SCHEMA_AUTH, + SCHEMA_EQUIPMENT, + SCHEMA_EQUIPMENT_WATCH, + SCHEMA_SMS, + SCHEMA_VLR, + SCHEMA_APDU, + SCHEMA_COUNTERS, + SCHEMA_RATE, + SCHEMA_AUTHKEY, + SCHEMA_AUTHLAST, +}; -static char *create_stmts[] = { - "CREATE TABLE IF NOT EXISTS Meta (" +static const char *create_stmts[] = { + [SCHEMA_META] = "CREATE TABLE IF NOT EXISTS Meta (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "key TEXT UNIQUE NOT NULL, " "value TEXT NOT NULL" ")", - "INSERT OR IGNORE INTO Meta " + [INSERT_META] = "INSERT OR IGNORE INTO Meta " "(key, value) " "VALUES " "('revision', " SCHEMA_REVISION ")", - "CREATE TABLE IF NOT EXISTS Subscriber (" + [SCHEMA_SUBSCRIBER] = "CREATE TABLE IF NOT EXISTS Subscriber (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "created TIMESTAMP NOT NULL, " "updated TIMESTAMP NOT NULL, " @@ -66,13 +85,13 @@ static char *create_stmts[] = { "lac INTEGER NOT NULL DEFAULT 0, " "expire_lu TIMESTAMP DEFAULT NULL" ")", - "CREATE TABLE IF NOT EXISTS AuthToken (" + [SCHEMA_AUTH] = "CREATE TABLE IF NOT EXISTS AuthToken (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "subscriber_id INTEGER UNIQUE NOT NULL, " "created TIMESTAMP NOT NULL, " "token TEXT UNIQUE NOT NULL" ")", - "CREATE TABLE IF NOT EXISTS Equipment (" + [SCHEMA_EQUIPMENT] = "CREATE TABLE IF NOT EXISTS Equipment (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "created TIMESTAMP NOT NULL, " "updated TIMESTAMP NOT NULL, " @@ -82,7 +101,7 @@ static char *create_stmts[] = { "classmark3 BLOB, " "imei NUMERIC UNIQUE NOT NULL" ")", - "CREATE TABLE IF NOT EXISTS EquipmentWatch (" + [SCHEMA_EQUIPMENT_WATCH] = "CREATE TABLE IF NOT EXISTS EquipmentWatch (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "created TIMESTAMP NOT NULL, " "updated TIMESTAMP NOT NULL, " @@ -90,13 +109,11 @@ static char *create_stmts[] = { "equipment_id NUMERIC NOT NULL, " "UNIQUE (subscriber_id, equipment_id) " ")", - "CREATE TABLE IF NOT EXISTS SMS (" + [SCHEMA_SMS] = "CREATE TABLE IF NOT EXISTS SMS (" /* metadata, not part of sms */ "id INTEGER PRIMARY KEY AUTOINCREMENT, " "created TIMESTAMP NOT NULL, " "sent TIMESTAMP, " - "sender_id INTEGER NOT NULL, " - "receiver_id INTEGER NOT NULL, " "deliver_attempts INTEGER NOT NULL DEFAULT 0, " /* data directly copied/derived from SMS */ "valid_until TIMESTAMP, " @@ -105,45 +122,50 @@ static char *create_stmts[] = { "protocol_id INTEGER NOT NULL, " "data_coding_scheme INTEGER NOT NULL, " "ud_hdr_ind INTEGER NOT NULL, " - "dest_addr TEXT, " + "src_addr TEXT NOT NULL, " + "src_ton INTEGER NOT NULL, " + "src_npi INTEGER NOT NULL, " + "dest_addr TEXT NOT NULL, " + "dest_ton INTEGER NOT NULL, " + "dest_npi INTEGER NOT NULL, " "user_data BLOB, " /* TP-UD */ /* additional data, interpreted from SMS */ "header BLOB, " /* UD Header */ "text TEXT " /* decoded UD after UDH */ ")", - "CREATE TABLE IF NOT EXISTS VLR (" + [SCHEMA_VLR] = "CREATE TABLE IF NOT EXISTS VLR (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "created TIMESTAMP NOT NULL, " "updated TIMESTAMP NOT NULL, " "subscriber_id NUMERIC UNIQUE NOT NULL, " "last_bts NUMERIC NOT NULL " ")", - "CREATE TABLE IF NOT EXISTS ApduBlobs (" + [SCHEMA_APDU] = "CREATE TABLE IF NOT EXISTS ApduBlobs (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "created TIMESTAMP NOT NULL, " "apdu_id_flags INTEGER NOT NULL, " "subscriber_id INTEGER NOT NULL, " "apdu BLOB " ")", - "CREATE TABLE IF NOT EXISTS Counters (" + [SCHEMA_COUNTERS] = "CREATE TABLE IF NOT EXISTS Counters (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "timestamp TIMESTAMP NOT NULL, " "value INTEGER NOT NULL, " "name TEXT NOT NULL " ")", - "CREATE TABLE IF NOT EXISTS RateCounters (" + [SCHEMA_RATE] = "CREATE TABLE IF NOT EXISTS RateCounters (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "timestamp TIMESTAMP NOT NULL, " "value INTEGER NOT NULL, " "name TEXT NOT NULL, " "idx INTEGER NOT NULL " ")", - "CREATE TABLE IF NOT EXISTS AuthKeys (" + [SCHEMA_AUTHKEY] = "CREATE TABLE IF NOT EXISTS AuthKeys (" "subscriber_id INTEGER PRIMARY KEY, " "algorithm_id INTEGER NOT NULL, " "a3a8_ki BLOB " ")", - "CREATE TABLE IF NOT EXISTS AuthLastTuples (" + [SCHEMA_AUTHLAST] = "CREATE TABLE IF NOT EXISTS AuthLastTuples (" "subscriber_id INTEGER PRIMARY KEY, " "issued TIMESTAMP NOT NULL, " "use_count INTEGER NOT NULL DEFAULT 0, " @@ -182,7 +204,7 @@ static int update_db_revision_2(void) "WHERE key = 'revision'"); if (!result) { LOGP(DDB, LOGL_ERROR, - "Failed set new revision (upgrade vom rev 2).\n"); + "Failed to update DB schema revision (upgrade from rev 2).\n"); return -EINVAL; } dbi_result_free(result); @@ -190,6 +212,160 @@ static int update_db_revision_2(void) return 0; } +/** + * Copied from the normal sms_from_result_v3 to avoid having + * to make sure that the real routine will remain backward + * compatible. + */ +static struct gsm_sms *sms_from_result_v3(dbi_result result) +{ + struct gsm_sms *sms = sms_alloc(); + long long unsigned int sender_id; + struct gsm_subscriber *sender; + const char *text, *daddr; + const unsigned char *user_data; + char buf[32]; + + if (!sms) + return NULL; + + sms->id = dbi_result_get_ulonglong(result, "id"); + + sender_id = dbi_result_get_ulonglong(result, "sender_id"); + snprintf(buf, sizeof(buf), "%llu", sender_id); + sender = db_get_subscriber(GSM_SUBSCRIBER_ID, buf); + OSMO_ASSERT(sender); + strncpy(sms->src.addr, sender->extension, sizeof(sms->src.addr)-1); + subscr_direct_free(sender); + sender = NULL; + + sms->reply_path_req = dbi_result_get_uint(result, "reply_path_req"); + sms->status_rep_req = dbi_result_get_uint(result, "status_rep_req"); + sms->ud_hdr_ind = dbi_result_get_uint(result, "ud_hdr_ind"); + sms->protocol_id = dbi_result_get_uint(result, "protocol_id"); + sms->data_coding_scheme = dbi_result_get_uint(result, + "data_coding_scheme"); + + daddr = dbi_result_get_string(result, "dest_addr"); + if (daddr) { + strncpy(sms->dst.addr, daddr, sizeof(sms->dst.addr)); + sms->dst.addr[sizeof(sms->dst.addr)-1] = '\0'; + } + + sms->user_data_len = dbi_result_get_field_length(result, "user_data"); + user_data = dbi_result_get_binary(result, "user_data"); + if (sms->user_data_len > sizeof(sms->user_data)) + sms->user_data_len = (uint8_t) sizeof(sms->user_data); + memcpy(sms->user_data, user_data, sms->user_data_len); + + text = dbi_result_get_string(result, "text"); + if (text) { + strncpy(sms->text, text, sizeof(sms->text)); + sms->text[sizeof(sms->text)-1] = '\0'; + } + return sms; +} + +static int update_db_revision_3(void) +{ + dbi_result result; + struct gsm_sms *sms; + + LOGP(DDB, LOGL_NOTICE, "Going to migrate from revision 3\n"); + + result = dbi_conn_query(conn, "BEGIN EXCLUSIVE TRANSACTION"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to begin transaction (upgrade from rev 3)\n"); + return -EINVAL; + } + dbi_result_free(result); + + /* Rename old SMS table to be able create a new one */ + result = dbi_conn_query(conn, "ALTER TABLE SMS RENAME TO SMS_3"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to rename the old SMS table (upgrade from rev 3).\n"); + goto rollback; + } + dbi_result_free(result); + + /* Create new SMS table with all the bells and whistles! */ + result = dbi_conn_query(conn, create_stmts[SCHEMA_SMS]); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to create a new SMS table (upgrade from rev 3).\n"); + goto rollback; + } + dbi_result_free(result); + + /* Cycle through old messages and convert them to the new format */ + result = dbi_conn_queryf(conn, "SELECT * FROM SMS_3"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed fetch messages from the old SMS table (upgrade from rev 3).\n"); + goto rollback; + } + while (dbi_result_next_row(result)) { + sms = sms_from_result_v3(result); + if (db_sms_store(sms) != 0) { + LOGP(DDB, LOGL_ERROR, "Failed to store message to the new SMS table(upgrade from rev 3).\n"); + sms_free(sms); + dbi_result_free(result); + goto rollback; + } + sms_free(sms); + } + dbi_result_free(result); + + /* Remove the temporary table */ + result = dbi_conn_query(conn, "DROP TABLE SMS_3"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to drop the old SMS table (upgrade from rev 3).\n"); + goto rollback; + } + dbi_result_free(result); + + /* We're done. Bump DB Meta revision to 4 */ + result = dbi_conn_query(conn, + "UPDATE Meta " + "SET value = '4' " + "WHERE key = 'revision'"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to update DB schema revision (upgrade from rev 3).\n"); + goto rollback; + } + dbi_result_free(result); + + result = dbi_conn_query(conn, "COMMIT TRANSACTION"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to commit the transaction (upgrade from rev 3)\n"); + return -EINVAL; + } + + /* Shrink DB file size by actually wiping out SMS_3 table data */ + result = dbi_conn_query(conn, "VACUUM"); + if (!result) + LOGP(DDB, LOGL_ERROR, + "VACUUM failed. Ignoring it (upgrade from rev 3).\n"); + else + dbi_result_free(result); + + return 0; + +rollback: + result = dbi_conn_query(conn, "ROLLBACK TRANSACTION"); + if (!result) + LOGP(DDB, LOGL_ERROR, + "Rollback failed (upgrade from rev 3).\n"); + else + dbi_result_free(result); + return -EINVAL; +} + static int check_db_revision(void) { dbi_result result; @@ -215,6 +391,12 @@ static int check_db_revision(void) dbi_result_free(result); return -EINVAL; } + } else if (!strcmp(rev_s, "3")) { + if (update_db_revision_3()) { + LOGP(DDB, LOGL_FATAL, "Failed to update database from schema revision '%s'.\n", rev_s); + dbi_result_free(result); + return -EINVAL; + } } else if (!strcmp(rev_s, SCHEMA_REVISION)) { /* everything is fine */ } else { @@ -1214,7 +1396,7 @@ int db_subscriber_assoc_imei(struct gsm_subscriber *subscriber, char imei[GSM_IM int db_sms_store(struct gsm_sms *sms) { dbi_result result; - char *q_text, *q_daddr; + char *q_text, *q_daddr, *q_saddr; unsigned char *q_udata; char *validity_timestamp = "2222-2-2"; @@ -1222,25 +1404,35 @@ int db_sms_store(struct gsm_sms *sms) dbi_conn_quote_string_copy(conn, (char *)sms->text, &q_text); dbi_conn_quote_string_copy(conn, (char *)sms->dst.addr, &q_daddr); + dbi_conn_quote_string_copy(conn, (char *)sms->src.addr, &q_saddr); dbi_conn_quote_binary_copy(conn, sms->user_data, sms->user_data_len, &q_udata); + /* FIXME: correct validity period */ result = dbi_conn_queryf(conn, "INSERT INTO SMS " - "(created, sender_id, receiver_id, valid_until, " + "(created, valid_until, " "reply_path_req, status_rep_req, protocol_id, " - "data_coding_scheme, ud_hdr_ind, dest_addr, " - "user_data, text) VALUES " - "(datetime('now'), %llu, %llu, %u, " - "%u, %u, %u, %u, %u, %s, %s, %s)", - sms->sender->id, - sms->receiver ? sms->receiver->id : 0, validity_timestamp, + "data_coding_scheme, ud_hdr_ind, " + "user_data, text, " + "dest_addr, dest_ton, dest_npi, " + "src_addr, src_ton, src_npi) VALUES " + "(datetime('now'), %u, " + "%u, %u, %u, " + "%u, %u, " + "%s, %s, " + "%s, %u, %u, " + "%s, %u, %u)", + validity_timestamp, sms->reply_path_req, sms->status_rep_req, sms->protocol_id, sms->data_coding_scheme, sms->ud_hdr_ind, - q_daddr, q_udata, q_text); + q_udata, q_text, + q_daddr, sms->dst.ton, sms->dst.npi, + q_saddr, sms->src.ton, sms->src.npi); free(q_text); - free(q_daddr); free(q_udata); + free(q_daddr); + free(q_saddr); if (!result) return -EIO; @@ -1252,8 +1444,7 @@ int db_sms_store(struct gsm_sms *sms) static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result result) { struct gsm_sms *sms = sms_alloc(); - long long unsigned int sender_id, receiver_id; - const char *text, *daddr; + const char *text, *daddr, *saddr; const unsigned char *user_data; if (!sms) @@ -1261,28 +1452,6 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul sms->id = dbi_result_get_ulonglong(result, "id"); - sender_id = dbi_result_get_ulonglong(result, "sender_id"); - sms->sender = subscr_get_by_id(net, sender_id); - if (!sms->sender) { - LOGP(DLSMS, LOGL_ERROR, - "Failed to find sender(%llu) for id(%llu)\n", - sender_id, sms->id); - sms_free(sms); - return NULL; - } - - strncpy(sms->src.addr, sms->sender->extension, sizeof(sms->src.addr)-1); - - receiver_id = dbi_result_get_ulonglong(result, "receiver_id"); - sms->receiver = subscr_get_by_id(net, receiver_id); - if (!sms->receiver) { - LOGP(DLSMS, LOGL_ERROR, - "Failed to find receiver(%llu) for id(%llu)\n", - receiver_id, sms->id); - sms_free(sms); - return NULL; - } - /* FIXME: validity */ /* FIXME: those should all be get_uchar, but sqlite3 is braindead */ sms->reply_path_req = dbi_result_get_uint(result, "reply_path_req"); @@ -1293,11 +1462,22 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul "data_coding_scheme"); /* sms->msg_ref is temporary and not stored in DB */ + sms->dst.npi = dbi_result_get_uint(result, "dest_npi"); + sms->dst.ton = dbi_result_get_uint(result, "dest_ton"); daddr = dbi_result_get_string(result, "dest_addr"); if (daddr) { strncpy(sms->dst.addr, daddr, sizeof(sms->dst.addr)); sms->dst.addr[sizeof(sms->dst.addr)-1] = '\0'; } + sms->receiver = subscr_get_by_extension(net, sms->dst.addr); + + sms->src.npi = dbi_result_get_uint(result, "src_npi"); + sms->src.ton = dbi_result_get_uint(result, "src_ton"); + saddr = dbi_result_get_string(result, "src_addr"); + if (saddr) { + strncpy(sms->src.addr, saddr, sizeof(sms->src.addr)); + sms->src.addr[sizeof(sms->src.addr)-1] = '\0'; + } sms->user_data_len = dbi_result_get_field_length(result, "user_data"); user_data = dbi_result_get_binary(result, "user_data"); @@ -1344,7 +1524,7 @@ struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, unsigned long long mi result = dbi_conn_queryf(conn, "SELECT SMS.* " "FROM SMS JOIN Subscriber ON " - "SMS.receiver_id = Subscriber.id " + "SMS.dest_addr = Subscriber.extension " "WHERE SMS.id >= %llu AND SMS.sent IS NULL " "AND Subscriber.lac > 0 " "ORDER BY SMS.id LIMIT 1", @@ -1374,10 +1554,10 @@ struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, result = dbi_conn_queryf(conn, "SELECT SMS.* " "FROM SMS JOIN Subscriber ON " - "SMS.receiver_id = Subscriber.id " - "WHERE SMS.receiver_id >= %llu AND SMS.sent IS NULL " + "SMS.dest_addr = Subscriber.extension " + "WHERE Subscriber.id >= %llu AND SMS.sent IS NULL " "AND Subscriber.lac > 0 AND SMS.deliver_attempts < %u " - "ORDER BY SMS.receiver_id, SMS.id LIMIT 1", + "ORDER BY Subscriber.id, SMS.id LIMIT 1", min_subscr_id, failed); if (!result) return NULL; @@ -1403,8 +1583,8 @@ struct gsm_sms *db_sms_get_unsent_for_subscr(struct gsm_subscriber *subscr) result = dbi_conn_queryf(conn, "SELECT SMS.* " "FROM SMS JOIN Subscriber ON " - "SMS.receiver_id = Subscriber.id " - "WHERE SMS.receiver_id = %llu AND SMS.sent IS NULL " + "SMS.dest_addr = Subscriber.extension " + "WHERE Subscriber.id = %llu AND SMS.sent IS NULL " "AND Subscriber.lac > 0 " "ORDER BY SMS.id LIMIT 1", subscr->id); diff --git a/openbsc/src/libmsc/gsm_04_11.c b/openbsc/src/libmsc/gsm_04_11.c index 5f107599d..b2100d8b5 100644 --- a/openbsc/src/libmsc/gsm_04_11.c +++ b/openbsc/src/libmsc/gsm_04_11.c @@ -73,8 +73,6 @@ struct gsm_sms *sms_alloc(void) void sms_free(struct gsm_sms *sms) { /* drop references to subscriber structure */ - if (sms->sender) - subscr_put(sms->sender); if (sms->receiver) subscr_put(sms->receiver); #ifdef BUILD_SMPP @@ -97,8 +95,7 @@ struct gsm_sms *sms_from_text(struct gsm_subscriber *receiver, sms->receiver = subscr_get(receiver); strncpy(sms->text, text, sizeof(sms->text)-1); - sms->sender = subscr_get(sender); - strncpy(sms->src.addr, sms->sender->extension, sizeof(sms->src.addr)-1); + strncpy(sms->src.addr, sender->extension, sizeof(sms->src.addr)-1); sms->reply_path_req = 0; sms->status_rep_req = 0; sms->ud_hdr_ind = 0; @@ -378,12 +375,12 @@ static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *m } } - gsms->sender = subscr_get(conn->subscr); + strncpy(gsms->src.addr, conn->subscr->extension, sizeof(gsms->src.addr)-1); LOGP(DLSMS, LOGL_INFO, "RX SMS: Sender: %s, MTI: 0x%02x, VPF: 0x%02x, " "MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, DA: %s, " "UserDataLength: 0x%02x, UserData: \"%s\"\n", - subscr_name(gsms->sender), sms_mti, sms_vpf, gsms->msg_ref, + subscr_name(conn->subscr), sms_mti, sms_vpf, gsms->msg_ref, gsms->protocol_id, gsms->data_coding_scheme, gsms->dst.addr, gsms->user_data_len, sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text : diff --git a/openbsc/src/libmsc/smpp_openbsc.c b/openbsc/src/libmsc/smpp_openbsc.c index ab558ce9d..ec541c271 100644 --- a/openbsc/src/libmsc/smpp_openbsc.c +++ b/openbsc/src/libmsc/smpp_openbsc.c @@ -133,7 +133,6 @@ static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net, strncpy(sms->dst.addr, dest->extension, sizeof(sms->dst.addr)-1); /* fill in the source address */ - sms->sender = subscr_get_by_id(net, 1); sms->src.ton = submit->source_addr_ton; sms->src.npi = submit->source_addr_npi; strncpy(sms->src.addr, (char *)submit->source_addr, sizeof(sms->src.addr)-1); @@ -475,13 +474,13 @@ static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms, deliver.source_addr_npi = NPI_Land_Mobile_E212; snprintf((char *)deliver.source_addr, sizeof(deliver.source_addr), "%s", - sms->sender->imsi); + conn->subscr->imsi); } 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", - sms->sender->extension); + conn->subscr->extension); } deliver.dest_addr_ton = sms->dst.ton; diff --git a/openbsc/tests/db/Makefile.am b/openbsc/tests/db/Makefile.am index 26ea70345..647b51991 100644 --- a/openbsc/tests/db/Makefile.am +++ b/openbsc/tests/db/Makefile.am @@ -2,7 +2,7 @@ AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBSMPP34_CFLAGS) $(COVERAGE_CFLAGS) AM_LDFLAGS = $(COVERAGE_LDFLAGS) -EXTRA_DIST = db_test.ok +EXTRA_DIST = db_test.ok db_test.err hlr.sqlite3 noinst_PROGRAMS = db_test diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c index e117b7933..1494e77f7 100644 --- a/openbsc/tests/db/db_test.c +++ b/openbsc/tests/db/db_test.c @@ -21,6 +21,7 @@ #include <openbsc/debug.h> #include <openbsc/db.h> #include <openbsc/gsm_subscriber.h> +#include <openbsc/gsm_04_11.h> #include <osmocom/core/application.h> @@ -59,6 +60,97 @@ static struct gsm_network dummy_net; printf("Extensions do not match in %s:%d '%s' '%s'\n", \ __FUNCTION__, __LINE__, original->extension, copy->extension); \ +/* + * Create/Store a SMS and then try to load it. + */ +static void test_sms(void) +{ + int rc; + struct gsm_sms *sms; + struct gsm_subscriber *subscr; + subscr = db_get_subscriber(GSM_SUBSCRIBER_IMSI, "9993245423445"); + OSMO_ASSERT(subscr); + subscr->net = &dummy_net; + + sms = sms_alloc(); + sms->receiver = subscr_get(subscr); + + sms->src.ton = 0x23; + sms->src.npi = 0x24; + memcpy(sms->src.addr, "1234", strlen("1234") + 1); + + sms->dst.ton = 0x32; + sms->dst.npi = 0x42; + memcpy(sms->dst.addr, subscr->extension, sizeof(subscr->extension)); + + memcpy(sms->text, "Text123", strlen("Text123") + 1); + memcpy(sms->user_data, "UserData123", strlen("UserData123") + 1); + sms->user_data_len = strlen("UserData123"); + + /* random values */ + sms->reply_path_req = 1; + sms->status_rep_req = 2; + sms->ud_hdr_ind = 3; + sms->protocol_id = 4; + sms->data_coding_scheme = 5; + + rc = db_sms_store(sms); + sms_free(sms); + OSMO_ASSERT(rc == 0); + + /* now query */ + sms = db_sms_get_unsent_for_subscr(subscr); + OSMO_ASSERT(sms); + OSMO_ASSERT(sms->receiver == subscr); + OSMO_ASSERT(sms->reply_path_req == 1); + OSMO_ASSERT(sms->status_rep_req == 2); + OSMO_ASSERT(sms->ud_hdr_ind == 3); + OSMO_ASSERT(sms->protocol_id == 4); + OSMO_ASSERT(sms->data_coding_scheme == 5); + OSMO_ASSERT(sms->src.ton == 0x23); + OSMO_ASSERT(sms->src.npi == 0x24); + OSMO_ASSERT(sms->dst.ton == 0x32); + OSMO_ASSERT(sms->dst.npi == 0x42); + OSMO_ASSERT(strcmp((char *) sms->text, "Text123") == 0); + OSMO_ASSERT(sms->user_data_len == strlen("UserData123")); + OSMO_ASSERT(strcmp((char *) sms->user_data, "UserData123") == 0); + + subscr_put(subscr); +} + +static void test_sms_migrate(void) +{ + struct gsm_subscriber *rcv_subscr; + struct gsm_sms *sms; + static const uint8_t user_data_1[] = { + 0x41, 0xf1, 0xd8, 0x05, 0x22, 0x96, 0xcd, 0x2e, + 0x90, 0xf1, 0xfd, 0x06, 0x00 }; + static const uint8_t user_data_2[] = { + 0x41, 0xf1, 0xd8, 0x05, 0x22, 0x96, 0xcd, 0x2e, + 0xd0, 0xf1, 0xfd, 0x06, 0x00 }; + + rcv_subscr = db_get_subscriber(GSM_SUBSCRIBER_IMSI, "901010000001111"); + rcv_subscr->net = &dummy_net; + + sms = db_sms_get(&dummy_net, 1); + OSMO_ASSERT(sms->id == 1); + OSMO_ASSERT(sms->receiver == rcv_subscr); + OSMO_ASSERT(strcmp(sms->text, "Abc. Def. Foo") == 0); + OSMO_ASSERT(sms->user_data_len == ARRAY_SIZE(user_data_1)); + OSMO_ASSERT(memcmp(sms->user_data, user_data_1, ARRAY_SIZE(user_data_1)) == 0); + sms_free(sms); + + sms = db_sms_get(&dummy_net, 2); + OSMO_ASSERT(sms->id == 2); + OSMO_ASSERT(sms->receiver == rcv_subscr); + OSMO_ASSERT(strcmp(sms->text, "Abc. Def. Goo") == 0); + OSMO_ASSERT(sms->user_data_len == ARRAY_SIZE(user_data_2)); + OSMO_ASSERT(memcmp(sms->user_data, user_data_2, ARRAY_SIZE(user_data_2)) == 0); + sms_free(sms); + + subscr_put(rcv_subscr); +} + int main() { char scratch_str[256]; @@ -142,6 +234,9 @@ int main() SUBSCR_PUT(alice_db); SUBSCR_PUT(alice); + test_sms(); + test_sms_migrate(); + db_fini(); printf("Done\n"); diff --git a/openbsc/tests/db/db_test.err b/openbsc/tests/db/db_test.err new file mode 100644 index 000000000..0a0f2f38c --- /dev/null +++ b/openbsc/tests/db/db_test.err @@ -0,0 +1,2 @@ +<000d> db.c:274 Going to migrate from revision 3 +[0;m
\ No newline at end of file diff --git a/openbsc/tests/db/hlr.sqlite3 b/openbsc/tests/db/hlr.sqlite3 Binary files differnew file mode 100644 index 000000000..e59dcdca3 --- /dev/null +++ b/openbsc/tests/db/hlr.sqlite3 diff --git a/openbsc/tests/testsuite.at b/openbsc/tests/testsuite.at index b2c551859..4465b2528 100644 --- a/openbsc/tests/testsuite.at +++ b/openbsc/tests/testsuite.at @@ -10,7 +10,9 @@ AT_CLEANUP AT_SETUP([db]) AT_KEYWORDS([db]) cat $abs_srcdir/db/db_test.ok > expout -AT_CHECK([$abs_top_builddir/tests/db/db_test], [], [expout], [ignore]) +cat $abs_srcdir/db/db_test.err > experr +cat $abs_srcdir/db/hlr.sqlite3 > hlr.sqlite3 +AT_CHECK([$abs_top_builddir/tests/db/db_test], [], [expout], [experr]) AT_CLEANUP AT_SETUP([channel]) |