Added CA BLE packet format changed codes
authorjaehyun Cho <jaehyun3.cho@samsung.com>
Fri, 5 Aug 2016 02:16:15 +0000 (11:16 +0900)
committerAshok Babu Channa <ashok.channa@samsung.com>
Thu, 1 Sep 2016 09:57:37 +0000 (09:57 +0000)
description : https://jira.iotivity.org/browse/IOT-1210

Change-Id: I6f886989e8fdc14fd5128e0c96f1de3f7687bffe
Signed-off-by: jaehyun Cho <jaehyun3.cho@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/9979
Reviewed-by: jihwan seo <jihwan.seo@samsung.com>
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Ashok Babu Channa <ashok.channa@samsung.com>
resource/csdk/connectivity/inc/cafragmentation.h [new file with mode: 0644]
resource/csdk/connectivity/src/SConscript
resource/csdk/connectivity/src/adapter_util/cafragmentation.c [new file with mode: 0644]
resource/csdk/connectivity/src/bt_le_adapter/arduino/cableserver.cpp
resource/csdk/connectivity/src/bt_le_adapter/caleadapter.c

diff --git a/resource/csdk/connectivity/inc/cafragmentation.h b/resource/csdk/connectivity/inc/cafragmentation.h
new file mode 100644 (file)
index 0000000..0aff468
--- /dev/null
@@ -0,0 +1,297 @@
+/* ****************************************************************
+ *
+ * Copyright 2016 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ *
+ * This file contains common utility functions to manage the CA msg
+ * fragmentation and reassemebly.
+ */
+
+
+#ifndef CA_FRAGMENTATION_H_
+#define CA_FRAGMENTATION_H_
+
+#include "cacommon.h"
+#include "logger.h"
+
+/**
+ * The MTU supported for BLE adapter
+ */
+#define CA_SUPPORTED_BLE_MTU_SIZE  20
+
+/**
+ * The maximum port value for BLE packet format
+ */
+#define CA_SUPPORTED_BLE_MAX_PORT  127
+
+/**
+ * The minimum port value for BLE packet format
+ */
+#define CA_SUPPORTED_BLE_MIN_PORT  1
+
+/**
+ * The multicaset packet remote port value
+ */
+#define CA_BLE_MULTICAST_PORT  0
+
+/**
+ * The header size for ble fragmentation.
+ * Specific header descriptions are below.
+ */
+#define CA_BLE_HEADER_SIZE 2
+
+/**
+ * The length header size for ble fragmentation.
+ * Length header is embedded in first packet of entire CoAP PDU.
+ */
+#define CA_BLE_LENGTH_HEADER_SIZE 4
+
+/**
+ * Current Header version.
+ */
+#define HEADER_VERSION 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * This enum value is used to make the CA BLE packet header.
+ * 1st bit is used to check whether the packet is start packet or not.
+ * Start packet should be marked ad CA_BLE_PACKET_START(1) and any other
+ * packet is marked as CA_BLE_PACKET_NOT_START(0).
+ */
+typedef enum {
+    CA_BLE_PACKET_NOT_START     = 0,
+    CA_BLE_PACKET_START         = 1
+} CABLEPacketStart_t;
+
+/**
+ * This enum value is used to make the CA BLE packet header.
+ * 9th bit is uesd to check the packet use secure logic(dtls) or not.
+ * Secure packet should be marking CA_BLE_PACKET_SECURE(1) and other
+ * packet is makred CA_BLE_PACKET_NON_SECURE(0).
+ */
+typedef enum {
+    CA_BLE_PACKET_NON_SECURE    = 0,
+    CA_BLE_PACKET_SECURE        = 1
+} CABLEPacketSecure_t;
+
+
+/*****************************************************************
+ * @file The CA Header format
+ * CA Header will be defined by 2 bytes of Header.
+ * First one bit : Header type that is start packet or not.
+ * 2nd to 8th bit : Own unique port value.
+ * 9th bit: Secure type using dtls(1) or not(0).
+ * 10th to 16th bit : Remote endpoint unique port value.
+ *
+ * Start packet has additional 4 bytes size length header which
+ * represent total packet size.
+ *****************************************************************/
+
+/**
+ * This function is used to generate the CA BLE variable related to
+ * maintain the fragmentation logic. The variable is used in BLE send routine.
+ *
+ * @param[in]   dataLength      Original packet size about data to send.
+ * @param[out]  midPacketCount  Number of mid packet except first and last
+ *                              packet.
+ * @param[out]  remainingLen    Size of last packet before adding header.
+ * @param[out]  totalLengh      The total length of the data.
+ *
+ * @return ::CA_STATUS_OK on success. One of the CA_STATUS_FAILED
+ *           or other error values on error.
+ * @retval ::CA_STATUS_OK             Successful
+ * @retval ::CA_STATUS_FAILED         Operation failed
+ */
+CAResult_t CAGenerateVariableForFragmentation(size_t dataLength,
+                                              uint32_t *midPacketCount,
+                                              size_t *remainingLen,
+                                              size_t *totalLength);
+
+/**
+ * This function is used to generate the CA BLE header to
+ * maintain the fragmentation logic. The header structure explained
+ * above will be formed and returned to the caller.
+ *
+ * @param[in,out] header       Pointer to the octet array that will
+ *                             contain the generated header.
+ * @param[in]     type         Enum value to check start packet or not.
+ *                             it will be embedded in bit 1 of the header
+ * @param[in]     sourcePort   Source(own) port of the unique(in device)
+ *                             value. it will be embedded in bits 2~8 of
+ *                             the header.
+ * @param[in]     secure       Enum value to check whether secure or not.
+ *                             it will be embedded in bit 9 of the header.
+ * @param[in]     destPort     Destination(remote endpoint) port of the
+ *                             unique(in device) value. it will be embedded
+ *                             in bits 10~16 of the header.
+ *
+ * @return ::CA_STATUS_OK on success. One of the CA_STATUS_FAILED
+ *           or other error values on error.
+ * @retval ::CA_STATUS_OK             Successful
+ * @retval ::CA_STATUS_INVALID_PARAM  Invalid input arguments
+ * @retval ::CA_STATUS_FAILED         Operation failed
+ */
+CAResult_t CAGenerateHeader(uint8_t *header,
+                            CABLEPacketStart_t type,
+                            const uint8_t sourcePort,
+                            CABLEPacketSecure_t secure,
+                            const uint8_t destPort);
+
+/**
+ * This function is used to generate the CA BLE length header to
+ * maintain the fragmentation logic. The header structure explained
+ * above will be formed and returned to the caller.
+ *
+ * @param[in,out] header       Pointer to the octet array that will
+ *                             contain the generated length header.
+ * @param[in]     headerLength Length about header array. it should be
+ *                             same as CA_BLE_LENGTH_HEADER_SIZE.
+ * @param[in]     dataLength   The total length of data size. it will
+ *                             be embedded in 4 bytes of the length header.
+ *
+ * @return ::CA_STATUS_OK on success. One of the CA_STATUS_FAILED
+ *           or other error values on error.
+ * @retval ::CA_STATUS_OK             Successful
+ * @retval ::CA_STATUS_INVALID_PARAM  Invalid input arguments
+ * @retval ::CA_STATUS_FAILED         Operation failed
+ */
+CAResult_t CAGenerateHeaderPayloadLength(uint8_t *header,
+                                         size_t headerLength,
+                                         size_t dataLength);
+
+/**
+ * This function is used to make the CA BLE first data segment to
+ * maintain the fragmentation logic. start data segment is included
+ * 2 bytes header, 4 bytes length header and transmit data.
+ *
+ * @param[out]  dataSegment    Pointer to the octet array that will
+ *                             contain the generated data packet.
+ * @param[in]   data           Data to the octet array that required
+ *                             transmittin to remote device. it will
+ *                             be embedded in 7th byte to data length.
+ * @param[in]   dataLength     The length of data size.
+ * @param[in]   dataHeader     Pointer to the octet array that contain
+ *                             data header.
+ * @param[in]   lengthHeader   Pointer to the octet array that contain
+ *                             length header.
+ *
+ * @return ::CA_STATUS_OK on success. One of the CA_STATUS_FAILED
+ *           or other error values on error.
+ * @retval ::CA_STATUS_OK             Successful
+ * @retval ::CA_STATUS_INVALID_PARAM  Invalid input arguments
+ * @retval ::CA_STATUS_FAILED         Operation failed
+ */
+CAResult_t CAMakeFirstDataSegment(uint8_t *dataSegment,
+                                  const uint8_t *data,
+                                  const uint32_t dataLength,
+                                  const uint8_t *dataHeader,
+                                  const uint8_t *lengthHeader);
+
+/**
+ * This function is used to make the CA BLE second to end data segment
+ * to maintain the fragmentation logic. start data segment is included
+ * 2 bytes header and transmit data.
+ *
+ * @param[out]  dataSegment    Pointer to the octet array that will
+ *                             contain the generated data packet.
+ * @param[in]   data           Data to the octet array that required
+ *                             transmittin to remote device. it will
+ *                             be embedded in 7th byte to data length.
+ * @param[in]   dataLength     The length of data size.
+ * @param[in]   index          Index to determine whether some of the
+ *                             total data
+ * @param[in]   dataHeader     Pointer to the octet array that contain
+ *                             data header.
+ *
+ * @return ::CA_STATUS_OK on success. One of the CA_STATUS_FAILED
+ *           or other error values on error.
+ * @retval ::CA_STATUS_OK             Successful
+ * @retval ::CA_STATUS_INVALID_PARAM  Invalid input arguments
+ * @retval ::CA_STATUS_FAILED         Operation failed
+ */
+CAResult_t CAMakeRemainDataSegment(uint8_t *dataSegment,
+                                   const uint8_t *data,
+                                   const uint32_t dataLength,
+                                   const uint32_t index,
+                                   const uint8_t *dataHeader);
+
+/**
+ * This function is used to parse the header in the receiver end. This
+ * function will provide the information of the type of the packet, source(remote) /
+ * destination port info and secure infomation.
+ *
+ * @param[in]   header      Pointer to the octet array data which contains
+ *                          the header information.  Note that pointer should
+ *                          point to two bytes of data header which needs to
+ *                          be parsed.
+ * @param[out]  type        Enum value to check start packet or not.
+ *                          it will be embedded in bit 1 of the header
+ * @param[out]  sourcePort  Source(own) port of the unique(in device)
+ *                          value. it will be embedded in bits 2~8 of
+ *                          the header.
+ * @param[out]  secure      Enum value to check whether secure or not.
+ *                          it will be embedded in bit 9 of the header.
+ * @param[out]  destPort    Destination(remote endpoint) port of the
+ *                          unique(in device) value. it will be embedded
+ *                          in bits 10~16 of the header.
+ *
+ * @return ::CA_STATUS_OK on success. One of the CA_STATUS_FAILED
+ *           or other error values on error.
+ * @retval ::CA_STATUS_OK             Successful
+ * @retval ::CA_STATUS_INVALID_PARAM  Invalid input arguments
+ * @retval ::CA_STATUS_FAILED         Operation failed
+ */
+CAResult_t CAParseHeader(const uint8_t *header,
+                         CABLEPacketStart_t *startFlag,
+                         uint16_t *sourcePort,
+                         CABLEPacketSecure_t *secureFlag,
+                         uint16_t *destPort);
+
+/**
+ * This function is used to parse the length header in the receiver end. This
+ * function will provide the total data length about defragmented data.
+ *
+ * @param[in]   header        Pointer to the octet array that will
+ *                            contain length infomation.
+ * @param[out]  headerLength  Length about header array. it should be
+ *                            same as CA_BLE_LENGTH_HEADER_SIZE.
+ * @param[out]  dataLength    The total length of data size. it will
+ *                            be embedded in 4 bytes of the length header.
+ *
+ * @return ::CA_STATUS_OK on success. One of the CA_STATUS_FAILED
+ *           or other error values on error.
+ * @retval ::CA_STATUS_OK             Successful
+ * @retval ::CA_STATUS_INVALID_PARAM  Invalid input arguments
+ * @retval ::CA_STATUS_FAILED         Operation failed
+ */
+CAResult_t CAParseHeaderPayloadLength(uint8_t *header,
+                                      size_t headerLength,
+                                      uint32_t *dataLength);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif  /* CA_FRAGMENTATION_H_ */
index e0a1e49..6063875 100644 (file)
@@ -55,6 +55,8 @@ if env.get('SECURED') == '1':
 
 env.AppendUnique(CA_SRC = [os.path.join(ca_path,
                                         'adapter_util/caadapterutils.c')])
