Update snapshot(2018-01-04)
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / tcp_adapter / catcpserver.c
index d998ad6..7136fe0 100644 (file)
  */
 #define MAX_CONNECTION_COUNTS   500
 
+#define COAP_TCP_MAX_BUFFER_CHUNK_SIZE 65530 //64kb - 6 (coap+tcp max header size)
+
 /**
  * Thread pool.
  */
 static ca_thread_pool_t g_threadPool = NULL;
 
 /**
- * An unique identifier of receive thread.
- */
-static uint32_t g_recvThreadId = 0;
-
-/**
  * Mutex to synchronize device object list.
  */
 static oc_mutex g_mutexObjectList = NULL;
@@ -386,6 +383,7 @@ void CACleanData(CATCPSessionInfo_t *svritem)
         svritem->tlsLen = 0;
 #endif
         svritem->totalLen = 0;
+        svritem->bufLen = 0;
         svritem->protocol = UNKNOWN;
     }
 }
@@ -426,6 +424,7 @@ CAResult_t CAConstructCoAP(CATCPSessionInfo_t *svritem, unsigned char **data,
         // copy 1 byte to parse coap header length
         memcpy(svritem->data, inBuffer, 1);
         svritem->len = 1;
+        svritem->bufLen = COAP_MAX_HEADER_SIZE;
         inBuffer++;
         inLen--;
     }
@@ -470,28 +469,41 @@ CAResult_t CAConstructCoAP(CATCPSessionInfo_t *svritem, unsigned char **data,
 
         //calculate CoAP message length
         svritem->totalLen = CAGetTotalLengthFromHeader(svritem->data);
-
-        // allocate required memory
-        unsigned char *buffer = OICRealloc(svritem->data, svritem->totalLen);
-        if (NULL == buffer)
-        {
-            OIC_LOG(ERROR, TAG, "OICRealloc - out of memory");
-            return CA_MEMORY_ALLOC_FAILED;
-        }
-        svritem->data = buffer;
     }
 
     // PAYLOAD
     if (inLen > 0)
     {
-        // read required bytes to have full CoAP payload
+        // Calculate length of data to be copied.
         copyLen = svritem->totalLen - svritem->len;
         if (inLen < copyLen)
         {
             copyLen = inLen;
         }
 
-        //read required bytes to have full CoAP header
+        // Is buffer not big enough for remaining data ?
+        if (svritem->len + copyLen > svritem->bufLen)
+        {
+            // Resize buffer to accommodate enough space
+            size_t extLen = svritem->totalLen - svritem->bufLen;
+            if (extLen > COAP_TCP_MAX_BUFFER_CHUNK_SIZE)
+            {
+                extLen = COAP_TCP_MAX_BUFFER_CHUNK_SIZE;
+            }
+
+            // Allocate required memory
+            unsigned char *buffer = OICRealloc(svritem->data, svritem->bufLen + extLen);
+            if (NULL == buffer)
+            {
+                OIC_LOG(ERROR, TAG, "OICRealloc - out of memory");
+                return CA_MEMORY_ALLOC_FAILED;
+            }
+
+            svritem->data = buffer;
+            svritem->bufLen += extLen;
+        }
+
+        // Read required bytes to have full CoAP payload
         memcpy(svritem->data + svritem->len, inBuffer, copyLen);
         svritem->len += copyLen;
         inBuffer += copyLen;
@@ -614,10 +626,10 @@ static void CAReceiveMessage(int fd)
     {
         if (CA_STATUS_OK != CATCPDisconnectSession(&svritem->sep.endpoint))
         {
+            CASearchAndDeleteTCPSession(&svritem->sep.endpoint);
             OIC_LOG(ERROR, TAG, "Failed to disconnect TCP session");
         }
 
-        CASearchAndDeleteTCPSession(&svritem->sep.endpoint);
         return;
     }
 }
@@ -963,14 +975,13 @@ CAResult_t CATCPStartServer(const ca_thread_pool_t threadPool)
 
     CAResult_t res = CA_STATUS_OK;
 #ifndef __TIZENRT__
-    res = ca_thread_pool_add_task(g_threadPool, CAReceiveHandler, NULL, &g_recvThreadId);
+    res = ca_thread_pool_add_task(g_threadPool, CAReceiveHandler, NULL, NULL);
 #else
-    res = ca_thread_pool_add_task(g_threadPool, CAReceiveHandler, NULL, &g_recvThreadId,
+    res = ca_thread_pool_add_task(g_threadPool, CAReceiveHandler, NULL, NULL,
                                  "IoT_TCPReceive", CONFIG_IOTIVITY_TCPRECEIVE_PTHREAD_STACKSIZE);
 #endif
     if (CA_STATUS_OK != res)
     {
-        g_recvThreadId = 0;
         oc_mutex_unlock(g_mutexObjectList);
         OIC_LOG(ERROR, TAG, "thread_pool_add_task failed");
         CATCPStopServer();
@@ -997,6 +1008,14 @@ void CATCPStopServer()
     // set terminate flag.
     caglobals.tcp.terminate = true;
 
+#ifdef __TIZENRT__
+    if (caglobals.tcp.started)
+    {
+        oc_cond_wait(g_condObjectList, g_mutexObjectList);
+        caglobals.tcp.started = false;
+    }
+#endif
+
     // close accept socket.
 #ifndef __WITH_TLS__
     CLOSE_SOCKET(ipv4);
@@ -1017,25 +1036,17 @@ void CATCPStopServer()
         caglobals.tcp.shutdownFds[1] = OC_INVALID_SOCKET;
         // receive thread will stop immediately
     }
-#endif
     if (caglobals.tcp.started)
     {
         oc_cond_wait(g_condObjectList, g_mutexObjectList);
         caglobals.tcp.started = false;
     }
-#ifndef __TIZENRT__
     if (caglobals.tcp.shutdownFds[0] != OC_INVALID_SOCKET)
     {
         close(caglobals.tcp.shutdownFds[0]);
         caglobals.tcp.shutdownFds[0] = OC_INVALID_SOCKET;
     }
 #endif
-    CAResult_t res = ca_thread_pool_remove_task(g_threadPool, g_recvThreadId);
-    if (CA_STATUS_OK != res)
-    {
-        OIC_LOG(ERROR, TAG, "ca_thread_pool_remove_task failed");
-    }
-    g_recvThreadId = 0;
     oc_mutex_unlock(g_mutexObjectList);
 
     CATCPDisconnectAll();