0e33b4680b10df99548d0d7f64b64aa7211bc8e8
[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();
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()
156 {
157     CAQueueingThreadDestroy(g_sendQueueHandle);
158     OICFree(g_sendQueueHandle);
159     g_sendQueueHandle = NULL;
160 }
161
162 void CATCPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status)
163 {
164     (void)ipAddress;
165     (void)status;
166 }
167
168 CAResult_t CATCPPacketReceivedCB(const CASecureEndpoint_t *sep, const void *data,
169                                  uint32_t dataLength)
170 {
171     VERIFY_NON_NULL(sep, TAG, "sep is NULL");
172     VERIFY_NON_NULL(data, TAG, "data is NULL");
173
174     OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", sep->endpoint.addr, sep->endpoint.port);
175
176     CAResult_t res = CA_STATUS_OK;
177 #ifdef SINGLE_THREAD
178     if (g_networkPacketCallback)
179     {
180         res = g_networkPacketCallback(sep, data, dataLength);
181         if (CA_STATUS_OK != res)
182         {
183             OIC_LOG(ERROR, TAG, "Error parsing CoAP data");
184         }
185     }
186 #else
187     unsigned char *buffer = (unsigned char*)data;
188     size_t bufferLen = dataLength;
189     size_t index = 0;
190
191     //get remote device information from file descriptor.
192     CATCPSessionInfo_t *svritem = CAGetTCPSessionInfoFromEndpoint(&sep->endpoint, &index);
193     if (!svritem)
194     {
195         OIC_LOG(ERROR, TAG, "there is no connection information in list");
196         return CA_STATUS_INVALID_PARAM;
197     }
198     if (UNKNOWN == svritem->protocol)
199     {
200         OIC_LOG(ERROR, TAG, "invalid protocol type");
201         return CA_STATUS_INVALID_PARAM;
202     }
203
204     //totalLen filled only when header fully read and parsed
205     while (0 != bufferLen)
206     {
207         res = CAConstructCoAP(svritem, &buffer, &bufferLen);
208         if (CA_STATUS_OK != res)
209         {
210             OIC_LOG_V(ERROR, TAG, "CAConstructCoAP return error : %d", res);
211             return res;
212         }
213
214         //when successfully read all required data - pass them to upper layer.
215         if (svritem->len == svritem->totalLen)
216         {
217             if (g_networkPacketCallback)
218             {
219                 res = g_networkPacketCallback(sep, svritem->data, svritem->totalLen);
220                 if (CA_STATUS_OK != res)
221                 {
222                     OIC_LOG(ERROR, TAG, "Error parsing CoAP data");
223                     return res;
224                 }
225             }
226             CACleanData(svritem);
227         }
228         else
229         {
230             OIC_LOG_V(DEBUG, TAG, "%zd bytes required for complete CoAP",
231                                 svritem->totalLen - svritem->len);
232         }
233     }
234 #endif
235     return res;
236 }
237
238 #ifdef __WITH_TLS__
239 static ssize_t CATCPPacketSendCB(CAEndpoint_t *endpoint, const void *data, size_t dataLength)
240 {
241     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
242     VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint is NULL", -1);
243     VERIFY_NON_NULL_RET(data, TAG, "data is NULL", -1);
244
245     OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", endpoint->addr, endpoint->port);
246     OIC_LOG_BUFFER(DEBUG, TAG, data, dataLength);
247
248     ssize_t ret = CATCPSendData(endpoint, data, dataLength);
249     OIC_LOG_V(DEBUG, TAG, "Out %s : %zd bytes sent", __func__, ret);
250     return ret;
251 }
252 #endif
253
254 static void CATCPErrorHandler(const CAEndpoint_t *endpoint, const void *data,
255                               size_t dataLength, CAResult_t result)
256 {
257     VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
258     VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
259
260     if (g_errorCallback)
261     {
262         g_errorCallback(endpoint, data, dataLength, result);
263     }
264 }
265
266 static void CATCPConnectionHandler(const CAEndpoint_t *endpoint, bool isConnected, bool isClient)
267 {
268     // Pass the changed connection status to RI Layer for keepalive.
269     if (g_connKeepAliveCallback)
270     {
271         g_connKeepAliveCallback(endpoint, isConnected, isClient);
272     }
273
274     // Pass the changed connection status to CAUtil.
275     if (g_connectionChangeCallback)
276     {
277         g_connectionChangeCallback(endpoint, isConnected);
278     }
279 }
280
281 void CATCPSetKeepAliveCallbacks(CAKeepAliveConnectionCallback ConnHandler)
282 {
283     g_connKeepAliveCallback = ConnHandler;
284 }
285
286 void CATCPAdapterHandler(CATransportAdapter_t adapter, CANetworkStatus_t status)
287 {
288     if (g_networkChangeCallback)
289     {
290         g_networkChangeCallback(adapter, status);
291     }
292
293     if (CA_INTERFACE_DOWN == status)
294     {
295         OIC_LOG(INFO, TAG, "Network status is down, close all session");
296
297         CAResult_t res = CAQueueingThreadClearData(g_sendQueueHandle);
298         if (res != CA_STATUS_OK)
299         {
300             OIC_LOG_V(ERROR, TAG, "CAQueueingThreadClearData failed[%d]", res);
301         }
302
303         oc_mutex_lock(g_mutexAdapter);
304         if (!g_skipCloseOnIFDown)
305         {
306             CATCPStopServer();
307         }
308         else
309         {
310             OIC_LOG(INFO, TAG, "Skip closing servers!");
311         }
312         oc_mutex_unlock(g_mutexAdapter);
313     }
314     else if (CA_INTERFACE_UP == status)
315     {
316         OIC_LOG(INFO, TAG, "Network status is up, create new socket for listening");
317
318         CAResult_t ret = CA_STATUS_FAILED;
319 #ifndef SINGLE_THREAD
320         ret = CATCPStartServer((const ca_thread_pool_t)caglobals.tcp.threadpool);
321 #else
322         ret = CATCPStartServer();
323 #endif
324         if (CA_STATUS_OK != ret)
325         {
326             OIC_LOG_V(ERROR, TAG, "CATCPStartServer failed[%d]", ret);
327         }
328     }
329 }
330
331 static void CAInitializeTCPGlobals()
332 {
333     caglobals.tcp.ipv4.fd = -1;
334     caglobals.tcp.ipv4s.fd = -1;
335     caglobals.tcp.ipv6.fd = -1;
336     caglobals.tcp.ipv6s.fd = -1;
337
338     // Set the port number received from application.
339     caglobals.tcp.ipv4.port = caglobals.ports.tcp.u4;
340     caglobals.tcp.ipv4s.port = caglobals.ports.tcp.u4s;
341     caglobals.tcp.ipv6.port = caglobals.ports.tcp.u6;
342     caglobals.tcp.ipv6s.port = caglobals.ports.tcp.u6s;
343
344     caglobals.tcp.selectTimeout = CA_TCP_SELECT_TIMEOUT;
345     caglobals.tcp.listenBacklog = CA_TCP_LISTEN_BACKLOG;
346     caglobals.tcp.svrlist = NULL;
347
348     CATransportFlags_t flags = 0;
349     if (caglobals.client)
350     {
351         flags |= caglobals.clientFlags;
352     }
353
354 #ifndef DISABLE_TCP_SERVER
355     if (caglobals.server)
356     {
357         flags |= caglobals.serverFlags;
358     }
359 #endif
360
361     caglobals.tcp.ipv4tcpenabled = flags & CA_IPV4;
362     caglobals.tcp.ipv6tcpenabled = flags & CA_IPV6;
363 }
364
365 CAResult_t CAInitializeTCP(CARegisterConnectivityCallback registerCallback,
366                            CANetworkPacketReceivedCallback networkPacketCallback,
367                            CAAdapterChangeCallback netCallback,
368                            CAConnectionChangeCallback connCallback,
369                            CAErrorHandleCallback errorCallback, ca_thread_pool_t handle)
370 {
371     OIC_LOG(DEBUG, TAG, "IN");
372     VERIFY_NON_NULL(registerCallback, TAG, "registerCallback");
373     VERIFY_NON_NULL(networkPacketCallback, TAG, "networkPacketCallback");
374     VERIFY_NON_NULL(netCallback, TAG, "netCallback");
375 #ifndef SINGLE_THREAD
376     VERIFY_NON_NULL(handle, TAG, "thread pool handle");
377 #endif
378
379     g_networkChangeCallback = netCallback;
380     g_connectionChangeCallback = connCallback;
381     g_networkPacketCallback = networkPacketCallback;
382     g_errorCallback = errorCallback;
383
384     CAInitializeTCPGlobals();
385
386     // Create Mutex for synchronize access at adapter level
387     if (!g_mutexAdapter)
388     {
389         g_mutexAdapter = oc_mutex_new();
390         if (!g_mutexAdapter)
391         {
392             OIC_LOG(ERROR, TAG, "Failed to create mutex!");
393             return CA_STATUS_FAILED;
394         }
395     }
396
397     g_skipCloseOnIFDown = false;
398
399     CAResult_t res = CATCPCreateMutex();
400     if (CA_STATUS_OK == res)
401     {
402         res = CATCPCreateCond();
403     }
404     if (CA_STATUS_OK != res)
405     {
406         OIC_LOG(ERROR, TAG, "failed to create mutex/cond");
407         CATCPDestroyMutex();
408         CATCPDestroyCond();
409         return res;
410     }
411
412     res = CATCPCreateSendMutex();
413     if (CA_STATUS_OK == res)
414     {
415         res = CATCPCreateSendCond();
416     }
417     if (CA_STATUS_OK != res)
418     {
419         OIC_LOG(ERROR, TAG, "failed to create send data mutex/cond");
420         CATCPDestroyMutex();
421         CATCPDestroyCond();
422         CATCPDestroySendMutex();
423         CATCPDestroySendCond();
424         return res;
425     }
426
427 #ifndef SINGLE_THREAD
428     caglobals.tcp.threadpool = handle;
429 #endif
430
431     CATCPSetConnectionChangedCallback(CATCPConnectionHandler);
432     CATCPSetPacketReceiveCallback(CATCPPacketReceivedCB);
433     CATCPSetErrorHandler(CATCPErrorHandler);
434
435 #ifdef __WITH_TLS__
436     CAsetSslAdapterCallbacks(CATCPPacketReceivedCB, CATCPPacketSendCB, CA_ADAPTER_TCP);
437 #endif
438
439     CAConnectivityHandler_t tcpHandler = {
440         .startAdapter = CAStartTCP,
441         .startListenServer = CAStartTCPListeningServer,
442         .stopListenServer = CAStopTCPListeningServer,
443         .startDiscoveryServer = CAStartTCPDiscoveryServer,
444         .sendData = CASendTCPUnicastData,
445         .sendDataToAll = CASendTCPMulticastData,
446         .GetnetInfo = CAGetTCPInterfaceInformation,
447         .readData = CAReadTCPData,
448         .stopAdapter = CAStopTCP,
449         .terminate = CATerminateTCP,
450         .cType = CA_ADAPTER_TCP};
451
452     registerCallback(tcpHandler);
453
454     OIC_LOG(INFO, TAG, "OUT IntializeTCP is Success");
455     return CA_STATUS_OK;
456 }
457
458 CAResult_t CAStartTCP()
459 {
460     OIC_LOG(DEBUG, TAG, "IN");
461
462 #ifndef SINGLE_THREAD
463     if (CA_STATUS_OK != CATCPInitializeQueueHandles())
464     {
465         OIC_LOG(ERROR, TAG, "Failed to Initialize Queue Handle");
466         CATerminateTCP();
467         return CA_STATUS_FAILED;
468     }
469
470     // Start send queue thread
471 #ifndef __TIZENRT__
472     if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
473 #else
474     if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle, "IoT_TCPSendQueue"))
475 #endif
476     {
477         OIC_LOG(ERROR, TAG, "Failed to Start Send Data Thread");
478         return CA_STATUS_FAILED;
479     }
480 #else
481     CAResult_t ret = CATCPStartServer();
482     if (CA_STATUS_OK != ret)
483     {
484         OIC_LOG_V(DEBUG, TAG, "CATCPStartServer failed[%d]", ret);
485         return ret;
486     }
487 #endif
488
489     // Start network monitoring to receive adapter status changes.
490     CAIPStartNetworkMonitor(CATCPAdapterHandler, CA_ADAPTER_TCP);
491
492     return CA_STATUS_OK;
493 }
494
495 static bool CAClearQueueEndpointDataContext(void *data, uint32_t size, void *ctx)
496 {
497     (void)size;
498
499     if (NULL == data || NULL == ctx)
500     {
501         return false;
502     }
503
504     CATCPData *tcpData = (CATCPData *)data;
505     CAEndpoint_t *endpoint = (CAEndpoint_t *)ctx;
506
507     if (NULL != tcpData && NULL != tcpData->remoteEndpoint)
508     {
509         if (strcmp(tcpData->remoteEndpoint->addr, endpoint->addr) == 0
510             && tcpData->remoteEndpoint->port == endpoint->port)
511         {
512             return true;
513         }
514     }
515     return false;
516 }
517
518 CAResult_t CATCPDisconnectSession(const CAEndpoint_t *endpoint)
519 {
520     CAResult_t res = CAQueueingThreadClearContextData(g_sendQueueHandle,
521                                                       CAClearQueueEndpointDataContext,
522                                                       endpoint);
523     if (CA_STATUS_OK != res)
524     {
525         OIC_LOG(ERROR, TAG, "failed to clear context data");
526     }
527
528 #ifdef __WITH_TLS__
529     res = CAcloseSslConnection(endpoint);
530     if (CA_STATUS_OK != res)
531     {
532         OIC_LOG(ERROR, TAG, "failed to close TLS session");
533     }
534 #endif
535
536     res = CASearchAndDeleteTCPSession(endpoint);
537     if (CA_STATUS_OK != res)
538     {
539         OIC_LOG(ERROR, TAG, "failed to close TCP session");
540     }
541
542     return res;
543 }
544
545 void CATCPSkipCloseOnInterfaceDown(bool state)
546 {
547     oc_mutex_lock(g_mutexAdapter);
548     g_skipCloseOnIFDown = state;
549     oc_mutex_unlock(g_mutexAdapter);
550 }
551
552 CAResult_t CAStartTCPListeningServer()
553 {
554 #if !defined(SINGLE_THREAD) && !defined(DISABLE_TCP_SERVER)
555     if (!caglobals.server)
556     {
557         caglobals.server = true;    // only needed to run CA tests
558     }
559
560     CAResult_t ret = CATCPStartServer((const ca_thread_pool_t)caglobals.tcp.threadpool);
561     if (CA_STATUS_OK != ret)
562     {
563         OIC_LOG_V(ERROR, TAG, "Failed to start listening server![%d]", ret);
564         return ret;
565     }
566 #endif
567
568     return CA_STATUS_OK;
569 }
570
571 CAResult_t CAStopTCPListeningServer()
572 {
573     return CA_STATUS_OK;
574 }
575
576 CAResult_t CAStartTCPDiscoveryServer()
577 {
578     if (!caglobals.client)
579     {
580         caglobals.client = true;    // only needed to run CA tests
581     }
582
583     CAResult_t ret = CATCPStartServer((const ca_thread_pool_t)caglobals.tcp.threadpool);
584     if (CA_STATUS_OK != ret)
585     {
586         OIC_LOG_V(ERROR, TAG, "Failed to start discovery server![%d]", ret);
587         return ret;
588     }
589
590     return CA_STATUS_OK;
591 }
592
593 static size_t CAQueueTCPData(bool isMulticast, const CAEndpoint_t *endpoint,
594                              const void *data, size_t dataLength)
595 {
596     VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint", -1);
597     VERIFY_NON_NULL_RET(data, TAG, "data", -1);
598
599     if (0 == dataLength)
600     {
601         OIC_LOG(ERROR, TAG, "Invalid Data Length");
602         return -1;
603     }
604
605     VERIFY_NON_NULL_RET(g_sendQueueHandle, TAG, "sendQueueHandle", -1);
606
607     // Create TCPData to add to queue
608     CATCPData *tcpData = CACreateTCPData(endpoint, data, dataLength, isMulticast);
609     if (!tcpData)
610     {
611         OIC_LOG(ERROR, TAG, "Failed to create ipData!");
612         return -1;
613     }
614     // Add message to send queue
615     CAQueueingThreadAddData(g_sendQueueHandle, tcpData, sizeof(CATCPData));
616
617     return dataLength;
618 }
619
620 int32_t CASendTCPUnicastData(const CAEndpoint_t *endpoint,
621                              const void *data, uint32_t dataLength,
622                              CADataType_t dataType)
623 {
624     OIC_LOG(DEBUG, TAG, "IN");
625     (void)dataType;
626 #ifndef SINGLE_THREAD
627     return CAQueueTCPData(false, endpoint, data, dataLength);
628 #else
629     return CATCPSendData(endpoint, data, dataLength);
630 #endif
631 }
632
633 int32_t CASendTCPMulticastData(const CAEndpoint_t *endpoint,
634                                const void *data, uint32_t dataLength,
635                                CADataType_t dataType)
636 {
637     (void)endpoint;
638     (void)data;
639     (void)dataLength;
640     (void)dataType;
641
642     OIC_LOG(ERROR, TAG, "TCP adapter does not support multicast sending!");
643     return 0;
644 }
645
646 CAResult_t CAReadTCPData()
647 {
648     OIC_LOG(DEBUG, TAG, "IN");
649 #ifdef SINGLE_THREAD
650     CATCPPullData();
651 #endif
652     return CA_STATUS_OK;
653 }
654
655 CAResult_t CAStopTCP()
656 {
657     CAIPStopNetworkMonitor(CA_ADAPTER_TCP);
658
659     /* Some times send queue thread fails to terminate as it's worker
660        thread gets blocked at TCP session's socket connect operation.
661        So closing sockets which are in connect operation at the time
662        of termination of adapter would save send queue thread from
663        getting blocked. */
664     CATCPCloseInProgressConnections();
665
666 #ifndef SINGLE_THREAD
667     // Stop send queue thread.
668     if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
669     {
670         CAQueueingThreadStop(g_sendQueueHandle);
671     }
672     CATCPDeinitializeQueueHandles();
673 #endif
674
675     // Close TCP servers and established connections.
676     CATCPStopServer();
677
678     // Re-initializing the Globals to start them again.
679     CAInitializeTCPGlobals();
680
681     return CA_STATUS_OK;
682 }
683
684 void CATerminateTCP()
685 {
686     CATCPSetPacketReceiveCallback(NULL);
687
688     CATCPDestroyMutex();
689     CATCPDestroyCond();
690
691     CATCPDestroySendMutex();
692     CATCPDestroySendCond();
693
694     g_skipCloseOnIFDown = false;
695
696     // Free adapter mutex
697     if (g_mutexAdapter)
698     {
699         oc_mutex_free(g_mutexAdapter);
700         g_mutexAdapter = NULL;
701     }
702 }
703
704 void CATCPSendDataThread(void *threadData)
705 {
706     CATCPData *tcpData = (CATCPData *) threadData;
707     if (!tcpData)
708     {
709         OIC_LOG(DEBUG, TAG, "Invalid TCP data!");
710         return;
711     }
712
713     if (caglobals.tcp.terminate)
714     {
715         OIC_LOG(DEBUG, TAG, "Adapter is not enabled");
716         CATCPErrorHandler(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen,
717                           CA_SEND_FAILED);
718         return;
719     }
720
721     if (tcpData->isMulticast)
722     {
723         //Processing for sending multicast
724         OIC_LOG(DEBUG, TAG, "Send Multicast Data is called, not supported");
725         return;
726     }
727     else
728     {
729 #ifdef __WITH_TLS__
730         if (tcpData->remoteEndpoint && tcpData->remoteEndpoint->flags & CA_SECURE)
731         {
732             CAResult_t result = CA_STATUS_OK;
733             OIC_LOG(DEBUG, TAG, "CAencryptSsl called!");
734             result = CAencryptSsl(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen);
735
736             if (CA_STATUS_OK != result)
737             {
738                 OIC_LOG(ERROR, TAG, "CAAdapterNetDtlsEncrypt failed!");
739                 CASearchAndDeleteTCPSession(tcpData->remoteEndpoint);
740                 CATCPErrorHandler(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen,
741                                   CA_SEND_FAILED);
742             }
743             OIC_LOG_V(DEBUG, TAG,
744                       "CAAdapterNetDtlsEncrypt returned with result[%d]", result);
745             return;
746         }
747 #endif
748         //Processing for sending unicast
749          ssize_t dlen = CATCPSendData(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen);
750          if (-1 == dlen)
751          {
752              OIC_LOG(ERROR, TAG, "CATCPSendData failed");
753              CASearchAndDeleteTCPSession(tcpData->remoteEndpoint);
754              CATCPErrorHandler(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen,
755                                CA_SEND_FAILED);
756          }
757     }
758 }
759
760 CATCPData *CACreateTCPData(const CAEndpoint_t *remoteEndpoint, const void *data,
761                            size_t dataLength, bool isMulticast)
762 {
763     VERIFY_NON_NULL_RET(remoteEndpoint, TAG, "remoteEndpoint is NULL", NULL);
764     VERIFY_NON_NULL_RET(data, TAG, "data is NULL", NULL);
765
766     CATCPData *tcpData = (CATCPData *) OICCalloc(1, sizeof(*tcpData));
767     if (!tcpData)
768     {
769         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
770         return NULL;
771     }
772
773     tcpData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
774     tcpData->data = (void *) OICMalloc(dataLength);
775     if (!tcpData->data)
776     {
777         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
778         CAFreeTCPData(tcpData);
779         return NULL;
780     }
781
782     memcpy(tcpData->data, data, dataLength);
783     tcpData->dataLen = dataLength;
784
785     tcpData->isMulticast = isMulticast;
786
787     return tcpData;
788 }
789
790 void CAFreeTCPData(CATCPData *tcpData)
791 {
792     VERIFY_NON_NULL_VOID(tcpData, TAG, "tcpData is NULL");
793
794     CAFreeEndpoint(tcpData->remoteEndpoint);
795     OICFree(tcpData->data);
796     OICFree(tcpData);
797 }
798
799 void CADataDestroyer(void *data, uint32_t size)
800 {
801     if (size < sizeof(CATCPData))
802     {
803 #ifndef __TIZENRT__
804         OIC_LOG_V(ERROR, TAG, "Destroy data too small %p %" PRIu32, data, size);
805 #endif
806     }
807     CATCPData *TCPData = (CATCPData *) data;
808
809     CAFreeTCPData(TCPData);
810 }
811
812 #ifdef SINGLE_THREAD
813 size_t CAGetTotalLengthFromPacketHeader(const unsigned char *recvBuffer, size_t size)
814 {
815     OIC_LOG(DEBUG, TAG, "IN - CAGetTotalLengthFromHeader");
816
817     if (NULL == recvBuffer || !size)
818     {
819         OIC_LOG(ERROR, TAG, "recvBuffer is NULL");
820         return 0;
821     }
822
823     coap_transport_t transport = coap_get_tcp_header_type_from_initbyte(
824             ((unsigned char *)recvBuffer)[0] >> 4);
825     size_t optPaylaodLen = coap_get_length_from_header((unsigned char *)recvBuffer,
826                                                         transport);
827     size_t headerLen = coap_get_tcp_header_length((unsigned char *)recvBuffer);
828
829     OIC_LOG_V(DEBUG, TAG, "option/paylaod length [%d]", optPaylaodLen);
830     OIC_LOG_V(DEBUG, TAG, "header length [%d]", headerLen);
831     OIC_LOG_V(DEBUG, TAG, "total data length [%d]", headerLen + optPaylaodLen);
832
833     OIC_LOG(DEBUG, TAG, "OUT - CAGetTotalLengthFromHeader");
834     return headerLen + optPaylaodLen;
835 }
836
837 void CAGetTCPHeaderDetails(unsigned char* recvBuffer, coap_transport_t *transport,
838                            size_t *headerlen)
839 {
840     if (NULL == recvBuffer)
841     {
842         OIC_LOG(ERROR, TAG, "recvBuffer is NULL");
843         return;
844     }
845
846     if (NULL == transport)
847     {
848         OIC_LOG(ERROR, TAG, "transport is NULL");
849         return;
850     }
851
852     if (NULL == headerlen)
853     {
854         OIC_LOG(ERROR, TAG, "headerlen is NULL");
855         return;
856     }
857
858     *transport = coap_get_tcp_header_type_from_initbyte(
859         ((unsigned char *)recvBuffer)[0] >> 4);
860     *headerlen = coap_get_tcp_header_length_for_transport(*transport);
861 }
862 #endif