+env.AppendUnique(CA_SRC = [os.path.join(ca_path,
+                                        'adapter_util/cafragmentation.c')])
 
 if env.get('SECURED') == '1':
        env.AppendUnique(CA_SRC = [os.path.join(ca_path,
diff --git a/resource/csdk/connectivity/src/adapter_util/cafragmentation.c b/resource/csdk/connectivity/src/adapter_util/cafragmentation.c
new file mode 100644 (file)
index 0000000..64af936
--- /dev/null
@@ -0,0 +1,256 @@
+/******************************************************************
+ *
+ * Copyright 2016 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
+
+#include <string.h>
+#include <math.h>
+
+#include "cacommon.h"
+#include "caadapterutils.h"
+#include "cafragmentation.h"
+
+/**
+ * Debugging tag for fragmentation module.
+ */
+#define TAG "OIC_CA_FRAG"
+
+//packet format define value
+#define CA_BLE_START_POS 7
+#define CA_BLE_START_LEN 1
+#define CA_BLE_SOURCE_PORT_POS 6
+#define CA_BLE_SOURCE_PORT_LEN 7
+#define CA_BLE_SECURE_POS 7
+#define CA_BLE_SECURE_LEN 1
+#define CA_BLE_DESTINATION_PORT_POS 6
+#define CA_BLE_DESTINATION_PORT_LEN 7
+
+/**
+ * This function is used to set value in specific bit position.
+ *
+ * @param[out]  x  Pointer to the octet variable that will contain
+ *                 value in specific bit position.
+ * @param[in]   p  Position which need to embed specific bits(0~7).
+ * @param[in]   n  Length to fill several bits from the position.
+ * @param[in]   v  Value to contain in specific bit position.
+ */
+static void CASetBits(uint8_t *x, unsigned p, unsigned n, unsigned v)
+{
+    if ((p+1) < n)
+    {
+        OIC_LOG(ERROR, TAG, "set bits - lower err");
+        return;
+    }
+    else if(~(unsigned)(~0<<n) < v)
+    {
+        OIC_LOG(ERROR, TAG, "set bits - upper err");
+        return;
+    }
+    *x = (*x & (~(~0 << (p-n+1)))) | (*x & (~0 << (p+1))) | ((v & ~(~0 << n)) << (p-n+1));
+}
+
+/**
+ * This function is used to get value in specific bit position.
+ *
+ * @param[in]   x  Pointer to the octet variable that have infomation
+ *                 to be extracted.
+ * @param[in]   p  Position which need to get specific bits(0~7).
+ * @param[in]   n  Length to get several bits from the position.
+ *
+ * @return @c Extracted value from specific position.
+ */
+static uint8_t CAGetBits(uint8_t x, unsigned p, unsigned n)
+{
+    return (x >> (p + 1 - n)) & ~(~0 << n);
+}
+
+CAResult_t CAGenerateVariableForFragmentation(size_t dataLength,
+                                              uint32_t *midPacketCount,
+                                              size_t *remainingLen,
+                                              size_t *totalLength)
+{
+    OIC_LOG_V(DEBUG, TAG, "IN, dataLength = %d", dataLength);
+
+    size_t remainDataSize = 0;
+    size_t dataOnlyLen =
+        CA_SUPPORTED_BLE_MTU_SIZE - (CA_BLE_HEADER_SIZE + CA_BLE_LENGTH_HEADER_SIZE);
+    //total data size is smaller than 14 byte case.
+    if (dataLength < dataOnlyLen)
+    {
+        remainDataSize = 0;
+    }
+    else
+    {
+        remainDataSize = dataLength - dataOnlyLen;
+    }
+
+    if (CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE <= 0)
+    {
+        OIC_LOG_V(ERROR, TAG, "BLE header size shouldn't be bigger than BLE MTU size.");
+        return CA_STATUS_FAILED;
+    }
+
+    *midPacketCount = (uint32_t)remainDataSize / (CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE);
+    *remainingLen = (uint32_t)remainDataSize % (CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE);
+    uint32_t remainHeaderSize = CA_BLE_HEADER_SIZE * (*midPacketCount + (*remainingLen == 0 ? 0:1));
+    *totalLength = dataLength + (CA_BLE_HEADER_SIZE + CA_BLE_LENGTH_HEADER_SIZE) + remainHeaderSize;
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAGenerateHeader(uint8_t *header,
+                            CABLEPacketStart_t type,
+                            const uint8_t sourcePort,
+                            CABLEPacketSecure_t secure,
+                            const uint8_t destPort)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    VERIFY_NON_NULL(header, TAG, "header is NULL");
+
+    if (sourcePort > CA_SUPPORTED_BLE_MAX_PORT ||
+        sourcePort < CA_SUPPORTED_BLE_MIN_PORT ||
+        destPort > CA_SUPPORTED_BLE_MAX_PORT ||
+        destPort < CA_BLE_MULTICAST_PORT)
+    {
+        OIC_LOG_V(ERROR, TAG, "source port(%d) or destination port(%d) is invalid number!!",
+                sourcePort, destPort);
+        return CA_STATUS_FAILED;
+    }
+
+    CASetBits(&header[0], CA_BLE_START_POS, CA_BLE_START_LEN, type);
+    CASetBits(&header[0], CA_BLE_SOURCE_PORT_POS, CA_BLE_SOURCE_PORT_LEN, sourcePort);
+    CASetBits(&header[1], CA_BLE_SECURE_POS, CA_BLE_SECURE_LEN, secure);
+    CASetBits(&header[1], CA_BLE_DESTINATION_PORT_POS, CA_BLE_DESTINATION_PORT_LEN, destPort);
+
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAGenerateHeaderPayloadLength(uint8_t *header,
+                                         size_t headerLength,
+                                         size_t dataLength)
+{
+    VERIFY_NON_NULL(header, TAG, "header is NULL");
+
+    if (headerLength != CA_BLE_LENGTH_HEADER_SIZE)
+    {
+        return CA_STATUS_FAILED;
+    }
+
+    for(size_t idx = 1; idx < CA_BLE_LENGTH_HEADER_SIZE; idx++)
+    {
+        header[CA_BLE_LENGTH_HEADER_SIZE - idx] = dataLength & 0xFF;
+        dataLength >>= 8;
+    }
+    header[0] = dataLength & 0xFF;
+
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAMakeFirstDataSegment(uint8_t *dataSegment,
+                                  const uint8_t *data,
+                                  const uint32_t dataLength,
+                                  const uint8_t *dataHeader,
+                                  const uint8_t *lengthHeader)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    VERIFY_NON_NULL(dataSegment, TAG, "dataSegment is NULL");
+    VERIFY_NON_NULL(dataHeader, TAG, "dataHeader is NULL");
+    VERIFY_NON_NULL(lengthHeader, TAG, "lengthHeader is NULL");
+
+    memcpy(dataSegment, dataHeader, CA_BLE_HEADER_SIZE);
+    memcpy(dataSegment + CA_BLE_HEADER_SIZE, lengthHeader, CA_BLE_LENGTH_HEADER_SIZE);
+    memcpy(dataSegment + CA_BLE_HEADER_SIZE + CA_BLE_LENGTH_HEADER_SIZE, data, dataLength);
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAMakeRemainDataSegment(uint8_t *dataSegment,
+                                   const uint8_t *data,
+                                   const uint32_t dataLength,
+                                   const uint32_t index,
+                                   const uint8_t *dataHeader)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    VERIFY_NON_NULL(dataSegment, TAG, "dataSegment is NULL");
+    VERIFY_NON_NULL(dataHeader, TAG, "dataHeader is NULL");
+
+    uint8_t *cur_pos = data +
+        (CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE - CA_BLE_LENGTH_HEADER_SIZE +
+         (index * (CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE)));
+    if (cur_pos == NULL)
+    {
+        OIC_LOG(ERROR, TAG, "data is NULL");
+        return CA_STATUS_FAILED;
+    }
+
+    memcpy(dataSegment, dataHeader, CA_BLE_HEADER_SIZE);
+    memcpy(dataSegment + CA_BLE_HEADER_SIZE, cur_pos, dataLength);
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAParseHeader(const uint8_t *header,
+                         CABLEPacketStart_t *startFlag,
+                         uint16_t *sourcePort,
+                         CABLEPacketSecure_t *secureFlag,
+                         uint16_t *destPort)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    VERIFY_NON_NULL(header, TAG, "header is NULL");
+
+    *startFlag = CAGetBits(header[0], CA_BLE_START_POS, CA_BLE_START_LEN);
+    *sourcePort = CAGetBits(header[0], CA_BLE_SOURCE_PORT_POS, CA_BLE_SOURCE_PORT_LEN);
+    *secureFlag = CAGetBits(header[1], CA_BLE_SECURE_POS, CA_BLE_SECURE_LEN);
+    *destPort = CAGetBits(header[1], CA_BLE_DESTINATION_PORT_POS, CA_BLE_DESTINATION_PORT_LEN);
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAParseHeaderPayloadLength(uint8_t *header,
+                                      size_t headerLength,
+                                      uint32_t *dataLength)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    VERIFY_NON_NULL(header, TAG, "header is NULL");
+
+    if (headerLength != CA_BLE_LENGTH_HEADER_SIZE)
+    {
+        return CA_STATUS_FAILED;
+    }
+
+    for(size_t idx = 0; idx < headerLength; idx++)
+    {
+        *dataLength <<= 8;
+        *dataLength |= header[CA_BLE_HEADER_SIZE+idx];
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
index 6e2c639..e7706f1 100644 (file)
@@ -34,6 +34,8 @@
 #include "oic_malloc.h"
 #include "caadapterutils.h"
 
+#include "cafragmentation.h"
+
 #define TAG "LES"
 /**
  * Maximum TCP header length.
@@ -77,11 +79,10 @@ void CACheckLEDataInternal()
 
     if (CAIsLEDataAvailable())
     {
-        // Allocate Memory for COAP Buffer and do ParseHeader
         if (NULL == g_coapBuffer)
         {
             OIC_LOG(DEBUG, TAG, "IN");
-            size_t bufSize = TCP_MAX_HEADER_LENGTH;
+            size_t bufSize = CA_SUPPORTED_BLE_MTU_SIZE;
             g_coapBuffer = (uint8_t *)OICCalloc(bufSize, 1);
             if (NULL == g_coapBuffer)
             {
@@ -89,56 +90,24 @@ void CACheckLEDataInternal()
                 return;
             }
 
-            g_coapBuffer[g_receivedDataLen++] = CALEReadData();
-            size_t headerLen;
-            CAGetTCPHeaderDetails(g_coapBuffer, &headerLen);
-            OIC_LOG_V(INFO, TAG, "hdr len %d", headerLen);
-            while (CAIsLEDataAvailable() && g_receivedDataLen < headerLen)
+            while (CAIsLEDataAvailable())
             {
                 g_coapBuffer[g_receivedDataLen++] = CALEReadData();
             }
 
-            g_packetDataLen = coap_get_total_message_length(g_coapBuffer, g_receivedDataLen);
-            OIC_LOG_V(INFO, TAG, "pkt len %d", g_packetDataLen);
-            if (g_packetDataLen > COAP_MAX_PDU_SIZE)
-            {
-                OIC_LOG(ERROR, TAG, "len > pdu_size");
-                return;
-            }
+            OIC_LOG(DEBUG, TAG, "Read Comp BLE Pckt");
 
-            bufSize = g_packetDataLen;
-            uint8_t *newBuf = (uint8_t *)OICRealloc(g_coapBuffer, bufSize);
-            if (NULL == newBuf)
+            if (g_receivedDataLen > 0)
             {
-                OIC_LOG(ERROR, TAG, "malloc");
-                OICFree(g_coapBuffer);
-                g_coapBuffer = NULL;
-                return;
+                OIC_LOG_V(DEBUG, TAG, "recv dataLen=%u", g_receivedDataLen);
+                uint32_t sentLength = 0;
+                g_bleServerDataReceivedCallback("", g_coapBuffer,
+                                                g_receivedDataLen, &sentLength);
             }
-            g_coapBuffer = newBuf;
-        }
 
-        while (CAIsLEDataAvailable())
-        {
-            OIC_LOG(DEBUG, TAG, "In While loop");
-            g_coapBuffer[g_receivedDataLen++] = CALEReadData();
-            if (g_receivedDataLen == g_packetDataLen)
-            {
-                OIC_LOG(DEBUG, TAG, "Read Comp BLE Pckt");
-                if (g_receivedDataLen > 0)
-                {
-                    OIC_LOG_V(DEBUG, TAG, "recv dataLen=%u", g_receivedDataLen);
-                    uint32_t sentLength = 0;
-                    // g_coapBuffer getting freed by CAMesssageHandler
-                    g_bleServerDataReceivedCallback("", g_coapBuffer,
-                                                    g_receivedDataLen, &sentLength);
-                }
-
-                g_receivedDataLen = 0;
-                OICFree(g_coapBuffer);
-                g_coapBuffer = NULL;
-                break;
-            }
+            g_receivedDataLen = 0;
+            OICFree(g_coapBuffer);
+            g_coapBuffer = NULL;
         }
         OIC_LOG(DEBUG, TAG, "OUT");
     }
index f6c001f..e459eb0 100644 (file)
@@ -22,6 +22,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "cafragmentation.h"
+
 #include "caleinterface.h"
 #include "cacommon.h"
 #include "camutex.h"
 #define CALEADAPTER_TAG "OIC_CA_LE_ADAP"
 
 /**
- * The MTU supported for BLE adapter
- */
-#define CA_SUPPORTED_BLE_MTU_SIZE  20
-
-/**
  * Stores information of all the senders.
  *
  * This structure will be used to track and defragment all incoming
@@ -81,6 +78,11 @@ static CAAdapterChangeCallback g_networkCallback = NULL;
 static CAConnectionChangeCallback g_connectionCallback = NULL;
 
 /**
+ * Own port value to identify packet owner. Default port value is 1.
+ */
+static uint8_t g_localBLESourcePort = 1;
+
+/**
  * bleAddress of the local adapter. Value will be initialized to zero,
  * and will be updated later.
  */
@@ -151,6 +153,42 @@ static CANetworkPacketReceivedCallback g_networkPacketReceivedCallback = NULL;
  */
 static CAErrorHandleCallback g_errorHandler = NULL;
 
+#ifdef SINGLE_THREAD
+/**
+ * Pointer to defragment received data from single threaded routine.
+ */
+static CABLESenderInfo_t *g_singleThreadReceiveData = NULL;
+
+/**
+ * This function will be associated with the receive for single thread.
+ *
+ * This function will defragment the received data from sender
+ * respectively and will send it up to CA layer. Respective sender's
+ * header will provide the length of the data sent.
+ *
+ * @param[in] data       Actual data received from the remote
+ *                       device.
+ * @param[in] dataLen    Length of the data received from the
+ *                       remote device.
+ */
+static void CALEDataReceiverHandlerSingleThread(const uint8_t *data,
+                                                uint32_t dataLen);
+
+/**
+ * This function will be associated with the send for single threaded
+ * GattServer.
+ *
+ * This function will fragment the data to the MTU of the transport
+ * and send the data in fragments to the adapters. The function will
+ * be blocked until all data is sent out from the adapter.
+ *
+ * @param[in] data       Data to be transmitted from LE.
+ * @param[in] dataLen    Length of the Data being transmitted.
+ */
+static CAResult_t CALEServerSendDataSingleThread(const uint8_t *data,
+                                                 uint32_t dataLen);
+#endif
+
 /**
  * Register network change notification callback.
  *
@@ -422,6 +460,37 @@ static void CALERemoveSendQueueData(CAQueueingThread_t *queueHandle,
  */
 static void CALERemoveReceiveQueueData(u_arraylist_t *dataInfoList,
                                        const char* address);
+
+/**
+ * get received data info and positioned index from the received data list
+ * for client / server which is matched same leAddress and port.
+ *
+ * @param[in]  leAddress       target address to get serderInfo.
+ * @param[in]  port            target port to get serderInfo.
+ * @param[in]  senderInfoList  received data list for client / server.
+ * @param[out] senderInfo      Pointer to contain matched(leAddress and port)
+ *                             received data info.
+ * @param[out] senderIndex     Pointer to contain matched(leAddress and port)
+ *                             received data info index.
+ */
+static CAResult_t CALEGetSenderInfo(const char *leAddress,
+                                    const uint16_t port,
+                                    u_arraylist_t *senderInfoList,
+                                    CABLESenderInfo_t **senderInfo,
+                                    uint32_t *senderIndex);
+
+/**
+ * get ports related to remote address. It is need because multi application
+ * can have more than 2 senderInfo using same BLE address. So before remove
+ * receive queue data, should get port list from sender Info.
+ *
+ * @param[in]  leAddress       target address to get port in serderInfo.
+ * @param[in]  senderInfoList  received data list to remove for client / server.
+ * @param[out] portList        target port list related to leAddress.
+ */
+static CAResult_t CALEGetPortsFromSenderInfo(const char *leAddress,
+                                            u_arraylist_t *senderInfoList,
+                                            u_arraylist_t *portList);
 #endif
 
 static CAResult_t CAInitLEServerQueues()
@@ -667,6 +736,7 @@ static void CATerminateLEQueues()
 }
 
 static CAResult_t CALEGetSenderInfo(const char *leAddress,
+                                    const uint16_t port,
                                     u_arraylist_t *senderInfoList,
                                     CABLESenderInfo_t **senderInfo,
                                     uint32_t *senderIndex)
@@ -685,19 +755,22 @@ static CAResult_t CALEGetSenderInfo(const char *leAddress,
     for (uint32_t index = 0; index < listLength; index++)
     {
         CABLESenderInfo_t *info = (CABLESenderInfo_t *) u_arraylist_get(senderInfoList, index);
-        if(!info || !(info->remoteEndpoint))
+        if (!info || !(info->remoteEndpoint))
         {
             continue;
         }
 
-        if(!strncmp(info->remoteEndpoint->addr, leAddress, addrLength))
+        if (!strncmp(info->remoteEndpoint->addr, leAddress, addrLength))
         {
-            *senderIndex = index;
-            if(senderInfo)
+            if (info->remoteEndpoint->port == port)
             {
-                *senderInfo = info;
+                *senderIndex = index;
+                if (senderInfo)
+                {
+                    *senderInfo = info;
+                }
+                return CA_STATUS_OK;
             }
-            return CA_STATUS_OK;
         }
     }
 
@@ -739,18 +812,66 @@ static void CALEDataReceiverHandler(void *threadData)
         CABLESenderInfo_t *senderInfo = NULL;
         uint32_t senderIndex = 0;
 
-        if(CA_STATUS_OK != CALEGetSenderInfo(bleData->remoteEndpoint->addr,
-                                             bleData->senderInfo,
-                                             &senderInfo, &senderIndex))
+        //packet parsing
+        CABLEPacketStart_t startFlag = CA_BLE_PACKET_NOT_START;
+        CABLEPacketSecure_t secureFlag = CA_BLE_PACKET_NON_SECURE;
+        uint16_t sourcePort = 0;
+        uint16_t destPort = 0;
+
+        CAParseHeader(bleData->data, &startFlag, &sourcePort, &secureFlag, &destPort);
+        OIC_LOG_V(DEBUG, CALEADAPTER_TAG,
+                  "header info: startFlag[%X] sourcePort[%d] secureFlag[%X] destPort[%d]",
+                  startFlag, sourcePort, secureFlag, destPort);
+
+        if (destPort != g_localBLESourcePort && destPort != CA_BLE_MULTICAST_PORT)
         {
-            OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "This is a new client [%s]",
-                      bleData->remoteEndpoint->addr);
+            OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                      "this packet is not valid for this app(port mismatch[mine:%d, packet:%d])",
+                      g_localBLESourcePort, destPort);
+            ca_mutex_unlock(g_bleReceiveDataMutex);
+            return;
+        }
+
+        bleData->remoteEndpoint->port = sourcePort;
+
+        if (CA_STATUS_OK != CALEGetSenderInfo(bleData->remoteEndpoint->addr,
+                                              bleData->remoteEndpoint->port,
+                                              bleData->senderInfo,
+                                              &senderInfo, &senderIndex))
+        {
+            OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "This is a new client [%s:%X]",
+                      bleData->remoteEndpoint->addr, bleData->remoteEndpoint->port);
+        }
+        else
+        {
+            if (startFlag)
+            {
+                OIC_LOG(ERROR, CALEADAPTER_TAG,
+                        "This packet is start packet but exist senderInfo. Remove senderInfo");
+                u_arraylist_remove(bleData->senderInfo, senderIndex);
+                OICFree(senderInfo->defragData);
+                OICFree(senderInfo);
+                senderInfo = NULL;
+                senderIndex = 0;
+            }
         }
 
-        if(!senderInfo)
+        if (!senderInfo)
         {
+            uint32_t totalLength = 0;
+            if (startFlag)
+            {
+                CAParseHeaderPayloadLength(bleData->data, CA_BLE_LENGTH_HEADER_SIZE, &totalLength);
+            }
+            else
+            {
+                OIC_LOG(ERROR, CALEADAPTER_TAG, "This packet is wrong packet! ignore.");
+                ca_mutex_unlock(g_bleReceiveDataMutex);
+                return;
+            }
+
             CABLESenderInfo_t *newSender = OICMalloc(sizeof(CABLESenderInfo_t));
-            if(!newSender)
+            if (!newSender)
             {
                 OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed for new sender");
                 ca_mutex_unlock(g_bleReceiveDataMutex);
@@ -763,9 +884,9 @@ static void CALEDataReceiverHandler(void *threadData)
 
             OIC_LOG(DEBUG, CALEADAPTER_TAG, "Parsing the header");
 
-            newSender->totalDataLen = coap_get_total_message_length(bleData->data, bleData->dataLen);
+            newSender->totalDataLen = totalLength;
 
-            if(!(newSender->totalDataLen))
+            if (!(newSender->totalDataLen))
             {
                 OIC_LOG(ERROR, CALEADAPTER_TAG, "Total Data Length is parsed as 0!!!");
                 OICFree(newSender);
@@ -773,10 +894,12 @@ static void CALEDataReceiverHandler(void *threadData)
                 return;
             }
 
+            size_t dataOnlyLen =
+                bleData->dataLen - (CA_BLE_HEADER_SIZE + CA_BLE_LENGTH_HEADER_SIZE);
             OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Total data to be accumulated [%u] bytes",
                       newSender->totalDataLen);
             OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "data received in the first packet [%u] bytes",
-                      bleData->dataLen);
+                      dataOnlyLen);
 
             newSender->defragData = OICCalloc(newSender->totalDataLen + 1,
                                               sizeof(*newSender->defragData));
@@ -793,7 +916,8 @@ static void CALEDataReceiverHandler(void *threadData)
             newSender->remoteEndpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
                                                                CA_ADAPTER_GATT_BTLE,
                                                                remoteAddress,
-                                                               0);
+                                                               bleData->remoteEndpoint->port);
+
             if (NULL == newSender->remoteEndpoint)
             {
                 OIC_LOG(ERROR, CALEADAPTER_TAG, "remoteEndpoint is NULL!");
@@ -803,7 +927,7 @@ static void CALEDataReceiverHandler(void *threadData)
                 return;
             }
 
