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