summaryrefslogtreecommitdiffstats
path: root/tinySMS/src
diff options
context:
space:
mode:
authorbossiel <bossiel@yahoo.fr>2011-08-10 22:59:15 +0000
committerbossiel <bossiel@yahoo.fr>2011-08-10 22:59:15 +0000
commit1ebf5a5fcda0c9154e22ed02404fd46525a7fd9f (patch)
tree4b6214a7142ab1035cb0e47444e88af38e712421 /tinySMS/src
downloaddoubango-1.0.zip
doubango-1.0.tar.gz
Move deprecated v1.0 from trunk to branches1.0
Diffstat (limited to 'tinySMS/src')
-rw-r--r--tinySMS/src/rpdu/tsms_rpdu.c611
-rw-r--r--tinySMS/src/tpdu/tsms_tpdu_command.c275
-rw-r--r--tinySMS/src/tpdu/tsms_tpdu_deliver.c263
-rw-r--r--tinySMS/src/tpdu/tsms_tpdu_report.c284
-rw-r--r--tinySMS/src/tpdu/tsms_tpdu_status_report.c327
-rw-r--r--tinySMS/src/tpdu/tsms_tpdu_submit.c317
-rw-r--r--tinySMS/src/tsms.c453
-rw-r--r--tinySMS/src/tsms_address.c249
-rw-r--r--tinySMS/src/tsms_common.c417
-rw-r--r--tinySMS/src/tsms_packing.c343
10 files changed, 3539 insertions, 0 deletions
diff --git a/tinySMS/src/rpdu/tsms_rpdu.c b/tinySMS/src/rpdu/tsms_rpdu.c
new file mode 100644
index 0000000..c11bf40
--- /dev/null
+++ b/tinySMS/src/rpdu/tsms_rpdu.c
@@ -0,0 +1,611 @@
+/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsms_rpdu.c
+ * @brief SMS RPDU encoder/decoder as per 3GPP TS 23.011.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinysms/rpdu/tsms_rpdu.h"
+
+
+#include "tsk_debug.h"
+
+#define TSMS_ERROR_TOO_SHORT(type)\
+ TSK_DEBUG_ERROR("%s == Data too short.", type);\
+ failed = tsk_true;\
+ goto bail;
+
+/*=== RP-DATA as per 3GPP TS 24.011 section 7.3.1. ===*/
+
+/** internal function used to deserialize a RP-DATA message from binary content. */
+tsms_rpdu_message_t* _tsms_rpdu_rpdata_deserialize(const void* data, tsk_size_t size)
+{
+ /* don't need to test data and size --> already done by tsms_rpdu_message_deserialize() */
+ tsms_rpdu_data_t* self = tsms_rpdu_data_create(0x00, tsk_null, tsk_null, tsk_false);
+ tsk_bool_t failed = tsk_false;
+ const uint8_t* pdata = data;
+ const uint8_t* pend = pdata + size;
+ tsk_size_t smsc_len;
+
+ /* 3GPP TS 24.011 ==> 8.2.2 Message type indicator (MTI) */
+ TSMS_RPDU_MESSAGE(self)->mti = *pdata++;
+
+ /* 3GPP TS 24.011 ==> 8.2.3 Message reference */
+ TSMS_RPDU_MESSAGE(self)->mr = *pdata++;
+
+ /* 3GPP TS 24.011 ==> 8.2.5.1 Originator address element */
+ if(TSMS_RPDU_MESSAGE(self)->mti == tsms_rpdu_type_data_mt){
+ /* 7.3.1.1 RP DATA (Network to Mobile Station) */
+ if((self->oa = tsms_address_deserialize(pdata, (pend-pdata), tsms_addr_smsc, &smsc_len))){
+ pdata += smsc_len;
+ }
+ /* 7.3.1.2 RP DATA (Mobile Station to Network) */
+ pdata++; /* 1o */
+ }
+ else if(TSMS_RPDU_MESSAGE(self)->mti == tsms_rpdu_type_data_mo){
+ /* 7.3.1.1 RP DATA (Network to Mobile Station) */
+ pdata++; /* 1o */
+ /* 7.3.1.2 RP DATA (Mobile Station to Network) */
+ if((self->da = tsms_address_deserialize(pdata, (pend-pdata), tsms_addr_smsc, &smsc_len))){
+ pdata += smsc_len;
+ }
+ }
+ else{
+ failed = tsk_true;
+ TSK_DEBUG_ERROR("%d Not a valid RP-DATA messsage", TSMS_RPDU_MESSAGE(self)->mti);
+ goto bail;
+ }
+
+ /* 3GPP TS 24.011 ==> 8.2.5.3 RP-User data element */
+ if((pend-pdata) > 1){
+ tsk_size_t length = *pdata++; // length-indicator
+ if((length != (pend-pdata))){
+ TSK_DEBUG_WARN("Invalid length-indicator.");
+ }
+ else{
+ self->udata = tsk_buffer_create(pdata, length);
+ }
+ }
+ else{
+ TSK_DEBUG_WARN("RP-User data element is mandatory for RP-DATA messages.");
+ }
+
+
+bail:
+ if(failed){
+ TSK_OBJECT_SAFE_FREE(self);
+ }
+ return TSMS_RPDU_MESSAGE(self);
+}
+
+/** internal function used to serialize a RP-DATA message as binary content.*/
+int _tsms_rpdu_rpdata_serialize(const tsms_rpdu_message_t* _self, tsk_buffer_t* output)
+{
+ /* don't need to test output and self --> already done by tsms_rpdu_message_serialize() */
+ const tsms_rpdu_data_t* self = (const tsms_rpdu_data_t*)_self;
+
+ /* 3GPP TS 24.011 ==> 8.2.2 Message type indicator (MTI) */
+ tsk_buffer_append(output, &_self->mti, 1);
+
+ /* 3GPP TS 24.011 ==> 8.2.3 Message reference */
+ tsk_buffer_append(output, &_self->mr, 1);
+
+ /* 3GPP TS 24.011 ==> 8.2.5.1 Originator address element */
+ tsms_address_serialize(self->oa, output);
+
+ /* 3GPP TS 24.011 ==> 8.2.5.2 Destination address element */
+ tsms_address_serialize(self->da, output);
+
+ /* 3GPP TS 24.011 ==> 8.2.5.3 RP-User data element */
+ if(self->udata){
+ tsk_buffer_append(output, &self->udata->size, 1); // length-indicator
+ tsk_buffer_append(output, self->udata->data, self->udata->size);
+ }
+ else{
+ static uint8_t _1byte = 0x00;
+ tsk_buffer_append(output, &_1byte, 1); // length-indicator
+ }
+
+ return 0;
+}
+
+/**@ingroup tsms_rpdu_group
+* Creates a @a RP-DATA message.
+* @a RP-DATA messages could be sent from the Network to Mobile Station (MT) or from the Mobile Station to the Network (MO).
+* For more information, please refer to 3GPP TS 24.011 section 7.3.1.
+* @param mr @a RP-Message Reference as per 3GPP TS 24.011 section 8.2.3.
+* @param smsc The address of the SMSC. e.g. "+331253688".
+* @param tpdu A Pointer to the @a TP-Message to relay.
+* @param MobOrig Indicates whether to create a Mobile Originated @a RP-DATA message or not.
+* @retval Mobile Originated @a RP-DATA message.
+* @sa @ref tsms_rpdu_data_create_mt<br>@ref tsms_rpdu_data_create_mo
+*
+* See For more information, see @ref tsms_rpdu_group_DATA "RP-DATA".
+*/
+tsms_rpdu_data_t* tsms_rpdu_data_create(uint8_t mr, const tsms_address_string_t smsc, const tsms_tpdu_message_t* tpdu, tsk_bool_t MobOrig)
+{
+ tsms_rpdu_data_t* ret = tsk_null;
+
+ if(!(ret = tsk_object_new(tsms_rpdu_data_def_t))){
+ goto bail;
+ }
+
+ /* 3GPP TS 24.011 ==> 8.2.2 Message type indicator (MTI) */
+ TSMS_RPDU_MESSAGE(ret)->mti = MobOrig? tsms_rpdu_type_data_mo : tsms_rpdu_type_data_mt;
+
+ /* 3GPP TS 24.011 ==> 8.2.3 Message reference */
+ TSMS_RPDU_MESSAGE(ret)->mr = mr;
+
+ /* 3GPP TS 24.341 section B5 (Moblie Originated RP-DATA message)
+ The payload includes an RP-DATA message (see 3GPP TS 24.011 [8]). It includes:
+ - Address of the originating UE: this field includes the length indicator only;
+ - Address of the destination SC, which is configured in the UE; and
+ - RP-User-Data (see 3GPP TS 23.040 [3]), which includes SMS-SUBMIT as type indicator.
+ */
+
+
+ /* 3GPP TS 24.011 ==> 8.2.5.1 Originator address element */
+ if(smsc){
+ if(TSMS_RPDU_MESSAGE(ret)->mti == tsms_rpdu_type_data_mt){
+ /* 7.3.1.1 RP DATA (Network to Mobile Station) */
+ ret->oa = tsms_address_smsc_create(smsc);
+ }
+ else{
+ /* 7.3.1.2 RP DATA (Mobile Station to Network) */
+ ret->da = tsms_address_smsc_create(smsc);
+ }
+ }
+
+ /* 3GPP TS 24.011 ==> 8.2.5.3 RP-User data element */
+ if(tpdu && (ret->udata = tsk_buffer_create_null())){
+ tsms_tpdu_message_serialize(tpdu, ret->udata, MobOrig);
+ }
+
+bail:
+ return ret;
+}
+
+//
+// RP-DATA object definition
+//
+static tsk_object_t* tsms_rpdu_data_ctor(tsk_object_t * self, va_list * app)
+{
+ tsms_rpdu_data_t *rpdata = self;
+ if(rpdata){
+ TSMS_RPDU_MESSAGE(rpdata)->mti = tsms_rpdu_type_data_mo;
+ }
+ else{
+ TSK_DEBUG_ERROR("Null");
+ }
+ return self;
+}
+
+static tsk_object_t* tsms_rpdu_data_dtor(tsk_object_t * self)
+{
+ tsms_rpdu_data_t *rpdata = self;
+ if(rpdata){
+ TSK_OBJECT_SAFE_FREE(rpdata->oa);
+ TSK_OBJECT_SAFE_FREE(rpdata->da);
+ TSK_OBJECT_SAFE_FREE(rpdata->udata);
+ }
+ else{
+ TSK_DEBUG_ERROR("Null");
+ }
+
+ return self;
+}
+
+static const tsk_object_def_t tsms_rpdu_data_def_s =
+{
+ sizeof(tsms_rpdu_data_t),
+ tsms_rpdu_data_ctor,
+ tsms_rpdu_data_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tsms_rpdu_data_def_t = &tsms_rpdu_data_def_s;
+
+/*=== RP-SMMA as per 3GPP TS 24.011 section 7.3.2. ===*/
+
+/** internal function used to deserialize a RP-SMMA message from binary content. */
+tsms_rpdu_message_t* _tsms_rpdu_rpsmma_deserialize(const void* data, tsk_size_t size)
+{
+ /* don't need to test data and size --> already done by tsms_rpdu_message_deserialize() */
+ tsms_rpdu_smma_t* self = tsms_rpdu_smma_create(0);
+ const uint8_t* pdata = data;
+
+ /* 3GPP TS 24.011 ==> 8.2.2 Message type indicator (MTI) */
+ TSMS_RPDU_MESSAGE(self)->mti = *pdata++;
+
+ /* 3GPP TS 24.011 ==> 8.2.3 Message reference */
+ TSMS_RPDU_MESSAGE(self)->mr = *pdata++;
+
+ return TSMS_RPDU_MESSAGE(self);
+}
+
+/** internal function used to serialize a RP-SMMA message as binary content. */
+int _tsms_rpdu_rpsmma_serialize(const tsms_rpdu_message_t* _self, tsk_buffer_t* output)
+{
+ /* don't need to test output and self --> already done by tsms_rpdu_message_serialize() */
+ //const tsms_rpdu_smma_t* self = (const tsms_rpdu_smma_t*)_self;
+
+ /* 3GPP TS 24.011 ==> 8.2.2 Message type indicator (MTI) */
+ tsk_buffer_append(output, &_self->mti, 1);
+
+ /* 3GPP TS 24.011 ==> 8.2.3 Message reference */
+ tsk_buffer_append(output, &_self->mr, 1);
+
+ return 0;
+}
+
+/**@ingroup tsms_rpdu_group
+* Creates a @a RP-SMMA message.
+* This message is sent by the mobile station to relay a notification to the network that the mobile has memory available to receive one or more short messages.
+* For more information, please refer to 3GPP TS 24.011 section 7.3.2.
+* @param mr @a RP-Message Reference as per 3GPP TS 24.011 section 8.2.3.
+* @retval Mobile Originated @a RP-SMMA message.
+*
+* See For more information, see @ref tsms_rpdu_group_SMMA "RP-SMMA".
+*/
+tsms_rpdu_smma_t* tsms_rpdu_smma_create(uint8_t mr)
+{
+ tsms_rpdu_smma_t* ret = tsk_null;
+
+ if((ret = tsk_object_new(tsms_rpdu_smma_def_t))){
+ TSMS_RPDU_MESSAGE(ret)->mr = mr;
+ }
+ return ret;
+}
+
+//
+// RP-SMMA object definition
+//
+static tsk_object_t* tsms_rpdu_smma_ctor(tsk_object_t * self, va_list * app)
+{
+ tsms_rpdu_smma_t *smma = self;
+ if(smma){
+ TSMS_RPDU_MESSAGE(smma)->mti = tsms_rpdu_type_smma_mo;
+ }
+ else{
+ TSK_DEBUG_ERROR("Null");
+ }
+ return self;
+}
+
+static tsk_object_t* tsms_rpdu_smma_dtor(tsk_object_t * self)
+{
+ tsms_rpdu_smma_t *smma = self;
+ if(smma){
+ }
+ else{
+ TSK_DEBUG_ERROR("Null");
+ }
+
+ return self;
+}
+
+static const tsk_object_def_t tsms_rpdu_smma_def_s =
+{
+ sizeof(tsms_rpdu_smma_t),
+ tsms_rpdu_smma_ctor,
+ tsms_rpdu_smma_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tsms_rpdu_smma_def_t = &tsms_rpdu_smma_def_s;
+
+
+/*=== RP-ACK as per 3GPP TS 24.011 section 7.3.3. ===*/
+
+/** internal function used to deserialize an RP-ACK message from binary content. */
+tsms_rpdu_message_t* _tsms_rpdu_rpack_deserialize(const void* data, tsk_size_t size)
+{
+ /* don't need to test data and size --> already done by tsms_rpdu_message_deserialize() */
+ tsms_rpdu_ack_t* self = tsms_rpdu_ack_create(0, tsk_null, tsk_false);
+ const uint8_t* pdata = data;
+ const uint8_t* pend = pdata + size;
+
+ /* 3GPP TS 24.011 ==> 8.2.2 Message type indicator (MTI) */
+ TSMS_RPDU_MESSAGE(self)->mti = *pdata++;
+
+ /* 3GPP TS 24.011 ==> 8.2.3 Message reference */
+ TSMS_RPDU_MESSAGE(self)->mr = *pdata++;
+
+ /* 3GPP TS 24.011 ==> 8.2.5.3 RP-User data element */
+ if((pend-pdata) > 1){
+ tsk_size_t length;
+ /*uint8_t iei =*/ *pdata++; // IEI MUST be equal to 0x41
+ length = *pdata++; // length-indicator
+ if((length != (pend-pdata))){
+ TSK_DEBUG_WARN("Invalid length-indicator.");
+ }
+ else{
+ self->udata = tsk_buffer_create(pdata, length);
+ }
+ }
+
+ return TSMS_RPDU_MESSAGE(self);
+}
+
+/** internal function used to serialize a RP-ACK message as binary content. */
+int _tsms_rpdu_rpack_serialize(const tsms_rpdu_message_t* _self, tsk_buffer_t* output)
+{
+ /* don't need to test output and self --> already done by tsms_rpdu_message_serialize() */
+ const tsms_rpdu_ack_t* self = (const tsms_rpdu_ack_t*)_self;
+
+ /* 3GPP TS 24.011 ==> 8.2.2 Message type indicator (MTI) */
+ tsk_buffer_append(output, &_self->mti, 1);
+
+ /* 3GPP TS 24.011 ==> 8.2.3 Message reference */
+ tsk_buffer_append(output, &_self->mr, 1);
+
+ /* 3GPP TS 24.011 ==> 8.2.5.3 RP-User data element */
+ if(self->udata){
+ static uint8_t iei = 0x41;
+ tsk_buffer_append(output, &iei, 1); // IEI
+ tsk_buffer_append(output, &self->udata->size, 1); // length-indicator
+ tsk_buffer_append(output, self->udata->data, self->udata->size);
+ }
+ else{
+ static uint8_t _1byte = 0x00;
+ tsk_buffer_append(output, &_1byte, 1); // length-indicator
+ }
+
+ return 0;
+}
+
+/**@ingroup tsms_rpdu_group
+* Creates a @a RP-ACK message.
+* @a RP-ACK is sent between the MSC and the mobile station in both directions and used to relay the acknowledgement of a RP-DATA or RP-SMMA message reception.
+* For more information, please refer to 3GPP TS 24.011 section 7.3.2.3
+* @param mr @a RP-Message Reference as per 3GPP TS 24.011 section 8.2.3.
+* @param tpdu A Pointer to the @a TP-Message to include as RP-User data.
+* @param MobOrig Indicates whether to create a Mobile Originated @a RP-ACK message or not.
+* @retval Mobile Originated @a RP-ACK message.
+*
+* See For more information, see @ref tsms_rpdu_group_ACK "RP-ACK".
+*/
+tsms_rpdu_ack_t* tsms_rpdu_ack_create(uint8_t mr, const tsms_tpdu_message_t* tpdu, tsk_bool_t MobOrig)
+{
+ tsms_rpdu_ack_t* ret = tsk_null;
+
+ if(!tpdu){
+ TSK_DEBUG_WARN("TPDU for RP-ACK message is Null.");
+ }
+
+ if(!(ret = tsk_object_new(tsms_rpdu_ack_def_t))){
+ goto bail;
+ }
+
+ /* 3GPP TS 24.011 ==> 8.2.2 Message type indicator (MTI) */
+ TSMS_RPDU_MESSAGE(ret)->mti = MobOrig? tsms_rpdu_type_ack_mo : tsms_rpdu_type_ack_mt;
+
+ /* 3GPP TS 24.011 ==> 8.2.3 Message reference */
+ TSMS_RPDU_MESSAGE(ret)->mr = mr;
+
+ /* 3GPP TS 24.011 ==> 8.2.5.3 RP-User data element */
+ if(tpdu && (ret->udata = tsk_buffer_create_null())){
+ tsms_tpdu_message_serialize(tpdu, ret->udata, MobOrig);
+ }
+
+bail:
+ return ret;
+}
+
+//
+// RP-ACK object definition
+//
+static tsk_object_t* tsms_rpdu_ack_ctor(tsk_object_t * self, va_list * app)
+{
+ tsms_rpdu_ack_t *ack = self;
+ if(ack){
+ TSMS_RPDU_MESSAGE(ack)->mti = tsms_rpdu_type_ack_mo;
+ }
+ else{
+ TSK_DEBUG_ERROR("Null");
+ }
+ return self;
+}
+
+static tsk_object_t* tsms_rpdu_ack_dtor(tsk_object_t * self)
+{
+ tsms_rpdu_ack_t *ack = self;
+ if(ack){
+ TSK_OBJECT_SAFE_FREE(ack->udata);
+ }
+ else{
+ TSK_DEBUG_ERROR("Null");
+ }
+
+ return self;
+}
+
+static const tsk_object_def_t tsms_rpdu_ack_def_s =
+{
+ sizeof(tsms_rpdu_ack_t),
+ tsms_rpdu_ack_ctor,
+ tsms_rpdu_ack_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tsms_rpdu_ack_def_t = &tsms_rpdu_ack_def_s;
+
+/*=== RP-ERROR as per 3GPP TS 24.011 section 7.3.4. ===*/
+
+/** internal function used to deserialize a RP-ERROR message from binary content. */
+tsms_rpdu_message_t* _tsms_rpdu_rperror_deserialize(const void* data, tsk_size_t size)
+{
+ /* don't need to test data and size --> already done by tsms_rpdu_message_deserialize() */
+ tsms_rpdu_error_t* self = tsms_rpdu_error_create(0, tsk_null, 0, tsk_false);
+ const uint8_t* pdata = data;
+ const uint8_t* pend = pdata + size;
+ tsk_bool_t failed = tsk_false;
+ uint8_t cause_count;
+
+ /* 3GPP TS 24.011 ==> 8.2.2 Message type indicator (MTI) */
+ TSMS_RPDU_MESSAGE(self)->mti = *pdata++;
+
+ /* 3GPP TS 24.011 ==> 8.2.3 Message reference */
+ TSMS_RPDU_MESSAGE(self)->mr = *pdata++;
+
+ /* 3GPP TS 24.011 ==> 8.2.5.4 RP Cause
+ * Only 1 cause (LV)*/
+ if((cause_count = *pdata++)){
+ self->cause[0] = cause_count;
+ self->cause[1] = *pdata++;
+ if((pdata += (cause_count-1)) >= pend){
+ TSMS_ERROR_TOO_SHORT("RP-ERROR");
+ }
+ }
+
+ /* 3GPP TS 24.011 ==> 8.2.5.3 RP-User data element */
+ if((pend-pdata) > 2){
+ tsk_size_t length;
+ /*uint8_t iei =*/ *pdata++; // IEI MUST be equal to 0x41
+ length = *pdata++; // length-indicator
+ if((length != (pend-pdata))){
+ TSK_DEBUG_WARN("Invalid length-indicator.");
+ }
+ else{
+ self->udata = tsk_buffer_create(pdata, length);
+ }
+ }
+
+
+bail:
+ if(failed){
+ TSK_OBJECT_SAFE_FREE(self);
+ }
+ return TSMS_RPDU_MESSAGE(self);
+}
+
+/** internal function used to serialize a RP-ERROR message as binary content. */
+int _tsms_rpdu_rperror_serialize(const tsms_rpdu_message_t* _self, tsk_buffer_t* output)
+{
+ /* don't need to test output and self --> already done by tsms_rpdu_message_serialize() */
+ const tsms_rpdu_error_t* self = (const tsms_rpdu_error_t*)_self;
+
+ /* 3GPP TS 24.011 ==> 8.2.2 Message type indicator (MTI) */
+ tsk_buffer_append(output, &_self->mti, 1);
+
+ /* 3GPP TS 24.011 ==> 8.2.3 Message reference */
+ tsk_buffer_append(output, &_self->mr, 1);
+
+ /* 3GPP TS 24.011 ==> 8.2.5.4 RP Cause
+ * Only 1 cause (LV)*/
+ tsk_buffer_append(output, self->cause, 2);
+
+ /* 3GPP TS 24.011 ==> 8.2.5.3 RP-User data element */
+ if(self->udata){
+ static uint8_t iei = 0x41;
+ tsk_buffer_append(output, &iei, 1); // IEI
+ tsk_buffer_append(output, &self->udata->size, 1); // length-indicator
+ tsk_buffer_append(output, self->udata->data, self->udata->size);
+ }
+ else{
+ static uint8_t _1byte = 0x00;
+ tsk_buffer_append(output, &_1byte, 1); // length-indicator
+ }
+
+ return 0;
+}
+
+/**@ingroup tsms_rpdu_group
+* Creates a @a RP-ERROR message.
+* @a RP-ERROR is sent between the MSC and the mobile station in both directions and used to relay an error cause from an erroneous short message or notification transfer attempt.
+* For more information, please refer to 3GPP TS 24.011 section 7.3.2.4.
+* @param mr @a RP-Message Reference as per 3GPP TS 24.011 section 8.2.3.
+* @param tpdu A Pointer to the @a TP-Message to include as RP-User data.
+* @param cause RP-Cause value as per 3GPP TS 24.011 section 8.2.5.4.
+* @param MobOrig Indicates whether to create a Mobile Originated @a RP-ERROR message or not.
+* @retval Mobile Originated @a RP-ERROR message.
+*
+* See For more information, see @ref tsms_rpdu_group_ERROR "RP-ERROR".
+*/
+tsms_rpdu_error_t* tsms_rpdu_error_create(uint8_t mr, const tsms_tpdu_message_t* tpdu, uint8_t cause, tsk_bool_t MobOrig)
+{
+ tsms_rpdu_error_t* ret = tsk_null;
+
+ /*if(!tpdu){
+ TSK_DEBUG_WARN("TPDU for RP-ERROR message is Null.");
+ }*/
+
+ if(!(ret = tsk_object_new(tsms_rpdu_error_def_t))){
+ goto bail;
+ }
+
+ /* 3GPP TS 24.011 ==> 8.2.2 Message type indicator (MTI) */
+ TSMS_RPDU_MESSAGE(ret)->mti = MobOrig? tsms_rpdu_type_error_mo : tsms_rpdu_type_error_mt;
+
+ /* 3GPP TS 24.011 ==> 8.2.3 Message reference */
+ TSMS_RPDU_MESSAGE(ret)->mr = mr;
+
+ /* 3GPP TS 24.011 ==> 8.2.5.4 RP Cause */
+ ret->cause[0] = 1 /*len*/;
+ ret->cause[1] = cause;
+
+ /* 3GPP TS 24.011 ==> 8.2.5.3 RP-User data element */
+ if(tpdu && (ret->udata = tsk_buffer_create_null())){
+ tsms_tpdu_message_serialize(tpdu, ret->udata, MobOrig);
+ }
+
+bail:
+ return ret;
+}
+
+//
+// RP-ERROR object definition
+//
+static tsk_object_t* tsms_rpdu_error_ctor(tsk_object_t * self, va_list * app)
+{
+ tsms_rpdu_error_t *error = self;
+ if(error){
+ TSMS_RPDU_MESSAGE(error)->mti = tsms_rpdu_type_error_mo;
+ }
+ else{
+ TSK_DEBUG_ERROR("Null");
+ }
+ return self;
+}
+
+static tsk_object_t* tsms_rpdu_error_dtor(tsk_object_t * self)
+{
+ tsms_rpdu_error_t *error = self;
+ if(error){
+ TSK_OBJECT_SAFE_FREE(error->udata);
+ }
+ else{
+ TSK_DEBUG_ERROR("Null");
+ }
+
+ return self;
+}
+
+static const tsk_object_def_t tsms_rpdu_error_def_s =
+{
+ sizeof(tsms_rpdu_error_t),
+ tsms_rpdu_error_ctor,
+ tsms_rpdu_error_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tsms_rpdu_error_def_t = &tsms_rpdu_error_def_s;
+
diff --git a/tinySMS/src/tpdu/tsms_tpdu_command.c b/tinySMS/src/tpdu/tsms_tpdu_command.c
new file mode 100644
index 0000000..9b15057
--- /dev/null
+++ b/tinySMS/src/tpdu/tsms_tpdu_command.c
@@ -0,0 +1,275 @@
+/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsms_tpdu_command.c
+ * @brief SMS TPDU SMS-COMMAND message as per 3GPP TS 23.040 section 9.2.2.4.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinysms/tpdu/tsms_tpdu_command.h"
+
+#include "tsk_debug.h"
+
+#define TSMS_ERROR_TOO_SHORT()\
+ TSK_DEBUG_ERROR("SMS-COMMAND == Data too short.");\
+ failed = tsk_true;\
+ goto bail;
+
+/** internal function used to deserialse a SMS-COMMAND message from binary content. */
+tsms_tpdu_message_t* _tsms_tpdu_command_deserialize(const void* data, tsk_size_t size)
+{
+ /* You don't need to test data and test, this is an internal function called by tsms_tpdu_message_deserialize() */
+ tsms_tpdu_command_t* self = tsms_tpdu_command_create(0, tsk_null, tsk_null, 0, tsms_tpdu_cmd_rel);
+ tsk_bool_t failed = tsk_false;
+ tsk_size_t any_len;
+ const uint8_t* pdata = data;
+ const uint8_t* pend = pdata + size;
+
+ /* SMSC address */
+#if TSMS_TPDU_APPEND_SMSC
+ if(!(self->smsc = tsms_address_deserialize(data, size, tsms_addr_smsc, &any_len)) || !any_len){
+ TSK_DEBUG_ERROR("SMS-COMMAND == Failed to parse SMSC address");
+ failed = tsk_true;
+ goto bail;
+ }
+ else{
+ if((pdata += any_len) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+ }
+#endif
+
+ /* SMS-COMMAND first Octect:
+ - TP-Message-Type-Indicator(2b)
+ - TP-User-Data-Header-Indicator(1b)
+ - TP-Status-Report-Request(1b)
+
+ +----+----+----+----+----+----+----+----+
+ | |UDHI|SRR | | | | MTI |
+ +----+----+----+----+----+----+----+----+
+ */
+ TSMS_TPDU_MESSAGE(self)->mti = (*pdata & 0x03);
+ self->srr = (*pdata & 0x20)>>5,
+ self->udhi = (*pdata & 0x40)>>6;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.6 TP-Message-Reference (TP-MR)
+ * 1o */
+ self->mr = *pdata;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.9 TP-Protocol-Identifier (TP-PID)
+ * 1o */
+ TSMS_TPDU_MESSAGE(self)->pid = *pdata;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.19 TP-Command-Type (TP-CT)
+ * 1o */
+ self->ct = *pdata;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.18 TP-Message-Number (TP-MN)
+ * 1o */
+ self->mn = *pdata;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.8 TP-Destination-Address (TP-DA) */
+ if(!(self->da = tsms_address_deserialize(pdata, (pend-pdata), tsms_addr_da, &any_len)) || !any_len){
+ TSK_DEBUG_ERROR("SMS-DELIVER == Failed to parse DA address");
+ failed = tsk_true;
+ goto bail;
+ }
+ else{
+ if((pdata += any_len) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.20 TP Command Data Length (TP CDL)
+ * 1o */
+ TSMS_TPDU_MESSAGE(self)->udl = *pdata;
+ pdata++;
+
+ /* 3GPP TS 23.040 ==> 9.2.3.21 TP Command Data (TP CD) */
+ if((pend-pdata) > 0){
+ TSMS_TPDU_MESSAGE(self)->ud = tsk_buffer_create(pdata, (pend-pdata));
+ }
+
+ bail:
+ if(failed){
+ TSK_OBJECT_SAFE_FREE(self);
+ }
+ return TSMS_TPDU_MESSAGE(self);
+}
+
+/** internal function used to serialize a SMS-COMMAND message as binary content. */
+int _tsms_tpdu_command_serialize(const tsms_tpdu_command_t* self, tsk_buffer_t* output)
+{
+ uint8_t _1byte;
+
+ if(!self){
+ return -1;
+ }
+
+ /* SMSC address */
+#if TSMS_TPDU_APPEND_SMSC
+ tsms_address_serialize(self->smsc, output);
+#endif
+
+ /* SMS-COMMAND first Octect:
+ - TP-Message-Type-Indicator(2b)
+ - TP-User-Data-Header-Indicator(1b)
+ - TP-Status-Report-Request(1b)
+
+ +----+----+----+----+----+----+----+----+
+ | |UDHI|SRR | | | | MTI |
+ +----+----+----+----+----+----+----+----+
+ */
+ _1byte = (TSMS_TPDU_MESSAGE(self)->mti & 0xF3); /*2b*/
+ _1byte |=
+ /*1b*/
+ /*2b*/
+ ((uint8_t)self->srr) << 5 /*1b*/
+ | ((uint8_t)self->udhi) << 6; /*1b*/
+ tsk_buffer_append(output, &_1byte, 1);
+
+ /* 3GPP TS 23.040 ==> 9.2.3.6 TP-Message-Reference (TP-MR) */
+ tsk_buffer_append(output, &self->mr, 1); /*0-255 ==> 1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.9 TP-Protocol-Identifier (TP-PID) */
+ tsk_buffer_append(output, &TSMS_TPDU_MESSAGE(self)->pid, 1); /*1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.19 TP-Command-Type (TP-CT) */
+ tsk_buffer_append(output, &self->ct, 1); /*1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.18 TP-Message-Number (TP-MN) */
+ tsk_buffer_append(output, &self->mn, 1); /*1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.8 TP-Destination-Address (TP-DA) */
+ tsms_address_serialize(self->da, output);
+
+ /* 3GPP TS 23.040 ==> 9.2.3.20 TP Command Data Length (TP CDL) */
+ tsk_buffer_append(output, &TSMS_TPDU_MESSAGE(self)->udl, 1); /*1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.21 TP Command Data (TP CD) */
+ tsk_buffer_append(output, TSK_BUFFER_DATA(TSMS_TPDU_MESSAGE(self)->ud), TSK_BUFFER_SIZE(TSMS_TPDU_MESSAGE(self)->ud));
+
+ return 0;
+}
+
+/**@ingroup tsms_tpdu_group
+* Creates new @a SMS-COMMAND message.
+* @a SMS-COMMAND messages are used to convey commands from the MS (Mobile Station) to the SC (Service Center).<br>
+* For more information, please refer to 3GPP TS 23.040 section 9.2.2.4.
+* @param mr TP-Message-Reference (TP-MR) as per 3GPP TS 23.040 section 9.2.3.6.
+* @param smsc The address of the SMSC. e.g. "+331253688".
+* @param dest The address of the destination. e.g. "+331253688".
+* @param msg_num The message number. For more information, please refer to 3GPP TS 23.040 section 9.2.3.18 (TP-MN).
+* @param cmd The command type as per 3GPP TS 23.040 v910 section 9.2.3.19 (TP-CT).
+* @retval SMS-COMMAND message.
+*
+* See For more information, see @ref tsms_tpdu_group_COMMAND "SMS-COMMAND".
+*/
+tsms_tpdu_command_t* tsms_tpdu_command_create(uint8_t mr, const tsms_address_string_t smsc, const tsms_address_string_t dest, uint8_t msg_num, tsms_tpdu_cmd_t cmd)
+{
+ return tsk_object_new(tsms_tpdu_command_def_t, mr, smsc, dest, msg_num, cmd);
+}
+
+
+
+//=================================================================================================
+// SMS TPDU SMS-COMMAND object definition
+//
+static tsk_object_t* tsms_tpdu_command_ctor(tsk_object_t * self, va_list * app)
+{
+ tsms_tpdu_command_t *command = self;
+ if(command){
+ const char* smsc, *dest;
+ uint8_t mr, msg_num;
+ tsms_tpdu_cmd_t cmd;
+
+#if defined(__GNUC__)
+ mr = (uint8_t)va_arg(*app, unsigned);
+#else
+ mr = va_arg(*app, uint8_t);
+#endif
+
+ smsc = va_arg(*app, const char*);
+ dest = va_arg(*app, const char*);
+
+#if defined(__GNUC__)
+ msg_num = (uint8_t)va_arg(*app, unsigned);
+#else
+ msg_num = va_arg(*app, uint8_t);
+#endif
+ cmd = va_arg(*app, tsms_tpdu_cmd_t);
+
+ /* init base*/
+ tsms_tpdu_message_init(TSMS_TPDU_MESSAGE(command), tsms_tpdu_mti_command_mo);
+ /* init self */
+ command->mr = mr;
+ if(smsc){
+ command->smsc = tsms_address_smsc_create((const uint8_t*)smsc);
+ }
+ if(dest){
+ command->da = tsms_address_da_create((const uint8_t*)dest);
+ }
+ command->mn = msg_num;
+ command->ct = cmd;
+ }
+ return self;
+}
+
+static tsk_object_t* tsms_tpdu_command_dtor(tsk_object_t * self)
+{
+ tsms_tpdu_command_t *command = self;
+ if(command){
+ /*deinit base*/
+ tsms_tpdu_message_deinit(TSMS_TPDU_MESSAGE(command));
+ /*deinit self*/
+ TSK_OBJECT_SAFE_FREE(command->smsc);
+ TSK_OBJECT_SAFE_FREE(command->da);
+ }
+
+ return self;
+}
+
+static const tsk_object_def_t tsms_tpdu_command_def_s =
+{
+ sizeof(tsms_tpdu_command_t),
+ tsms_tpdu_command_ctor,
+ tsms_tpdu_command_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tsms_tpdu_command_def_t = &tsms_tpdu_command_def_s;
diff --git a/tinySMS/src/tpdu/tsms_tpdu_deliver.c b/tinySMS/src/tpdu/tsms_tpdu_deliver.c
new file mode 100644
index 0000000..d85660b
--- /dev/null
+++ b/tinySMS/src/tpdu/tsms_tpdu_deliver.c
@@ -0,0 +1,263 @@
+/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsms_tpdu_deliver.c
+ * @brief SMS TPDU SMS-DELIVER message as per 3GPP TS 23.040 section 9.2.2.1.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinysms/tpdu/tsms_tpdu_deliver.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+#include <string.h> /* memcpy */
+
+#define TSMS_ERROR_TOO_SHORT()\
+ TSK_DEBUG_ERROR("SMS-DELIVER == Data too short.");\
+ failed = tsk_true;\
+ goto bail;
+
+/** internal function used to deserialize a buffer containing a SMS-DELIVER message. */
+tsms_tpdu_message_t* _tsms_tpdu_deliver_deserialize(const void* data, tsk_size_t size)
+{
+ /* You don't need to test data and test, this is an internal function called by tsms_tpdu_message_deserialize() */
+ tsms_tpdu_deliver_t* self = tsms_tpdu_deliver_create(tsk_null, tsk_null);
+ tsk_bool_t failed = tsk_false;
+ tsk_size_t any_len;
+ const uint8_t* pdata = data;
+ const uint8_t* pend = pdata + size;
+
+ /* SMSC address */
+#if TSMS_TPDU_APPEND_SMSC
+ if(!(self->smsc = tsms_address_deserialize(data, size, tsms_addr_smsc, &any_len)) || !any_len){
+ TSK_DEBUG_ERROR("SMS-DELIVER == Failed to parse SMSC address");
+ failed = tsk_true;
+ goto bail;
+ }
+ else{
+ if((pdata += any_len) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+ }
+#endif
+
+ /* SMS-DELIVER first Octect:
+ - TP-Message-Type-Indicator(2b)
+ - TP-More-Messages-to-Send(1b)
+ - TP-Loop-Prevention(1b)
+ - TP-Reply-Path(1b)
+ - TP-User-Data-Header-Indicator(1b)
+ - TP-Status-Report-Indication(1b)
+ +----+----+----+----+----+----+----+----+
+ | RP|UDHI|SRI | |LP |MMS | MTI |
+ +----+----+----+----+----+----+----+----+
+ */
+ TSMS_TPDU_MESSAGE(self)->mti = (*pdata & 0x03);
+ self->mms = (*pdata & 0x04)>>2,
+ self->lp = (*pdata & 0x08)>>3,
+ self->sri = (*pdata & 0x20)>>5,
+ self->udhi = (*pdata & 0x40)>>6,
+ self->rp = (*pdata & 0x80)>>7;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ /* 3GPP TS 23.040 ==> TP-Originating-Address (TP-OA)*/
+ if(!(self->oa = tsms_address_deserialize(pdata, (pend-pdata), tsms_addr_oa, &any_len)) || !any_len){
+ TSK_DEBUG_ERROR("SMS-DELIVER == Failed to parse OA address");
+ failed = tsk_true;
+ goto bail;
+ }
+ else{
+ if((pdata += any_len) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.9 TP-Protocol-Identifier (TP-PID)
+ * 1o */
+ TSMS_TPDU_MESSAGE(self)->pid = *pdata;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.10 TP-Data-Coding-Scheme (TP-DCS)
+ * 1o */
+ TSMS_TPDU_MESSAGE(self)->dcs = *pdata;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ /* 3GPP TS 23.040 ==> TP-Service-Centre-Time-Stamp (TP-SCTS)
+ * 7o */
+ if((pend - pdata)<=7){
+ TSMS_ERROR_TOO_SHORT();
+ }
+ memcpy(self->scts, pdata, 7);
+ pdata += 7;
+
+
+ /* 3GPP TS 23.040 ==> 9.2.3.16 TP-User-Data-Length (TP-UDL)
+ * 1o */
+ TSMS_TPDU_MESSAGE(self)->udl = *pdata;
+ pdata++;
+
+ /* 3GPP TS 23.040 ==> 9.2.3.24 TP-User Data (TP-UD) */
+ if((pend-pdata) > 0){
+ TSMS_TPDU_MESSAGE(self)->ud = tsk_buffer_create(pdata, (pend-pdata));
+ }
+
+ bail:
+ if(failed){
+ TSK_OBJECT_SAFE_FREE(self);
+ }
+ return TSMS_TPDU_MESSAGE(self);
+}
+
+/** internal function used to serialize a SMS-DELIVER message. */
+int _tsms_tpdu_deliver_serialize(const tsms_tpdu_deliver_t* self, tsk_buffer_t* output)
+{
+ uint8_t _1byte;
+
+ if(!self){
+ return -1;
+ }
+
+/* SMSC address */
+#if TSMS_TPDU_APPEND_SMSC
+ tsms_address_serialize(self->smsc, output);
+#endif
+
+ /* SMS-DELIVER first Octect:
+ - TP-Message-Type-Indicator(2b)
+ - TP-More-Messages-to-Send(1b)
+ - TP-Loop-Prevention(1b)
+ - TP-Reply-Path(1b)
+ - TP-User-Data-Header-Indicator(1b)
+ - TP-Status-Report-Indication(1b)
+ +----+----+----+----+----+----+----+----+
+ | RP|UDHI|SRI | |LP |MMS | MTI |
+ +----+----+----+----+----+----+----+----+
+ */
+ _1byte = (TSMS_TPDU_MESSAGE(self)->mti & 0xF3); /*2b*/
+ _1byte |= ((uint8_t)self->mms) << 2 /*1b*/
+ | ((uint8_t)self->lp) << 3 /*1b*/
+ /*1b (unused)*/
+ | ((uint8_t)self->sri) << 5 /*1b*/
+ | ((uint8_t)self->udhi) << 6 /*1b*/
+ | ((uint8_t)self->rp) << 7; /*1b*/
+ tsk_buffer_append(output, &_1byte, 1);
+
+ /* 3GPP TS 23.040 ==> TP-Originating-Address (TP-OA)*/
+ tsms_address_serialize(self->oa, output);
+
+ /* 3GPP TS 23.040 ==> 9.2.3.9 TP-Protocol-Identifier (TP-PID)*/
+ tsk_buffer_append(output, &TSMS_TPDU_MESSAGE(self)->pid, 1); /*1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.10 TP-Data-Coding-Scheme (TP-DCS)*/
+ tsk_buffer_append(output, &TSMS_TPDU_MESSAGE(self)->dcs, 1); /*1o*/
+
+ /* 3GPP TS 23.040 ==> TP-Service-Centre-Time-Stamp (TP-SCTS)*/
+ tsk_buffer_append(output, self->scts, sizeof(self->scts)); /*7o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.16 TP-User-Data-Length (TP-UDL) */
+ tsk_buffer_append(output, &TSMS_TPDU_MESSAGE(self)->udl, 1); /*1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.24 TP-User Data (TP-UD) */
+ tsk_buffer_append(output, TSK_BUFFER_DATA(TSMS_TPDU_MESSAGE(self)->ud), TSK_BUFFER_SIZE(TSMS_TPDU_MESSAGE(self)->ud));
+
+ return 0;
+}
+
+/**@ingroup tsms_tpdu_group
+* Creates new @a SMS-DELIVER message.
+* @a SMS-DELIVER messages are used to convey short messages from the SC (Service Center) to the MS (Mobile Station).<br>
+* For more information, please refer to 3GPP TS 23.040 section 9.2.2.1.
+* @param smsc SMSC address. e.g. "+331253688".
+* @param orig The Originator address. e.g. "+331253688".
+* @retval SMS-DELIVER message.
+*
+* See For more information, see @ref tsms_tpdu_group_DELIVER "SMS-DELIVER".
+*/
+tsms_tpdu_deliver_t* tsms_tpdu_deliver_create(const tsms_address_string_t smsc, const tsms_address_string_t orig)
+{
+ tsms_tpdu_deliver_t* ret = tsk_null;
+
+ if(!(ret = tsk_object_new(tsms_tpdu_deliver_def_t, smsc, orig))){
+ goto bail;
+ }
+
+bail:
+ return ret;
+}
+
+//=================================================================================================
+// SMS TPDU SMS-DELIVER object definition
+//
+static tsk_object_t* tsms_tpdu_deliver_ctor(tsk_object_t * self, va_list * app)
+{
+ tsms_tpdu_deliver_t *deliver = self;
+ if(deliver){
+ const char* smsc, *orig;
+
+ smsc = va_arg(*app, const char*);
+ orig = va_arg(*app, const char*);
+
+ /* init base*/
+ tsms_tpdu_message_init(TSMS_TPDU_MESSAGE(deliver), tsms_tpdu_mti_deliver_mt);
+ /* init self */
+ deliver->mms = TSMS_TPDU_DEFAULT_MMS;
+ if(smsc){
+ deliver->smsc = tsms_address_smsc_create((const uint8_t*)smsc);
+ }
+ if(orig){
+ deliver->oa = tsms_address_oa_create((const uint8_t*)orig);
+ }
+ }
+ return self;
+}
+
+static tsk_object_t* tsms_tpdu_deliver_dtor(tsk_object_t * self)
+{
+ tsms_tpdu_deliver_t *deliver = self;
+ if(deliver){
+ /*deinit base*/
+ tsms_tpdu_message_deinit(TSMS_TPDU_MESSAGE(deliver));
+ /*deinit self*/
+ TSK_OBJECT_SAFE_FREE(deliver->oa);
+ TSK_OBJECT_SAFE_FREE(deliver->smsc);
+ }
+ return self;
+}
+
+static const tsk_object_def_t tsms_tpdu_deliver_def_s =
+{
+ sizeof(tsms_tpdu_deliver_t),
+ tsms_tpdu_deliver_ctor,
+ tsms_tpdu_deliver_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tsms_tpdu_deliver_def_t = &tsms_tpdu_deliver_def_s;
diff --git a/tinySMS/src/tpdu/tsms_tpdu_report.c b/tinySMS/src/tpdu/tsms_tpdu_report.c
new file mode 100644
index 0000000..ee03f98
--- /dev/null
+++ b/tinySMS/src/tpdu/tsms_tpdu_report.c
@@ -0,0 +1,284 @@
+/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsms_tpdu_report.c
+ * @brief SMS TPDU SMS-DELIVER-REPORT and SMS-SUBMIT-REPORT message as per 3GPP TS 23.040 section 9.2.2.1a and 9.2.2.2a.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinysms/tpdu/tsms_tpdu_report.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+#include <string.h> /* memcpy */
+
+#define TSMS_ERROR_TOO_SHORT()\
+ TSK_DEBUG_ERROR("SMS-DELIVER-REPORT/MS-SUBMIT-REPORT == Data too short.");\
+ failed = tsk_true;\
+ goto bail;
+
+tsms_tpdu_message_t* _tsms_tpdu_report_deserialize_2(const void* data, tsk_size_t size, tsk_bool_t error)
+{
+ /* You don't need to test data and test, this is an internal function called by tsms_tpdu_message_deserialize() */
+ tsms_tpdu_report_t* self = tsms_tpdu_report_create(tsk_null, tsk_false, error);
+ tsk_bool_t failed = tsk_false;
+// tsk_size_t any_len;
+ const uint8_t* pdata = data;
+ const uint8_t* pend = pdata + size;
+
+ /* SMSC address */
+#if TSMS_TPDU_APPEND_SMSC && 0
+ if(!(self->smsc = tsms_address_deserialize(data, size, tsms_addr_smsc, &any_len)) || !any_len){
+ TSK_DEBUG_ERROR("SMS-DELIVER == Failed to parse SMSC address");
+ failed = tsk_true;
+ goto bail;
+ }
+ else{
+ if((pdata += any_len) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+ }
+#endif
+
+ /* SMS-DELIVER-REPORT/MS-SUBMIT-REPORT (both ACK and ERROR) first Octect:
+ - TP-Message-Type-Indicator(2b)
+ - TP-User-Data-Header-Indication(1b)
+
+ +----+----+----+----+----+----+----+----+
+ | |UDHI| | | | | MTI |
+ +----+----+----+----+----+----+----+----+
+ */
+ TSMS_TPDU_MESSAGE(self)->mti = *pdata & 0x03;
+ self->udhi = (*pdata & 0x40)>>6;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ if(self->error){ /* FIXME ==> should comes from RP layer */
+ /* 3GPP TS 23.040 ==> 9.2.3.22 TP-Failure-Cause(TP-FCS) */
+ //tsk_buffer_append(output, &self->fcs, 1); /*0x00-0xFF ==> 1o*/
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.27 TP-Parameter-Indicator (TP-PI)
+ * 1o
+ bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0
+ Extension bit Reserved Reserved Reserved Reserved TP UDL TP DCS TP PID
+ */
+ self->pi = *pdata;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ if(TSMS_TPDU_MESSAGE(self)->mti == tsms_tpdu_mti_submit_report_mt){
+ /* 3GPP TS 23.040 ==> TP-Service-Centre-Time-Stamp (TP-SCTS)
+ * 7o */
+ if((pend - pdata)<7){
+ TSMS_ERROR_TOO_SHORT();
+ }
+ memcpy(self->scts, pdata, 7);
+ pdata += 7;
+ }
+
+ if(self->pi & 0x01){ /* bit 0 */
+ /* 3GPP TS 23.040 ==> 9.2.3.9 TP-Protocol-Identifier (TP-PID)
+ * 1o */
+ TSMS_TPDU_MESSAGE(self)->pid = *pdata;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+ }
+
+ if(self->pi & 0x02){ /* bit 1 */
+ /* 3GPP TS 23.040 ==> 9.2.3.10 TP-Data-Coding-Scheme (TP-DCS)
+ * 1o */
+ TSMS_TPDU_MESSAGE(self)->dcs = *pdata;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+ }
+
+ if(self->pi & 0x04){ /* bit 2 */
+ /* 3GPP TS 23.040 ==> 9.2.3.16 TP-User-Data-Length (TP-UDL)
+ * 1o */
+ TSMS_TPDU_MESSAGE(self)->udl = *pdata;
+ pdata++;
+
+ /* 3GPP TS 23.040 ==> 9.2.3.24 TP-User Data (TP-UD) */
+ if((pend-pdata) > 0){
+ TSMS_TPDU_MESSAGE(self)->ud = tsk_buffer_create(pdata, (pend-pdata));
+ }
+ }
+
+bail:
+ if(failed){
+ TSK_OBJECT_SAFE_FREE(self);
+ }
+ return TSMS_TPDU_MESSAGE(self);
+}
+
+tsms_tpdu_message_t* _tsms_tpdu_report_deserialize(const void* data, tsk_size_t size)
+{
+ return _tsms_tpdu_report_deserialize_2(data, size, tsk_false);
+}
+
+int _tsms_tpdu_report_serialize(const tsms_tpdu_report_t* self, tsk_buffer_t* output)
+{
+ uint8_t _1byte;
+
+ if(!self){
+ return -1;
+ }
+
+ /* SMSC address */
+#if TSMS_TPDU_APPEND_SMSC
+ tsms_address_serialize(self->smsc, output);
+#endif
+
+ /* SMS-DELIVER-REPORT/MS-SUBMIT-REPORT (both ACK and ERROR) first Octect:
+ - TP-Message-Type-Indicator(2b)
+ - TP-User-Data-Header-Indication(1b)
+
+ +----+----+----+----+----+----+----+----+
+ | |UDHI| | | | | MTI |
+ +----+----+----+----+----+----+----+----+
+ */
+ _1byte = (TSMS_TPDU_MESSAGE(self)->mti & 0xF3); /*2b*/
+ _1byte |= ((uint8_t)self->udhi) << 6; /*1b*/
+ tsk_buffer_append(output, &_1byte, 1);
+
+ if(self->error){
+ /* 3GPP TS 23.040 ==> 9.2.3.22 TP-Failure-Cause(TP-FCS) */
+ tsk_buffer_append(output, &self->fcs, 1); /*0x00-0xFF ==> 1o*/
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.27 TP-Parameter-Indicator (TP-PI)
+ bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0
+ Extension bit Reserved Reserved Reserved Reserved TP UDL TP DCS TP PID
+ As we are the serializer, we know which field should be added or not ==> append our own TP-PI field
+ */
+ _1byte = self->pi | 0x07 /* Bits 2,1 and 0 to '1' */;
+ tsk_buffer_append(output, &_1byte, 1); /* 1o*/
+
+ if(TSMS_TPDU_MESSAGE(self)->mti == tsms_tpdu_mti_submit_report_mt){
+ /* 3GPP TS 23.040 ==> TP-Service-Centre-Time-Stamp (TP-SCTS) */
+ tsk_buffer_append(output, self->scts, sizeof(self->scts)); /*7o*/
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.9 TP-Protocol-Identifier (TP-PID) */
+ tsk_buffer_append(output, &TSMS_TPDU_MESSAGE(self)->pid, 1); /*1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.10 TP-Data-Coding-Scheme (TP-DCS) */
+ tsk_buffer_append(output, &TSMS_TPDU_MESSAGE(self)->dcs, 1); /*1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.16 TP-User-Data-Length (TP-UDL) */
+ tsk_buffer_append(output, &TSMS_TPDU_MESSAGE(self)->udl, 1); /*1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.24 TP-User Data (TP-UD) */
+ tsk_buffer_append(output, TSK_BUFFER_DATA(TSMS_TPDU_MESSAGE(self)->ud), TSK_BUFFER_SIZE(TSMS_TPDU_MESSAGE(self)->ud));
+
+ return 0;
+}
+
+tsms_tpdu_report_t* tsms_tpdu_report_create(const tsms_address_string_t smsc, tsk_bool_t submit, tsk_bool_t error)
+{
+ tsms_tpdu_report_t* ret = tsk_null;
+
+ if(!(ret = tsk_object_new(tsms_tpdu_report_def_t, smsc, submit, error))){
+ goto bail;
+ }
+
+bail:
+ return ret;
+}
+
+
+int tsms_tpdu_report_set_fcs(tsms_tpdu_report_t* self, uint8_t code)
+{
+ if(self){
+ tsms_tpdu_report_t* report = self;
+ report->fcs = code;
+ return 0;
+ }
+ return -1;
+}
+
+//=================================================================================================
+// SMS TPDU SMS-DELIVER-REPORT/SMS-SUBMIT-REPORT object definition
+//
+static tsk_object_t* tsms_tpdu_report_ctor(tsk_object_t * self, va_list * app)
+{
+ tsms_tpdu_report_t *report = self;
+ if(report){
+ const char* smsc;
+ tsk_bool_t error, submit;
+
+ smsc = va_arg(*app, const char*);
+ submit = va_arg(*app, tsk_bool_t);
+ error = va_arg(*app, tsk_bool_t);
+
+ /* init base*/
+ tsms_tpdu_message_init(TSMS_TPDU_MESSAGE(report), submit?tsms_tpdu_mti_submit_report_mt
+ :tsms_tpdu_mti_deliver_report_mo);
+ /* init self */
+ if(smsc){
+ report->smsc = tsms_address_smsc_create((const uint8_t*)smsc);
+ }
+ report->error = error;
+
+ /*init self*/
+ if(report->error){
+ report->fcs = TSMS_TPDU_DEFAULT_FCS;
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Null");
+ }
+ return self;
+}
+
+static tsk_object_t* tsms_tpdu_report_dtor(tsk_object_t * self)
+{
+ tsms_tpdu_report_t *report = self;
+ if(report){
+ /*deinit base*/
+ tsms_tpdu_message_deinit(TSMS_TPDU_MESSAGE(report));
+ /*deinit self*/
+ TSK_OBJECT_SAFE_FREE(report->smsc);
+ }
+ else{
+ TSK_DEBUG_ERROR("Null");
+ }
+ return self;
+}
+
+static const tsk_object_def_t tsms_tpdu_report_def_s =
+{
+ sizeof(tsms_tpdu_report_t),
+ tsms_tpdu_report_ctor,
+ tsms_tpdu_report_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tsms_tpdu_report_def_t = &tsms_tpdu_report_def_s;
diff --git a/tinySMS/src/tpdu/tsms_tpdu_status_report.c b/tinySMS/src/tpdu/tsms_tpdu_status_report.c
new file mode 100644
index 0000000..cca4b0a
--- /dev/null
+++ b/tinySMS/src/tpdu/tsms_tpdu_status_report.c
@@ -0,0 +1,327 @@
+/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsms_tpdu_status_report.c
+ * @brief SMS TPDU SMS-STATUS-REPORT message as per 3GPP TS 23.040 section 9.2.2.3.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinysms/tpdu/tsms_tpdu_status_report.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+#include <string.h> /* memcpy */
+
+#define TSMS_ERROR_TOO_SHORT()\
+ TSK_DEBUG_ERROR("SMS-STATUS-REPORT == Data too short.");\
+ failed = tsk_true;\
+ goto bail;
+
+/** internal function used to deserialize a SMS-STATUS-REPORT message from a binary buffer. */
+tsms_tpdu_message_t* _tsms_tpdu_status_report_deserialize(const void* data, tsk_size_t size)
+{
+ /* You don't need to test data and test, this is an internal function called by tsms_tpdu_message_deserialize() */
+ tsms_tpdu_status_report_t* self = tsms_tpdu_status_report_create(0, tsk_null, tsk_null, tsms_tpdu_status_received, tsk_false);
+ tsk_bool_t failed = tsk_false;
+ tsk_size_t any_len;
+ const uint8_t* pdata = data;
+ const uint8_t* pend = pdata + size;
+
+ /* SMSC address */
+#if TSMS_TPDU_APPEND_SMSC
+ if(!(self->smsc = tsms_address_deserialize(data, size, tsms_addr_smsc, &any_len)) || !any_len){
+ TSK_DEBUG_ERROR("SMS-STATUS-REPORT == Failed to parse SMSC address");
+ failed = tsk_true;
+ goto bail;
+ }
+ else{
+ if((pdata += any_len) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+ }
+#endif
+
+ /* SMS-STATUS-REPORT first Octect:
+ - TP-Message-Type-Indicator(2b)
+ - TP-More-Messages-to-Send(1b)
+ - TP-Loop-Prevention(1b)
+ - TP-User-Data-Header-Indicator(1b)
+ - TP-Status-Report-Qualifier(1b)
+ +----+----+----+----+----+----+----+----+
+ | |UDHI| SRQ| |LP |MMS | MTI |
+ +----+----+----+----+----+----+----+----+
+ */
+ TSMS_TPDU_MESSAGE(self)->mti = *pdata & 0x03;
+ self->mms = (*pdata & 0x04)>>2,
+ self->lp = (*pdata & 0x08)>>3,
+ self->srq = (*pdata & 0x20)>>5,
+ self->udhi = (*pdata & 0x40)>>6;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.6 TP-Message-Reference (TP-MR)
+ * 1o */
+ self->mr = *pdata;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ /* 3GPP TS 23.040 ==> xxxx TP-Recipient-Address (TP-RA) */
+ if(!(self->ra = tsms_address_deserialize(pdata, (pend-pdata), tsms_addr_da, &any_len)) || !any_len){
+ TSK_DEBUG_ERROR("SMS-STATUS-REPORT == Failed to parse RA address");
+ failed = tsk_true;
+ goto bail;
+ }
+ else{
+ if((pdata += any_len) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+ }
+
+ /* 3GPP TS 23.040 ==> TP-Service-Centre-Time-Stamp (TP-SCTS)
+ * 7o */
+ if((pend - pdata)<=7){
+ TSMS_ERROR_TOO_SHORT();
+ }
+ memcpy(self->scts, pdata, 7);
+ pdata += 7;
+
+ /* 3GPP TS 23.040 ==> xxxx TP Discharge Time(TP-DT)
+ * 7o */
+ if((pend - pdata)<=7){
+ TSMS_ERROR_TOO_SHORT();
+ }
+ memcpy(self->dt, pdata, 7);
+ pdata += 7;
+
+ /* 3GPP TS 23.040 ==> 9.2.3.15 TP Status(TP-ST)
+ * 1o */
+ self->st = *pdata;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ /* 3GPP TS 23.040 ==> xxxx TP-Parameter-Indicator (TP-PI)
+ * 1o */
+ self->pi = *pdata;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.9 TP-Protocol-Identifier (TP-PID)
+ * 1o */
+ TSMS_TPDU_MESSAGE(self)->pid = *pdata;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.10 TP-Data-Coding-Scheme (TP-DCS)
+ * 1o */
+ TSMS_TPDU_MESSAGE(self)->dcs = *pdata;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.16 TP-User-Data-Length (TP-UDL)
+ * 1o */
+ TSMS_TPDU_MESSAGE(self)->udl = *pdata;
+ pdata++;
+
+ /* 3GPP TS 23.040 ==> 9.2.3.24 TP-User Data (TP-UD) */
+ if((pend-pdata) > 0){
+ TSMS_TPDU_MESSAGE(self)->ud = tsk_buffer_create(pdata, (pend-pdata));
+ }
+
+ bail:
+ if(failed){
+ TSK_OBJECT_SAFE_FREE(self);
+ }
+ return TSMS_TPDU_MESSAGE(self);
+}
+
+/* internal function used to serialize a SMS-STATUS-REPORT to binary content. */
+int _tsms_tpdu_status_report_serialize(const tsms_tpdu_status_report_t* self, tsk_buffer_t* output)
+{
+ uint8_t _1byte;
+
+ if(!self){
+ return -1;
+ }
+
+ /* SMSC address */
+#if TSMS_TPDU_APPEND_SMSC
+ tsms_address_serialize(self->smsc, output);
+#endif
+
+ /* SMS-STATUS-REPORT first Octect:
+ - TP-Message-Type-Indicator(2b)
+ - TP-More-Messages-to-Send(1b)
+ - TP-Loop-Prevention(1b)
+ - TP-User-Data-Header-Indicator(1b)
+ - TP-Status-Report-Qualifier(1b)
+ +----+----+----+----+----+----+----+----+
+ | |UDHI| SRQ| |LP |MMS | MTI |
+ +----+----+----+----+----+----+----+----+
+ */
+ _1byte = (TSMS_TPDU_MESSAGE(self)->mti & 0xF3); /*2b*/
+ _1byte |= ((uint8_t)self->mms) << 2 /*1b*/
+ | ((uint8_t)self->lp) << 3 /*1b*/
+ /*1b (unused)*/
+ | ((uint8_t)self->srq) << 5 /*1b*/
+ | ((uint8_t)self->udhi) << 6; /*1b*/
+ tsk_buffer_append(output, &_1byte, 1);
+
+ /* 3GPP TS 23.040 ==> 9.2.3.6 TP-Message-Reference (TP-MR) */
+ tsk_buffer_append(output, &self->mr, 1); /*0-255 ==> 1o*/
+
+ /* 3GPP TS 23.040 ==> xxxx TP-Recipient-Address (TP-RA) */
+ tsms_address_serialize(self->ra, output);
+
+ /* 3GPP TS 23.040 ==> TP-Service-Centre-Time-Stamp (TP-SCTS) */
+ tsk_buffer_append(output, self->scts, sizeof(self->scts)); /*7o*/
+
+ /* 3GPP TS 23.040 ==> xxxx TP Discharge Time(TP-DT) */
+ tsk_buffer_append(output, self->dt, sizeof(self->dt)); /*7o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.15 TP Status(TP-ST) */
+ tsk_buffer_append(output, &self->st, 1); /*0-255 ==> 1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.27 TP-Parameter-Indicator (TP-PI)
+ bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0
+ Extension bit Reserved Reserved Reserved Reserved TP UDL TP DCS TP PID
+ As we are the serializer, we know which field should be added or not ==> append our own TP-PI field
+ */
+ _1byte = self->pi | 0x07 /* Bits 2,1 and 0 to '1' */;
+ tsk_buffer_append(output, &_1byte, 1); /* 1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.9 TP-Protocol-Identifier (TP-PID) */
+ tsk_buffer_append(output, &TSMS_TPDU_MESSAGE(self)->pid, 1); /*1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.10 TP-Data-Coding-Scheme (TP-DCS) */
+ tsk_buffer_append(output, &TSMS_TPDU_MESSAGE(self)->dcs, 1); /*1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.16 TP-User-Data-Length (TP-UDL) */
+ tsk_buffer_append(output, &TSMS_TPDU_MESSAGE(self)->udl, 1); /*1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.24 TP-User Data (TP-UD) */
+ tsk_buffer_append(output, TSK_BUFFER_DATA(TSMS_TPDU_MESSAGE(self)->ud), TSK_BUFFER_SIZE(TSMS_TPDU_MESSAGE(self)->ud));
+
+ return 0;
+}
+
+/**@ingroup tsms_tpdu_group
+* Creates new @a SMS-STATUS-REPORT message.
+* @a SMS-STATUS-REPORT messages are used to convey status reports from the SC (Service Center) to the MS (Mobile Station).<br>
+* For more information, please refer to 3GPP TS 23.040 section 9.2.2.3.
+* @param mr TP-Message-Reference (TP-MR) as per 3GPP TS 23.040 section 9.2.3.6.
+* @param smsc The address of the SMSC. e.g. "+331253688".
+* @param recipient The address of the recipient. e.g. "+331253688".
+* @param status the status code as per 3GPP TS 23.040 v910 section 9.2.3.15 (TP-ST).
+* @param submit Indicates whether the report is for a @a SMS-SUBMIT message or not (@a SMS-COMMAND).<br>
+* See 3GPP TS 23.040 v910 section 9.2.3.26 (TP-SRQ).
+* @retval SMS-STATUS-REPORT message.
+*
+* See For more information, see @ref tsms_tpdu_group_STATUS_REPORT "SMS-STATUS-REPORT".
+*/
+tsms_tpdu_status_report_t* tsms_tpdu_status_report_create(uint8_t mr, const tsms_address_string_t smsc, const tsms_address_string_t recipient, tsms_tpdu_status_type_t status, tsk_bool_t submit)
+{
+ tsms_tpdu_status_report_t* ret = tsk_null;
+
+ if(!(ret = tsk_object_new(tsms_tpdu_status_report_def_t, mr, smsc, recipient, status))){
+ goto bail;
+ }
+
+bail:
+ return ret;
+}
+
+//=================================================================================================
+// SMS TPDU SMS-SUMBIT object definition
+//
+static tsk_object_t* tsms_tpdu_status_report_ctor(tsk_object_t * self, va_list * app)
+{
+ tsms_tpdu_status_report_t *status_report = self;
+ if(status_report){
+ const char* smsc, *recipient;
+ uint8_t mr;
+ tsms_tpdu_status_type_t status;
+ tsk_bool_t submit;
+
+#if defined(__GNUC__)
+ mr = (uint8_t)va_arg(*app, unsigned);
+#else
+ mr = va_arg(*app, uint8_t);
+#endif
+ smsc = va_arg(*app, const char*);
+ recipient = va_arg(*app, const char*);
+ status = va_arg(*app, tsms_tpdu_status_type_t);
+ submit = va_arg(*app, tsk_bool_t);
+
+ /* init base*/
+ tsms_tpdu_message_init(TSMS_TPDU_MESSAGE(status_report), tsms_tpdu_mti_status_report_mt);
+ /* init self */
+ status_report->mr = mr;
+ if(smsc){
+ status_report->smsc = tsms_address_smsc_create((const uint8_t*)smsc);
+ }
+ if(recipient){
+ status_report->ra = tsms_address_da_create((const uint8_t*)recipient);
+ }
+ status_report->st = status;
+ status_report->mms = TSMS_TPDU_DEFAULT_MMS;
+ status_report->srq = submit?0:1/*SMS-COMAND*/;
+ }
+ else{
+ TSK_DEBUG_ERROR("Null");
+ }
+ return self;
+}
+
+static tsk_object_t* tsms_tpdu_status_report_dtor(tsk_object_t * self)
+{
+ tsms_tpdu_status_report_t *status_report = self;
+ if(status_report){
+ /*deinit base*/
+ tsms_tpdu_message_deinit(TSMS_TPDU_MESSAGE(status_report));
+ /*deinit self*/
+ TSK_OBJECT_SAFE_FREE(status_report->smsc);
+ TSK_OBJECT_SAFE_FREE(status_report->ra);
+ }
+ else{
+ TSK_DEBUG_ERROR("Null");
+ }
+ return self;
+}
+
+static const tsk_object_def_t tsms_tpdu_status_report_def_s =
+{
+ sizeof(tsms_tpdu_status_report_t),
+ tsms_tpdu_status_report_ctor,
+ tsms_tpdu_status_report_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tsms_tpdu_status_report_def_t = &tsms_tpdu_status_report_def_s;
diff --git a/tinySMS/src/tpdu/tsms_tpdu_submit.c b/tinySMS/src/tpdu/tsms_tpdu_submit.c
new file mode 100644
index 0000000..3cec4d2
--- /dev/null
+++ b/tinySMS/src/tpdu/tsms_tpdu_submit.c
@@ -0,0 +1,317 @@
+/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsms_tpdu_submit.c
+ * @brief SMS TPDU SMS-SUBMIT (MO) message as per 3GPP TS 23.040 section 9.2.2.2.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinysms/tpdu/tsms_tpdu_submit.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+#include <string.h> /* memcpy */
+
+#define TSMS_ERROR_TOO_SHORT()\
+ TSK_DEBUG_ERROR("SMS-SUBMIT == Data too short.");\
+ failed = tsk_true;\
+ goto bail;
+
+/** internal function used to deserialize SMS-SUBMIT function.
+*/
+tsms_tpdu_message_t* _tsms_tpdu_submit_deserialize(const void* data, tsk_size_t size)
+{
+ /* You don't need to test data and test, this is an internal function called by tsms_tpdu_message_deserialize() */
+ tsms_tpdu_submit_t* self = tsms_tpdu_submit_create(0, tsk_null, tsk_null);
+ tsk_bool_t failed = tsk_false;
+ tsk_size_t any_len;
+ const uint8_t* pdata = data;
+ const uint8_t* pend = pdata + size;
+
+ /* SMSC address */
+#if TSMS_TPDU_APPEND_SMSC
+ if(!(self->smsc = tsms_address_deserialize(data, size, tsms_addr_smsc, &any_len)) || !any_len){
+ TSK_DEBUG_ERROR("SMS-SUBMIT == Failed to parse SMSC address");
+ failed = tsk_true;
+ goto bail;
+ }
+ else{
+ if((pdata += any_len) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+ }
+#endif
+
+ /* SMS-SUBMIT first Octect:
+ - TP-Message-Type-Indicator(2b)
+ - TP-Reject-Duplicates(1b)
+ - TP-Validity-Period-Format(1b)
+ - TP-Reply-Path(1b)
+ - TP-User-Data-Header-Indicator(1b)
+ - TP-Status-Report-Request(1b)
+
+ +----+----+----+----+----+----+----+----+
+ |RP |UDHI|SRR |VPF | RD | MTI |
+ +----+----+----+----+----+----+----+----+
+ */
+ TSMS_TPDU_MESSAGE(self)->mti = *pdata & 0x03;
+ self->rd = (*pdata & 0x04)>>2,
+ self->vpf = (*pdata & 0x18)>>3,
+ self->srr = (*pdata & 0x20)>>5,
+ self->udhi = (*pdata & 0x40)>>6,
+ self->rp = (*pdata & 0x80)>>7;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.6 TP-Message-Reference (TP-MR)
+ * 1o */
+ self->mr = *pdata;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.8 TP-Destination-Address (TP-DA) */
+ if(!(self->da = tsms_address_deserialize(pdata, (pend-pdata), tsms_addr_da, &any_len)) || !any_len){
+ TSK_DEBUG_ERROR("SMS-SUBMIT == Failed to parse DA address");
+ failed = tsk_true;
+ goto bail;
+ }
+ else{
+ if((pdata += any_len) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.9 TP-Protocol-Identifier (TP-PID)
+ * 1o */
+ TSMS_TPDU_MESSAGE(self)->pid = *pdata;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.10 TP-Data-Coding-Scheme (TP-DCS)
+ * 1o */
+ TSMS_TPDU_MESSAGE(self)->dcs = *pdata;
+ if((++pdata) >= pend){
+ TSMS_ERROR_TOO_SHORT();
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.12 TP-Validity-Period
+ * 1o for Relative format (9.2.3.12.1)
+ * 7o for Absolute format (9.2.3.12.2)
+ * 7o for Enhanced format (9.2.3.12.3)*/
+ switch(self->vpf){
+ case tsms_tpdu_vpf_relative:
+ any_len = 1; break;
+ case tsms_tpdu_vpf_enhanced:
+ case tsms_tpdu_vpf_absolute:
+ any_len = 7; break;
+ default:
+ case tsms_tpdu_vpf_not_present:
+ any_len = 0; break;
+ }
+ if((tsk_size_t)(pend-pdata) <= any_len){
+ TSMS_ERROR_TOO_SHORT();
+ }
+ memcpy(self->vp, pdata, any_len);
+ pdata += any_len;
+
+ /* 3GPP TS 23.040 ==> 9.2.3.16 TP-User-Data-Length (TP-UDL)
+ * 1o */
+ TSMS_TPDU_MESSAGE(self)->udl = *pdata;
+ pdata++;
+
+ /* 3GPP TS 23.040 ==> 9.2.3.24 TP-User Data (TP-UD) */
+ if((pend-pdata) > 0){
+ TSMS_TPDU_MESSAGE(self)->ud = tsk_buffer_create(pdata, (pend-pdata));
+ }
+
+bail:
+ if(failed){
+ TSK_OBJECT_SAFE_FREE(self);
+ }
+ return TSMS_TPDU_MESSAGE(self);
+}
+
+
+/** internal function used to serialize a SMS-SUBMIT message
+*/
+int _tsms_tpdu_submit_serialize(const tsms_tpdu_submit_t* self, tsk_buffer_t* output)
+{
+ uint8_t _1byte;
+
+ if(!self){
+ return -1;
+ }
+
+ /* SMSC address */
+#if TSMS_TPDU_APPEND_SMSC
+ tsms_address_serialize(self->smsc, output);
+#endif
+
+ /* SMS-SUBMIT first Octect:
+ - TP-Message-Type-Indicator(2b)
+ - TP-Reject-Duplicates(1b)
+ - TP-Validity-Period-Format(1b)
+ - TP-Reply-Path(1b)
+ - TP-User-Data-Header-Indicator(1b)
+ - TP-Status-Report-Request(1b)
+
+ +----+----+----+----+----+----+----+----+
+ |RP |UDHI|SRR |VPF | RD | MTI |
+ +----+----+----+----+----+----+----+----+
+ */
+ _1byte = (TSMS_TPDU_MESSAGE(self)->mti & 0xF3); /*2b*/
+ _1byte |= ((uint8_t)self->rd) << 2 /*1b*/
+ | ((uint8_t)self->vpf) << 3 /*2b*/
+ | ((uint8_t)self->srr) << 5 /*1b*/
+ | ((uint8_t)self->udhi) << 6; /*1b*/
+ tsk_buffer_append(output, &_1byte, 1);
+
+ /* 3GPP TS 23.040 ==> 9.2.3.6 TP-Message-Reference (TP-MR) */
+ tsk_buffer_append(output, &self->mr, 1); /*0-255 ==> 1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.8 TP-Destination-Address (TP-DA) */
+ tsms_address_serialize(self->da, output);
+
+ /* 3GPP TS 23.040 ==> 9.2.3.9 TP-Protocol-Identifier (TP-PID) */
+ tsk_buffer_append(output, &TSMS_TPDU_MESSAGE(self)->pid, 1); /*1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.10 TP-Data-Coding-Scheme (TP-DCS) */
+ tsk_buffer_append(output, &TSMS_TPDU_MESSAGE(self)->dcs, 1); /*1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.12 TP-Validity-Period
+ * 1o for Relative format (9.2.3.12.1)
+ * 7o for Absolute format (9.2.3.12.2)
+ * 7o for Enhanced format (9.2.3.12.3)*/
+ switch(self->vpf){
+ case tsms_tpdu_vpf_relative:
+ tsk_buffer_append(output, &self->vp, 1);
+ break;
+ case tsms_tpdu_vpf_enhanced:
+ case tsms_tpdu_vpf_absolute:
+ tsk_buffer_append(output, &self->vp, 7);
+ break;
+ default:
+ case tsms_tpdu_vpf_not_present:
+ break;
+ }
+
+ /* 3GPP TS 23.040 ==> 9.2.3.16 TP-User-Data-Length (TP-UDL) */
+ tsk_buffer_append(output, &TSMS_TPDU_MESSAGE(self)->udl, 1); /*1o*/
+
+ /* 3GPP TS 23.040 ==> 9.2.3.24 TP-User Data (TP-UD) */
+ tsk_buffer_append(output, TSK_BUFFER_DATA(TSMS_TPDU_MESSAGE(self)->ud), TSK_BUFFER_SIZE(TSMS_TPDU_MESSAGE(self)->ud));
+
+ return 0;
+}
+
+/**@ingroup tsms_tpdu_group
+* Creates new @a SMS-SUBMIT message.
+* @a SMS-SUBMIT messages are used to convey short messages from the MS (Mobile Station) to the SC (Service Center).<br>
+* For more information, please refer to 3GPP TS 23.040 section 9.2.2.2.
+* @param mr TP-Message-Reference (TP-MR) as per 3GPP TS 23.040 section 9.2.3.6.
+* @param smsc The address of the SMS. e.g. "+331253688".
+* @param dest The destination address. e.g. "+331253688".
+* @retval SMS-SUBMIT message.
+*
+* See For more information, see @ref tsms_tpdu_group_SUBMIT "SMS-SUBMIT".
+*/
+tsms_tpdu_submit_t* tsms_tpdu_submit_create(uint8_t mr, const tsms_address_string_t smsc, const tsms_address_string_t dest)
+{
+ tsms_tpdu_submit_t* ret = tsk_null;
+
+ if(!(ret = tsk_object_new(tsms_tpdu_submit_def_t, mr, smsc, dest))){
+ goto bail;
+ }
+
+bail:
+ return ret;
+}
+
+//=================================================================================================
+// SMS TPDU SMS-SUMBIT object definition
+//
+static tsk_object_t* tsms_tpdu_submit_ctor(tsk_object_t * self, va_list * app)
+{
+ tsms_tpdu_submit_t *submit = self;
+ if(submit){
+ const char* smsc, *dest;
+ uint8_t mr;
+
+#if defined(__GNUC__)
+ mr = (uint8_t)va_arg(*app, unsigned);
+#else
+ mr = va_arg(*app, uint8_t);
+#endif
+ smsc = va_arg(*app, const char*);
+ dest = va_arg(*app, const char*);
+
+ /* init base*/
+ tsms_tpdu_message_init(TSMS_TPDU_MESSAGE(submit), tsms_tpdu_mti_submit_mo);
+ /* init self */
+ submit->mr = mr;
+ if(smsc){
+ submit->smsc = tsms_address_smsc_create((const uint8_t*)smsc);
+ }
+ if(dest){
+ submit->da = tsms_address_da_create((const uint8_t*)dest);
+ }
+
+ submit->vp[0] = TSMS_TPDU_DEFAULT_VP;
+ submit->vpf = TSMS_TPDU_DEFAULT_VPF;
+ }
+ else{
+ TSK_DEBUG_ERROR("Null");
+ }
+ return self;
+}
+
+static tsk_object_t* tsms_tpdu_submit_dtor(tsk_object_t * self)
+{
+ tsms_tpdu_submit_t *submit = self;
+ if(submit){
+ /*deinit base*/
+ tsms_tpdu_message_deinit(TSMS_TPDU_MESSAGE(submit));
+ /*deinit self*/
+ TSK_OBJECT_SAFE_FREE(submit->smsc);
+ TSK_OBJECT_SAFE_FREE(submit->da);
+ }
+ else{
+ TSK_DEBUG_ERROR("Null");
+ }
+ return self;
+}
+
+static const tsk_object_def_t tsms_tpdu_submit_def_s =
+{
+ sizeof(tsms_tpdu_submit_t),
+ tsms_tpdu_submit_ctor,
+ tsms_tpdu_submit_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tsms_tpdu_submit_def_t = &tsms_tpdu_submit_def_s;
diff --git a/tinySMS/src/tsms.c b/tinySMS/src/tsms.c
new file mode 100644
index 0000000..66c1cbd
--- /dev/null
+++ b/tinySMS/src/tsms.c
@@ -0,0 +1,453 @@
+/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsms.h
+ * @brief SMS over IP Networks.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinysms/tsms.h"
+
+/** @mainpage tinySMS API Overview
+*
+* ======
+*
+* - @ref tsms_packing_group
+* - @ref tsms_tpdu_group
+* - @ref tsms_rpdu_group
+*
+* ======
+*
+*
+* <h1> 18 SMS over IP</h1>
+*
+* SMS stands for Short Message Service or Silent Messaging Service and is a communication service standardized in the GSM mobile communication system, using standardized communications protocols allowing the interchange of short text messages between mobile telephone devices.
+*
+* SMS technology has been specified by the ETSI in GSM 03.40 and 03.38 documents (3GPP TS 23.040 and 3GPP TS 23.038 respectively). These documents only describe how to use SMS over mobile networks (nothing for IP networks). The support of SMS over IP networks has been defined in 3GPP TS 24.341, which is fully implemented by doubango through tinySMS.
+*
+* In this section we will explain how to use SMS technology over IP within the IP Multimedia (IM) Core Network (CN) subsystem based on the Session Initiation Protocol (SIP) and SIP Events as defined in 3GPP TS 24.229.
+*
+*
+* @image html SMS_Architecture.png "Protocol layer overview for the Short Message Service"
+*
+* <h2>18.1 Modes</h2>
+* In real world, there are two ways to receive or send SMS messages over mobile networks: Binary (PDU) and Text mode.
+*
+* <h3>18.1.1 Text mode</h3>
+* The UE shall send the SMS as any other SIP MESSAGE request and it’s up to the IP-SM-GW to encode the payload before retransmission. This mode is out of scope because there is nothing special to do.
+*
+* <h3>18.1.2 Binary mode</h3>
+* The UE shall implement the roles of an SM-over-IP sender and an SM-over-IP receiver, according the procedures in sections 5.3.1 and 5.3.2 in 3GPP TS 24.341.
+*
+* The IMS core network shall take the role of an IP-SM-GW and support the general procedures in Section 5.3.3.1 of 3GPP TS 24.341, and the functions (answering of routing information query, and transport layer interworking) according to the procedures in Sections 5.3.3.3 and 5.3.3.4 in 3GPP TS 24.341.
+*
+* It’s up to the UE to encode the payload in binary format before sending the SMS. The payload contains a sequence of hexadecimal octets or decimal semi-octets strings encoded in binary format. The overall PDU (Protocol Data Unit) string contains some useful information (SMSC address, Service center time stamp, sender number, message reference ...) plus the actual message.
+* The message length can be up to 160 characters where each character represent 7bits [160/7bits], [140/8bits] or [70/16bits]. By default, each character represents 7bits encoded as per 3GPP TS 23.038.
+*
+* For IMS and LTE Networks, SMS messages shall be encapsulated in RPDUs (Relay Protocol Data Unit) data string as defined in 3GPP TS 24.011 section 7.3. The RPDU data is transferred from SM entity to SM entity using SIP MESSAGE requests. These SIP requests shall use the MIME type <b>"application/vnd.3gpp.sms"</b> for this purpose.
+*
+*/
+
+
+
+
+
+
+/**@defgroup tsms_tpdu_group Service provided by the SM-TL (Transport)
+* The Short Message Transfer Layer (SM TL) provides a service to the Short Message Application Layer (SM AL).
+*
+* This service enables the SM AL to transfer short messages to its peer entity, receive short messages from its
+* peer entity and receive reports about earlier requests for short messages to be transferred.
+*
+* ======
+*
+* - @ref tsms_tpdu_group_SUBMIT "18.2.1 SMS-SUBMIT"
+* - @ref tsms_tpdu_group_DELIVER "18.2.2 SMS-DELIVER"
+* - @ref tsms_tpdu_group_STATUS_REPORT "18.2.3 SMS-STATUS-REPORT"
+* - @ref tsms_tpdu_group_COMMAND "18.2.4 SMS-COMMAND"
+*
+* ======
+*
+* <h2> 18.2.1 SMS-SUBMIT @anchor tsms_tpdu_group_SUBMIT </h2>
+* <i>SMS-SUBMIT</i> messages are used to convey short messages from the MS (Mobile Station) to the SC (Service Center).<br>
+* <i>SMS-SUBMIT-REPORT</i> messages are used for positive or negative acknowledgement to an <i>SMS-DELIVER</i> or <i>SMS-STATUS-REPORT</i>.
+*
+* For more information, please refer to 3GPP TS 23.040 section 9.2.2.2.
+*
+* The code below shows how to send a <i>SMS-SUBMIT</i> message from the MS to the SC (MO).
+*
+* @code
+#include "tsk.h"
+#include "tinysms.h"
+
+int ret;
+tsms_tpdu_submit_t* submit = tsk_null;
+tsk_buffer_t* buffer = tsk_null;
+char* hex;
+const char* smsc = "+331000009";
+const char* destination = "+333361234567";
+const char* short_message = "hello world";
+uint8_t mr = 0xF5;
+
+submit = tsms_tpdu_submit_create(mr, smsc, destination);
+
+// encode the user data to GSM 7-bit alphabet
+if((buffer = tsms_pack_to_7bit(short_message))){
+ ret = tsms_tpdu_submit_set_userdata(submit, buffer, tsms_alpha_7bit);
+ if((hex = tsms_tpdu_submit_tohexastring(submit))){
+ TSK_DEBUG_INFO("SMS-SUBMIT=%s", hex);
+ TSK_FREE(hex);
+ }
+ TSK_OBJECT_SAFE_FREE(buffer);
+}
+TSK_OBJECT_SAFE_FREE(submit);
+* @endcode
+*
+* The message should be sent over the network as binary content. For <i>SMS-SUBMIT</i> messages, binary serialization is performed by @ref tsms_tpdu_submit_serialize().<br>
+* The code below shows how to serialize a <i>SMS-SUBMIT</i> message as binary content.
+*
+*
+*
+* <h2>18.2.2 SMS-DELIVER @anchor tsms_tpdu_group_DELIVER</h2>
+* <i>SMS-DELIVER</i> messages are used to convey short messages from the SC (Service Center) to the MS (Mobile Station). <i>SMS-DELIVER-REPORT</i> messages are used for positive or negative acknowledgement to an <i>SMS-DELIVER</i> or <i>SMS-STATUS-REPORT</i>.<br>
+* For more information, please refer to 3GPP TS 23.040 section 9.2.2.1.<br>
+* The code below shows how to receive a <i>SMS-DELIVER</i> message, sent from the SC to the MS (MT).<br>
+*
+* @code
+#include "tsk.h"
+#include "tinysms.h"
+
+tsms_tpdu_message_t* sms_any = tsms_tpdu_message_deserialize_mt(data, size);
+if(sms_any && sms_any->mti == tsms_tpdu_mti_deliver_mt){
+ //tsms_tpdu_deliver_t* sms_deliver = TSMS_TPDU_DELIVER(sms_any); ==> Yes we can !
+ char* ascii;
+ if((ascii = tsms_tpdu_message_get_payload(sms_any))){
+ TSK_DEBUG_INFO("Message=%s", ascii);
+ TSK_FREE(ascii);
+ }
+}
+TSK_OBJECT_SAFE_FREE(sms_any);
+* @endcode
+*
+* When the MS receive a SMS-DELIVER message, it should send back a <i>SMS-DELIVER-REPORT</i> message. The code bellow shows how to send this kind of message.
+*
+* @code
+#include "tsk.h"
+#include "tinysms.h"
+
+int ret;
+tsms_tpdu_report_t* report = tsk_null;
+tsk_buffer_t* buffer = tsk_null;
+const char* smsc = "+331000009";
+tsk_bool_t isSUBMIT = tsk_false;
+tsk_bool_t isERROR = tsk_false;
+report = tsms_tpdu_report_create(smsc, isSUBMIT, isERROR);
+buffer = tsk_buffer_create_null();
+if(!(ret = tsms_tpdu_report_serialize(report, buffer))){
+//send(buffer->data, buffer->size);
+}
+TSK_OBJECT_SAFE_FREE(report);
+TSK_OBJECT_SAFE_FREE(buffer);
+* @endcode
+*
+*
+*
+* <h2>18.2.3 SMS-STATUS-REPORT @anchor tsms_tpdu_group_STATUS_REPORT</h2>
+* <i>SMS-STATUS-REPORT</i> messages are used to convey status reports from the SC (Service Center) to the MS (Mobile Station).<br>
+* For more information, please refer to 3GPP TS 23.040 section 9.2.2.3.<br>
+* The code below shows how to receive a <i>SMS-STATUS-REPORT</i> message, sent from the SC to the MS (MT).<br>
+*
+* @code
+#include "tsk.h"
+#include "tinysms.h"
+
+tsms_tpdu_message_t* sms_any = tsms_tpdu_message_deserialize_mt(buffer->data, buffer->size);
+if(sms_any && sms_any->mti == tsms_tpdu_mti_status_report_mt){
+ tsms_tpdu_status_report_t* sms_status_report = TSMS_TPDU_STATUS_REPORT(sms_any);
+ switch(sms_status_report->st){
+ case tsms_tpdu_status_received:
+ case tsms_tpdu_status_forwarded:
+ case tsms_tpdu_status_replaced:
+ // ...
+ default:
+ break;
+ }
+}
+* @endcode
+*
+*
+*
+* <h2>18.2.4 SMS-COMMAND @anchor tsms_tpdu_group_COMMAND</h2>
+* <i>SMS-COMMAND</i> messages are used to convey commands from the MS (Mobile Station) to the SC (Service Center).<br>
+* For more information, please refer to 3GPP TS 23.040 section 9.2.2.4.<br>
+* The code below shows how to send a <i>SMS-COMMAND</i> (DELETE) from the MS to the SC.<br>
+*
+* @code
+#include "tsk.h"
+#include "tinysms.h"
+
+tsms_tpdu_command_t* command = tsk_null;
+char* hex;
+tsk_buffer_t* buffer = tsk_null;
+const char* smsc = "+331000009";
+const char* destination = "+333361234567";
+uint8_t mr = 0xF5;
+uint8_t message_number = 0xF8;
+
+command = tsms_tpdu_command_create(mr, smsc, destination, message_number, tsms_tpdu_cmd_delete);
+
+if((hex = tsms_tpdu_command_tohexastring(command))){
+ TSK_DEBUG_INFO("SMS-COMMAND=%s", hex);
+ TSK_FREE(hex);
+}
+TSK_OBJECT_SAFE_FREE(command);
+* @endcode
+*
+* The message should be sent over the network as binary content. For SMS-COMMAND messages, binary serialization is performed by @ref tsms_tpdu_command_serialize().
+* The code below shows how to serialize a SMS-COMMAND message as binary content.
+* @code
+#include "tsk.h"
+#include "tinysms.h"
+
+if ((buffer = tsk_buffer_create_null())){
+ret = tsms_tpdu_command_serialize(command, buffer);
+// ret = send(socket, buffer->data, buffer->size);
+TSK_OBJECT_SAFE_FREE(buffer);
+}
+* @endcode
+* A SC receiving binary <i>SMS-COMMAND</i> message (or any other SMS-*) over the network should use @ref tsms_tpdu_message_deserialize_mo() function to deserialize the content.
+*/
+
+
+
+
+
+
+
+
+
+
+
+
+/**@defgroup tsms_rpdu_group Service provided by the SM-RL (Relay)
+*
+* The Short Message Relay Layer (SM-RL) provides a service to the Short Message Transfer Layer (SM-TL). This service enables the SM TL to send Transfer Protocol Data Units (TPDUs) to its peer entity, receive TPDUs from its peer entity and receive reports about earlier requests for TPDUs to be transferred.<br>
+*
+* For more information about how doubango provides SM-TL services, please refer to @ref tsms_tpdu_group "SM-TL".
+*
+* ======
+*
+* - @ref tsms_rpdu_group_DATA "18.3.1 RP-DATA"
+* - @ref tsms_rpdu_group_SMMA "18.3.2 RP-SMMA"
+* - @ref tsms_rpdu_group_ACK "18.3.3 RP-ACK"
+* - @ref tsms_rpdu_group_ERROR "18.3.4 RP-ERROR"
+*
+* ======
+*
+* <h2> 18.3.1 RP-DATA @anchor tsms_rpdu_group_DATA</h2>
+* <i>RP-DATA</i> messages are use to relay the TPDUs. These messages could be sent from the Network to Mobile Station (MT) or from the Mobile Station to the Network (MO).<br>
+* For more information, please refer to 3GPP TS 24.011 section 7.3.1.<br>
+* The code below shows how to send a RP-DATA message with a RP-User-Data (see 3GPP TS 23.011 section 8.2.5.3) information element which includes <i>SMS-SUBMIT</i> as type indicator (this use case comes from 3GPP TS 24.341 chapter B.5). <br>
+*
+* @code
+#include "tsk.h"
+#include "tinysms.h"
+
+int ret;
+tsk_buffer_t* buffer = tsk_null;
+tsms_tpdu_submit_t* sms_submit = tsk_null;
+tsms_rpdu_data_t* rp_data = tsk_null;
+const char* smsc = "+331000009";
+const char* destination = "+333361234567";
+const char* short_message = "hello world";
+uint8_t mr = 0xF5;
+uint8_t message_number = 0xF8;
+char* hex;
+
+// create SMS-SUBMIT message
+sms_submit = tsms_tpdu_submit_create(mr, smsc, destination);
+// Set content for SMS-SUBMIT
+if((buffer = tsms_pack_to_7bit(short_message))){
+ ret = tsms_tpdu_submit_set_userdata(sms_submit, buffer, tsms_alpha_7bit);
+ TSK_OBJECT_SAFE_FREE(buffer);
+}
+// create RP-DATA(SMS-SUBMIT) message and print its content (for test only)
+rp_data = tsms_rpdu_data_create_mo(mr, smsc, TSMS_TPDU_MESSAGE(sms_submit));
+if((hex = tsms_rpdu_message_tohexastring(TSMS_RPDU_MESSAGE(rp_data)))){
+ TSK_DEBUG_INFO("RP-DATA=%s", hex);
+ TSK_FREE(hex);
+}
+
+TSK_OBJECT_SAFE_FREE(buffer);
+TSK_OBJECT_SAFE_FREE(sms_submit);
+TSK_OBJECT_SAFE_FREE(rp_data);
+* @endcode
+*
+* The message should be sent over the network as binary content. For <i>RP-DATA</i> messages, binary serialization is performed by @ref tsms_rpdu_data_serialize().<br>
+* The code below shows how to serialize a <i>RP-DATA</i> message as binary content.<br>
+* @code
+#include "tsk.h"
+#include "tinysms.h"
+
+if ((buffer = tsk_buffer_create_null())){
+ret = tsms_rpdu_data_serialize(rp_data, buffer);
+// ret = send(socket, buffer->data, buffer->size);
+TSK_OBJECT_SAFE_FREE(buffer);
+}
+* @endcode
+*
+* A SC receiving binary <i>RP-DATA</i> message (or any other <i>RP-*</i>) from the network should use tsms_rpdu_message_deserialize() function to deserialize the content.<br>
+* The code below shows how to receive a <i>RP-DATA</i> message with a <i>RP-User-Data</i> (see 3GPP TS 23.011 section 8.2.5.3) information element which includes <i>SMS-DELIVER</i> as type indicator (this use case comes from 3GPP TS 24.341 chapter B.6). <br>
+*
+* @code
+#include "tsk.h"
+#include "tinysms.h"
+
+* tsms_rpdu_message_t* rp_message = tsk_null;
+* tsms_tpdu_message_t* tpdu = tsk_null;
+
+if(!(rp_message = tsms_rpdu_message_deserialize(data, size))){ // Deserialize RP-* Message
+ TSK_DEBUG_ERROR("Failed to deserialize the RP-MESSAGE");
+ goto bail;
+}
+
+if(rp_message->mti == tsms_rpdu_type_data_mt){ // RP-DATA from SC to MS
+ char* ascii = tsk_null;
+ tsms_rpdu_data_t* rp_data = TSMS_RPDU_DATA(rp_message);
+ if((tpdu = tsms_tpdu_message_deserialize_mt(rp_data->udata->data, rp_data->udata->size))){ //Deserialize SMS-* Message (From SC to MS)
+ if(tpdu->mti == tsms_tpdu_mti_deliver_mt){ // SMS-DELIVER from SC to MS
+ if((ascii = tsms_tpdu_message_get_payload(tpdu))){
+ TSK_DEBUG_INFO("ASCII message=%s", ascii);
+ TSK_FREE(ascii);
+ }
+ }
+ }
+}
+
+bail:
+TSK_OBJECT_SAFE_FREE(rp_message);
+TSK_OBJECT_SAFE_FREE(tpdu);
+* @endcode
+*
+*
+*
+* <h2> 18.3.2 RP-SMMA @anchor tsms_rpdu_group_SMMA</h2>
+* This message is sent by the mobile station to relay a notification to the network that the mobile has memory available to receive one or more short messages.<br>
+* For more information, please refer to 3GPP TS 24.011 section 7.3.2.<br>
+* The code below shows how to send a <i>RP-SMMA</i> message.<br>
+*
+* @code
+#include "tsk.h"
+#include "tinysms.h"
+
+int ret;
+tsk_buffer_t* buffer = tsk_null;
+tsms_rpdu_smma_t* rp_smma = tsk_null;
+uint8_t mr = 0xF5;
+
+// create RP-SMMA message
+rp_smma = tsms_rpdu_smma_create(mr);
+// serialize
+buffer = tsk_buffer_create_null();
+ret = tsms_rpdu_data_serialize(rp_smma, buffer);
+// send(socket, buffer->data, buffer->size);
+
+TSK_OBJECT_SAFE_FREE(buffer);
+TSK_OBJECT_SAFE_FREE(rp_smma);
+* @endcode
+*
+*
+*
+* <h2> 18.3.3 RP-ACK @anchor tsms_rpdu_group_ACK</h2>
+* This message is sent between the MSC and the mobile station in both directions and used to relay the acknowledgement of a <i>RP-DATA</i> or <i>RP-SMMA</i> message reception.<br>
+* For more information, please refer to 3GPP TS 24.011 section 7.3.2.3.<br>
+* The code below shows how to send a <i>RP-ACK</i> message with a <i>RP-User-Data</i> (see 3GPP TS 23.011 section 8.2.5.3) information element which includes <i>SMS-DELIVER-REPORT</i> as type indicator (this use case comes from 3GPP TS 24.341 chapter B.6 section 8). <br>
+*
+* @code
+#include "tsk.h"
+#include "tinysms.h"
+
+int ret;
+tsk_buffer_t* buffer = tsk_null;
+tsms_tpdu_report_t* sms_report = tsk_null;
+tsms_rpdu_ack_t* rp_ack= tsk_null;
+const char* smsc = "+331000000";
+tsk_bool_t isSUBMIT = tsk_false; // is SMS-DELIVER-REPORT
+tsk_bool_t isERROR = tsk_false;
+uint8_t mr = 0xF5;
+
+// create SMS-DELIVER-REPORT message
+sms_report = tsms_tpdu_report_create(smsc, isSUBMIT, isERROR);
+// create RP-ACK message (From MS to SC)
+rp_ack = tsms_rpdu_ack_create_mo(mr, TSMS_TPDU_MESSAGE(sms_report));
+// serialize
+buffer = tsk_buffer_create_null();
+if(!(ret = tsms_rpdu_data_serialize(rp_ack, buffer))){
+// send(socket, buffer->data, buffer->size);
+}
+TSK_OBJECT_SAFE_FREE(buffer);
+TSK_OBJECT_SAFE_FREE(sms_report);
+TSK_OBJECT_SAFE_FREE(rp_ack);
+
+* @endcode
+*
+*
+*
+*
+* <h2> 18.3.4 RP-ERROR @anchor tsms_rpdu_group_ERROR</h2>
+* This message is sent between the MSC and the mobile station in both directions and used to relay an error cause from an erroneous short message or notification transfer attempt.<br>
+* For more information, please refer to 3GPP TS 24.011 section7.3.2.4.<br>
+* The code below shows how to send a <i>RP-ERROR</i> message with a <i>RP-User-Data</i> (see 3GPP TS 23.011 section 8.2.5.3) information element which includes <i>SMS-DELIVER-REPORT</i> as type indicator. In this example, the error message is sent because the “call is barred”. For more information about the cause values that may be contained in an <i>RP-ERROR</i> message, please refer to 3GPP TS 24.011 section 8.2.5.4.<br>
+*
+* @code
+#include "tsk.h"
+#include "tinysms.h"
+
+int ret;
+tsk_buffer_t* buffer = tsk_null;
+tsms_tpdu_report_t* sms_report = tsk_null;
+tsms_rpdu_error_t* rp_error= tsk_null;
+tsk_bool_t isSUBMIT = tsk_false; // is SMS-DELIVER-REPORT
+tsk_bool_t isERROR = tsk_true;
+const char* smsc = "+331000000";
+uint8_t mr = 0xF5;
+
+// create SMS-DELIVER-REPORT message
+sms_report = tsms_tpdu_report_create(smsc, isSUBMIT, isERROR);
+// create RP-ERROR message
+rp_error = tsms_rpdu_error_create_mo(mr, TSMS_TPDU_MESSAGE(sms_report),
+0x0A//call barred
+);
+// serialize
+buffer = tsk_buffer_create_null();
+if(!(ret = tsms_rpdu_data_serialize(rp_error, buffer))){
+ // send(socket, buffer->data, buffer->size);
+}
+
+TSK_OBJECT_SAFE_FREE(buffer);
+TSK_OBJECT_SAFE_FREE(sms_report);
+TSK_OBJECT_SAFE_FREE(rp_error);
+
+* @endcode
+*/
diff --git a/tinySMS/src/tsms_address.c b/tinySMS/src/tsms_address.c
new file mode 100644
index 0000000..3ab5d18
--- /dev/null
+++ b/tinySMS/src/tsms_address.c
@@ -0,0 +1,249 @@
+/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsms_address.c
+ * @brief SMS address encoder/decoder.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinysms/tsms_address.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+#include <string.h>
+
+/** swaps the address from 'abcd' to 'badc'
+*/
+char* tsms_address_swap(const char* in, tsk_size_t in_len)
+{
+ tsk_size_t i;
+ char* ret = tsk_null;
+ if(tsk_strnullORempty(in)){
+ goto bail;
+ }
+ ret = tsk_calloc(in_len + 2/*\0 and trainling F*/, sizeof(uint8_t));
+
+ if(in_len>=2){
+ for(i=0; i<in_len; i+=2){
+ ret[i] = in[i+1];
+ ret[i+1] = in[i];
+ }
+ }
+
+ if(in_len & 0x01){ /* odd number? */
+ ret[i-2] = 'F';
+ ret[i-1] = in[i-2];
+ }
+
+bail:
+ return ret;
+}
+
+tsms_address_t* tsms_address_create(const tsms_address_string_t digits, tsms_address_type_t type)
+{
+ return tsk_object_new(tsms_address_def_t, digits, type);
+}
+
+tsms_address_t* tsms_address_oa_create(const tsms_address_string_t digits)
+{
+ return tsms_address_create(digits, tsms_addr_oa);
+}
+
+tsms_address_t* tsms_address_da_create(const tsms_address_string_t digits)
+{
+ return tsms_address_create(digits, tsms_addr_da);
+}
+
+tsms_address_t* tsms_address_smsc_create(const tsms_address_string_t digits)
+{
+ return tsms_address_create(digits, tsms_addr_smsc);
+}
+
+/** Serialize the address as per 3GPP TS 23.040 v910 section 9.1.2.5. */
+int tsms_address_serialize(const tsms_address_t* address, tsk_buffer_t* output)
+{
+ char* number = tsk_null;
+ tsk_size_t i, num_len/*real len*/;
+ uint8_t type_of_address;
+ if(!output){
+ return -1;
+ }
+
+ /* For more information see 3GPP TS 23.040 v910 section 9.1.2.5
+
+ 1 - Address-Length
+ 2 - Type-of-Address
+ +----+----+----+----+----+----+----+----+
+ | 1 | TON | NPI |
+ +----+----+----+----+----+----+----+----+
+ 3 - Phone number in semi octets
+ */
+ number = tsms_address_swap(address ? address->digits : tsk_null, address ? strlen(address->digits) : 0);
+
+ if(number){
+ tsk_size_t len = (address->type == tsms_addr_smsc) ?
+ ((strlen(number)/2) + 1) /* Number of octets plus 1. */
+ : strlen(address->digits); /* Number of BCD digits */
+ /* 1 - Address-Length */
+ tsk_buffer_append(output, &len, 1);
+ }
+ else{
+ /* 1 - Address-Length */
+ static uint8_t _1bytes = 0x00;
+ tsk_buffer_append(output, &_1bytes, 1);
+ goto bail; /* neither 2 nor 3 will be executed */
+ }
+
+ /* 2 - Type-of-Address */
+ type_of_address = (address->npi | (((address->ton << 4) | 0x80)));
+ tsk_buffer_append(output, &type_of_address, 1);
+ /* 3 - Phone number in semi octets (BCD digits) */
+ if(((num_len = strlen(number)))){
+ unsigned _1bytes; /* do not use neither int8_t nor uint8_t */
+ /* as number comes from swap ==> num_len not odd */
+ for(i=0; i<num_len; i+=2){
+ if(sscanf(&number[i], "%2x", &_1bytes)){ /*do not use tsk_atox(str), because str should end with '\0'.*/
+ tsk_buffer_append(output, &_1bytes, 1);
+ }
+ }
+ }
+
+bail:
+ TSK_FREE(number);
+ return 0;
+}
+
+
+tsms_address_t* tsms_address_deserialize(const void* data, tsk_size_t size, tsms_address_type_t xtype, tsk_size_t *length)
+{
+ tsms_address_t* address = tsk_null;
+ uint8_t addr_len, _1byte, i;
+ const uint8_t* pdata = data;
+ *length = 0;
+
+ if(!pdata || size<=2){
+ TSK_DEBUG_ERROR("Invalid Parameter.");
+ goto bail;
+ }
+
+ /* 1 - Address-Length */
+ addr_len = *pdata;
+ pdata++;
+
+ /*== len=0 ==*/
+ if(!addr_len){
+ address = tsms_address_create(tsk_null, xtype);
+ *length = 1;
+ goto bail;
+ }
+ /*== check validity for non-zero-length address ==*/
+ addr_len = (xtype == tsms_addr_smsc) ?
+ (addr_len - 1) /* Number of octets plus 1. */
+ : ((addr_len/2) + (addr_len%2)); /* Number of BCD digits */
+ if((tsk_size_t)(1 /*Address-Length*/ + 1 /*Type-of-Address*/ + addr_len /* digits */) >= size){
+ TSK_DEBUG_ERROR("Too short to contain an address.");
+ goto bail;
+ }
+ else{
+ address = tsms_address_create(tsk_null, xtype);
+ *length = 1 /*Address-Length*/ + 1 /*Type-of-Address*/ + addr_len /* digits */;
+ }
+
+ /* 2 - Type-of-Address
+ +----+----+----+----+----+----+----+----+
+ | 1 | TON | NPI |
+ +----+----+----+----+----+----+----+----+
+ */
+ address->ton = ((*pdata &0x70) >> 4);
+ address->npi = (*pdata &0x0F);
+ pdata++;
+
+ /* 3 - Phone number in semi octets (BCD digits) */
+ //address->digits = tsk_calloc((addr_len/2) + 1, sizeof(uint8_t));
+ for(i=0; i<addr_len; i++, pdata++){
+ _1byte = ((*pdata << 4) | (*pdata >> 4));
+ if((_1byte & 0x0F) == 0x0F){ /* ends with 'F'? */
+ _1byte = ((_1byte & 0xF0) >> 4);
+ tsk_strcat_2(&address->digits, "%.1x", _1byte);
+ }
+ else{
+ tsk_strcat_2(&address->digits, "%.2x", _1byte);
+ }
+ }
+
+bail:
+ return address;
+}
+
+//=================================================================================================
+// SMS Address object definition
+//
+static tsk_object_t* tsms_address_ctor(tsk_object_t * self, va_list * app)
+{
+ tsms_address_t *address = self;
+ if(address){
+ const char* digits = va_arg(*app, const char*);
+ address->type = va_arg(*app, tsms_address_type_t);
+
+ if(!tsk_strnullORempty(digits)){
+ if(*digits == '+'){
+ address->npi = tsms_addr_npi_isdn;
+ address->ton = tsms_addr_ton_international;
+ address->digits = tsk_strdup((digits+1));
+ }
+ else{
+ address->npi = tsms_addr_npi_national;
+ address->ton = tsms_addr_ton_national;
+ address->digits = tsk_strdup((digits));
+ }
+ }
+ else{
+ address->npi = tsms_addr_npi_unknown;
+ address->ton = tsms_addr_ton_unknown;
+ }
+
+ }
+ return self;
+}
+
+static tsk_object_t* tsms_address_dtor(tsk_object_t * self)
+{
+ tsms_address_t *address = self;
+ if(address){
+ TSK_FREE(address->digits);
+ }
+
+ return self;
+}
+
+static const tsk_object_def_t tsms_address_def_s =
+{
+ sizeof(tsms_address_t),
+ tsms_address_ctor,
+ tsms_address_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tsms_address_def_t = &tsms_address_def_s;
diff --git a/tinySMS/src/tsms_common.c b/tinySMS/src/tsms_common.c
new file mode 100644
index 0000000..c60ba18
--- /dev/null
+++ b/tinySMS/src/tsms_common.c
@@ -0,0 +1,417 @@
+/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsms_common.c
+ * @brief SMS Commons (3GPP TS 23.038 and al.).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinysms/tsms_common.h"
+
+#include "tinysms/tsms_packing.h"
+
+#include "tsk_object.h"
+#include "tsk_string.h"
+#include "tsk_debug.h"
+
+#include <string.h> /* strlen() */
+
+/* ======================== TPDU ========================
+=========================================================*/
+
+extern tsms_tpdu_message_t* _tsms_tpdu_submit_deserialize(const void* data, tsk_size_t size);
+extern tsms_tpdu_message_t* _tsms_tpdu_deliver_deserialize(const void* data, tsk_size_t size);
+extern tsms_tpdu_message_t* _tsms_tpdu_command_deserialize(const void* data, tsk_size_t size);
+extern tsms_tpdu_message_t* _tsms_tpdu_report_deserialize(const void* data, tsk_size_t size);
+extern tsms_tpdu_message_t* _tsms_tpdu_status_report_deserialize(const void* data, tsk_size_t size);
+
+extern int _tsms_tpdu_submit_serialize(const tsms_tpdu_message_t* self, tsk_buffer_t* output);
+extern int _tsms_tpdu_deliver_serialize(const tsms_tpdu_message_t* self, tsk_buffer_t* output);
+extern int _tsms_tpdu_command_serialize(const tsms_tpdu_message_t* self, tsk_buffer_t* output);
+extern int _tsms_tpdu_report_serialize(const tsms_tpdu_message_t* self, tsk_buffer_t* output);
+extern int _tsms_tpdu_status_report_serialize(const tsms_tpdu_message_t* self, tsk_buffer_t* output);
+
+int tsms_tpdu_message_init(tsms_tpdu_message_t* self, tsms_tpdu_mti_t mti)
+{
+ if(self){
+ self->MobOrig = tsk_true;
+ self->mti = mti;
+ self->pid = TSMS_TPDU_DEFAULT_PID;
+ self->dcs = TSMS_TPDU_DEFAULT_DCS;
+ return 0;
+ }
+ return -1;
+}
+
+/**@ingroup tsms_tpdu_group
+* Serialize a @a TP-Message (@a SMS-SUBMIT, @a SMS-COMMAND, @a SMS-DELIVER, ...) as binary content.
+* @param self The @a TP-Message to serialize.
+* @param output A pointer to the @a output buffer.
+* @param MobOrig Indicates whether the message is Mobile Originated or not.
+* @retval Zero if succeed and non-zero error code otherwise.
+*
+* @sa @ref tsms_tpdu_submit_serialize<br>@ref tsms_tpdu_command_serialize<br>@ref tsms_tpdu_deliver_serialize<br>@ref tsms_tpdu_report_serialize<br>@ref tsms_tpdu_status_report_serialize
+*/
+int tsms_tpdu_message_serialize(const tsms_tpdu_message_t* self, tsk_buffer_t* output, tsk_bool_t MobOrig)
+{
+ if(!self){
+ return -1;
+ }
+
+ /* 3GPP TS 23.040 - 9.2.3.1 TP Message Type Indicator (TP MTI)
+ bit1 bit0 Message type
+ 0 0 SMS-DELIVER (in the direction SC to MS)
+ 0 0 SMS-DELIVER-REPORT (in the direction MS to SC)
+ 1 0 SMS-STATUS-REPORT (in the direction SC to MS)
+ 1 0 SMS-COMMAND (in the direction MS to SC)
+ 0 1 SMS-SUBMIT (in the direction MS to SC)
+ 0 1 SMS-SUBMIT-REPORT (in the direction SC to MS)
+ 1 1 Reserved
+ */
+ if(MobOrig){ /* MO */
+ switch(self->mti){
+ case tsms_tpdu_mti_deliver_report_mo: return _tsms_tpdu_report_serialize(self, output); /* SMS-DELIVER-REPORT */
+ case tsms_tpdu_mti_command_mo: return _tsms_tpdu_command_serialize(self, output); /* SMS-COMMAND */
+ case tsms_tpdu_mti_submit_mo: return _tsms_tpdu_submit_serialize(self, output); /* SMS-SUBMIT */
+ default: return -2;
+ }
+ }
+ else{ /* MT */
+ switch(self->mti){
+ case tsms_tpdu_mti_deliver_mt: return _tsms_tpdu_deliver_serialize(self, output); /* SMS-DELIVER */
+ case tsms_tpdu_mti_status_report_mt: return _tsms_tpdu_status_report_serialize(self, output); /* SMS-STATUS-REPORT */
+ case tsms_tpdu_mti_submit_report_mt: return _tsms_tpdu_report_serialize(self, output); /* SMS-SUBMIT-REPORT */
+ default: return -2;
+ }
+ }
+}
+
+/**@ingroup tsms_tpdu_group
+* Deserialize a @a TP-Message (@a SMS-SUBMIT, @a SMS-COMMAND, @a SMS-DELIVER, ...) from binary content.
+* @param data A pointer to the binary data.
+* @param size The size of the buffer holding the binary data.
+* @param MobOrig Indicates whether the binaray content is Mobile Originated (Sent by the MS) or not.
+* @retval @ref tsms_tpdu_message_t if succeed and @a Null otherwise.
+*/
+tsms_tpdu_message_t* tsms_tpdu_message_deserialize(const void* data, tsk_size_t size, tsk_bool_t MobOrig)
+{
+ tsms_tpdu_mti_t mti;
+ uint8_t smsc_len = 0;
+ tsms_tpdu_message_t* ret = tsk_null;
+
+ if(!data || size<=1){
+ TSK_DEBUG_ERROR("Invalid parameter.");
+ return tsk_null;
+ }
+
+#if TSMS_TPDU_APPEND_SMSC
+ smsc_len = *((uint8_t*)data) + 1/* len itself*/;
+ if(smsc_len>=size){
+ TSK_DEBUG_ERROR("Too short.");
+ return tsk_null;
+ }
+#endif
+
+ mti = (*(((uint8_t*)data)+smsc_len) & 0x03);
+
+ /* 3GPP TS 23.040 - 9.2.3.1 TP Message Type Indicator (TP MTI)
+ bit1 bit0 Message type
+ 0 0 SMS-DELIVER (in the direction SC to MS)
+ 0 0 SMS-DELIVER-REPORT (in the direction MS to SC)
+ 1 0 SMS-STATUS-REPORT (in the direction SC to MS)
+ 1 0 SMS-COMMAND (in the direction MS to SC)
+ 0 1 SMS-SUBMIT (in the direction MS to SC)
+ 0 1 SMS-SUBMIT-REPORT (in the direction SC to MS)
+ 1 1 Reserved
+ */
+ if(MobOrig){ /* MO */
+ switch(mti){
+ case tsms_tpdu_mti_deliver_report_mo: ret = _tsms_tpdu_report_deserialize(data, size); break; /* SMS-DELIVER-REPORT */
+ case tsms_tpdu_mti_command_mo: ret = _tsms_tpdu_command_deserialize(data, size); break; /* SMS-COMMAND */
+ case tsms_tpdu_mti_submit_mo: ret = _tsms_tpdu_submit_deserialize(data, size); break; /* SMS-SUBMIT */
+ default: return tsk_null;
+ }
+ }
+ else{ /* MT */
+ switch(mti){
+ case tsms_tpdu_mti_deliver_mt: ret = _tsms_tpdu_deliver_deserialize(data, size); break;/* SMS-DELIVER */
+ case tsms_tpdu_mti_status_report_mt: ret = _tsms_tpdu_status_report_deserialize(data, size); break;/* SMS-STATUS-REPORT */
+ case tsms_tpdu_mti_submit_report_mt: ret = _tsms_tpdu_report_deserialize(data, size); break;/* SMS-SUBMIT-REPORT */
+ default: return tsk_null;
+ }
+ }
+
+ if(ret){
+ ret->MobOrig = MobOrig;
+ }
+ return ret;
+}
+
+/**@ingroup tsms_tpdu_group
+* For debugging.
+*/
+char* tsms_tpdu_message_tostring(const tsms_tpdu_message_t* self, tsk_bool_t MobOrig)
+{
+ char* ret = tsk_null;
+ tsk_buffer_t* output = tsk_null;
+ if(!self){
+ goto bail;
+ }
+
+ if((output = tsk_buffer_create_null())){
+ if(!tsms_tpdu_message_serialize(self, output, MobOrig)){
+ ret = tsk_strndup(output->data, output->size);
+ }
+ TSK_OBJECT_SAFE_FREE(output);
+ }
+
+bail:
+ return ret;
+}
+
+/**@ingroup tsms_tpdu_group
+* Serializes any @a TP-Message(@a SMS-SUBMIT, @a SMS-DELIVER, @a SMS-COMMAND ...) as hexa-string content.
+* @param self A pointer to the @a TP-Message to serialize.
+* @param MobOrig Indicates whether its an Mobile originated message or not.
+* @retval A pointer to the hexa-string if succeed and Null otherwise.
+*
+* @sa @ref tsms_tpdu_submit_tohexastring<br>@ref tsms_tpdu_command_tohexastring<br>@ref tsms_tpdu_deliver_tohexastring<br>@ref tsms_tpdu_report_tohexastring<br>@ref tsms_tpdu_status_report_tohexastring
+*/
+char* tsms_tpdu_message_tohexastring(const tsms_tpdu_message_t* self, tsk_bool_t MobOrig)
+{
+ char* ret = tsk_null;
+ tsk_buffer_t* output = tsk_null;
+ if(!self){
+ goto bail;
+ }
+
+ if((output = tsk_buffer_create_null())){
+ if(!tsms_tpdu_message_serialize(self, output, MobOrig)){
+ tsk_size_t i;
+ for(i=0;i<output->size;i++){
+ tsk_strcat_2(&ret, "%.2X", *(TSK_BUFFER_TO_U8(output)+i));
+ }
+ }
+ TSK_OBJECT_SAFE_FREE(output);
+ }
+
+bail:
+ return ret;
+}
+
+/**@ingroup tsms_tpdu_group
+* Gets the payload (ASCII string) of the @a TP-Message(@a SMS-SUBMIT, @a SMS-DELIVER, @a SMS-COMMAND ...).
+* @param self Any @a TP-Message which holds the user content. Should be @a SMS-SUBMIT or @a SMS-DELIVER.
+* @retval A pointer to the ascii string if succeed and non-zero error code otherwise.
+*/
+char* tsms_tpdu_message_get_payload(const tsms_tpdu_message_t* self)
+{
+ if(!self || !self->ud || !self->ud->data || !self->ud->size){
+ TSK_DEBUG_WARN("No content.");
+ return tsk_null;
+ }
+
+ switch(TSMS_ALPHA_FROM_DCS(self->dcs)){
+ case tsms_alpha_7bit:
+ return tsms_pack_from_7bit(self->ud->data, self->ud->size);
+ case tsms_alpha_8bit:
+ return tsms_pack_from_8bit(self->ud->data, self->ud->size);
+ case tsms_alpha_ucs2:
+ return tsms_pack_from_ucs2(self->ud->data, self->ud->size);
+ case tsms_alpha_reserved:
+ default:
+ {
+ TSK_DEBUG_ERROR("%d alpha not suported", TSMS_ALPHA_FROM_DCS(self->dcs));
+ return tsk_null;
+ }
+ }
+}
+
+/**@ingroup tsms_tpdu_group
+* Sets the content of any @a TP-Message(@a SMS-SUBMIT, @a SMS-DELIVER, @a SMS-COMMAND ...).
+* @param self A pointer to the message.
+* @param udata A pointer the content.
+* @param alpha The alphabet used to encode the content.
+* @retval Zero if succeed and non-zero error code otherwise.
+* @sa @ref tsms_tpdu_submit_set_userdata<br>@ref tsms_tpdu_command_set_cmddata<br>@ref tsms_tpdu_report_set_userdata<br>@ref tsms_tpdu_status_report_set_userdata
+*/
+int tsms_tpdu_message_set_userdata(tsms_tpdu_message_t* self, const tsk_buffer_t* udata, tsms_alphabet_t alpha)
+{
+ if(!self || !udata){
+ return -1;
+ }
+ /* SMS alphabet values as per 3GPP TS 23.038 v911 section 4.
+ * Part of TP-DCS (SMS Data Coding Scheme).
+ */
+ self->dcs = ((self->dcs & 0xF3) | (alpha << 2)); /* Bit3 and Bit2 */
+
+ TSK_OBJECT_SAFE_FREE(self->ud);
+
+ /* 3GPP TS 23.040 ==> 9.2.3.16 TP-User-Data-Length (TP-UDL)
+ * (alpha = SMS_ALPHA_7bit) ==> number of septets.
+ * ((alpha == SMS_ALPHA_8bit) || (alpha == SMS_ALPHA_UCS2)) ==> number of octes.
+ */
+
+ /* 3GPP TS 23.040 ==> 9.2.3.24 TP-User Data (TP-UD) */
+ switch(alpha){
+ case tsms_alpha_7bit: {
+ self->udl = (udata->size) + (udata->size/7);
+ self->ud = tsk_buffer_create(udata->data, udata->size);
+ }
+ break;
+ case tsms_alpha_8bit:
+ case tsms_alpha_ucs2: {
+ self->udl = udata->size;
+ self->ud = tsk_buffer_create(udata->data, udata->size);
+ }
+ break;
+
+ default:
+ {
+ TSK_DEBUG_ERROR("Invalid Alphabet.");
+ return -2;
+ }
+ }
+ return 0;
+}
+
+/** internal function used to deinit a TP-Message.*/
+int tsms_tpdu_message_deinit(tsms_tpdu_message_t* self)
+{
+ if(self){
+ TSK_OBJECT_SAFE_FREE(self->ud);
+ return 0;
+ }
+ return -1;
+}
+
+
+
+/* ======================== RPDU ========================
+=========================================================*/
+
+extern int _tsms_rpdu_rpdata_serialize(const tsms_rpdu_message_t* self, tsk_buffer_t* output);
+extern int _tsms_rpdu_rpsmma_serialize(const tsms_rpdu_message_t* self, tsk_buffer_t* output);
+extern int _tsms_rpdu_rpack_serialize(const tsms_rpdu_message_t* self, tsk_buffer_t* output);
+extern int _tsms_rpdu_rperror_serialize(const tsms_rpdu_message_t* self, tsk_buffer_t* output);
+
+
+extern tsms_rpdu_message_t* _tsms_rpdu_rpdata_deserialize(const void* data, tsk_size_t size);
+extern tsms_rpdu_message_t* _tsms_rpdu_rpsmma_deserialize(const void* data, tsk_size_t size);
+extern tsms_rpdu_message_t* _tsms_rpdu_rpack_deserialize(const void* data, tsk_size_t size);
+extern tsms_rpdu_message_t* _tsms_rpdu_rperror_deserialize(const void* data, tsk_size_t size);
+
+
+/**@ingroup tsms_rpdu_group
+* Serialize a @a RP-Message (@a RP-DATA, @a RP-SMMA, @a SMS-ACK, ...) as binary content.
+* @param self A pointer to the @a RP-Message to serialize.
+* @param output A pointer to the @a output buffer.
+* @retval Zero if succeed and non-zero error code otherwise.
+*
+* @sa @ref tsms_rpdu_data_serialize<br>@ref tsms_rpdu_smma_serialize<br>@ref tsms_rpdu_ack_serialize<br>@ref tsms_rpdu_error_serialize
+*/
+int tsms_rpdu_message_serialize(const tsms_rpdu_message_t* self, tsk_buffer_t* output)
+{
+ if(!self || !output){
+ TSK_DEBUG_ERROR("Invalid Parameter");
+ return -1;
+ }
+
+ switch(self->mti){
+ case tsms_rpdu_type_data_mo:
+ case tsms_rpdu_type_data_mt:
+ return _tsms_rpdu_rpdata_serialize(self, output);
+ case tsms_rpdu_type_ack_mo:
+ case tsms_rpdu_type_ack_mt:
+ return _tsms_rpdu_rpack_serialize(self, output);
+ case tsms_rpdu_type_error_mo:
+ case tsms_rpdu_type_error_mt:
+ return _tsms_rpdu_rperror_serialize(self, output);
+ case tsms_rpdu_type_smma_mo:
+ return _tsms_rpdu_rpsmma_serialize(self, output);
+ }
+
+ return -2;
+}
+
+/**@ingroup tsms_rpdu_group
+* Deserialize a @a RP-Message (@a RP-DATA, @a RP-SMMA, @a SMS-ACK, ...) from binary content.
+* @param data A pointer to the binary data.
+* @param size The size of the buffer holding the binary data.
+* @retval @ref tsms_rpdu_message_t if succeed and @a Null otherwise.
+*/
+tsms_rpdu_message_t* tsms_rpdu_message_deserialize(const void* data, tsk_size_t size)
+{
+ tsms_rpdu_type_t mti;
+
+ if(!data || size<2 /* MTI and MR*/){
+ TSK_DEBUG_ERROR("Invalid parameter.");
+ return tsk_null;
+ }
+
+ mti = (*((uint8_t*)data) & 0x07);
+
+ switch(mti){
+ case tsms_rpdu_type_data_mo:
+ case tsms_rpdu_type_data_mt:
+ return _tsms_rpdu_rpdata_deserialize(data, size);
+ case tsms_rpdu_type_ack_mo:
+ case tsms_rpdu_type_ack_mt:
+ return _tsms_rpdu_rpack_deserialize(data, size);
+ case tsms_rpdu_type_error_mo:
+ case tsms_rpdu_type_error_mt:
+ return _tsms_rpdu_rperror_deserialize(data, size);
+ case tsms_rpdu_type_smma_mo:
+ return _tsms_rpdu_rpsmma_deserialize(data, size);
+ }
+
+ return tsk_null;
+}
+
+/**@ingroup tsms_rpdu_group
+* Serializes any @a RP-Message (@a RP-DATA, @a RP-SMMA, @a SMS-ACK, ...) as hexa-string content.
+* @param self A pointer to the @a RP-Message to serialize.
+* @retval A pointer to the hexa-string if succeed and Null otherwise.
+*/
+char* tsms_rpdu_message_tohexastring(const tsms_rpdu_message_t* self)
+{
+ char* ret = tsk_null;
+ tsk_buffer_t* output = tsk_null;
+ if(!self){
+ goto bail;
+ }
+
+ if((output = tsk_buffer_create_null())){
+ if(!tsms_rpdu_message_serialize(self, output)){
+ tsk_size_t i;
+ for(i=0;i<output->size;i++){
+ tsk_strcat_2(&ret, "%.2X", *(TSK_BUFFER_TO_U8(output)+i));
+ }
+ }
+ TSK_OBJECT_SAFE_FREE(output);
+ }
+
+bail:
+ return ret;
+}
diff --git a/tinySMS/src/tsms_packing.c b/tinySMS/src/tsms_packing.c
new file mode 100644
index 0000000..048f732
--- /dev/null
+++ b/tinySMS/src/tsms_packing.c
@@ -0,0 +1,343 @@
+/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsms_packing.c
+ * @brief SMS Packing (3GPP TS 23.038 subclause 6.1.2).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinysms/tsms_packing.h"
+
+#include "tinysms/tsms_etsi_gsm_03_38.h"
+
+#include "tsk_memory.h"
+#include "tsk_string.h"
+#include "tsk_debug.h"
+
+#include <string.h> /* strlen() */
+
+/**@defgroup tsms_packing_group SMS Packing
+*/
+
+/**@ingroup tsms_packing_group
+* Converts ASCII string to GSM 7-bit characters as per 3GPP TS 23.038 v911 section 6.1.2.1.
+* @param ascii Null-Terminated ascii string to convert.
+* @retval Buffer containing GSM 7-bit characters if succeed and @a Null otherwise.
+* @sa @ref tsms_pack_from_7bit
+*/
+tsk_buffer_t* tsms_pack_to_7bit(const char* ascii)
+{
+ /* 3GPP TS 23.038 - 6.1.2.1.1 Packing of 7-bit characters
+ If a character number $ is noted in the following way:
+ b7 b6 b5 b4 b3 b2 b1
+ $a $b $c $d $e $f $g
+ The packing of the 7-bitscharacters in octets is done by completing the octets with zeros on the left.
+ For examples, packing: $
+ - one character in one octet:
+ - bits number:
+ 7 6 5 4 3 2 1 0
+ 0 1a 1b 1c 1d 1e 1f 1g
+
+ - two characters in two octets:
+ - bits number:
+ 7 6 5 4 3 2 1 0
+ 2g 1a 1b 1c 1d 1e 1f 1g
+ 0 0 2a 2b 2c 2d 2e 2f
+
+ - three characters in three octets:
+ - bits number:
+ 7 6 5 4 3 2 1 0
+ 2g 1a 1b 1c 1d 1e 1f 1g
+ 3f 3g 2a 2b 2c 2d 2e 2f
+ 0 0 0 3a 3b 3c 3d 3e
+
+ - seven characters in seven octets:
+ - bits number:
+ 7 6 5 4 3 2 1 0
+ 2g 1a 1b 1c 1d 1e 1f 1g
+ 3f 3g 2a 2b 2c 2d 2e 2f
+ 4e 4f 4g 3a 3b 3c 3d 3e
+ 5d 5e 5f 5g 4a 4b 4c 4d
+ 6c 6d 6e 6f 6g 5a 5b 5c
+ 7b 7c 7d 7e 7f 7g 6a 6b
+ 0 0 0 0 0 0 0 7a
+
+ - eight characters in seven octets:
+ - bits number:
+ 7 6 5 4 3 2 1 0
+ 2g 1a 1b 1c 1d 1e 1f 1g
+ 3f 3g 2a 2b 2c 2d 2e 2f
+ 4e 4f 4g 3a 3b 3c 3d 3e
+ 5d 5e 5f 5g 4a 4b 4c 4d
+ 6c 6d 6e 6f 6g 5a 5b 5c
+ 7b 7c 7d 7e 7f 7g 6a 6b
+ 8a 8b 8c 8d 8e 8f 8g 7a
+
+ The bit number zero is always transmitted first.
+ Therefore, in 140 octets, it is possible to pack (140x8)/7=160 characters.
+ */
+ tsk_buffer_t* ret = tsk_null;
+ uint8_t* _ret = tsk_null;
+ register tsk_size_t len, bcount = 1/*1-7*/, index = 0, retindex = 0, retlen = 0;
+ const uint8_t* pascii = (const uint8_t*)ascii;
+
+ if(!ascii || !(len = strlen(ascii))){
+ TSK_DEBUG_WARN("Null or Empty ascci string.");
+ goto bail;
+ }
+
+ retlen = len - (len/7) + 1;
+ if(!(_ret = tsk_calloc(retlen, sizeof(uint8_t)))){
+ goto bail;
+ }
+
+ while(index < len){
+ if(index == 0){
+ _ret[retindex] |= (pascii[index] & (0xFF >> bcount)) |
+ (pascii[index+1] << (8 - bcount));
+ }
+ else{
+ _ret[retindex] = ((pascii[index] >> (bcount - 1))& (0xFF >> bcount))
+ | (pascii[index+1] <<(8-bcount));
+ }
+
+ /* how many bytes to use to complete on the left? */
+ if(++bcount == 8){
+ bcount = 1, ++index;
+ }
+ /* next */
+ retindex++;
+ index++;
+ }
+
+ /* creat ret */
+ ret = tsk_buffer_create(_ret, (retlen-1));
+bail:
+ TSK_FREE(_ret);
+
+ return ret;
+}
+
+/**@ingroup tsms_packing_group
+* Converts ASCII string to UCS-2(2-byte Universal Character Set) characters.
+* @param ascii Null-Terminated ascii string to convert.
+* @retval Buffer containing UCS-2 characters if succeed and @a Null otherwise.
+* @sa @ref tsms_pack_from_ucs2
+*/
+tsk_buffer_t* tsms_pack_to_ucs2(const char* ascii)
+{
+ register tsk_size_t i, j;
+ tsk_size_t len, retlen = 0;
+ uint8_t* str = tsk_null;
+ tsk_buffer_t* ret = tsk_null;
+
+ if(!ascii || !(len=strlen(ascii))){
+ TSK_DEBUG_WARN("Null or Empty gsm7bit buffer.");
+ goto bail;
+ }
+
+ if(!(str = tsk_calloc(len, sizeof(uint8_t)*2))){
+ goto bail;
+ }
+
+ /* very bas way to do conversion ==> to be fixed */
+ for(i=0; i<len; i++){
+ for(j=0; j<TSMS_ETSI_GSM_03_38_COUNT; j++){
+ if((uint8_t)ascii[i] == (uint8_t)(TSMS_ETSI_GSM_03_38[j][1] & 0xFF)){
+ retlen++; /* 00 */
+ *(str + retlen++) = (TSMS_ETSI_GSM_03_38[j][0] & 0xFF);
+ }
+ }
+ }
+
+ /* create buffer */
+ ret = tsk_buffer_create(str, retlen);
+
+bail:
+ TSK_FREE(str);
+ return ret;
+}
+
+/**@ingroup tsms_packing_group
+* Converts ASCII string to 8-bit characters.
+* @param ascii Null-terminated ascii string to convert.
+* @retval Buffer containing 8-bit characters if succeed and @a Null otherwise.
+* @sa @ref tsms_pack_from_8bit
+*/
+tsk_buffer_t* tsms_pack_to_8bit(const char* ascii)
+{
+ register tsk_size_t i, j;
+ tsk_size_t len, retlen = 0;
+ uint8_t* str = tsk_null;
+ tsk_buffer_t* ret = tsk_null;
+
+ if(!ascii || !(len=strlen(ascii))){
+ TSK_DEBUG_WARN("Null or Empty gsm7bit buffer.");
+ goto bail;
+ }
+
+ if(!(str = tsk_calloc(len, sizeof(uint8_t)))){
+ goto bail;
+ }
+
+ /* very bas way to do conversion ==> to be fixed */
+ for(i = 0; i<len; i++){
+ for(j = 0; j<TSMS_ETSI_GSM_03_38_COUNT; j++){
+ if((uint8_t)ascii[i] == (uint8_t)(TSMS_ETSI_GSM_03_38[j][1] & 0xFF)){
+ *(str + retlen++) = (TSMS_ETSI_GSM_03_38[j][0] & 0xFF);
+ continue;
+ }
+ }
+ }
+
+ /* create buffer */
+ ret = tsk_buffer_create(str, retlen);
+
+bail:
+ TSK_FREE(str);
+ return ret;
+}
+
+/**@ingroup tsms_packing_group
+* Converts GSM 7-bit characters to ASCII string.
+* @param gsm7bit Buffer containing GSM 7-bit characters to convert.
+* @param size The size of the buffer.
+* @retval Null-terminated ASCII string, ready to be shown to the screen.
+* @sa @ref tsms_pack_to_7bit
+*/
+char* tsms_pack_from_7bit(const void* gsm7bit, tsk_size_t size)
+{
+ char* ret = tsk_null;
+ register tsk_size_t bcount = 1/*1-7*/, index = 0, retindex = 0, retsize = 0;
+ const uint8_t* pgsm7bit = gsm7bit;
+
+ if(!gsm7bit || !size){
+ TSK_DEBUG_WARN("Null or Empty gsm7bit buffer.");
+ goto bail;
+ }
+
+ // dup the gsm7bit buffer
+ retsize = size + (size/7) + 1; // variable used for debug
+ if(!(ret = tsk_calloc(retsize, sizeof(uint8_t)))){
+ goto bail;
+ }
+
+ while(index < size){
+ ret[retindex] = (pgsm7bit[index] & (0xFF >>bcount));
+ if(index){
+ ret[retindex] = (ret[retindex] << (bcount - 1))
+ | (pgsm7bit[index-1] >> (8 - bcount + 1));
+ }
+
+ /* how many bytes to use to complete on the right? */
+ if(bcount++ == 8){
+ bcount = 1, --index;
+ }
+ /* next */
+ index++;
+ retindex++;
+ }
+
+ /* special one */
+ if(!(size%7)){
+ ret[retindex] = pgsm7bit[size-1]>>1;
+ }
+
+bail:
+
+ return ret;
+}
+
+/**@ingroup tsms_packing_group
+* Converts UCS-2(2-byte Universal Character Set) characters to ASCII string.
+* @param ucs2 Buffer containing UCS-2 characters to convert.
+* @param size The size of the buffer.
+* @retval Null-terminated ASCII string, ready to be shown to the screen.
+* @sa @ref tsms_pack_to_ucs2
+*/
+char* tsms_pack_from_ucs2(const void* ucs2, tsk_size_t size)
+{
+ register tsk_size_t i, j;
+ char* ret = tsk_null;
+
+ const uint16_t* pucs2 = ucs2;
+
+ if(!ucs2 || !size){
+ TSK_DEBUG_WARN("Null or Empty gsm8bit buffer.");
+ goto bail;
+ }
+
+ if(!(ret = tsk_calloc(size+1, sizeof(uint8_t)))){
+ goto bail;
+ }
+
+ for(i=0; i<size; i++){
+ for(j=0; j<TSMS_ETSI_GSM_03_38_COUNT; j++){
+ if(*(pucs2 + i) == (TSMS_ETSI_GSM_03_38[j][0])){
+ *(ret+i) = (TSMS_ETSI_GSM_03_38[j][1] & 0xFF);
+ continue;
+ }
+ }
+ }
+
+bail:
+ return ret;
+}
+
+/**@ingroup tsms_packing_group
+* Converts 8-bit characters to ASCII string.
+* @param gsm8bit Buffer containing GSM 8-bit characters to convert.
+* @param size The size of the buffer.
+* @retval Null-terminated ASCII string, ready to be shown to the screen.
+* @sa @ref tsms_pack_to_8bit
+*/
+char* tsms_pack_from_8bit(const void* gsm8bit, tsk_size_t size)
+{
+ register tsk_size_t i, j;
+ char* ret = tsk_null;
+
+ const uint8_t* pgsm8bit = gsm8bit;
+
+ if(!gsm8bit || !size){
+ TSK_DEBUG_WARN("Null or Empty gsm8bit buffer.");
+ goto bail;
+ }
+
+ if(!(ret = tsk_calloc(size+1, sizeof(uint8_t)))){
+ goto bail;
+ }
+
+ /* Very bad way to do convertion ==> to be changed */
+ for(i=0; i<size; i++){
+ for(j=0; j<TSMS_ETSI_GSM_03_38_COUNT; j++){
+ if(*(pgsm8bit + i) == (TSMS_ETSI_GSM_03_38[j][0] & 0xFF)){
+ *(ret+i) = (TSMS_ETSI_GSM_03_38[j][1] & 0xFF);
+ continue;
+ }
+ }
+ }
+
+bail:
+ return ret;
+}
OpenPOWER on IntegriCloud