-            if (newSender->recvDataLen + bleData->dataLen > newSender->totalDataLen)
+            if (newSender->recvDataLen + dataOnlyLen > newSender->totalDataLen)
             {
                 OIC_LOG(ERROR, CALEADAPTER_TAG, "buffer is smaller than received data");
                 OICFree(newSender->defragData);
@@ -812,15 +936,19 @@ static void CALEDataReceiverHandler(void *threadData)
                 ca_mutex_unlock(g_bleReceiveDataMutex);
                 return;
             }
-            memcpy(newSender->defragData, bleData->data, bleData->dataLen);
-            newSender->recvDataLen += bleData->dataLen;
+            memcpy(newSender->defragData,
+                   bleData->data + (CA_BLE_HEADER_SIZE + CA_BLE_LENGTH_HEADER_SIZE),
+                   dataOnlyLen);
+            newSender->recvDataLen += dataOnlyLen;
 
             u_arraylist_add(bleData->senderInfo,(void *)newSender);
 
             //Getting newSender index position in bleSenderInfo array list
-            if(CA_STATUS_OK !=
-                CALEGetSenderInfo(newSender->remoteEndpoint->addr, bleData->senderInfo,
-                                  NULL, &senderIndex))
+            if (CA_STATUS_OK !=
+                    CALEGetSenderInfo(newSender->remoteEndpoint->addr,
+                                      newSender->remoteEndpoint->port,
+                                      bleData->senderInfo,
+                                      NULL, &senderIndex))
             {
                 OIC_LOG(ERROR, CALEADAPTER_TAG, "Existing sender index not found!!");
                 OICFree(newSender->defragData);
@@ -833,11 +961,12 @@ static void CALEDataReceiverHandler(void *threadData)
         }
         else
         {
-            if(senderInfo->recvDataLen + bleData->dataLen > senderInfo->totalDataLen)
+            size_t dataOnlyLen = bleData->dataLen - CA_BLE_HEADER_SIZE;
+            if (senderInfo->recvDataLen + dataOnlyLen > senderInfo->totalDataLen)
             {
                 OIC_LOG_V(ERROR, CALEADAPTER_TAG,
                           "Data Length exceeding error!! Receiving [%d] total length [%d]",
-                          senderInfo->recvDataLen + bleData->dataLen, senderInfo->totalDataLen);
+                          senderInfo->recvDataLen + dataOnlyLen, senderInfo->totalDataLen);
                 u_arraylist_remove(bleData->senderInfo, senderIndex);
                 OICFree(senderInfo->defragData);
                 OICFree(senderInfo);
@@ -845,10 +974,11 @@ static void CALEDataReceiverHandler(void *threadData)
                 return;
             }
             OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Copying the data of length [%d]",
