Update snapshot(2017-11-29)
[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     if (caglobals.server)
335     {
336         flags |= caglobals.serverFlags;
337     }
338
339     caglobals.tcp.ipv4tcpenabled = flags & CA_IPV4;
340     caglobals.tcp.ipv6tcpenabled = flags & CA_IPV6;
341 }
342
343 CAResult_t CAInitializeTCP(CARegisterConnectivityCallback registerCallback,
344                            CANetworkPacketReceivedCallback networkPacketCallback,
345                            CAAdapterChangeCallback netCallback,
346                            CAConnectionChangeCallback connCallback,
347                            CAErrorHandleCallback errorCallback, ca_thread_pool_t handle)
348 {
349     OIC_LOG(DEBUG, TAG, "IN");
350     VERIFY_NON_NULL(registerCallback, TAG, "registerCallback");
351     VERIFY_NON_NULL(networkPacketCallback, TAG, "networkPacketCallback");
352     VERIFY_NON_NULL(netCallback, TAG, "netCallback");
353 #ifndef SINGLE_THREAD
354     VERIFY_NON_NULL(handle, TAG, "thread pool handle");
355 #endif
356
357     g_networkChangeCallback = netCallback;
358     g_connectionChangeCallback = connCallback;
359     g_networkPacketCallback = networkPacketCallback;
360     g_errorCallback = errorCallback;
361
362     CAInitializeTCPGlobals();
363
364     CAResult_t res = CATCPCreateMutex();
365     if (CA_STATUS_OK == res)
366     {
367         res = CATCPCreateCond();
368     }
369     if (CA_STATUS_OK != res)
370     {
371         OIC_LOG(ERROR, TAG, "failed to create mutex/cond");
372         CATCPDestroyMutex();
373         CATCPDestroyCond();
374         return res;
375     }
376
377 #ifndef SINGLE_THREAD
378     caglobals.tcp.threadpool = handle;
379 #endif
380
381     CATCPSetConnectionChangedCallback(CATCPConnectionHandler);
382     CATCPSetPacketReceiveCallback(CATCPPacketReceivedCB);
383     CATCPSetErrorHandler(CATCPErrorHandler);
384
385 #ifdef __WITH_TLS__
386     CAsetSslAdapterCallbacks(CATCPPacketReceivedCB, CATCPPacketSendCB, CA_ADAPTER_TCP);
387 #endif
388
389     CAConnectivityHandler_t tcpHandler = {
390         .startAdapter = CAStartTCP,
391         .startListenServer = CAStartTCPListeningServer,
392         .stopListenServer = CAStopTCPListeningServer,
393         .startDiscoveryServer = CAStartTCPDiscoveryServer,
394         .sendData = CASendTCPUnicastData,
395         .sendDataToAll = CASendTCPMulticastData,
396         .GetnetInfo = CAGetTCPInterfaceInformation,
397         .readData = CAReadTCPData,
398         .stopAdapter = CAStopTCP,
399         .terminate = CATerminateTCP,
400         .cType = CA_ADAPTER_TCP};
401
402     registerCallback(tcpHandler);
403
404     OIC_LOG(INFO, TAG, "OUT IntializeTCP is Success");
405     return CA_STATUS_OK;
406 }
407
408 CAResult_t CAStartTCP()
409 {
410     OIC_LOG(DEBUG, TAG, "IN");
411
412 #ifndef SINGLE_THREAD
413     if (CA_STATUS_OK != CATCPInitializeQueueHandles())
414     {
415         OIC_LOG(ERROR, TAG, "Failed to Initialize Queue Handle");
416         CATerminateTCP();
417         return CA_STATUS_FAILED;
418     }
419
420     // Start send queue thread
421 #ifndef __TIZENRT__
422     if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
423 #else
424     if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle, "IoT_TCPSendQueue"))
425 #endif
426     {
427         OIC_LOG(ERROR, TAG, "Failed to Start Send Data Thread");
428         return CA_STATUS_FAILED;
429     }
430 #else
431     CAResult_t ret = CATCPStartServer();
432     if (CA_STATUS_OK != ret)
433     {
434         OIC_LOG_V(DEBUG, TAG, "CATCPStartServer failed[%d]", ret);
435         return ret;
436     }
437 #endif
438
439     // Start network monitoring to receive adapter status changes.
440     CAIPStartNetworkMonitor(CATCPAdapterHandler, CA_ADAPTER_TCP);
441
442     return CA_STATUS_OK;
443 }
444
445 static bool CAClearQueueEndpointDataContext(void *data, uint32_t size, void *ctx)
446 {
447     if (NULL == data || NULL == ctx)
448     {
449         return false;
450     }
451
452     CATCPData *tcpData = (CATCPData *)data;
453     CAEndpoint_t *endpoint = (CAEndpoint_t *)ctx;
454
455     if (NULL != tcpData && NULL != tcpData->remoteEndpoint)
456     {
457         if (strcmp(tcpData->remoteEndpoint->addr, endpoint->addr) == 0
458             && tcpData->remoteEndpoint->port == endpoint->port)
459         {
460             return true;
461         }
462     }
463     return false;
464 }
465
466 CAResult_t CATCPDisconnectSession(const CAEndpoint_t *endpoint)
467 {
468     CAResult_t res = CA_STATUS_OK;
469 #ifdef __WITH_TLS__
470     res = CAcloseSslConnection(endpoint);
471     if (CA_STATUS_OK != res)
472     {
473         OIC_LOG(ERROR, TAG, "failed to close TLS session");
474         res = CAQueueingThreadClearContextData(g_sendQueueHandle,
475                                                CAClearQueueEndpointDataContext,
476                                                endpoint);
477         if (CA_STATUS_OK != res)
478         {
479             OIC_LOG(ERROR, TAG, "failed to clear context data");
480         }
481
482         return res;
483     }
484 #endif
485
486     res = CASearchAndDeleteTCPSession(endpoint);
487     if (CA_STATUS_OK != res)
488     {
489         OIC_LOG(ERROR, TAG, "failed to close TCP session");
490     }
491
492     res = CAQueueingThreadClearContextData(g_sendQueueHandle,
493                                            CAClearQueueEndpointDataContext,
494                                            endpoint);
495     if (CA_STATUS_OK != res)
496     {
497         OIC_LOG(ERROR, TAG, "failed to clear context data");
498     }
499
500     return res;
501 }
502
503 CAResult_t CAStartTCPListeningServer()
504 {
505 #ifndef SINGLE_THREAD
506     if (!caglobals.server)
507     {
508         caglobals.server = true;    // only needed to run CA tests
509     }
510
511     CAResult_t ret = CATCPStartServer((const ca_thread_pool_t)caglobals.tcp.threadpool);
512     if (CA_STATUS_OK != ret)
513     {
514         OIC_LOG_V(ERROR, TAG, "Failed to start listening server![%d]", ret);
515         return ret;
516     }
517 #endif
518
519     return CA_STATUS_OK;
520 }
521
522 CAResult_t CAStopTCPListeningServer()
523 {
524     return CA_STATUS_OK;
525 }
526
527 CAResult_t CAStartTCPDiscoveryServer()
528 {
529     if (!caglobals.client)
530     {
531         caglobals.client = true;    // only needed to run CA tests
532     }
533
534     CAResult_t ret = CATCPStartServer((const ca_thread_pool_t)caglobals.tcp.threadpool);
535     if (CA_STATUS_OK != ret)
536     {
537         OIC_LOG_V(ERROR, TAG, "Failed to start discovery server![%d]", ret);
538         return ret;
539     }
540
541     return CA_STATUS_OK;
542 }
543
544 static size_t CAQueueTCPData(bool isMulticast, const CAEndpoint_t *endpoint,
545                              const void *data, size_t dataLength)
546 {
547     VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint", -1);
548     VERIFY_NON_NULL_RET(data, TAG, "data", -1);
549
550     if (0 == dataLength)
551     {
552         OIC_LOG(ERROR, TAG, "Invalid Data Length");
553         return -1;
554     }
555
556     VERIFY_NON_NULL_RET(g_sendQueueHandle, TAG, "sendQueueHandle", -1);
557
558     // Create TCPData to add to queue
559     CATCPData *tcpData = CACreateTCPData(endpoint, data, dataLength, isMulticast);
560     if (!tcpData)
561     {
562         OIC_LOG(ERROR, TAG, "Failed to create ipData!");
563         return -1;
564     }
565     // Add message to send queue
566     CAQueueingThreadAddData(g_sendQueueHandle, tcpData, sizeof(CATCPData));
567
568     return dataLength;
569 }
570
571 int32_t CASendTCPUnicastData(const CAEndpoint_t *endpoint,
572                              const void *data, uint32_t dataLength,
573                              CADataType_t dataType)
574 {
575     OIC_LOG(DEBUG, TAG, "IN");
576     (void)dataType;
577 #ifndef SINGLE_THREAD
578     return CAQueueTCPData(false, endpoint, data, dataLength);
579 #else
580     return CATCPSendData(endpoint, data, dataLength);
581 #endif
582 }
583
584 int32_t CASendTCPMulticastData(const CAEndpoint_t *endpoint,
585                                const void *data, uint32_t dataLength,
586                                CADataType_t dataType)
587 {
588     (void)dataType;
589     return CAQueueTCPData(true, endpoint, data, dataLength);
590 }
591
592 CAResult_t CAReadTCPData()
593 {
594     OIC_LOG(DEBUG, TAG, "IN");
595 #ifdef SINGLE_THREAD
596     CATCPPullData();
597 #endif
598     return CA_STATUS_OK;
599 }
600
601 CAResult_t CAStopTCP()
602 {
603     CAIPStopNetworkMonitor(CA_ADAPTER_TCP);
604
605     /* Some times send queue thread fails to terminate as it's worker
606        thread gets blocked at TCP session's socket connect operation.
607        So closing sockets which are in connect operation at the time
608        of termination of adapter would save send queue thread from
609        getting blocked. */
610     CATCPCloseInProgressConnections();
611
612 #ifndef SINGLE_THREAD
613     // Stop send queue thread.
614     if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
615     {
616         CAQueueingThreadStop(g_sendQueueHandle);
617     }
618     CATCPDeinitializeQueueHandles();
619 #endif
620
621     // Close TCP servers and established connections.
622     CATCPStopServer();
623
624     // Re-initializing the Globals to start them again.
625     CAInitializeTCPGlobals();
626
627     return CA_STATUS_OK;
628 }
629
630 void CATerminateTCP()
631 {
632     CATCPSetPacketReceiveCallback(NULL);
633
634     CATCPDestroyMutex();
635     CATCPDestroyCond();
636 }
637
638 void CATCPSendDataThread(void *threadData)
639 {
640     CATCPData *tcpData = (CATCPData *) threadData;
641     if (!tcpData)
642     {
643         OIC_LOG(DEBUG, TAG, "Invalid TCP data!");
644         return;
645     }
646
647     if (caglobals.tcp.terminate)
648     {
649         OIC_LOG(DEBUG, TAG, "Adapter is not enabled");
650         CATCPErrorHandler(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen,
651                           CA_SEND_FAILED);
652         return;
653     }
654
655     if (tcpData->isMulticast)
656     {
657         //Processing for sending multicast
658         OIC_LOG(DEBUG, TAG, "Send Multicast Data is called, not supported");
659         return;
660     }
661     else
662     {
663 #ifdef __WITH_TLS__
664         if (tcpData->remoteEndpoint && tcpData->remoteEndpoint->flags & CA_SECURE)
665         {
666             CAResult_t result = CA_STATUS_OK;
667             OIC_LOG(DEBUG, TAG, "CAencryptSsl called!");
668             result = CAencryptSsl(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen);
669
670             if (CA_STATUS_OK != result)
671             {
672                 OIC_LOG(ERROR, TAG, "CAAdapterNetDtlsEncrypt failed!");
673                 CASearchAndDeleteTCPSession(tcpData->remoteEndpoint);
674                 CATCPErrorHandler(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen,
675                                   CA_SEND_FAILED);
676             }
677             OIC_LOG_V(DEBUG, TAG,
678                       "CAAdapterNetDtlsEncrypt returned with result[%d]", result);
679             return;
680         }
681 #endif
682         //Processing for sending unicast
683          ssize_t dlen = CATCPSendData(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen);
684          if (-1 == dlen)
685          {
686              OIC_LOG(ERROR, TAG, "CATCPSendData failed");
687              CASearchAndDeleteTCPSession(tcpData->remoteEndpoint);
688              CATCPErrorHandler(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen,
689                                CA_SEND_FAILED);
690          }
691     }
692 }
693
694 CATCPData *CACreateTCPData(const CAEndpoint_t *remoteEndpoint, const void *data,
695                            size_t dataLength, bool isMulticast)
696 {
697     VERIFY_NON_NULL_RET(remoteEndpoint, TAG, "remoteEndpoint is NULL", NULL);
698     VERIFY_NON_NULL_RET(data, TAG, "data is NULL", NULL);
699
700     CATCPData *tcpData = (CATCPData *) OICCalloc(1, sizeof(*tcpData));
701     if (!tcpData)
702     {
703         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
704         return NULL;
705     }
706
707     tcpData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
708     tcpData->data = (void *) OICMalloc(dataLength);
709     if (!tcpData->data)
710     {
711         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
712         CAFreeTCPData(tcpData);
713         return NULL;
714     }
715
716     memcpy(tcpData->data, data, dataLength);
717     tcpData->dataLen = dataLength;
718
719     tcpData->isMulticast = isMulticast;
720
721     return tcpData;
722 }
723
724 void CAFreeTCPData(CATCPData *tcpData)
725 {
726     VERIFY_NON_NULL_VOID(tcpData, TAG, "tcpData is NULL");
727
728     CAFreeEndpoint(tcpData->remoteEndpoint);
729     OICFree(tcpData->data);
730     OICFree(tcpData);
731 }
732
733 void CADataDestroyer(void *data, uint32_t size)
734 {
735     if (size < sizeof(CATCPData))
736     {
737 #ifndef __TIZENRT__
738         OIC_LOG_V(ERROR, TAG, "Destroy data too small %p %" PRIu32, data, size);
739 #endif
740     }
741     CATCPData *TCPData = (CATCPData *) data;
742
743     CAFreeTCPData(TCPData);
744 }
745
746 #ifdef SINGLE_THREAD
747 size_t CAGetTotalLengthFromPacketHeader(const unsigned char *recvBuffer, size_t size)
748 {
749     OIC_LOG(DEBUG, TAG, "IN - CAGetTotalLengthFromHeader");
750
751     if (NULL == recvBuffer || !size)
752     {
753         OIC_LOG(ERROR, TAG, "recvBuffer is NULL");
754         return 0;
755     }
756
757     coap_transport_t transport = coap_get_tcp_header_type_from_initbyte(
758             ((unsigned char *)recvBuffer)[0] >> 4);
759     size_t optPaylaodLen = coap_get_length_from_header((unsigned char *)recvBuffer,
760                                                         transport);
761     size_t headerLen = coap_get_tcp_header_length((unsigned char *)recvBuffer);
762
763     OIC_LOG_V(DEBUG, TAG, "option/paylaod length [%d]", optPaylaodLen);
764     OIC_LOG_V(DEBUG, TAG, "header length [%d]", headerLen);
765     OIC_LOG_V(DEBUG, TAG, "total data length [%d]", headerLen + optPaylaodLen);
766
767     OIC_LOG(DEBUG, TAG, "OUT - CAGetTotalLengthFromHeader");
768     return headerLen + optPaylaodLen;
769 }
770
771 void CAGetTCPHeaderDetails(unsigned char* recvBuffer, coap_transport_t *transport,
772                            size_t *headerlen)
773 {
774     if (NULL == recvBuffer)
775     {
776         OIC_LOG(ERROR, TAG, "recvBuffer is NULL");
777         return;
778     }
779
780     if (NULL == transport)
781     {
782         OIC_LOG(ERROR, TAG, "transport is NULL");
783         return;
784     }
785
786     if (NULL == headerlen)
787     {
788         OIC_LOG(ERROR, TAG, "headerlen is NULL");
789         return;
790     }
791
792     *transport = coap_get_tcp_header_type_from_initbyte(
793         ((unsigned char *)recvBuffer)[0] >> 4);
794     *headerlen = coap_get_tcp_header_length_for_transport(*transport);
795 }
796 #endif