Hello Holger
Here are the patches. It was necessary to rewrite your patch for task 1
because some code was missing.
Best Regards
Dennis
On 24.07.2011 20:30, Holger Hans Peter Freyther wrote:
On 07/24/2011 08:20 PM, Holger Hans Peter Freyther wrote:
On 07/24/2011 03:01 PM, Holger Hans Peter Freyther wrote:
Would you have time to work on it? Do you need a hand with it?
I am now moving to the OpenBSC part of your patch.
Hi Dennis,
do you think you could split the work into multiple patches? E.g.
1.) Fix the truncation of the message when sent from the VTY
2.) Move from id to number in the SMS Table (also bump the db version)
3.) Implement multipart SMS?
I will try to start with 1st, it would be very kind of you could work on the
other parts.
holger
>From 8f297e946a6865461f777d3a8046cd764139b112 Mon Sep 17 00:00:00 2001
From: Dennis Wehrle <[email protected]>
Date: Wed, 27 Jul 2011 15:06:55 +0200
Subject: [PATCH] sms: Kill the text field, fix the size and truncation of SMS from the VTY
---
openbsc/src/libmsc/db.c | 36 ++++++++++++++++--------------------
openbsc/src/libmsc/gsm_04_11.c | 13 +++++++------
openbsc/src/libmsc/gsm_04_80.c | 4 +++-
3 files changed, 26 insertions(+), 27 deletions(-)
diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c
index a7eeda4..75fdae0 100644
--- a/openbsc/src/libmsc/db.c
+++ b/openbsc/src/libmsc/db.c
@@ -51,7 +51,7 @@ static char *create_stmts[] = {
"INSERT OR IGNORE INTO Meta "
"(key, value) "
"VALUES "
- "('revision', '2')",
+ "('revision', '3')",
"CREATE TABLE IF NOT EXISTS Subscriber ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"created TIMESTAMP NOT NULL, "
@@ -104,9 +104,7 @@ static char *create_stmts[] = {
"ud_hdr_ind INTEGER NOT NULL, "
"dest_addr TEXT, "
"user_data BLOB, " /* TP-UD */
- /* additional data, interpreted from SMS */
- "header BLOB, " /* UD Header */
- "text TEXT " /* decoded UD after UDH */
+ "ud_length INTEGER NOT NULL "
")",
"CREATE TABLE IF NOT EXISTS VLR ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
@@ -173,7 +171,7 @@ static int check_db_revision(void)
return -EINVAL;
}
rev = dbi_result_get_string(result, "value");
- if (!rev || atoi(rev) != 2) {
+ if (!rev || atoi(rev) != 3) {
dbi_result_free(result);
return -EINVAL;
}
@@ -986,15 +984,16 @@ 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_daddr;
unsigned char *q_udata;
char *validity_timestamp = "2222-2-2";
+ uint8_t octet_len = 0;
/* FIXME: generate validity timestamp based on validity_minutes */
- dbi_conn_quote_string_copy(conn, (char *)sms->text, &q_text);
dbi_conn_quote_string_copy(conn, (char *)sms->dest_addr, &q_daddr);
- dbi_conn_quote_binary_copy(conn, sms->user_data, sms->user_data_len,
+ octet_len = gsm_get_octet_len(sms->user_data_len);
+ dbi_conn_quote_binary_copy(conn, sms->user_data, octet_len,
&q_udata);
/* FIXME: correct validity period */
result = dbi_conn_queryf(conn,
@@ -1002,15 +1001,14 @@ int db_sms_store(struct gsm_sms *sms)
"(created, sender_id, receiver_id, valid_until, "
"reply_path_req, status_rep_req, protocol_id, "
"data_coding_scheme, ud_hdr_ind, dest_addr, "
- "user_data, text) VALUES "
+ "user_data, ud_length) VALUES "
"(datetime('now'), %llu, %llu, %u, "
- "%u, %u, %u, %u, %u, %s, %s, %s)",
+ "%u, %u, %u, %u, %u, %s, %s, %u)",
sms->sender->id,
sms->receiver ? sms->receiver->id : 0, 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);
- free(q_text);
+ q_daddr, q_udata, sms->user_data_len);
free(q_daddr);
free(q_udata);
@@ -1025,8 +1023,9 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul
{
struct gsm_sms *sms = sms_alloc();
long long unsigned int sender_id, receiver_id;
- const char *text, *daddr;
+ const char *daddr;
const unsigned char *user_data;
+ int octet_len;
if (!sms)
return NULL;
@@ -1055,17 +1054,14 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul
sms->dest_addr[sizeof(sms->dest_addr)-1] = '\0';
}
- sms->user_data_len = dbi_result_get_field_length(result, "user_data");
+ sms->user_data_len = dbi_result_get_uint(result, "ud_length");
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);
+ octet_len = gsm_get_octet_len(sms->user_data_len);
+ memcpy(sms->user_data, user_data, octet_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;
}
diff --git a/openbsc/src/libmsc/gsm_04_11.c b/openbsc/src/libmsc/gsm_04_11.c
index ee7f577..07ad393 100644
--- a/openbsc/src/libmsc/gsm_04_11.c
+++ b/openbsc/src/libmsc/gsm_04_11.c
@@ -526,9 +526,8 @@ static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
/* generate TP-UD */
switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
case DCS_7BIT_DEFAULT:
- octet_len = sms->user_data_len*7/8;
- if (sms->user_data_len*7%8 != 0)
- octet_len++;
+ octet_len = gsm_get_octet_len(sms->user_data_len);
+
/* Warning, user_data_len indicates the amount of septets
* (characters), we need amount of octets occupied */
smsp = msgb_put(msg, octet_len);
@@ -559,6 +558,7 @@ static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *m
uint8_t *sms_vp;
uint8_t da_len_bytes;
uint8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
+ uint8_t octet_len;
int rc = 0;
osmo_counter_inc(conn->bts->network->stats.sms.submitted);
@@ -624,11 +624,12 @@ static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *m
}
gsms->user_data_len = *smsp++;
if (gsms->user_data_len) {
- memcpy(gsms->user_data, smsp, gsms->user_data_len);
+ octet_len = gsm_get_octet_len(gsms->user_data_len);
+ memcpy(gsms->user_data, smsp, octet_len);
switch (sms_alphabet) {
case DCS_7BIT_DEFAULT:
- gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
+ gsm_7bit_decode_hdr(gsms->text, smsp, gsms->user_data_len, gsms->ud_hdr_ind);
break;
case DCS_8BIT_DATA:
case DCS_UCS2:
@@ -646,7 +647,7 @@ static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *m
gsms->protocol_id, gsms->data_coding_scheme, gsms->dest_addr,
gsms->user_data_len,
sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
- osmo_hexdump(gsms->user_data, gsms->user_data_len));
+ osmo_hexdump(gsms->user_data, octet_len));
gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
diff --git a/openbsc/src/libmsc/gsm_04_80.c b/openbsc/src/libmsc/gsm_04_80.c
index 39738a5..c7dad43 100644
--- a/openbsc/src/libmsc/gsm_04_80.c
+++ b/openbsc/src/libmsc/gsm_04_80.c
@@ -68,12 +68,14 @@ int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn,
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh;
uint8_t *ptr8;
+ uint8_t octet_len;
int response_len;
/* First put the payload text into the message */
ptr8 = msgb_put(msg, 0);
response_len = gsm_7bit_encode(ptr8, response_text);
- msgb_put(msg, response_len);
+ octet_len = gsm_get_octet_len(response_len);
+ msgb_put(msg, octet_len);
/* Then wrap it as an Octet String */
msgb_wrap_with_TL(msg, ASN1_OCTET_STRING_TAG);
--
1.7.1
>From 73ae076f1ba6d9aec9b0c3233fc60203fdb11e0a Mon Sep 17 00:00:00 2001
From: Dennis Wehrle <[email protected]>
Date: Wed, 27 Jul 2011 15:10:41 +0200
Subject: [PATCH] SMS-Table: Change sender_id and receiver_id (each subscriber ID's) to
soure_addr and dest_addr (each subscriber extensions).
---
openbsc/src/libmsc/db.c | 64 ++++++++++++++++++++++------------------------
1 files changed, 31 insertions(+), 33 deletions(-)
diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c
index 75fdae0..a358b95 100644
--- a/openbsc/src/libmsc/db.c
+++ b/openbsc/src/libmsc/db.c
@@ -51,7 +51,7 @@ static char *create_stmts[] = {
"INSERT OR IGNORE INTO Meta "
"(key, value) "
"VALUES "
- "('revision', '3')",
+ "('revision', '4')",
"CREATE TABLE IF NOT EXISTS Subscriber ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"created TIMESTAMP NOT NULL, "
@@ -92,17 +92,16 @@ static char *create_stmts[] = {
"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 */
+ "source_addr TEXT NOT NULL, "
+ "dest_addr TEXT, "
"valid_until TIMESTAMP, "
"reply_path_req INTEGER NOT NULL, "
"status_rep_req INTEGER NOT NULL, "
"protocol_id INTEGER NOT NULL, "
"data_coding_scheme INTEGER NOT NULL, "
"ud_hdr_ind INTEGER NOT NULL, "
- "dest_addr TEXT, "
"user_data BLOB, " /* TP-UD */
"ud_length INTEGER NOT NULL "
")",
@@ -171,7 +170,7 @@ static int check_db_revision(void)
return -EINVAL;
}
rev = dbi_result_get_string(result, "value");
- if (!rev || atoi(rev) != 3) {
+ if (!rev || atoi(rev) != 4) {
dbi_result_free(result);
return -EINVAL;
}
@@ -984,13 +983,14 @@ 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_daddr;
+ char *q_saddr, *q_daddr;
unsigned char *q_udata;
char *validity_timestamp = "2222-2-2";
uint8_t octet_len = 0;
/* FIXME: generate validity timestamp based on validity_minutes */
+ dbi_conn_quote_string_copy(conn, (char *)sms->sender->extension, &q_saddr);
dbi_conn_quote_string_copy(conn, (char *)sms->dest_addr, &q_daddr);
octet_len = gsm_get_octet_len(sms->user_data_len);
dbi_conn_quote_binary_copy(conn, sms->user_data, octet_len,
@@ -998,17 +998,17 @@ int db_sms_store(struct gsm_sms *sms)
/* FIXME: correct validity period */
result = dbi_conn_queryf(conn,
"INSERT INTO SMS "
- "(created, sender_id, receiver_id, valid_until, "
- "reply_path_req, status_rep_req, protocol_id, "
- "data_coding_scheme, ud_hdr_ind, dest_addr, "
- "user_data, ud_length) VALUES "
- "(datetime('now'), %llu, %llu, %u, "
- "%u, %u, %u, %u, %u, %s, %s, %u)",
- sms->sender->id,
- sms->receiver ? sms->receiver->id : 0, validity_timestamp,
+ "(created, source_addr, dest_addr, valid_until, "
+ "reply_path_req, status_rep_req, protocol_id, "
+ "data_coding_scheme, ud_hdr_ind, "
+ "user_data, ud_length) VALUES "
+ "(datetime('now'), %s, %s, %u, "
+ "%u, %u, %u, %u, %u, %s, %u)",
+ q_saddr, q_daddr, 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, sms->user_data_len);
+ q_udata, sms->user_data_len);
+ free(q_saddr);
free(q_daddr);
free(q_udata);
@@ -1022,8 +1022,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 *daddr;
+ const char *daddr, *saddr;
const unsigned char *user_data;
int octet_len;
@@ -1032,11 +1031,16 @@ 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);
+ saddr = dbi_result_get_string(result, "source_addr");
+ sms->sender = subscr_get_by_extension(net, saddr);
+
+ daddr = dbi_result_get_string(result, "dest_addr");
+ sms->receiver = subscr_get_by_extension(net, daddr);
- receiver_id = dbi_result_get_ulonglong(result, "receiver_id");
- sms->receiver = subscr_get_by_id(net, receiver_id);
+ if (daddr) {
+ strncpy(sms->dest_addr, daddr, sizeof(sms->dest_addr));
+ sms->dest_addr[sizeof(sms->dest_addr)-1] = '\0';
+ }
/* FIXME: validity */
/* FIXME: those should all be get_uchar, but sqlite3 is braindead */
@@ -1048,12 +1052,6 @@ 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 */
- daddr = dbi_result_get_string(result, "dest_addr");
- if (daddr) {
- strncpy(sms->dest_addr, daddr, sizeof(sms->dest_addr));
- sms->dest_addr[sizeof(sms->dest_addr)-1] = '\0';
- }
-
sms->user_data_len = dbi_result_get_uint(result, "ud_length");
user_data = dbi_result_get_binary(result, "user_data");
@@ -1096,7 +1094,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",
@@ -1126,10 +1124,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 SMS.dest_addr, SMS.id LIMIT 1",
min_subscr_id, failed);
if (!result)
return NULL;
@@ -1155,8 +1153,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);
--
1.7.1
>From 8aab1f8f31275fff6a61ae580e4677543729bf05 Mon Sep 17 00:00:00 2001
From: Dennis Wehrle <[email protected]>
Date: Wed, 27 Jul 2011 15:12:36 +0200
Subject: [PATCH] Implement multipart sms from the VTY.
Therefore a new struct gsm_sms_ud_header inside the gsm_sms struct was created.
The following functions were modified / created:
- sms_from_text (gsm_04_11.c): split the text into several sms
- gsm_add_user_data_header (gsm_04_11.c): prepend the header to the user data
- _send_sms_str (vty_interface_layer3.c): store the various sms parts to the db
---
openbsc/include/openbsc/gsm_04_11.h | 5 +
openbsc/include/openbsc/gsm_data.h | 15 +++
openbsc/src/libmsc/gsm_04_11.c | 139 +++++++++++++++++++++++++---
openbsc/src/libmsc/vty_interface_layer3.c | 23 ++++--
4 files changed, 160 insertions(+), 22 deletions(-)
diff --git a/openbsc/include/openbsc/gsm_04_11.h b/openbsc/include/openbsc/gsm_04_11.h
index 2abe3e2..8a4ca7f 100644
--- a/openbsc/include/openbsc/gsm_04_11.h
+++ b/openbsc/include/openbsc/gsm_04_11.h
@@ -4,6 +4,10 @@
#include <osmocom/gsm/protocol/gsm_04_11.h>
#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */
+#define UD_LEN 140 /* Number of Bytes => 140 Bytes = 160 Septets */
+#define UD_PAYLOAD_SIZE UD_LEN * sizeof(uint8_t)
+/* Add 'plus 1' to account for the 'user data header length'-field */
+#define UD_HEADER_SIZE(x) (x+1) * sizeof(uint8_t)
/* SMS deliver PDU */
struct sms_deliver {
@@ -30,6 +34,7 @@ int gsm0411_rcv_sms(struct gsm_subscriber_connection *conn, struct msgb *msg);
struct gsm_sms *sms_alloc(void);
void sms_free(struct gsm_sms *sms);
struct gsm_sms *sms_from_text(struct gsm_subscriber *receiver, int dcs, const char *text);
+void gsm_add_user_data_header(struct gsm_sms *sms);
void _gsm411_sms_trans_free(struct gsm_trans *trans);
int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 715ff1b..bd8ab19 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -293,6 +293,20 @@ struct gsm_network {
#define SMS_HDR_SIZE 128
#define SMS_TEXT_SIZE 256
struct gsm_sms {
+ struct gsm_sms_ud_header{
+ uint8_t udh_length; /* user data header length */
+ uint8_t iei; /* information element identifier:
+ * 0 = Concatenated short messages,
+ * 8-bit reference number (see table from 03.40 section 9.2.3.24).
+ * If we use 8-bit reference number we have to use padding bits
+ */
+ uint8_t length; /* element length */
+ uint8_t parts; /* number of parts */
+ uint8_t part; /* current part */
+ uint8_t mi; /* message identifier */
+ uint8_t padding; /* filling bits */
+ } ud_header;
+
unsigned long long id;
struct gsm_subscriber *sender;
struct gsm_subscriber *receiver;
@@ -309,6 +323,7 @@ struct gsm_sms {
uint8_t user_data_len;
uint8_t user_data[SMS_TEXT_SIZE];
+ struct gsm_sms *next; /* next sms part */
char text[SMS_TEXT_SIZE];
};
diff --git a/openbsc/src/libmsc/gsm_04_11.c b/openbsc/src/libmsc/gsm_04_11.c
index 07ad393..58f1409 100644
--- a/openbsc/src/libmsc/gsm_04_11.c
+++ b/openbsc/src/libmsc/gsm_04_11.c
@@ -117,31 +117,129 @@ void sms_free(struct gsm_sms *sms)
talloc_free(sms);
}
+void gsm_add_user_data_header(struct gsm_sms *sms){
+ uint8_t *gen_user_data = calloc(UD_LEN, sizeof(uint8_t));
+
+ gen_user_data[0] = sms->ud_header.udh_length;
+ gen_user_data[1] = sms->ud_header.iei;
+ gen_user_data[2] = sms->ud_header.length;
+ gen_user_data[3] = sms->ud_header.mi;
+ gen_user_data[4] = sms->ud_header.parts;
+ gen_user_data[5] = sms->ud_header.part;
+
+ memcpy(gen_user_data + UD_HEADER_SIZE(sms->ud_header.udh_length),
+ sms->user_data, UD_PAYLOAD_SIZE - UD_HEADER_SIZE(sms->ud_header.udh_length));
+ memset(sms->user_data, 0, sizeof(sms->user_data));
+ memcpy(sms->user_data, gen_user_data, UD_PAYLOAD_SIZE);
+
+ free(gen_user_data);
+}
+
struct gsm_sms *sms_from_text(struct gsm_subscriber *receiver, int dcs, const char *text)
{
+ int sms_part = 1;
+ int start_copy = 0;
+ int end_copy = 0;
+ int copySize = 0;
+ int udh_bits = 0;
+
+ int number_of_octets;
+ int number_of_septets;
+
+ uint8_t mi = rand();
+
+ /* prepare for the worst case, every character expanding to two bytes */
+ int septet_data_max_len = strlen(text) * 2;
+ uint8_t *septet_data = calloc(septet_data_max_len, sizeof(uint8_t));
+ uint8_t *tmp_data = calloc(160, sizeof(uint8_t));
struct gsm_sms *sms = sms_alloc();
- if (!sms)
+ if (!septet_data || !tmp_data || !sms)
return NULL;
- sms->receiver = subscr_get(receiver);
- strncpy(sms->text, text, sizeof(sms->text)-1);
+ number_of_septets = gsm_septet_encode(septet_data, text);
+
+ struct gsm_sms *sms_ptr = sms;
+
+ int sms_parts = number_of_septets / 160;
+ if (number_of_septets % 160 != 0)
+ sms_parts++;
+
+ do {
+ if (sms_part < sms_parts) {
+ sms_ptr->next = sms_alloc();
+ }
+
+ sms_ptr->receiver = subscr_get(receiver);
+
+ /* FIXME: don't use ID 1 static */
+ sms_ptr->sender = subscr_get_by_id(receiver->net, 1);
+ sms_ptr->reply_path_req = 0;
+ sms_ptr->status_rep_req = 0;
+ sms_ptr->protocol_id = 0; /* implicit */
+ sms_ptr->data_coding_scheme = dcs;
+ strncpy(sms_ptr->dest_addr, receiver->extension, sizeof(sms_ptr->dest_addr)-1);
+
+ /* single sms */
+ if (sms_parts <= 1) {
+ sms_ptr->ud_hdr_ind = 0;
+ sms_ptr->user_data_len = number_of_septets;
+ number_of_octets = gsm_septets2octets(sms_ptr->user_data, septet_data, number_of_septets, 0);
+ }
+
+ /* concatenated sms */
+ if (sms_parts > 1) {
+ sms_ptr->ud_hdr_ind = 1;
+
+ /*
+ * ATM: We use a fixed UDH.
+ * Therefore we can set the udh_length,
+ * iei, length and the padding bits.
+ */
+ sms_ptr->ud_header.udh_length = 5;
+ sms_ptr->ud_header.iei = 0;
+ sms_ptr->ud_header.length = 3;
+ sms_ptr->ud_header.mi = mi;
+ sms_ptr->ud_header.part = sms_part++;
+ sms_ptr->ud_header.parts = sms_parts;
+
+ udh_bits = (sms_ptr->ud_header.udh_length + 1) * 8;
+ sms_ptr->ud_header.padding = 7 - (udh_bits % 7);
+
+ /*
+ * Copy a maximum of 153 septets (or the remaining septets).
+ * Note: The number '152' represents the 153. spetet
+ * at the 'septet_data'-array
+ */
+ end_copy = (start_copy + 152) < number_of_septets ?
+ (start_copy + 152) : (number_of_septets - 1);
+ copySize = (end_copy - start_copy) + 1;
+
+ /* don't split a 2 byte extension character */
+ if (septet_data[end_copy] == 0x1b)
+ copySize--;
+
+ memset(tmp_data, 0, 160);
+ memcpy(tmp_data, septet_data + start_copy, copySize);
+
+ /* user_data_len = copySize + ud_header_size */
+ sms_ptr->user_data_len = copySize + ((udh_bits + sms_ptr->ud_header.padding) / 7);
+
+ number_of_octets = gsm_septets2octets(sms_ptr->user_data, tmp_data, copySize, sms_ptr->ud_header.padding);
+
+ gsm_add_user_data_header(sms_ptr);
+
+ start_copy += copySize;
+ }
+ sms_ptr = sms_ptr->next;
+ } while (sms_ptr != NULL);
- /* FIXME: don't use ID 1 static */
- sms->sender = subscr_get_by_id(receiver->net, 1);
- sms->reply_path_req = 0;
- sms->status_rep_req = 0;
- sms->ud_hdr_ind = 0;
- sms->protocol_id = 0; /* implicit */
- sms->data_coding_scheme = dcs;
- strncpy(sms->dest_addr, receiver->extension, sizeof(sms->dest_addr)-1);
- /* Generate user_data */
- sms->user_data_len = gsm_7bit_encode(sms->user_data, sms->text);
+ free(tmp_data);
+ free(septet_data);
return sms;
}
-
static void send_signal(int sig_no,
struct gsm_trans *trans,
struct gsm_sms *sms,
@@ -627,6 +725,16 @@ static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *m
octet_len = gsm_get_octet_len(gsms->user_data_len);
memcpy(gsms->user_data, smsp, octet_len);
+ if (gsms->ud_hdr_ind) {
+ gsms->ud_header.udh_length = gsms->user_data[0];
+ gsms->ud_header.iei = gsms->user_data[1];
+ gsms->ud_header.length = gsms->user_data[2];
+ gsms->ud_header.mi = gsms->user_data[3];
+ gsms->ud_header.parts = gsms->user_data[4];
+ gsms->ud_header.part = gsms->user_data[5];
+ gsms->ud_header.padding = 7 - (((gsms->ud_header.udh_length + 1) * 8) % 7);
+ }
+
switch (sms_alphabet) {
case DCS_7BIT_DEFAULT:
gsm_7bit_decode_hdr(gsms->text, smsp, gsms->user_data_len, gsms->ud_hdr_ind);
@@ -642,10 +750,11 @@ static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *m
LOGP(DSMS, LOGL_INFO, "RX SMS: Sender: %s, MTI: 0x%02x, VPF: 0x%02x, "
"MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, DA: %s, "
+ "ud_hdr_ind: 0x%02x, "
"UserDataLength: 0x%02x, UserData: \"%s\"\n",
subscr_name(gsms->sender), sms_mti, sms_vpf, gsms->msg_ref,
gsms->protocol_id, gsms->data_coding_scheme, gsms->dest_addr,
- gsms->user_data_len,
+ gsms->ud_hdr_ind, gsms->user_data_len,
sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
osmo_hexdump(gsms->user_data, octet_len));
diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c
index f31f05b..57d91fa 100644
--- a/openbsc/src/libmsc/vty_interface_layer3.c
+++ b/openbsc/src/libmsc/vty_interface_layer3.c
@@ -146,16 +146,25 @@ static int _send_sms_str(struct gsm_subscriber *receiver, char *str,
struct gsm_sms *sms;
sms = sms_from_text(receiver, 0, str);
- sms->protocol_id = tp_pid;
+ struct gsm_sms *sms_ptr = sms;
- /* store in database for the queue */
- if (db_sms_store(sms) != 0) {
- LOGP(DSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
+ do {
+ sms_ptr->protocol_id = tp_pid;
+
+ if (db_sms_store(sms_ptr) != 0) {
+ LOGP(DSMS, LOGL_ERROR, "Failed to store SMS %i \\ %i in Database\n",
+ sms_ptr->ud_header.part ? sms_ptr->ud_header.part : 1,
+ sms_ptr->ud_header.parts ? sms_ptr->ud_header.parts : 1);
+ sms_free(sms_ptr);
+ return CMD_WARNING;
+ }
+
+ sms = sms_ptr;
+ sms_ptr = sms_ptr->next;
sms_free(sms);
- return CMD_WARNING;
- }
- sms_free(sms);
+ } while(sms_ptr != NULL);
+
sms_queue_trigger(receiver->net->sms_queue);
return CMD_SUCCESS;
}
--
1.7.1