-                      bleData->dataLen);
-            memcpy(senderInfo->defragData + senderInfo->recvDataLen, bleData->data,
-                   bleData->dataLen);
-            senderInfo->recvDataLen += bleData->dataLen ;
+                      dataOnlyLen);
+            memcpy(senderInfo->defragData + senderInfo->recvDataLen,
+                   bleData->data + CA_BLE_HEADER_SIZE,
+                   dataOnlyLen);
+            senderInfo->recvDataLen += dataOnlyLen;
             OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "totalDatalength  [%d] received Datalen [%d]",
                                                 senderInfo->totalDataLen, senderInfo->recvDataLen);
         }
@@ -900,36 +1030,104 @@ static void CALEServerSendDataThread(void *threadData)
         return;
     }
 
-    const uint32_t totalLength = bleData->dataLen;
+    uint32_t midPacketCount = 0;
+    size_t remainingLen = 0;
+    size_t totalLength = 0;
+    CABLEPacketSecure_t secureFlag = CA_BLE_PACKET_NON_SECURE;
+
+    CAResult_t result = CAGenerateVariableForFragmentation(bleData->dataLen,
+                                                           &midPacketCount,
+                                                           &remainingLen,
+                                                           &totalLength);
+
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                  "CAGenerateVariableForFragmentation failed, result [%d]", result);
+        g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+        return;
+    }
+
+    OIC_LOG_V(DEBUG, CALEADAPTER_TAG,
+              "Packet info: data size[%d] midPacketCount[%d] remainingLen[%d] totalLength[%d]",
+              bleData->dataLen, midPacketCount, remainingLen, totalLength);
 
     OIC_LOG_V(DEBUG,
               CALEADAPTER_TAG,
               "Server total Data length with header is [%u]",
               totalLength);
 
