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