Set the queue handle to null before stop & destroy. (#525)
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / tcp_adapter / catcpadapter.c
1 /* ****************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************/
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdint.h>
25
26 #ifndef __STDC_FORMAT_MACROS
27 #define __STDC_FORMAT_MACROS
28 #endif
29 #include <inttypes.h>
30
31 #include "cainterface.h"
32 #include "caipnwmonitor.h"
33 #include "catcpadapter.h"
34 #include "catcpinterface.h"
35 #include "caqueueingthread.h"
36 #include "caadapterutils.h"
37 #include "octhread.h"
38 #include "uarraylist.h"
39 #include "caremotehandler.h"
40 #include "logger.h"
41 #include "oic_malloc.h"
42 #ifdef __WITH_TLS__
43 #include "ca_adapter_net_ssl.h"
44 #endif
45
46 /**
47  * Logging tag for module name.
48  */
49 #define TAG "OIC_CA_TCP_ADAP"
50
51 /**
52  * Holds internal thread TCP data information.
53  */
54 typedef struct
55 {
56     CAEndpoint_t *remoteEndpoint;
57     void *data;
58     size_t dataLen;
59     bool isMulticast;
60 } CATCPData;
61
62 #define CA_TCP_LISTEN_BACKLOG  3
63
64 #define CA_TCP_SELECT_TIMEOUT 10
65
66 /**
67  * Mutex to synchronize TCP adapter access.
68  */
69 static oc_mutex g_mutexAdapter = NULL;
70
71 /**
72  * State to control closing of TCP servers on interface down event.
73  */
74 static bool g_skipCloseOnIFDown;
75
76 /**
77  * Queue handle for Send Data.
78  */
79 static CAQueueingThread_t *g_sendQueueHandle = NULL;
80
81 /**
82  * Network Packet Received Callback to CA.
83  */
84 static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL;
85
86 /**
87  * Adapter Changed Callback to CA.
88  */
89 static CAAdapterChangeCallback g_networkChangeCallback = NULL;
90
91 /**
92  * Connection Changed Callback to CA.
93  */
94 static CAConnectionChangeCallback g_connectionChangeCallback = NULL;
95
96 /**
97  * error Callback to CA adapter.
98  */
99 static CAErrorHandleCallback g_errorCallback = NULL;
100
101 /**
102  * KeepAlive Connected or Disconnected Callback to CA adapter.
103  */
104 static CAKeepAliveConnectionCallback g_connKeepAliveCallback = NULL;
105
106 static CAResult_t CATCPPacketReceivedCB(const CASecureEndpoint_t *sep,
107                                         const void *data, uint32_t dataLength);
108
109 static void CATCPErrorHandler(const CAEndpoint_t *endpoint, const void *data,
110                               size_t dataLength, CAResult_t result);
111
112 static CAResult_t CATCPInitializeQueueHandles();
113
114 static void CATCPDeinitializeQueueHandles(CAQueueingThread_t *queueHandle);
115
116 static void CATCPSendDataThread(void *threadData);
117
118 static CATCPData *CACreateTCPData(const CAEndpoint_t *remoteEndpoint,
119                                   const void *data, size_t dataLength,
120                                   bool isMulticast);
121 void CAFreeTCPData(CATCPData *ipData);
122
123 static void CADataDestroyer(void *data, uint32_t size);
124
125 CAResult_t CATCPInitializeQueueHandles()
126 {
127     // Check if the message queue is already initialized
128     if (g_sendQueueHandle)
129     {
130         OIC_LOG(DEBUG, TAG, "send queue handle is already initialized!");
131         return CA_STATUS_OK;
132     }
133
134     // Create send message queue
135     g_sendQueueHandle = OICMalloc(sizeof(CAQueueingThread_t));
136     if (!g_sendQueueHandle)
137     {
138         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
139         return CA_MEMORY_ALLOC_FAILED;
140     }
141
142     if (CA_STATUS_OK != CAQueueingThreadInitialize(g_sendQueueHandle,
143                                 (const ca_thread_pool_t)caglobals.tcp.threadpool,
144                                 CATCPSendDataThread, CADataDestroyer))
145     {
146         OIC_LOG(ERROR, TAG, "Failed to Initialize send queue thread");
147         OICFree(g_sendQueueHandle);
148         g_sendQueueHandle = NULL;
149         return CA_STATUS_FAILED;
150     }
151
152     return CA_STATUS_OK;
153 }
154
155 void CATCPDeinitializeQueueHandles(CAQueueingThread_t *queueHandle)
156 {
157     CAQueueingThreadDestroy(queueHandle);
158     OICFree(queueHandle);
159 }
160
161 void CATCPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status)
162 {
163     (void)ipAddress;
164     (void)status;
165 }
166
167 CAResult_t CATCPPacketReceivedCB(const CASecureEndpoint_t *sep, const void *data,
168                                  uint32_t dataLength)
169 {
170     VERIFY_NON_NULL(sep, TAG, "sep is NULL");
171     VERIFY_NON_NULL(data, TAG, "data is NULL");
172
173     OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", sep->endpoint.addr, sep->endpoint.port);
174
175     CAResult_t res = CA_STATUS_OK;
176 #ifdef SINGLE_THREAD
177     if (g_networkPacketCallback)
178     {
179         res = g_networkPacketCallback(sep, data, dataLength);
180         if (CA_STATUS_OK != res)
181         {
182             OIC_LOG(ERROR, TAG, "Error parsing CoAP data");
183         }
184     }
185 #else
186     unsigned char *buffer = (unsigned char*)data;
187     size_t bufferLen = dataLength;
188     size_t index = 0;
189
190     //get remote device information from file descriptor.
191     CATCPSessionInfo_t *svritem = CAGetTCPSessionInfoFromEndpoint(&sep->endpoint, &index);
192     if (!svritem)
193     {
194         OIC_LOG(ERROR, TAG, "there is no connection information in list");
195         return CA_STATUS_INVALID_PARAM;
196     }
197     if (UNKNOWN == svritem->protocol)
198     {
199         OIC_LOG(ERROR, TAG, "invalid protocol type");
200         return CA_STATUS_INVALID_PARAM;
201     }
202
203     //totalLen filled only when header fully read and parsed
204     while (0 != bufferLen)
205     {
206         res = CAConstructCoAP(svritem, &buffer, &bufferLen);
207         if (CA_STATUS_OK != res)
208         {
209             OIC_LOG_V(ERROR, TAG, "CAConstructCoAP return error : %d", res);
210             return res;
211         }
212
213         //when successfully read all required data - pass them to upper layer.
214         if (svritem->len == svritem->totalLen)
215         {
216             if (g_networkPacketCallback)
217             {
218                 res = g_networkPacketCallback(sep, svritem->data, svritem->totalLen);
219                 if (CA_STATUS_OK != res)
220                 {
221                     OIC_LOG(ERROR, TAG, "Error parsing CoAP data");
222                     return res;
223                 }
224             }
225             CACleanData(svritem);
226         }
227         else
228         {
229             OIC_LOG_V(DEBUG, TAG, "%zd bytes required for complete CoAP",
230                                 svritem->totalLen - svritem->len);
231         }
232     }
233 #endif
234     return res;
235 }
236
237 #ifdef __WITH_TLS__
238 static ssize_t CATCPPacketSendCB(CAEndpoint_t *endpoint, const void *data, size_t dataLength)
239 {
240     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
241     VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint is NULL", -1);
242     VERIFY_NON_NULL_RET(data, TAG, "data is NULL", -1);
243
244     OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", endpoint->addr, endpoint->port);
245     OIC_LOG_BUFFER(DEBUG, TAG, data, dataLength);
246
247     ssize_t ret = CATCPSendData(endpoint, data, dataLength);
248     OIC_LOG_V(DEBUG, TAG, "Out %s : %zd bytes sent", __func__, ret);
249     return ret;
250 }
251 #endif
252
253 static void CATCPErrorHandler(const CAEndpoint_t *endpoint, const void *data,
254                               size_t dataLength, CAResult_t result)
255 {
256     VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
257     VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
258
259     if (g_errorCallback)
260     {
261         g_errorCallback(endpoint, data, dataLength, result);
262     }
263 }
264
265 static void CATCPConnectionHandler(const CAEndpoint_t *endpoint, bool isConnected, bool isClient)
266 {
267     // Pass the changed connection status to RI Layer for keepalive.
268     if (g_connKeepAliveCallback)
269     {
270         g_connKeepAliveCallback(endpoint, isConnected, isClient);
271     }
272
273     // Pass the changed connection status to CAUtil.
274     if (g_connectionChangeCallback)
275     {
276         g_connectionChangeCallback(endpoint, isConnected);
277     }
278 }
279
280 void CATCPSetKeepAliveCallbacks(CAKeepAliveConnectionCallback ConnHandler)
281 {
282     g_connKeepAliveCallback = ConnHandler;
283 }
284
285 void CATCPAdapterHandler(CATransportAdapter_t adapter, CANetworkStatus_t status)
286 {
287     if (g_networkChangeCallback)
288     {
289         g_networkChangeCallback(adapter, status);
290     }
291
292     if (CA_INTERFACE_DOWN == status)
293     {
294         OIC_LOG(INFO, TAG, "Network status is down, close all session");
295
296         CAResult_t res = CAQueueingThreadClearData(g_sendQueueHandle);
297         if (res != CA_STATUS_OK)
298         {
299             OIC_LOG_V(ERROR, TAG, "CAQueueingThreadClearData failed[%d]", res);
300         }
301
302         oc_mutex_lock(g_mutexAdapter);
303         if (!g_skipCloseOnIFDown)
304         {
305             CATCPStopServer();
306         }
307         else
308         {
309             OIC_LOG(INFO, TAG, "Skip closing servers!");
310         }
311         oc_mutex_unlock(g_mutexAdapter);
312     }
313     else if (CA_INTERFACE_UP == status)
314     {
315         OIC_LOG(INFO, TAG, "Network status is up, create new socket for listening");
316
317         CAResult_t ret = CA_STATUS_FAILED;
318 #ifndef SINGLE_THREAD
319         ret = CATCPStartServer((const ca_thread_pool_t)caglobals.tcp.threadpool);
320 #else
321         ret = CATCPStartServer();
322 #endif
323         if (CA_STATUS_OK != ret)
324         {
325             OIC_LOG_V(ERROR, TAG, "CATCPStartServer failed[%d]", ret);
326         }
327     }
328 }
329
330 static void CAInitializeTCPGlobals()
331 {
332     caglobals.tcp.ipv4.fd = -1;
333     caglobals.tcp.ipv4s.fd = -1;
334     caglobals.tcp.ipv6.fd = -1;
335     caglobals.tcp.ipv6s.fd = -1;
336
337     // Set the port number received from application.
338     caglobals.tcp.ipv4.port = caglobals.ports.tcp.u4;
339     caglobals.tcp.ipv4s.port = caglobals.ports.tcp.u4s;
340     caglobals.tcp.ipv6.port = caglobals.ports.tcp.u6;
341     caglobals.tcp.ipv6s.port = caglobals.ports.tcp.u6s;
342
343     caglobals.tcp.selectTimeout = CA_TCP_SELECT_TIMEOUT;
344     caglobals.tcp.listenBacklog = CA_TCP_LISTEN_BACKLOG;
345     caglobals.tcp.svrlist = NULL;
346
347     CATransportFlags_t flags = 0;
348     if (caglobals.client)
349     {
350         flags |= caglobals.clientFlags;
351     }
352
353 #ifndef DISABLE_TCP_SERVER
354     if (caglobals.server)
355     {
356         flags |= caglobals.serverFlags;
357     }
358 #endif
359
360     caglobals.tcp.ipv4tcpenabled = flags & CA_IPV4;
361     caglobals.tcp.ipv6tcpenabled = flags & CA_IPV6;
362 }
363
364 CAResult_t CAInitializeTCP(CARegisterConnectivityCallback registerCallback,
365                            CANetworkPacketReceivedCallback networkPacketCallback,
366                            CAAdapterChangeCallback netCallback,
367                            CAConnectionChangeCallback connCallback,
368                            CAErrorHandleCallback errorCallback, ca_thread_pool_t handle)
369 {
370     OIC_LOG(DEBUG, TAG, "IN");
371     VERIFY_NON_NULL(registerCallback, TAG, "registerCallback");
372     VERIFY_NON_NULL(networkPacketCallback, TAG, "networkPacketCallback");
373     VERIFY_NON_NULL(netCallback, TAG, "netCallback");
374 #ifndef SINGLE_THREAD
375     VERIFY_NON_NULL(handle, TAG, "thread pool handle");
376 #endif
377
378     g_networkChangeCallback = netCallback;
379     g_connectionChangeCallback = connCallback;
380     g_networkPacketCallback = networkPacketCallback;
381     g_errorCallback = errorCallback;
382
383     CAInitializeTCPGlobals();
384
385     // Create Mutex for synchronize access at adapter level
386     if (!g_mutexAdapter)
387     {
388         g_mutexAdapter = oc_mutex_new();
389         if (!g_mutexAdapter)
390         {
391             OIC_LOG(ERROR, TAG, "Failed to create mutex!");
392             return CA_STATUS_FAILED;
393         }
394     }
395
396     g_skipCloseOnIFDown = false;
397
398     CAResult_t res = CATCPCreateMutex();
399     if (CA_STATUS_OK == res)
400     {
401         res = CATCPCreateCond();
402     }
403     if (CA_STATUS_OK != res)
404     {
405         OIC_LOG(ERROR, TAG, "failed to create mutex/cond");
406         CATCPDestroyMutex();
407         CATCPDestroyCond();
408         return res;
409     }
410
411     res = CATCPCreateSendMutex();
412     if (CA_STATUS_OK == res)
413     {
414         res = CATCPCreateSendCond();
415     }
416     if (CA_STATUS_OK != res)
417     {
418         OIC_LOG(ERROR, TAG, "failed to create send data mutex/cond");
419         CATCPDestroyMutex();
420         CATCPDestroyCond();
421         CATCPDestroySendMutex();
422         CATCPDestroySendCond();
423         return res;
424     }
425
426 #ifndef SINGLE_THREAD
427     caglobals.tcp.threadpool = handle;
428 #endif
429
430     CATCPSetConnectionChangedCallback(CATCPConnectionHandler);
431     CATCPSetPacketReceiveCallback(CATCPPacketReceivedCB);
432     CATCPSetErrorHandler(CATCPErrorHandler);
433
434 #ifdef __WITH_TLS__
435     CAsetSslAdapterCallbacks(CATCPPacketReceivedCB, CATCPPacketSendCB, CA_ADAPTER_TCP);
436 #endif
437
438     CAConnectivityHandler_t tcpHandler = {
439         .startAdapter = CAStartTCP,
440         .startListenServer = CAStartTCPListeningServer,
441         .stopListenServer = CAStopTCPListeningServer,
442         .startDiscoveryServer = CAStartTCPDiscoveryServer,
443         .sendData = CASendTCPUnicastData,
444         .sendDataToAll = CASendTCPMulticastData,
445         .GetnetInfo = CAGetTCPInterfaceInformation,
446         .readData = CAReadTCPData,
447         .stopAdapter = CAStopTCP,
448         .terminate = CATerminateTCP,
449         .cType = CA_ADAPTER_TCP};
450
451     registerCallback(tcpHandler);
452
453     OIC_LOG(INFO, TAG, "OUT IntializeTCP is Success");
454     return CA_STATUS_OK;
455 }
456
457 CAResult_t CAStartTCP()
458 {
459     OIC_LOG(DEBUG, TAG, "IN");
460
461 #ifndef SINGLE_THREAD
462     if (CA_STATUS_OK != CATCPInitializeQueueHandles())
463     {
464         OIC_LOG(ERROR, TAG, "Failed to Initialize Queue Handle");
465         CATerminateTCP();
466         return CA_STATUS_FAILED;
467     }
468
469     // Start send queue thread
470 #ifndef __TIZENRT__
471     if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
472 #else
473     if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle, "IoT_TCPSendQueue"))
474 #endif
475     {
476         OIC_LOG(ERROR, TAG, "Failed to Start Send Data Thread");
477         return CA_STATUS_FAILED;
478     }
479 #else
480     CAResult_t ret = CATCPStartServer();
481     if (CA_STATUS_OK != ret)
482     {
483         OIC_LOG_V(DEBUG, TAG, "CATCPStartServer failed[%d]", ret);
484         return ret;
485     }
486 #endif
487
488     // Start network monitoring to receive adapter status changes.
489     CAIPStartNetworkMonitor(CATCPAdapterHandler, CA_ADAPTER_TCP);
490
491     return CA_STATUS_OK;
492 }
493
494 static bool CAClearQueueEndpointDataContext(void *data, uint32_t size, void *ctx)
495 {
496     (void)size;
497
498     if (NULL == data || NULL == ctx)
499     {
500         return false;
501     }
502
503     CATCPData *tcpData = (CATCPData *)data;
504     CAEndpoint_t *endpoint = (CAEndpoint_t *)ctx;
505
506     if (NULL != tcpData && NULL != tcpData->remoteEndpoint)
507     {
508         if (strcmp(tcpData->remoteEndpoint->addr, endpoint->addr) == 0
509             && tcpData->remoteEndpoint->port == endpoint->port)
510         {
511             return true;
512         }
513     }
514     return false;
515 }
516
517 CAResult_t CATCPDisconnectSession(const CAEndpoint_t *endpoint)
518 {
519     CAResult_t res = CAQueueingThreadClearContextData(g_sendQueueHandle,
520                                                       CAClearQueueEndpointDataContext,
521                                                       endpoint);
522     if (CA_STATUS_OK != res)
523     {
524         OIC_LOG(ERROR, TAG, "failed to clear context data");
525     }
526
527 #ifdef __WITH_TLS__
528     res = CAcloseSslConnection(endpoint);
529     if (CA_STATUS_OK != res)
530     {
531         OIC_LOG(ERROR, TAG, "failed to close TLS session");
532     }
533 #endif
534
535     res = CASearchAndDeleteTCPSession(endpoint);
536     if (CA_STATUS_OK != res)
537     {
538         OIC_LOG(ERROR, TAG, "failed to close TCP session");
539     }
540
541     return res;
542 }
543
544 void CATCPSkipCloseOnInterfaceDown(bool state)
545 {
546     oc_mutex_lock(g_mutexAdapter);
547     g_skipCloseOnIFDown = state;
548     oc_mutex_unlock(g_mutexAdapter);
549 }
550
551 CAResult_t CAStartTCPListeningServer()
552 {
553 #if !defined(SINGLE_THREAD) && !defined(DISABLE_TCP_SERVER)
554     if (!caglobals.server)
555     {
556         caglobals.server = true;    // only needed to run CA tests
557     }
558
559     CAResult_t ret = CATCPStartServer((const ca_thread_pool_t)caglobals.tcp.threadpool);
560     if (CA_STATUS_OK != ret)
561     {
562         OIC_LOG_V(ERROR, TAG, "Failed to start listening server![%d]", ret);
563         return ret;
564     }
565 #endif
566
567     return CA_STATUS_OK;
568 }
569
570 CAResult_t CAStopTCPListeningServer()
571 {
572     return CA_STATUS_OK;
573 }
574
575 CAResult_t CAStartTCPDiscoveryServer()
576 {
577     if (!caglobals.client)
578     {
579         caglobals.client = true;    // only needed to run CA tests
580     }
581
582     CAResult_t ret = CATCPStartServer((const ca_thread_pool_t)caglobals.tcp.threadpool);
583     if (CA_STATUS_OK != ret)
584     {
585         OIC_LOG_V(ERROR, TAG, "Failed to start discovery server![%d]", ret);
586         return ret;
587     }
588
589     return CA_STATUS_OK;
590 }
591
592 static size_t CAQueueTCPData(bool isMulticast, const CAEndpoint_t *endpoint,
593                              const void *data, size_t dataLength)
594 {
595     VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint", -1);
596     VERIFY_NON_NULL_RET(data, TAG, "data", -1);
597
598     if (0 == dataLength)
599     {
600         OIC_LOG(ERROR, TAG, "Invalid Data Length");
601         return -1;
602     }
603
604     VERIFY_NON_NULL_RET(g_sendQueueHandle, TAG, "sendQueueHandle", -1);
605
606     // Create TCPData to add to queue
607     CATCPData *tcpData = CACreateTCPData(endpoint, data, dataLength, isMulticast);
608     if (!tcpData)
609     {
610         OIC_LOG(ERROR, TAG, "Failed to create ipData!");
611         return -1;
612     }
613     // Add message to send queue
614     CAQueueingThreadAddData(g_sendQueueHandle, tcpData, sizeof(CATCPData));
615
616     return dataLength;
617 }
618
619 int32_t CASendTCPUnicastData(const CAEndpoint_t *endpoint,
620                              const void *data, uint32_t dataLength,
621                              CADataType_t dataType)
622 {
623     OIC_LOG(DEBUG, TAG, "IN");
624     (void)dataType;
625 #ifndef SINGLE_THREAD
626     return CAQueueTCPData(false, endpoint, data, dataLength);
627 #else
628     return CATCPSendData(endpoint, data, dataLength);
629 #endif
630 }
631
632 int32_t CASendTCPMulticastData(const CAEndpoint_t *endpoint,
633                                const void *data, uint32_t dataLength,
634                                CADataType_t dataType)
635 {
636     (void)endpoint;
637     (void)data;
638     (void)dataLength;
639     (void)dataType;
640
641     OIC_LOG(ERROR, TAG, "TCP adapter does not support multicast sending!");
642     return 0;
643 }
644
645 CAResult_t CAReadTCPData()
646 {
647     OIC_LOG(DEBUG, TAG, "IN");
648 #ifdef SINGLE_THREAD
649     CATCPPullData();
650 #endif
651     return CA_STATUS_OK;
652 }
653
654 CAResult_t CAStopTCP()
655 {
656     CAIPStopNetworkMonitor(CA_ADAPTER_TCP);
657
658     /* Some times send queue thread fails to terminate as it's worker
659        thread gets blocked at TCP session's socket connect operation.
660        So closing sockets which are in connect operation at the time
661        of termination of adapter would save send queue thread from
662        getting blocked. */
663     CATCPCloseInProgressConnections();
664
665 #ifndef SINGLE_THREAD
666     // Stop send queue thread.
667     if (g_sendQueueHandle != NULL)
668     {
669         // g_sendQueueHandle is set to NULL to prevent new requests from being enqueued.
670         CAQueueingThread_t *queueHandle = g_sendQueueHandle;
671         g_sendQueueHandle = NULL;
672
673         if (queueHandle->threadMutex)
674         {
675             CAQueueingThreadStop(queueHandle);
676         }
677         CATCPDeinitializeQueueHandles(queueHandle);
678     }
679 #endif
680
681     // Close TCP servers and established connections.
682     CATCPStopServer();
683
684     // Re-initializing the Globals to start them again.
685     CAInitializeTCPGlobals();
686
687     return CA_STATUS_OK;
688 }
689
690 void CATerminateTCP()
691 {
692     CATCPSetPacketReceiveCallback(NULL);
693
694     CATCPDestroyMutex();
695     CATCPDestroyCond();
696
697     CATCPDestroySendMutex();
698     CATCPDestroySendCond();
699
700     g_skipCloseOnIFDown = false;
701
702     // Free adapter mutex
703     if (g_mutexAdapter)
704     {
705         oc_mutex_free(g_mutexAdapter);
706         g_mutexAdapter = NULL;
707     }
708 }
709
710 void CATCPSendDataThread(void *threadData)
711 {
712     CATCPData *tcpData = (CATCPData *) threadData;
713     if (!tcpData)
714     {
715         OIC_LOG(DEBUG, TAG, "Invalid TCP data!");
716         return;
717     }
718
719     if (caglobals.tcp.terminate)
720     {
721         OIC_LOG(DEBUG, TAG, "Adapter is not enabled");
722         CATCPErrorHandler(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen,
723                           CA_SEND_FAILED);
724         return;
725     }
726
727     if (tcpData->isMulticast)
728     {
729         //Processing for sending multicast
730         OIC_LOG(DEBUG, TAG, "Send Multicast Data is called, not supported");
731         return;
732     }
733     else
734     {
735 #ifdef __WITH_TLS__
736         if (tcpData->remoteEndpoint && tcpData->remoteEndpoint->flags & CA_SECURE)
737         {
738             CAResult_t result = CA_STATUS_OK;
739             OIC_LOG(DEBUG, TAG, "CAencryptSsl called!");
740             result = CAencryptSsl(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen);
741
742             if (CA_STATUS_OK != result)
743             {
744                 OIC_LOG(ERROR, TAG, "CAAdapterNetDtlsEncrypt failed!");
745                 CASearchAndDeleteTCPSession(tcpData->remoteEndpoint);
746                 CATCPErrorHandler(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen,
747                                   CA_SEND_FAILED);
748             }
749             OIC_LOG_V(DEBUG, TAG,
750                       "CAAdapterNetDtlsEncrypt returned with result[%d]", result);
751             return;
752         }
753 #endif
754         //Processing for sending unicast
755          ssize_t dlen = CATCPSendData(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen);
756          if (-1 == dlen)
757          {
758              OIC_LOG(ERROR, TAG, "CATCPSendData failed");
759              CASearchAndDeleteTCPSession(tcpData->remoteEndpoint);
760              CATCPErrorHandler(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen,
761                                CA_SEND_FAILED);
762          }
763     }
764 }
765
766 CATCPData *CACreateTCPData(const CAEndpoint_t *remoteEndpoint, const void *data,
767                            size_t dataLength, bool isMulticast)
768 {
769     VERIFY_NON_NULL_RET(remoteEndpoint, TAG, "remoteEndpoint is NULL", NULL);
770     VERIFY_NON_NULL_RET(data, TAG, "data is NULL", NULL);
771
772     CATCPData *tcpData = (CATCPData *) OICCalloc(1, sizeof(*tcpData));
773     if (!tcpData)
774     {
775         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
776         return NULL;
777     }
778
779     tcpData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
780     tcpData->data = (void *) OICMalloc(dataLength);
781     if (!tcpData->data)
782     {
783         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
784         CAFreeTCPData(tcpData);
785         return NULL;
786     }
787
788     memcpy(tcpData->data, data, dataLength);
789     tcpData->dataLen = dataLength;
790
791     tcpData->isMulticast = isMulticast;
792
793     return tcpData;
794 }
795
796 void CAFreeTCPData(CATCPData *tcpData)
797 {
798     VERIFY_NON_NULL_VOID(tcpData, TAG, "tcpData is NULL");
799
800     CAFreeEndpoint(tcpData->remoteEndpoint);
801     OICFree(tcpData->data);
802     OICFree(tcpData);
803 }
804
805 void CADataDestroyer(void *data, uint32_t size)
806 {
807     if (size < sizeof(CATCPData))
808     {
809 #ifndef __TIZENRT__
810         OIC_LOG_V(ERROR, TAG, "Destroy data too small %p %" PRIu32, data, size);
811 #endif
812     }
813     CATCPData *TCPData = (CATCPData *) data;
814
815     CAFreeTCPData(TCPData);
816 }
817
818 #ifdef SINGLE_THREAD
819 size_t CAGetTotalLengthFromPacketHeader(const unsigned char *recvBuffer, size_t size)
820 {
821     OIC_LOG(DEBUG, TAG, "IN - CAGetTotalLengthFromHeader");
822
823     if (NULL == recvBuffer || !size)
824     {
825         OIC_LOG(ERROR, TAG, "recvBuffer is NULL");
826         return 0;
827     }
828
829     coap_transport_t transport = coap_get_tcp_header_type_from_initbyte(
830             ((unsigned char *)recvBuffer)[0] >> 4);
831     size_t optPaylaodLen = coap_get_length_from_header((unsigned char *)recvBuffer,
832                                                         transport);
833     size_t headerLen = coap_get_tcp_header_length((unsigned char *)recvBuffer);
834
835     OIC_LOG_V(DEBUG, TAG, "option/paylaod length [%d]", optPaylaodLen);
836     OIC_LOG_V(DEBUG, TAG, "header length [%d]", headerLen);
837     OIC_LOG_V(DEBUG, TAG, "total data length [%d]", headerLen + optPaylaodLen);
838
839     OIC_LOG(DEBUG, TAG, "OUT - CAGetTotalLengthFromHeader");
840     return headerLen + optPaylaodLen;
841 }
842
843 void CAGetTCPHeaderDetails(unsigned char* recvBuffer, coap_transport_t *transport,
844                            size_t *headerlen)
845 {
846     if (NULL == recvBuffer)
847     {
848         OIC_LOG(ERROR, TAG, "recvBuffer is NULL");
849         return;
850     }
851
852     if (NULL == transport)
853     {
854         OIC_LOG(ERROR, TAG, "transport is NULL");
855         return;
856     }
857
858     if (NULL == headerlen)
859     {
860         OIC_LOG(ERROR, TAG, "headerlen is NULL");
861         return;
862     }
863
864     *transport = coap_get_tcp_header_type_from_initbyte(
865         ((unsigned char *)recvBuffer)[0] >> 4);
866     *headerlen = coap_get_tcp_header_length_for_transport(*transport);
867 }
868 #endif