-    uint8_t * const dataSegment = OICCalloc(totalLength, 1);
+    uint8_t dataSegment[CA_SUPPORTED_BLE_MTU_SIZE] = {0};
+    uint8_t dataHeader[CA_BLE_HEADER_SIZE] = {0};
+
+    if (NULL != bleData->remoteEndpoint) //Unicast Data
+    {
+        secureFlag = bleData->remoteEndpoint->flags == CA_SECURE ?
+            CA_BLE_PACKET_SECURE : CA_BLE_PACKET_NON_SECURE;
+
+        result = CAGenerateHeader(dataHeader,
+                                  CA_BLE_PACKET_START,
+                                  g_localBLESourcePort,
+                                  secureFlag,
+                                  bleData->remoteEndpoint->port);
+    }
+    else                                //Multicast Data
+    {
+        result = CAGenerateHeader(dataHeader,
+                                  CA_BLE_PACKET_START,
+                                  g_localBLESourcePort,
+                                  secureFlag,
+                                  CA_BLE_MULTICAST_PORT);
+    }
 
-    if (NULL == dataSegment)
+    if (CA_STATUS_OK != result)
     {
-        OIC_LOG(ERROR, CALEADAPTER_TAG, "Malloc failed");
+        OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                  "CAGenerateHeader failed, result [%d]", result);
+        g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+        return;
+    }
+
+    uint8_t lengthHeader[CA_BLE_LENGTH_HEADER_SIZE] = {0};
+    result = CAGenerateHeaderPayloadLength(lengthHeader,
+                                           CA_BLE_LENGTH_HEADER_SIZE,
+                                           bleData->dataLen);
+
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                  "CAGenerateHeaderPayloadLength failed, result [%d]", result);
+        g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
         return;
     }
 
     uint32_t length = 0;
+    uint32_t dataLen = 0;
     if (CA_SUPPORTED_BLE_MTU_SIZE > totalLength)
     {
         length = totalLength;
-        memcpy(dataSegment, bleData->data, bleData->dataLen);
+        dataLen = bleData->dataLen;
     }
     else
     {
-        length =  CA_SUPPORTED_BLE_MTU_SIZE;
-        memcpy(dataSegment, bleData->data, CA_SUPPORTED_BLE_MTU_SIZE);
+        length = CA_SUPPORTED_BLE_MTU_SIZE;
+        dataLen = CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE - CA_BLE_LENGTH_HEADER_SIZE;
+    }
+
+    result = CAMakeFirstDataSegment(dataSegment,
+                                    bleData->data, dataLen,
+                                    dataHeader, lengthHeader);
+
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                  "Making data segment failed, result [%d]", result);
+        g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+        return;
     }
 
-    uint32_t iter = totalLength / CA_SUPPORTED_BLE_MTU_SIZE;
+    const uint32_t iter = midPacketCount;
     uint32_t index = 0;
-    CAResult_t result = CA_STATUS_FAILED;
 
     // Send the first segment with the header.
     if (NULL != bleData->remoteEndpoint) // Sending Unicast Data
@@ -950,7 +1148,6 @@ static void CALEServerSendDataThread(void *threadData)
                            bleData->data,
                            bleData->dataLen,
                            result);
-            OICFree(dataSegment);
             return;
         }
 
@@ -958,7 +1155,22 @@ static void CALEServerSendDataThread(void *threadData)
                   CALEADAPTER_TAG,
                   "Server Sent data length [%u]",
                   length);
-        for (index = 1; index < iter; index++)
+
+        result = CAGenerateHeader(dataHeader,
+                                  CA_BLE_PACKET_NOT_START,
+                                  g_localBLESourcePort,
+                                  secureFlag,
+                                  bleData->remoteEndpoint->port);
+
+        if (CA_STATUS_OK != result)
+        {
+            OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                      "CAGenerateHeader failed, result [%d]", result);
+            g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+            return;
+        }
+
+        for (index = 0; index < iter; index++)
         {
             // Send the remaining header.
             OIC_LOG_V(DEBUG,
@@ -966,10 +1178,24 @@ static void CALEServerSendDataThread(void *threadData)
                       "Sending the chunk number [%u]",
                       index);
 
+            result = CAMakeRemainDataSegment(dataSegment,
+                                             bleData->data,
+                                             CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE,
+                                             index,
+                                             dataHeader);
+
+            if (CA_STATUS_OK != result)
+            {
+                OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                            "Making data segment failed, result [%d]", result);
+                g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+                return;
+            }
+
             result =
                 CAUpdateCharacteristicsToGattClient(
                     bleData->remoteEndpoint->addr,
-                    bleData->data + ((index * CA_SUPPORTED_BLE_MTU_SIZE)),
+                    dataSegment,
                     CA_SUPPORTED_BLE_MTU_SIZE);
 
             if (CA_STATUS_OK != result)
@@ -977,26 +1203,36 @@ static void CALEServerSendDataThread(void *threadData)
                 OIC_LOG_V(ERROR, CALEADAPTER_TAG,
                             "Update characteristics failed, result [%d]", result);
                 g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
-                OICFree(dataSegment);
                 return;
             }
             OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server Sent data length [%d]",
                                                CA_SUPPORTED_BLE_MTU_SIZE);
         }
 
-        const uint32_t remainingLen =
-            totalLength % CA_SUPPORTED_BLE_MTU_SIZE;
-
         if (remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE))
         {
             // send the last segment of the data (Ex: 22 bytes of 622
             // bytes of data when MTU is 200)
             OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending the last chunk");
 
+            result = CAMakeRemainDataSegment(dataSegment,
+                                             bleData->data,
+                                             remainingLen,
+                                             index,
+                                             dataHeader);
+
+            if (CA_STATUS_OK != result)
+            {
+                OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                            "Making data segment failed, result [%d]", result);
+                g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+                return;
+            }
+
             result = CAUpdateCharacteristicsToGattClient(
                          bleData->remoteEndpoint->addr,
-                         bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE),
-                         remainingLen);
+                         dataSegment,
+                         remainingLen + CA_BLE_HEADER_SIZE);
 
             if (CA_STATUS_OK != result)
             {
@@ -1008,10 +1244,10 @@ static void CALEServerSendDataThread(void *threadData)
                                bleData->data,
                                bleData->dataLen,
                                result);
-                OICFree(dataSegment);
                 return;
             }
-            OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server Sent data length [%d]", remainingLen);
+            OIC_LOG_V(DEBUG, CALEADAPTER_TAG,
+                      "Server Sent data length [%d]", remainingLen + CA_BLE_HEADER_SIZE);
         }
      }
     else
@@ -1023,17 +1259,45 @@ static void CALEServerSendDataThread(void *threadData)
             OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics failed, result [%d]",
                       result);
             CALEErrorHandler(NULL, bleData->data, bleData->dataLen, result);
-            OICFree(dataSegment);
             return;
         }
         OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server Sent data length [%d]", length);
-        for (index = 1; index < iter; index++)
+
+        result = CAGenerateHeader(dataHeader,
+                                  CA_BLE_PACKET_NOT_START,
+                                  g_localBLESourcePort,
+                                  secureFlag,
+                                  CA_BLE_MULTICAST_PORT);
+
+        if (CA_STATUS_OK != result)
+        {
+            OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                      "CAGenerateHeader failed, result [%d]", result);
+            g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+            return;
+        }
+
+        for (index = 0; index < iter; index++)
         {
             // Send the remaining header.
             OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Sending the chunk number [%d]", index);
 
+            result = CAMakeRemainDataSegment(dataSegment,
+                                             bleData->data,
+                                             CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE,
+                                             index,
+                                             dataHeader);
+
+            if (CA_STATUS_OK != result)
+            {
+                OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                            "Making data segment failed, result [%d]", result);
+                g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+                return;
+            }
+
             result = CAUpdateCharacteristicsToAllGattClients(
-                         bleData->data + ((index * CA_SUPPORTED_BLE_MTU_SIZE)),
+                         dataSegment,
                          CA_SUPPORTED_BLE_MTU_SIZE);
 
             if (CA_STATUS_OK != result)
@@ -1041,35 +1305,46 @@ static void CALEServerSendDataThread(void *threadData)
                 OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics failed, result [%d]",
                           result);
                 CALEErrorHandler(NULL, bleData->data, bleData->dataLen, result);
-                OICFree(dataSegment);
                 return;
             }
             OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server Sent data length [%u]",
                       CA_SUPPORTED_BLE_MTU_SIZE);
         }
 
-        const uint32_t remainingLen = totalLength % CA_SUPPORTED_BLE_MTU_SIZE;
         if (remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE))
         {
             // send the last segment of the data
             OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending the last chunk");
 
+            result = CAMakeRemainDataSegment(dataSegment,
+                                             bleData->data,
+                                             remainingLen,
+                                             index,
+                                             dataHeader);
+
+            if (CA_STATUS_OK != result)
+            {
+                OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                            "Making data segment failed, result [%d]", result);
+                g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+                return;
+            }
+
             result = CAUpdateCharacteristicsToAllGattClients(
-                         bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE),
-                         remainingLen);
+                         dataSegment,
+                         remainingLen + CA_BLE_HEADER_SIZE);
 
             if (CA_STATUS_OK != result)
             {
                 OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics failed, result [%d]",
                           result);
                 CALEErrorHandler(NULL, bleData->data, bleData->dataLen, result);
-                OICFree(dataSegment);
                 return;
             }
-            OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server Sent data length [%d]", remainingLen);
+            OIC_LOG_V(DEBUG, CALEADAPTER_TAG,
+                      "Server Sent data length [%d]", remainingLen + CA_BLE_HEADER_SIZE);
         }
     }
-    OICFree(dataSegment);
 
     OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT - CALEServerSendDataThread");
 }
@@ -1085,33 +1360,98 @@ static void CALEClientSendDataThread(void *threadData)
         return;
     }
 
-    const uint32_t totalLength = bleData->dataLen;
+    uint32_t midPacketCount = 0;
+    size_t remainingLen = 0;
+    size_t totalLength = 0;
+    CABLEPacketSecure_t secureFlag = CA_BLE_PACKET_NON_SECURE;
+
+    CAResult_t result = CAGenerateVariableForFragmentation(bleData->dataLen,
+                                                           &midPacketCount,
+                                                           &remainingLen,
+                                                           &totalLength);
 
-    uint8_t *dataSegment = OICCalloc(totalLength, 1);
-    if (NULL == dataSegment)
+    if (CA_STATUS_OK != result)
     {
-        OIC_LOG(ERROR, CALEADAPTER_TAG, "Malloc failed");
+        OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                  "CAGenerateVariableForFragmentation failed, result [%d]", result);
+        g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+        return;
+    }
+
+    OIC_LOG_V(DEBUG, CALEADAPTER_TAG,
+              "Packet info: data size[%d] midPacketCount[%d] remainingLen[%d] totalLength[%d]",
+              bleData->dataLen, midPacketCount, remainingLen, totalLength);
+
+    uint8_t dataSegment[CA_SUPPORTED_BLE_MTU_SIZE] = {0};
+    uint8_t dataHeader[CA_BLE_HEADER_SIZE] = {0};
+
+    if (NULL != bleData->remoteEndpoint) //Unicast Data
+    {
+        secureFlag = bleData->remoteEndpoint->flags == CA_SECURE ?
+            CA_BLE_PACKET_SECURE : CA_BLE_PACKET_NON_SECURE;
+
+        result = CAGenerateHeader(dataHeader,
+                                  CA_BLE_PACKET_START,
+                                  g_localBLESourcePort,
+                                  secureFlag,
+                                  bleData->remoteEndpoint->port);
+    }
+    else                                //Multicast Data
+    {
+        result = CAGenerateHeader(dataHeader,
+                                  CA_BLE_PACKET_START,
+                                  g_localBLESourcePort,
+                                  secureFlag,
+                                  CA_BLE_MULTICAST_PORT);
+    }
+
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                  "CAGenerateHeader failed, result [%d]", result);
+        g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+        return;
+    }
+
+    uint8_t lengthHeader[CA_BLE_LENGTH_HEADER_SIZE] = {0};
+    result = CAGenerateHeaderPayloadLength(lengthHeader,
+                                           CA_BLE_LENGTH_HEADER_SIZE,
+                                           bleData->dataLen);
+
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                  "CAGenerateHeaderPayloadLength failed, result [%d]", result);
+        g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
         return;
     }
 
     uint32_t length = 0;
+    uint32_t dataLen = 0;
     if (CA_SUPPORTED_BLE_MTU_SIZE > totalLength)
     {
         length = totalLength;
-        memcpy(dataSegment,
-               bleData->data,
-               bleData->dataLen);
+        dataLen = bleData->dataLen;
     }
     else
     {
         length = CA_SUPPORTED_BLE_MTU_SIZE;
-        memcpy(dataSegment,
-               bleData->data,
-               CA_SUPPORTED_BLE_MTU_SIZE);
+        dataLen = CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE - CA_BLE_LENGTH_HEADER_SIZE;
     }
 
-    CAResult_t result = CA_STATUS_FAILED;
-    const uint32_t iter = totalLength / CA_SUPPORTED_BLE_MTU_SIZE;
+    result = CAMakeFirstDataSegment(dataSegment,
+                                    bleData->data, dataLen,
+                                    dataHeader, lengthHeader);
+
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                  "Making data segment failed, result [%d]", result);
+        g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+        return;
+    }
+
+    const uint32_t iter = midPacketCount;
     uint32_t index = 0;
     if (NULL != bleData->remoteEndpoint) //Sending Unicast Data
     {
@@ -1135,7 +1475,6 @@ static void CALEClientSendDataThread(void *threadData)
                            bleData->data,
                            bleData->dataLen,
                            result);
-            OICFree(dataSegment);
             return;
         }
 
@@ -1144,12 +1483,40 @@ static void CALEClientSendDataThread(void *threadData)
                   "Client Sent Data length  is [%u]",
                   length);
 
-        for (index = 1; index < iter; index++)
+        result = CAGenerateHeader(dataHeader,
+                                  CA_BLE_PACKET_NOT_START,
+                                  g_localBLESourcePort,
+                                  secureFlag,
+                                  bleData->remoteEndpoint->port);
+
+        if (CA_STATUS_OK != result)
         {
+            OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                      "CAGenerateHeader failed, result [%d]", result);
+            g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+            return;
+        }
+
+        for (index = 0; index < iter; index++)
+        {
+            result = CAMakeRemainDataSegment(dataSegment,
+                                             bleData->data,
+                                             CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE,
+                                             index,
+                                             dataHeader);
+
+            if (CA_STATUS_OK != result)
+            {
+                OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                            "Making data segment failed, result [%d]", result);
+                g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+                return;
+            }
+
             // Send the remaining header.
             result = CAUpdateCharacteristicsToGattServer(
                      bleData->remoteEndpoint->addr,
-                     bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE),
+                     dataSegment,
                      CA_SUPPORTED_BLE_MTU_SIZE,
                      LE_UNICAST, 0);
 
@@ -1160,24 +1527,36 @@ static void CALEClientSendDataThread(void *threadData)
                           "Update characteristics failed, result [%d]",
                           result);
                 g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
-                OICFree(dataSegment);
                 return;
             }
             OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Client Sent Data length  is [%d]",
                                                CA_SUPPORTED_BLE_MTU_SIZE);
         }
 
-        const uint32_t remainingLen = totalLength % CA_SUPPORTED_BLE_MTU_SIZE;
         if (remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE))
         {
             // send the last segment of the data (Ex: 22 bytes of 622
             // bytes of data when MTU is 200)
             OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending the last chunk");
 
+            result = CAMakeRemainDataSegment(dataSegment,
+                                             bleData->data,
+                                             remainingLen,
+                                             index,
+                                             dataHeader);
+
+            if (CA_STATUS_OK != result)
+            {
+                OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                            "Making data segment failed, result [%d]", result);
+                g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+                return;
+            }
+
             result = CAUpdateCharacteristicsToGattServer(
                      bleData->remoteEndpoint->addr,
-                     bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE),
-                     remainingLen,
+                     dataSegment,
+                     remainingLen + CA_BLE_HEADER_SIZE,
                      LE_UNICAST, 0);
 
             if (CA_STATUS_OK != result)
@@ -1185,10 +1564,10 @@ static void CALEClientSendDataThread(void *threadData)
                 OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics failed, result [%d]",
                                                    result);
                 g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
-                OICFree(dataSegment);
                 return;
             }
-            OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Client Sent Data length  is [%d]", remainingLen);
+            OIC_LOG_V(DEBUG, CALEADAPTER_TAG,
+                      "Client Sent Data length  is [%d]", remainingLen + CA_BLE_HEADER_SIZE);
         }
     }
     else
@@ -1202,15 +1581,43 @@ static void CALEClientSendDataThread(void *threadData)
             OIC_LOG_V(ERROR, CALEADAPTER_TAG,
                       "Update characteristics (all) failed, result [%d]", result);
             CALEErrorHandler(NULL, bleData->data, bleData->dataLen, result);
-            OICFree(dataSegment);
             return ;
         }
         OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Client Sent Data length  is [%d]", length);
+
+        result = CAGenerateHeader(dataHeader,
+                                  CA_BLE_PACKET_NOT_START,
+                                  g_localBLESourcePort,
+                                  secureFlag,
+                                  0);
+
+        if (CA_STATUS_OK != result)
+        {
+            OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                      "CAGenerateHeader failed, result [%d]", result);
+            g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+            return;
+        }
+
         // Send the remaining header.
-        for (index = 1; index < iter; index++)
+        for (index = 0; index < iter; index++)
         {
+            result = CAMakeRemainDataSegment(dataSegment,
+                                             bleData->data,
+                                             CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE,
+                                             index,
+                                             dataHeader);
+
+            if (CA_STATUS_OK != result)
+            {
+                OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                            "Making data segment failed, result [%d]", result);
+                g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+                return;
+            }
+
             result = CAUpdateCharacteristicsToAllGattServers(
-                         bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE),
+                         dataSegment,
                          CA_SUPPORTED_BLE_MTU_SIZE);
 
             if (CA_STATUS_OK != result)
@@ -1218,39 +1625,49 @@ static void CALEClientSendDataThread(void *threadData)
                 OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics failed, result [%d]",
                           result);
                 CALEErrorHandler(NULL, bleData->data, bleData->dataLen, result);
-                OICFree(dataSegment);
                 return;
             }
             OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Client Sent Data length  is [%d]",
                       CA_SUPPORTED_BLE_MTU_SIZE);
         }
 
-        uint32_t remainingLen = totalLength % CA_SUPPORTED_BLE_MTU_SIZE;
         if (remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE))
         {
             // send the last segment of the data (Ex: 22 bytes of 622
             // bytes of data when MTU is 200)
             OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending the last chunk");
+
+            result = CAMakeRemainDataSegment(dataSegment,
+                                             bleData->data,
+                                             remainingLen,
+                                             index,
+                                             dataHeader);
+
+            if (CA_STATUS_OK != result)
+            {
+                OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                            "Making data segment failed, result [%d]", result);
+                g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+                return;
+            }
+
             result =
                 CAUpdateCharacteristicsToAllGattServers(
-                    bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE),
-                    remainingLen);
+                    dataSegment,
+                    remainingLen + CA_BLE_HEADER_SIZE);
 
             if (CA_STATUS_OK != result)
             {
                 OIC_LOG_V(ERROR, CALEADAPTER_TAG,
                           "Update characteristics (all) failed, result [%d]", result);
                 CALEErrorHandler(NULL, bleData->data, bleData->dataLen, result);
-                OICFree(dataSegment);
                 return;
             }
-            OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Client Sent Data length  is [%d]", remainingLen);
+            OIC_LOG_V(DEBUG, CALEADAPTER_TAG,
+                      "Client Sent Data length  is [%d]", remainingLen + CA_BLE_HEADER_SIZE);
         }
-
     }
 
-    OICFree(dataSegment);
-
     OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT - CABLEClientSendDataThread");
 }
 
@@ -1309,6 +1726,299 @@ static void CALEDataDestroyer(void *data, uint32_t size)
 }
 #endif
 
+#ifdef SINGLE_THREAD
+static void CALEDataReceiverHandlerSingleThread(const uint8_t *data,
+                                                uint32_t dataLen)
+{
+    OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
+
+    VERIFY_NON_NULL(data, CALEADAPTER_TAG, "Param data is NULL");
+
+    //packet parsing
+    CABLEPacketStart_t startFlag = CA_BLE_PACKET_NOT_START;
+    CABLEPacketSecure_t secureFlag = CA_BLE_PACKET_NON_SECURE;
+    uint16_t sourcePort = 0;
+    uint16_t destPort = 0;
+
+    CAParseHeader(data, &startFlag, &sourcePort, &secureFlag, &destPort);
+    OIC_LOG_V(DEBUG, CALEADAPTER_TAG,
+              "header info: startFlag[%X] sourcePort[%d] secureFlag[%X] destPort[%d]",
+              startFlag, sourcePort, secureFlag, destPort);
+
+    if (destPort != g_localBLESourcePort && destPort != CA_BLE_MULTICAST_PORT)
+    {
+        OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                  "this packet is not valid for this app(port mismatch[mine:%d, packet:%d])",
+                  g_localBLESourcePort, destPort);
+        return;
+    }
+
+    if (startFlag)
+    {
+        if (g_singleThreadReceiveData)
+        {
+            OIC_LOG(ERROR, CALEADAPTER_TAG,
+                    "This packet is start packet but exist senderInfo. Remove senderInfo");
+            OICFree(g_singleThreadReceiveData->defragData);
+            OICFree(g_singleThreadReceiveData);
+            g_singleThreadReceiveData = NULL;
+        }
+
+        uint32_t totalLength = 0;
+        CAParseHeaderPayloadLength(data, CA_BLE_LENGTH_HEADER_SIZE, &totalLength);
+
+        g_singleThreadReceiveData = OICMalloc(sizeof(CABLESenderInfo_t));
+
+        if (!g_singleThreadReceiveData)
+        {
+            OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed for new sender");
+            return;
+        }
+        g_singleThreadReceiveData->recvDataLen = 0;
+        g_singleThreadReceiveData->totalDataLen = 0;
+        g_singleThreadReceiveData->defragData = NULL;
+        g_singleThreadReceiveData->remoteEndpoint = NULL;
+
+        OIC_LOG(DEBUG, CALEADAPTER_TAG, "Parsing the header");
+
+        g_singleThreadReceiveData->totalDataLen = totalLength;
+
+        if (!(g_singleThreadReceiveData->totalDataLen))
+        {
+            OIC_LOG(ERROR, CALEADAPTER_TAG, "Total Data Length is parsed as 0!!!");
+            OICFree(g_singleThreadReceiveData);
+            return;
+        }
+
+        size_t dataOnlyLen = dataLen - (CA_BLE_HEADER_SIZE + CA_BLE_LENGTH_HEADER_SIZE);
+        OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Total data to be accumulated [%u] bytes",
+                  g_singleThreadReceiveData->totalDataLen);
+        OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "data received in the first packet [%u] bytes",
+                  dataOnlyLen);
+
+        g_singleThreadReceiveData->defragData =
+            OICCalloc(g_singleThreadReceiveData->totalDataLen + 1,
+                    sizeof(*g_singleThreadReceiveData->defragData));
+
+        if (NULL == g_singleThreadReceiveData->defragData)
+        {
+            OIC_LOG(ERROR, CALEADAPTER_TAG, "defragData is NULL!");
+            OICFree(g_singleThreadReceiveData);
+            return;
+        }
+
+        if (g_singleThreadReceiveData->recvDataLen + dataOnlyLen
+                > g_singleThreadReceiveData->totalDataLen)
+        {
+            OIC_LOG(ERROR, CALEADAPTER_TAG, "buffer is smaller than received data");
+            OICFree(g_singleThreadReceiveData->defragData);
+            OICFree(g_singleThreadReceiveData);
+            return;
+        }
+        memcpy(g_singleThreadReceiveData->defragData,
+               data + (CA_BLE_HEADER_SIZE + CA_BLE_LENGTH_HEADER_SIZE),
+               dataOnlyLen);
+        g_singleThreadReceiveData->recvDataLen += dataOnlyLen;
+    }
+    else
+    {
+        size_t dataOnlyLen = dataLen - CA_BLE_HEADER_SIZE;
+        if (g_singleThreadReceiveData->recvDataLen + dataOnlyLen
+                > g_singleThreadReceiveData->totalDataLen)
+        {
+            OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                      "Data Length exceeding error!! Receiving [%d] total length [%d]",
+                      g_singleThreadReceiveData->recvDataLen + dataOnlyLen,
+                      g_singleThreadReceiveData->totalDataLen);
+            OICFree(g_singleThreadReceiveData->defragData);
+            OICFree(g_singleThreadReceiveData);
+            return;
+        }
+        OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Copying the data of length [%d]",
+                  dataOnlyLen);
+        memcpy(g_singleThreadReceiveData->defragData + g_singleThreadReceiveData->recvDataLen,
+               data + CA_BLE_HEADER_SIZE,
+               dataOnlyLen);
+        g_singleThreadReceiveData->recvDataLen += dataOnlyLen;
+        OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "totalDatalength  [%d] received Datalen [%d]",
+                g_singleThreadReceiveData->totalDataLen, g_singleThreadReceiveData->recvDataLen);
+    }
+}
+
+static CAResult_t CALEServerSendDataSingleThread(const uint8_t *data,
+                                                 uint32_t dataLen)
+{
+    OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
+
+    VERIFY_NON_NULL(data, CALEADAPTER_TAG, "Param data is NULL");
+
+    uint32_t midPacketCount = 0;
+    size_t remainingLen = 0;
+    size_t totalLength = 0;
+    CABLEPacketSecure_t secureFlag = CA_BLE_PACKET_NON_SECURE;
+
+    CAResult_t result = CAGenerateVariableForFragmentation(dataLen,
+                                                           &midPacketCount,
+                                                           &remainingLen,
+                                                           &totalLength);
+
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                  "CAGenerateVariableForFragmentation failed, result [%d]", result);
+        return result;
+    }
+
+    OIC_LOG_V(DEBUG, CALEADAPTER_TAG,
+              "Packet info: data size[%d] midPacketCount[%d] remainingLen[%d] totalLength[%d]",
+              dataLen, midPacketCount, remainingLen, totalLength);
+
+    OIC_LOG_V(DEBUG,
+              CALEADAPTER_TAG,
+              "Server total Data length with header is [%u]",
+              totalLength);
+
+    uint8_t dataSegment[CA_SUPPORTED_BLE_MTU_SIZE] = {0};
+    uint8_t dataHeader[CA_BLE_HEADER_SIZE] = {0};
+
+    result = CAGenerateHeader(dataHeader,
+                              CA_BLE_PACKET_START,
+                              g_localBLESourcePort,
+                              CA_BLE_PACKET_NON_SECURE,
+                              CA_BLE_MULTICAST_PORT);
+
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                  "CAGenerateHeader failed, result [%d]", result);
+        return result;
+    }
+
+    uint8_t lengthHeader[CA_BLE_LENGTH_HEADER_SIZE] = {0};
+    result = CAGenerateHeaderPayloadLength(lengthHeader,
+                                           CA_BLE_LENGTH_HEADER_SIZE,
+                                           dataLen);
+
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                  "CAGenerateHeaderPayloadLength failed, result [%d]", result);
+        return result;
+    }
+
+    uint32_t length = 0;
+    uint32_t dataOnlyLen = 0;
+    if (CA_SUPPORTED_BLE_MTU_SIZE > totalLength)
+    {
+        length = totalLength;
+        dataOnlyLen = dataLen;
+    }
+    else
+    {
+        length = CA_SUPPORTED_BLE_MTU_SIZE;
+        dataOnlyLen = CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE - CA_BLE_LENGTH_HEADER_SIZE;
+    }
+
+    result = CAMakeFirstDataSegment(dataSegment,
+                                    data, dataOnlyLen,
+                                    dataHeader, lengthHeader);
+
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                  "Making data segment failed, result [%d]", result);
+        return result;
+    }
+
+    OIC_LOG(DEBUG, CALEADAPTER_TAG, "Server Sending Multicast data");
+    result = CAUpdateCharacteristicsToAllGattClients(dataSegment, length);
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics failed, result [%d]",
+                result);
+        return result;
+    }
+
+    CALEDoEvents();
+
+    OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server Sent data length [%d]", length);
+
+    result = CAGenerateHeader(dataHeader,
+                              CA_BLE_PACKET_NOT_START,
+                              g_localBLESourcePort,
+                              CA_BLE_PACKET_NON_SECURE,
+                              CA_BLE_MULTICAST_PORT);
+
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                  "CAGenerateHeader failed, result [%d]", result);
+        return result;
+    }
+
+    const uint32_t dataLimit = midPacketCount;
+    for (uint32_t iter = 0; iter < dataLimit; iter++)
+    {
+        result = CAMakeRemainDataSegment(dataSegment,
+                                         data,
+                                         CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE,
+                                         iter,
+                                         dataHeader);
+
+        if (CA_STATUS_OK != result)
+        {
+            OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                    "Making data segment failed, result [%d]", result);
+            return result;
+        }
+
+        result = CAUpdateCharacteristicsToAllGattClients(
+                     dataSegment,
+                     CA_SUPPORTED_BLE_MTU_SIZE);
+
+        if (CA_STATUS_OK != result)
+        {
+            OIC_LOG(ERROR, CALEADAPTER_TAG, "Update characteristics failed");
+            return result;
+        }
+
+        CALEDoEvents();
+    }
+
+    if (remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE))
+    {
+        // send the last segment of the data
+        OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending the last chunk");
+
+        result = CAMakeRemainDataSegment(dataSegment,
+                                         data,
+                                         remainingLen,
+                                         dataLimit,
+                                         dataHeader);
+
+        if (CA_STATUS_OK != result)
+        {
+            OIC_LOG_V(ERROR, CALEADAPTER_TAG,
+                    "Making data segment failed, result [%d]", result);
+            return result;
+        }
+
+        result = CAUpdateCharacteristicsToAllGattClients(
+                     dataSegment,
+                     remainingLen + CA_BLE_HEADER_SIZE);
+
+        if (CA_STATUS_OK != result)
+        {
+            OIC_LOG(ERROR, CALEADAPTER_TAG, "Update characteristics failed");
+            return result;
+        }
+        CALEDoEvents();
+    }
+
+    return result;
+}
+#endif
+
 static CAResult_t CAInitLEAdapterMutex()
 {
     OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN - CAInitLEAdapterMutex");
@@ -2400,37 +3110,11 @@ static CAResult_t CALEAdapterServerSendData(const CAEndpoint_t *remoteEndpoint,
         return CA_STATUS_FAILED;
     }
 
-    CAResult_t result = CA_STATUS_OK;
-    const uint32_t dataLimit = dataLen / CA_SUPPORTED_BLE_MTU_SIZE;
-    for (uint32_t iter = 0; iter < dataLimit; iter++)
-    {
-        result =
-            CAUpdateCharacteristicsToAllGattClients(
-                data + (iter * CA_SUPPORTED_BLE_MTU_SIZE),
-                CA_SUPPORTED_BLE_MTU_SIZE);
-
-        if (CA_STATUS_OK != result)
-        {
-            OIC_LOG(ERROR, CALEADAPTER_TAG, "Update characteristics failed");
-            return CA_STATUS_FAILED;
-        }
-
-        CALEDoEvents();
-    }
-
-    const uint32_t remainingLen = dataLen % CA_SUPPORTED_BLE_MTU_SIZE;
-    if (remainingLen)
+    CAResult_t result = CALEServerSendDataSingleThread(data, dataLen);
+    if (CA_STATUS_OK != result)
     {
-        result =
-            CAUpdateCharacteristicsToAllGattClients(
-                data + (dataLimit * CA_SUPPORTED_BLE_MTU_SIZE),
-                remainingLen);
-        if (CA_STATUS_OK != result)
-        {
-            OIC_LOG(ERROR, CALEADAPTER_TAG, "Update characteristics failed");
-            return CA_STATUS_FAILED;
-        }
-        CALEDoEvents();
+        OIC_LOG(ERROR, CALEADAPTER_TAG, "CALEServerSendDataSingleThread failed");
+        return CA_STATUS_FAILED;
     }
 #else
     VERIFY_NON_NULL_RET(g_bleServerSendQueueHandle, CALEADAPTER_TAG,
@@ -2477,14 +3161,24 @@ static CAResult_t CALEAdapterServerReceivedData(const char *remoteAddress,
     VERIFY_NON_NULL(sentLength, CALEADAPTER_TAG, "Sent data length holder is null");
 
 #ifdef SINGLE_THREAD
-    if(g_networkPacketReceivedCallback)
-    {
-        // will be filled by upper layer
-        const CASecureEndpoint_t endpoint =
-            { .endpoint = { .adapter = CA_ADAPTER_GATT_BTLE } };
+    CALEDataReceiverHandlerSingleThread(data, dataLength);
 
+    if (g_singleThreadReceiveData->totalDataLen == g_singleThreadReceiveData->recvDataLen)
+    {
+        if(g_networkPacketReceivedCallback)
+        {
+            // will be filled by upper layer
+            const CASecureEndpoint_t endpoint =
+                { .endpoint = { .adapter = CA_ADAPTER_GATT_BTLE } };
 
-        g_networkPacketReceivedCallback(&endpoint, data, dataLength);
+            g_networkPacketReceivedCallback(&endpoint,
+                                            g_singleThreadReceiveData->defragData,
+                                            g_singleThreadReceiveData->recvDataLen);
+        }
+        g_singleThreadReceiveData->remoteEndpoint = NULL;
+        g_singleThreadReceiveData->defragData = NULL;
+        OICFree(g_singleThreadReceiveData);
+        g_singleThreadReceiveData = NULL;
     }
 #else
     VERIFY_NON_NULL_RET(g_bleReceiverQueue,
@@ -2673,19 +3367,68 @@ static void CALERemoveReceiveQueueData(u_arraylist_t *dataInfoList, const char*
     CABLESenderInfo_t *senderInfo = NULL;
     uint32_t senderIndex = 0;
 
-    if(CA_STATUS_OK == CALEGetSenderInfo(address, dataInfoList, &senderInfo,
-                                         &senderIndex))
+    u_arraylist_t *portList = u_arraylist_create();
+    if (CA_STATUS_OK == CALEGetPortsFromSenderInfo(address, dataInfoList, portList))
+    {
+        uint32_t arrayLength = u_arraylist_length(portList);
+        for (int i = 0; i < arrayLength; i++)
+        {
+            uint16_t port = u_arraylist_get(portList, i);
+            OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "port : %X", port);
+
+            if (CA_STATUS_OK == CALEGetSenderInfo(address, port,
+                                                  dataInfoList, &senderInfo,
+                                                  &senderIndex))
+            {
+                u_arraylist_remove(dataInfoList, senderIndex);
+                OICFree(senderInfo->defragData);
+                OICFree(senderInfo->remoteEndpoint);
+                OICFree(senderInfo);
+
+                OIC_LOG(DEBUG, CALEADAPTER_TAG,
+                        "SenderInfo is removed for disconnection");
+            }
+            else
+            {
+                OIC_LOG(DEBUG, CALEADAPTER_TAG, "SenderInfo doesn't exist");
+            }
+        }
+    }
+    u_arraylist_destroy(portList);
+}
+
+static CAResult_t CALEGetPortsFromSenderInfo(const char *leAddress,
+                                            u_arraylist_t *senderInfoList,
+                                            u_arraylist_t *portList)
+{
+    VERIFY_NON_NULL(leAddress,
+                    CALEADAPTER_TAG,
+                    "NULL BLE address argument");
+
+    const uint32_t listLength = u_arraylist_length(senderInfoList);
+    const uint32_t addrLength = strlen(leAddress);
+
+    for (uint32_t index = 0; index < listLength; index++)
     {
-        u_arraylist_remove(dataInfoList, senderIndex);
-        OICFree(senderInfo->defragData);
-        OICFree(senderInfo->remoteEndpoint);
-        OICFree(senderInfo);
+        CABLESenderInfo_t *info = (CABLESenderInfo_t *) u_arraylist_get(senderInfoList, index);
+        if (!info || !(info->remoteEndpoint))
+        {
+            continue;
+        }
 
-        OIC_LOG(DEBUG, CALEADAPTER_TAG, "SenderInfo is removed for disconnection");
+        if (!strncmp(info->remoteEndpoint->addr, leAddress, addrLength))
+        {
+            u_arraylist_add(portList, (void *) info->remoteEndpoint->port);
+        }
+    }
+
+    if (u_arraylist_length(portList) != 0)
+    {
+        return CA_STATUS_OK;
     }
     else
     {
-        OIC_LOG(DEBUG, CALEADAPTER_TAG, "SenderInfo doesn't exist");
+        return CA_STATUS_FAILED;
     }
 }
 #endif