replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / camessagehandler.c
1 /* *****************************************************************
2  *
3  * Copyright 2014 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 #include "cainterface.h"
27 #include "camessagehandler.h"
28 #include "caremotehandler.h"
29 #include "caprotocolmessage.h"
30 #include "logger.h"
31 #include "trace.h"
32 #ifndef WITH_UPSTREAM_LIBCOAP
33 #include "coap/config.h"
34 #endif
35 #include "oic_malloc.h"
36 #include "canetworkconfigurator.h"
37 #include "caadapterutils.h"
38 #include "cainterfacecontroller.h"
39 #include "caretransmission.h"
40 #include "oic_string.h"
41
42 #ifdef WITH_BWT
43 #include "cablockwisetransfer.h"
44 #endif
45
46 #ifndef  SINGLE_THREAD
47 #include "uqueue.h"
48 #include "cathreadpool.h" /* for thread pool */
49 #include "caqueueingthread.h"
50
51 #define SINGLE_HANDLE
52 #define MAX_THREAD_POOL_SIZE    20
53
54 // thread pool handle
55 static ca_thread_pool_t g_threadPoolHandle = NULL;
56
57 // message handler main thread
58 static CAQueueingThread_t g_sendThread;
59 static CAQueueingThread_t g_receiveThread;
60
61 #else
62 #define CA_MAX_RT_ARRAY_SIZE    3
63 #endif  // SINGLE_THREAD
64
65 #define TAG "OIC_CA_MSG_HANDLE"
66
67 static CARetransmission_t g_retransmissionContext;
68
69 // handler field
70 static CARequestCallback g_requestHandler = NULL;
71 static CAResponseCallback g_responseHandler = NULL;
72 static CAErrorCallback g_errorHandler = NULL;
73 static CANetworkMonitorCallback g_nwMonitorHandler = NULL;
74
75 static void CAErrorHandler(const CAEndpoint_t *endpoint,
76                            const void *data, uint32_t dataLen,
77                            CAResult_t result);
78
79 static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint,
80                                        const CARemoteId_t *identity,
81                                        const void *data, CADataType_t dataType);
82
83 static void CASendErrorInfo(const CAEndpoint_t *endpoint, const CAInfo_t *info,
84                             CAResult_t result);
85
86 #ifdef SINGLE_THREAD
87 static void CAProcessReceivedData(CAData_t *data);
88 #endif
89 static void CADestroyData(void *data, uint32_t size);
90 static void CALogPayloadInfo(CAInfo_t *info);
91 static bool CADropSecondMessage(CAHistory_t *history, const CAEndpoint_t *endpoint, uint16_t id,
92                                 CAToken_t token, uint8_t tokenLength);
93
94 /**
95  * print send / receive message of CoAP.
96  * @param[in] data      CA information which has send/receive message and endpoint.
97  * @param[in] pdu       CoAP pdu low data.
98  */
99 static void CALogPDUInfo(const CAData_t *data, const coap_pdu_t *pdu);
100
101 #ifndef ARDUINO
102 static char g_headerBuffer[MAX_LOG_BUFFER_SIZE] = {0};
103 static size_t g_headerIndex = 0;
104 static void CASamsungLogMessage(const CAData_t *data, const coap_pdu_t *pdu);
105 #endif
106
107 #ifdef WITH_BWT
108 void CAAddDataToSendThread(CAData_t *data)
109 {
110     VERIFY_NON_NULL_VOID(data, TAG, "data");
111
112     // add thread
113     CAQueueingThreadAddData(&g_sendThread, data, sizeof(CAData_t));
114 }
115
116 void CAAddDataToReceiveThread(CAData_t *data)
117 {
118     VERIFY_NON_NULL_VOID(data, TAG, "data");
119
120     // add thread
121     CAQueueingThreadAddData(&g_receiveThread, data, sizeof(CAData_t));
122 }
123 #endif
124
125 static bool CAIsSelectedNetworkAvailable()
126 {
127     u_arraylist_t *list = CAGetSelectedNetworkList();
128     if (!list || u_arraylist_length(list) == 0)
129     {
130         OIC_LOG(ERROR, TAG, "No selected network");
131         return false;
132     }
133
134     return true;
135 }
136
137 static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint,
138                                        const CARemoteId_t *identity,
139                                        const void *data, CADataType_t dataType)
140 {
141     OIC_LOG(DEBUG, TAG, "CAGenerateHandlerData IN");
142     CAInfo_t *info = NULL;
143     CAData_t *cadata = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
144     if (!cadata)
145     {
146         OIC_LOG(ERROR, TAG, "memory allocation failed");
147         return NULL;
148     }
149 #ifdef SINGLE_THREAD
150     CAEndpoint_t* ep = endpoint;
151 #else
152     CAEndpoint_t* ep = CACloneEndpoint(endpoint);
153     if (!ep)
154     {
155         OIC_LOG(ERROR, TAG, "endpoint clone failed");
156         goto exit;
157     }
158 #endif
159
160     OIC_LOG_V(DEBUG, TAG, "address : %s", ep->addr);
161
162     if (CA_RESPONSE_DATA == dataType)
163     {
164         CAResponseInfo_t* resInfo = (CAResponseInfo_t*)OICCalloc(1, sizeof(CAResponseInfo_t));
165         if (!resInfo)
166         {
167             OIC_LOG(ERROR, TAG, "memory allocation failed");
168             goto exit;
169         }
170
171         CAResult_t result = CAGetResponseInfoFromPDU(data, resInfo, endpoint);
172         if (CA_STATUS_OK != result)
173         {
174             OIC_LOG(ERROR, TAG, "CAGetResponseInfoFromPDU Failed");
175             CADestroyResponseInfoInternal(resInfo);
176             goto exit;
177         }
178         cadata->responseInfo = resInfo;
179         info = &resInfo->info;
180         if (identity)
181         {
182             info->identity = *identity;
183         }
184         OIC_LOG(DEBUG, TAG, "Response Info :");
185         CALogPayloadInfo(info);
186     }
187     else if (CA_REQUEST_DATA == dataType)
188     {
189         CARequestInfo_t* reqInfo = (CARequestInfo_t*)OICCalloc(1, sizeof(CARequestInfo_t));
190         if (!reqInfo)
191         {
192             OIC_LOG(ERROR, TAG, "memory allocation failed");
193             goto exit;
194         }
195
196         CAResult_t result = CAGetRequestInfoFromPDU(data, endpoint, reqInfo);
197         if (CA_STATUS_OK != result)
198         {
199             OIC_LOG(ERROR, TAG, "CAGetRequestInfoFromPDU failed");
200             CADestroyRequestInfoInternal(reqInfo);
201             goto exit;
202         }
203
204         if (CADropSecondMessage(&caglobals.ca.requestHistory, endpoint, reqInfo->info.messageId,
205                                 reqInfo->info.token, reqInfo->info.tokenLength))
206         {
207             OIC_LOG(INFO, TAG, "Second Request with same Token, Drop it");
208             CADestroyRequestInfoInternal(reqInfo);
209             goto exit;
210         }
211
212         cadata->requestInfo = reqInfo;
213         info = &reqInfo->info;
214         if (identity)
215         {
216             info->identity = *identity;
217         }
218         OIC_LOG(DEBUG, TAG, "Request Info :");
219         CALogPayloadInfo(info);
220    }
221     else if (CA_ERROR_DATA == dataType)
222     {
223         CAErrorInfo_t *errorInfo = (CAErrorInfo_t *)OICCalloc(1, sizeof (CAErrorInfo_t));
224         if (!errorInfo)
225         {
226             OIC_LOG(ERROR, TAG, "Memory allocation failed!");
227             goto exit;
228         }
229
230         CAResult_t result = CAGetErrorInfoFromPDU(data, endpoint, errorInfo);
231         if (CA_STATUS_OK != result)
232         {
233             OIC_LOG(ERROR, TAG, "CAGetErrorInfoFromPDU failed");
234             OICFree(errorInfo);
235             goto exit;
236         }
237
238         cadata->errorInfo = errorInfo;
239         info = &errorInfo->info;
240         if (identity)
241         {
242             info->identity = *identity;
243         }
244         OIC_LOG(DEBUG, TAG, "error Info :");
245         CALogPayloadInfo(info);
246     }
247
248     cadata->remoteEndpoint = ep;
249     cadata->dataType = dataType;
250
251     OIC_LOG(DEBUG, TAG, "CAGenerateHandlerData OUT");
252     return cadata;
253
254 exit:
255     OICFree(cadata);
256 #ifndef SINGLE_THREAD
257     CAFreeEndpoint(ep);
258 #endif
259     return NULL;
260 }
261
262 static void CATimeoutCallback(const CAEndpoint_t *endpoint, const void *pdu, uint32_t size)
263 {
264     VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint");
265     VERIFY_NON_NULL_VOID(pdu, TAG, "pdu");
266 #ifdef SINGLE_THREAD
267     CAEndpoint_t* ep = endpoint;
268 #else
269     CAEndpoint_t* ep = CACloneEndpoint(endpoint);
270     if (!ep)
271     {
272         OIC_LOG(ERROR, TAG, "clone failed");
273         return;
274     }
275 #endif
276
277     CAResponseInfo_t* resInfo = (CAResponseInfo_t*)OICCalloc(1, sizeof(CAResponseInfo_t));
278
279     if (!resInfo)
280     {
281         OIC_LOG(ERROR, TAG, "calloc failed");
282 #ifndef SINGLE_THREAD
283         CAFreeEndpoint(ep);
284 #endif
285         return;
286     }
287
288     resInfo->result = CA_RETRANSMIT_TIMEOUT;
289     resInfo->info.type = CAGetMessageTypeFromPduBinaryData(pdu, size);
290     resInfo->info.messageId = CAGetMessageIdFromPduBinaryData(pdu, size);
291
292     CAResult_t res = CAGetTokenFromPDU((const coap_hdr_transport_t *) pdu, &(resInfo->info),
293                                        endpoint);
294     if (CA_STATUS_OK != res)
295     {
296         OIC_LOG(ERROR, TAG, "fail to get Token from retransmission list");
297         CADestroyResponseInfoInternal(resInfo);
298 #ifndef SINGLE_THREAD
299         CAFreeEndpoint(ep);
300 #endif
301         return;
302     }
303
304     CAData_t *cadata = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
305     if (NULL == cadata)
306     {
307         OIC_LOG(ERROR, TAG, "memory allocation failed !");
308 #ifndef SINGLE_THREAD
309         CAFreeEndpoint(ep);
310 #endif
311         CADestroyResponseInfoInternal(resInfo);
312         return;
313     }
314
315     cadata->type = SEND_TYPE_UNICAST;
316     cadata->remoteEndpoint = ep;
317     cadata->requestInfo = NULL;
318     cadata->responseInfo = resInfo;
319
320 #ifdef WITH_BWT
321     if (CAIsSupportedBlockwiseTransfer(endpoint->adapter))
322     {
323         res = CARemoveBlockDataFromListWithSeed(resInfo->info.token, resInfo->info.tokenLength,
324                                                 endpoint->port);
325         if (CA_STATUS_OK != res)
326         {
327             OIC_LOG(ERROR, TAG, "CARemoveBlockDataFromListWithSeed failed");
328         }
329     }
330 #endif // WITH_BWT
331
332 #ifdef SINGLE_THREAD
333     CAProcessReceivedData(cadata);
334 #else
335     CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t));
336 #endif
337 }
338
339 static void CADestroyData(void *data, uint32_t size)
340 {
341     OIC_LOG(DEBUG, TAG, "CADestroyData IN");
342     if ((size_t)size < sizeof(CAData_t))
343     {
344         OIC_LOG_V(ERROR, TAG, "Destroy data too small %p %d", data, size);
345     }
346     CAData_t *cadata = (CAData_t *) data;
347
348     if (NULL == cadata)
349     {
350         OIC_LOG(ERROR, TAG, "cadata is NULL");
351         return;
352     }
353 #ifndef SINGLE_THREAD
354     if (NULL != cadata->remoteEndpoint)
355     {
356         CAFreeEndpoint(cadata->remoteEndpoint);
357     }
358 #endif
359
360     if (NULL != cadata->requestInfo)
361     {
362         CADestroyRequestInfoInternal((CARequestInfo_t *) cadata->requestInfo);
363     }
364
365     if (NULL != cadata->responseInfo)
366     {
367         CADestroyResponseInfoInternal((CAResponseInfo_t *) cadata->responseInfo);
368     }
369
370     if (NULL != cadata->errorInfo)
371     {
372         CADestroyErrorInfoInternal(cadata->errorInfo);
373     }
374
375     OICFree(cadata);
376     OIC_LOG(DEBUG, TAG, "CADestroyData OUT");
377 }
378
379 #ifdef SINGLE_THREAD
380 static void CAProcessReceivedData(CAData_t *data)
381 {
382     OIC_LOG(DEBUG, TAG, "CAProcessReceivedData IN");
383     if (!data)
384     {
385         OIC_LOG(ERROR, TAG, "thread data error!!");
386         return;
387     }
388
389     // parse the data and call the callbacks.
390     // #1 parse the data
391     // #2 get endpoint
392     CAEndpoint_t *rep = (CAEndpoint_t *)(data->remoteEndpoint);
393     if (!rep)
394     {
395         OIC_LOG(ERROR, TAG, "remoteEndpoint error!!");
396         return;
397     }
398
399     if (data->requestInfo && g_requestHandler)
400     {
401         g_requestHandler(rep, data->requestInfo);
402     }
403     else if (data->responseInfo && g_responseHandler)
404     {
405         g_responseHandler(rep, data->responseInfo);
406     }
407     else if (data->errorInfo && g_errorHandler)
408     {
409         g_errorHandler(rep, data->errorInfo);
410     }
411
412     CADestroyData(data, sizeof(CAData_t));
413
414     OIC_LOG(DEBUG, TAG, "CAProcessReceivedData OUT");
415 }
416 #endif
417
418 #ifndef SINGLE_THREAD
419 static void CAReceiveThreadProcess(void *threadData)
420 {
421 #ifndef SINGLE_HANDLE
422     CAData_t *data = (CAData_t *) threadData;
423     OIC_TRACE_BEGIN(%s:CAProcessReceivedData, TAG);
424     CAProcessReceivedData(data);
425     OIC_TRACE_END();
426 #else
427     (void)threadData;
428 #endif
429 }
430 #endif // SINGLE_THREAD
431
432 static CAResult_t CAProcessMulticastData(const CAData_t *data)
433 {
434     VERIFY_NON_NULL(data, TAG, "data");
435     VERIFY_NON_NULL(data->remoteEndpoint, TAG, "remoteEndpoint");
436
437     coap_pdu_t *pdu = NULL;
438     CAInfo_t *info = NULL;
439     coap_list_t *options = NULL;
440     coap_transport_t transport = COAP_UDP;
441     CAResult_t res = CA_SEND_FAILED;
442
443     if (!data->requestInfo && !data->responseInfo)
444     {
445         OIC_LOG(ERROR, TAG, "request or response info is empty");
446         return res;
447     }
448
449     if (data->requestInfo)
450     {
451         OIC_LOG(DEBUG, TAG, "requestInfo is available..");
452
453         info = &data->requestInfo->info;
454         pdu = CAGeneratePDU(CA_GET, info, data->remoteEndpoint, &options, &transport);
455     }
456     else if (data->responseInfo)
457     {
458         OIC_LOG(DEBUG, TAG, "responseInfo is available..");
459
460         info = &data->responseInfo->info;
461         pdu = CAGeneratePDU(data->responseInfo->result, info, data->remoteEndpoint,
462                             &options, &transport);
463     }
464
465     if (!pdu)
466     {
467         OIC_LOG(ERROR,TAG,"Failed to generate multicast PDU");
468         CASendErrorInfo(data->remoteEndpoint, info, CA_SEND_FAILED);
469         coap_delete_list(options);
470         return res;
471     }
472
473 #ifdef WITH_BWT
474     if (CAIsSupportedBlockwiseTransfer(data->remoteEndpoint->adapter))
475     {
476         // Blockwise transfer
477         res = CAAddBlockOption(&pdu, info, data->remoteEndpoint, &options);
478         if (CA_STATUS_OK != res)
479         {
480             OIC_LOG(DEBUG, TAG, "CAAddBlockOption has failed");
481             goto exit;
482         }
483     }
484 #endif // WITH_BWT
485
486     CALogPDUInfo(data, pdu);
487
488     res = CASendMulticastData(data->remoteEndpoint, pdu->transport_hdr, pdu->length, data->dataType);
489     if (CA_STATUS_OK != res)
490     {
491         OIC_LOG_V(ERROR, TAG, "send failed:%d", res);
492         goto exit;
493     }
494
495     coap_delete_list(options);
496     coap_delete_pdu(pdu);
497     return res;
498
499 exit:
500     CAErrorHandler(data->remoteEndpoint, pdu->transport_hdr, pdu->length, res);
501     coap_delete_list(options);
502     coap_delete_pdu(pdu);
503     return res;
504 }
505
506 static CAResult_t CAProcessSendData(const CAData_t *data)
507 {
508     VERIFY_NON_NULL(data, TAG, "data");
509     VERIFY_NON_NULL(data->remoteEndpoint, TAG, "remoteEndpoint");
510
511     CAResult_t res = CA_STATUS_FAILED;
512
513     if (CA_NETWORK_COMMAND == data->dataType)
514     {
515         if (CA_REQ_DISCONNECT == data->eventInfo)
516         {
517 #ifdef TCP_ADAPTER
518             // request TCP disconnect
519             if (CA_ADAPTER_TCP == data->remoteEndpoint->adapter)
520             {
521                 OIC_LOG(INFO, TAG, "request TCP disconnect");
522                 return CADisconnectSession(data->remoteEndpoint);
523             }
524 #endif
525         }
526     }
527
528     CASendDataType_t type = data->type;
529
530     coap_pdu_t *pdu = NULL;
531     CAInfo_t *info = NULL;
532     coap_list_t *options = NULL;
533     coap_transport_t transport = COAP_UDP;
534
535     if (SEND_TYPE_UNICAST == type)
536     {
537         OIC_LOG(DEBUG,TAG,"Unicast message");
538
539 #ifdef ROUTING_GATEWAY
540         /*
541          * When forwarding a packet, do not attempt retransmission as its the responsibility of
542          * packet originator node
543          */
544         bool skipRetransmission = false;
545 #endif
546
547         if (NULL != data->requestInfo)
548         {
549             OIC_LOG(DEBUG, TAG, "requestInfo is available..");
550
551             info = &data->requestInfo->info;
552 #ifdef ROUTING_GATEWAY
553             skipRetransmission = data->requestInfo->info.skipRetransmission;
554 #endif
555             pdu = CAGeneratePDU(data->requestInfo->method, info, data->remoteEndpoint,
556                                 &options, &transport);
557         }
558         else if (NULL != data->responseInfo)
559         {
560             OIC_LOG(DEBUG, TAG, "responseInfo is available..");
561
562             info = &data->responseInfo->info;
563 #ifdef ROUTING_GATEWAY
564             skipRetransmission = data->responseInfo->info.skipRetransmission;
565 #endif
566             pdu = CAGeneratePDU(data->responseInfo->result, info, data->remoteEndpoint,
567                                 &options, &transport);
568         }
569         else
570         {
571             OIC_LOG(DEBUG, TAG, "request info, response info is empty");
572             return CA_STATUS_INVALID_PARAM;
573         }
574
575         // interface controller function call.
576         if (NULL != pdu)
577         {
578 #ifdef WITH_BWT
579             if (CAIsSupportedBlockwiseTransfer(data->remoteEndpoint->adapter))
580             {
581                 // Blockwise transfer
582                 if (NULL != info)
583                 {
584                     CAResult_t res = CAAddBlockOption(&pdu, info,
585                                                       data->remoteEndpoint,
586                                                       &options);
587                     if (CA_STATUS_OK != res)
588                     {
589                         OIC_LOG(INFO, TAG, "to write block option has failed");
590                         CAErrorHandler(data->remoteEndpoint, pdu->transport_hdr, pdu->length, res);
591                         coap_delete_list(options);
592                         coap_delete_pdu(pdu);
593                         return res;
594                     }
595                 }
596             }
597 #endif // WITH_BWT
598             CALogPDUInfo(data, pdu);
599
600             OIC_LOG_V(INFO, TAG, "CASendUnicastData type : %d", data->dataType);
601             res = CASendUnicastData(data->remoteEndpoint, pdu->transport_hdr, pdu->length, data->dataType);
602             if (CA_STATUS_OK != res)
603             {
604                 OIC_LOG_V(ERROR, TAG, "send failed:%d", res);
605                 CAErrorHandler(data->remoteEndpoint, pdu->transport_hdr, pdu->length, res);
606                 coap_delete_list(options);
607                 coap_delete_pdu(pdu);
608                 return res;
609             }
610
611 #ifdef WITH_TCP
612             if (CAIsSupportedCoAPOverTCP(data->remoteEndpoint->adapter))
613             {
614                 OIC_LOG(INFO, TAG, "retransmission will be not worked");
615             }
616             else
617 #endif
618 #ifdef ROUTING_GATEWAY
619             if (!skipRetransmission)
620 #endif
621             {
622                 // for retransmission
623                 res = CARetransmissionSentData(&g_retransmissionContext,
624                                                data->remoteEndpoint,
625                                                data->dataType,
626                                                pdu->transport_hdr, pdu->length);
627                 if ((CA_STATUS_OK != res) && (CA_NOT_SUPPORTED != res))
628                 {
629                     //when retransmission not supported this will return CA_NOT_SUPPORTED, ignore
630                     OIC_LOG_V(INFO, TAG, "retransmission is not enabled due to error, res : %d", res);
631                     coap_delete_list(options);
632                     coap_delete_pdu(pdu);
633                     return res;
634                 }
635             }
636
637             coap_delete_list(options);
638             coap_delete_pdu(pdu);
639         }
640         else
641         {
642             OIC_LOG(ERROR,TAG,"Failed to generate unicast PDU");
643             CASendErrorInfo(data->remoteEndpoint, info, CA_SEND_FAILED);
644             return CA_SEND_FAILED;
645         }
646     }
647     else if (SEND_TYPE_MULTICAST == type)
648     {
649         OIC_LOG(DEBUG,TAG,"Multicast message");
650 #ifdef WITH_TCP
651         /*
652          * If CoAP over TCP is enabled, the CoAP pdu wont be same for IP and other adapters.
653          * That's why we need to generate two pdu's, one for IP and second for other transports.
654          * Two possible cases we might have to split: a) when adapter is CA_DEFAULT_ADAPTER
655          * b) when one of the adapter is IP adapter(ex: CA_ADAPTER_IP | CA_ADAPTER_GATT_BTLE)
656          */
657         if (data->remoteEndpoint->adapter == CA_DEFAULT_ADAPTER ||
658                 (CA_ADAPTER_IP & data->remoteEndpoint->adapter &&
659                     CA_ADAPTER_IP != data->remoteEndpoint->adapter))
660         {
661             if (data->remoteEndpoint->adapter == CA_DEFAULT_ADAPTER)
662             {
663                 data->remoteEndpoint->adapter = CA_ALL_ADAPTERS ^ CA_ADAPTER_IP;
664             }
665             else
666             {
667                 data->remoteEndpoint->adapter = data->remoteEndpoint->adapter ^ CA_ADAPTER_IP;
668             }
669             CAProcessMulticastData(data);
670             data->remoteEndpoint->adapter = CA_ADAPTER_IP;
671             CAProcessMulticastData(data);
672         }
673         else
674         {
675             CAProcessMulticastData(data);
676         }
677 #else
678         CAProcessMulticastData(data);
679 #endif
680     }
681     return CA_STATUS_OK;
682 }
683
684 #ifndef SINGLE_THREAD
685 static void CASendThreadProcess(void *threadData)
686 {
687     CAData_t *data = (CAData_t *) threadData;
688     OIC_TRACE_BEGIN(%s:CAProcessSendData, TAG);
689     CAProcessSendData(data);
690     OIC_TRACE_END();
691 }
692 #endif
693
694 /*
695  * If a second message arrives with the same message ID, token and the other address
696  * family, drop it.  Typically, IPv6 beats IPv4, so the IPv4 message is dropped.
697  */
698 static bool CADropSecondMessage(CAHistory_t *history, const CAEndpoint_t *ep, uint16_t id,
699                                 CAToken_t token, uint8_t tokenLength)
700 {
701     if (!ep)
702     {
703         return true;
704     }
705     if (ep->adapter != CA_ADAPTER_IP)
706     {
707         return false;
708     }
709     if (!caglobals.ip.dualstack)
710     {
711         return false;
712     }
713
714     if (tokenLength > CA_MAX_TOKEN_LEN)
715     {
716         /*
717          * If token length is more than CA_MAX_TOKEN_LEN,
718          * we compare the first CA_MAX_TOKEN_LEN bytes only.
719          */
720         tokenLength = CA_MAX_TOKEN_LEN;
721     }
722
723     bool ret = false;
724     CATransportFlags_t familyFlags = ep->flags & CA_IPFAMILY_MASK;
725
726     for (size_t i = 0; i < sizeof(history->items) / sizeof(history->items[0]); i++)
727     {
728         CAHistoryItem_t *item = &(history->items[i]);
729         if (id == item->messageId && tokenLength == item->tokenLength
730             && memcmp(item->token, token, tokenLength) == 0)
731         {
732             if ((familyFlags ^ item->flags) == CA_IPFAMILY_MASK)
733             {
734                 OIC_LOG_V(INFO, TAG, "IPv%c duplicate message ignored",
735                           familyFlags & CA_IPV6 ? '6' : '4');
736                 ret = true;
737                 break;
738             }
739         }
740     }
741
742     history->items[history->nextIndex].flags = familyFlags;
743     history->items[history->nextIndex].messageId = id;
744     if (token && tokenLength)
745     {
746         memcpy(history->items[history->nextIndex].token, token, tokenLength);
747         history->items[history->nextIndex].tokenLength = tokenLength;
748     }
749
750     if (++history->nextIndex >= HISTORYSIZE)
751     {
752         history->nextIndex = 0;
753     }
754
755     return ret;
756 }
757
758 static CAResult_t CAReceivedPacketCallback(const CASecureEndpoint_t *sep,
759                                            const void *data, uint32_t dataLen)
760 {
761     VERIFY_NON_NULL(sep, TAG, "remoteEndpoint");
762     VERIFY_NON_NULL(data, TAG, "data");
763     OIC_TRACE_BEGIN(%s:CAReceivedPacketCallback, TAG);
764
765     if (0 == dataLen)
766     {
767         OIC_LOG(ERROR, TAG, "dataLen is zero");
768         OIC_TRACE_END();
769
770         return CA_STATUS_FAILED;
771     }
772
773     // samsung log
774     OIC_LOG(DEBUG, TAG, "received pdu data :");
775     if (dataLen < 32)
776     {
777         OIC_LOG_BUFFER(DEBUG, TAG,  data, dataLen);
778     }
779     else
780     {
781         OIC_LOG_BUFFER(DEBUG, TAG,  data, 32);
782     }
783
784     CAResult_t res = CA_STATUS_OK;
785     uint32_t code = CA_NOT_FOUND;
786     CAData_t *cadata = NULL;
787
788     coap_pdu_t *pdu = (coap_pdu_t *) CAParsePDU((const char *) data, dataLen, &code,
789                                                 &(sep->endpoint));
790     if (NULL == pdu)
791     {
792         OIC_LOG(ERROR, TAG, "Parse PDU failed");
793         res = CA_STATUS_FAILED;
794         goto exit;
795     }
796
797     OIC_LOG_V(DEBUG, TAG, "code = %d", code);
798     if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code)
799     {
800         cadata = CAGenerateHandlerData(&(sep->endpoint), &(sep->identity), pdu, CA_REQUEST_DATA);
801         if (!cadata)
802         {
803             OIC_LOG(ERROR, TAG, "CAReceivedPacketCallback, CAGenerateHandlerData failed!");
804             coap_delete_pdu(pdu);
805             goto exit;
806         }
807     }
808     else
809     {
810         cadata = CAGenerateHandlerData(&(sep->endpoint), &(sep->identity), pdu, CA_RESPONSE_DATA);
811         if (!cadata)
812         {
813             OIC_LOG(ERROR, TAG, "CAReceivedPacketCallback, CAGenerateHandlerData failed!");
814             coap_delete_pdu(pdu);
815             goto exit;
816         }
817
818 #ifdef WITH_TCP
819         if (CAIsSupportedCoAPOverTCP(sep->endpoint.adapter))
820         {
821             OIC_LOG(INFO, TAG, "retransmission is not supported");
822         }
823         else
824 #endif
825         {
826             // for retransmission
827             void *retransmissionPdu = NULL;
828             CARetransmissionReceivedData(&g_retransmissionContext, cadata->remoteEndpoint, pdu->transport_hdr,
829                                          pdu->length, &retransmissionPdu);
830
831             // get token from saved data in retransmission list
832             if (retransmissionPdu && CA_EMPTY == code)
833             {
834                 if (cadata->responseInfo)
835                 {
836                     CAInfo_t *info = &cadata->responseInfo->info;
837                     CAResult_t res = CAGetTokenFromPDU((const coap_hdr_transport_t *)retransmissionPdu,
838                                                        info, &(sep->endpoint));
839                     if (CA_STATUS_OK != res)
840                     {
841                         OIC_LOG(ERROR, TAG, "fail to get Token from retransmission list");
842                         OICFree(info->token);
843                         info->tokenLength = 0;
844                     }
845                 }
846             }
847             OICFree(retransmissionPdu);
848         }
849     }
850
851     cadata->type = SEND_TYPE_UNICAST;
852
853     CALogPDUInfo(cadata, pdu);
854
855 #ifdef SINGLE_THREAD
856     CAProcessReceivedData(cadata);
857 #else
858 #ifdef WITH_BWT
859     if (CAIsSupportedBlockwiseTransfer(sep->endpoint.adapter))
860     {
861         CAResult_t res = CAReceiveBlockWiseData(pdu, &(sep->endpoint), cadata, dataLen);
862         if (CA_NOT_SUPPORTED == res || CA_REQUEST_TIMEOUT == res)
863         {
864             OIC_LOG(DEBUG, TAG, "this message does not have block option");
865             CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t));
866         }
867         else
868         {
869             CADestroyData(cadata, sizeof(CAData_t));
870         }
871     }
872     else
873 #endif
874     {
875         CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t));
876     }
877 #endif // SINGLE_THREAD
878
879     coap_delete_pdu(pdu);
880
881 exit:
882     OIC_LOG(DEBUG, TAG, "OUT - Recv Thread");
883     OIC_TRACE_END();
884     return res;
885 }
886
887 static void CAAdapterStateChangedCallback(CATransportAdapter_t transportType, bool enabled)
888 {
889     if (!enabled)
890     {
891         CAClearMessageHandler(transportType);
892     }
893 }
894
895 static bool CAClearQueueEndpointDataContext(void *data, uint32_t size, void *ctx)
896 {
897     if (NULL == data || NULL == ctx)
898     {
899         return false;
900     }
901
902     CAData_t *caData = (CAData_t *)data;
903     const CAEndpoint_t *endpoint = (const CAEndpoint_t *)ctx;
904
905     if (NULL != caData && NULL != caData->remoteEndpoint)
906     {
907         if (strcmp(caData->remoteEndpoint->addr, endpoint->addr) == 0
908             && caData->remoteEndpoint->port == endpoint->port
909             && caData->remoteEndpoint->adapter == endpoint->adapter)
910         {
911             return true;
912         }
913     }
914     return false;
915 }
916
917 static void CAConnectionStateChangedCallback(const CAEndpoint_t *info, bool isConnected)
918 {
919     if (!isConnected)
920     {
921         CAResult_t res = CAQueueingThreadClearContextData(&g_sendThread,
922                                                           CAClearQueueEndpointDataContext,
923                                                           info);
924         if (CA_STATUS_OK != res)
925         {
926             OIC_LOG(ERROR, TAG, "Could not clear the send queue");
927         }
928     }
929 }
930
931 void CAHandleRequestResponseCallbacks()
932 {
933 #ifdef SINGLE_THREAD
934     CAReadData();
935     CARetransmissionBaseRoutine((void *)&g_retransmissionContext);
936 #else
937 #ifdef SINGLE_HANDLE
938     // parse the data and call the callbacks.
939     // #1 parse the data
940     // #2 get endpoint
941
942     oc_mutex_lock(g_receiveThread.threadMutex);
943
944     u_queue_message_t *item = u_queue_get_element(g_receiveThread.dataQueue);
945
946     oc_mutex_unlock(g_receiveThread.threadMutex);
947
948     if (NULL == item || NULL == item->msg)
949     {
950         return;
951     }
952
953     // get endpoint
954     CAData_t *td = (CAData_t *) item->msg;
955
956     if (td->requestInfo && g_requestHandler)
957     {
958         OIC_LOG_V(DEBUG, TAG, "request callback : %d", td->requestInfo->info.numOptions);
959         g_requestHandler(td->remoteEndpoint, td->requestInfo);
960     }
961     else if (td->responseInfo && g_responseHandler)
962     {
963         OIC_LOG_V(DEBUG, TAG, "response callback : %d", td->responseInfo->info.numOptions);
964         g_responseHandler(td->remoteEndpoint, td->responseInfo);
965     }
966     else if (td->errorInfo && g_errorHandler)
967     {
968         OIC_LOG_V(DEBUG, TAG, "error callback error: %d", td->errorInfo->result);
969         g_errorHandler(td->remoteEndpoint, td->errorInfo);
970     }
971
972     CADestroyData(item->msg, sizeof(CAData_t));
973     OICFree(item);
974
975 #endif // SINGLE_HANDLE
976 #endif // SINGLE_THREAD
977 }
978
979 static CAData_t* CAPrepareSendData(const CAEndpoint_t *endpoint, const void *sendData,
980                                    CADataType_t dataType)
981 {
982     OIC_LOG(DEBUG, TAG, "CAPrepareSendData IN");
983
984     CAData_t *cadata = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
985     if (!cadata)
986     {
987         OIC_LOG(ERROR, TAG, "memory allocation failed");
988         return NULL;
989     }
990
991     if (CA_REQUEST_DATA == dataType)
992     {
993 #ifdef SINGLE_THREAD
994         CARequestInfo_t *request = (CARequestInfo_t *)sendData;
995 #else
996         // clone request info
997         CARequestInfo_t *request = CACloneRequestInfo((CARequestInfo_t *)sendData);
998         if (!request)
999         {
1000             OIC_LOG(ERROR, TAG, "CACloneRequestInfo failed");
1001             goto exit;
1002         }
1003 #endif
1004         cadata->type = request->isMulticast ? SEND_TYPE_MULTICAST : SEND_TYPE_UNICAST;
1005         cadata->requestInfo =  request;
1006     }
1007     else if (CA_RESPONSE_DATA == dataType || CA_RESPONSE_FOR_RES == dataType)
1008     {
1009 #ifdef SINGLE_THREAD
1010         CAResponseInfo_t *response = (CAResponseInfo_t *)sendData;
1011 #else
1012         // clone response info
1013         CAResponseInfo_t *response = CACloneResponseInfo((CAResponseInfo_t *)sendData);
1014         if (!response)
1015         {
1016             OIC_LOG(ERROR, TAG, "CACloneResponseInfo failed");
1017             goto exit;
1018         }
1019 #endif
1020         cadata->type = response->isMulticast ? SEND_TYPE_MULTICAST : SEND_TYPE_UNICAST;
1021         cadata->responseInfo = response;
1022     }
1023     else
1024     {
1025         OIC_LOG(ERROR, TAG, "CAPrepareSendData unknown data type");
1026         goto exit;
1027     }
1028
1029 #ifdef SINGLE_THREAD
1030     CAEndpoint_t* ep = endpoint;
1031 #else
1032     CAEndpoint_t* ep = CACloneEndpoint(endpoint);
1033     if (!ep)
1034     {
1035         OIC_LOG(ERROR, TAG, "endpoint clone failed");
1036         goto exit;
1037     }
1038 #endif
1039     cadata->remoteEndpoint = ep;
1040     cadata->dataType = dataType;
1041     return cadata;
1042
1043 exit:
1044 #ifndef SINGLE_THREAD
1045     CADestroyData(cadata, sizeof(CAData_t));
1046 #else
1047     OICFree(cadata);
1048 #endif
1049     return NULL;
1050 }
1051
1052 CAResult_t CADetachSendNetworkReqMessage(const CAEndpoint_t *endpoint,
1053                                          CAConnectEvent_t event,
1054                                          CADataType_t dataType)
1055 {
1056     VERIFY_NON_NULL(endpoint, TAG, "endpoint");
1057
1058     if (false == CAIsSelectedNetworkAvailable())
1059     {
1060         return CA_STATUS_FAILED;
1061     }
1062
1063 #ifndef SINGLE_THREAD
1064     CAData_t *cadata = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
1065     if (!cadata)
1066     {
1067         OIC_LOG(ERROR, TAG, "cadata memory allocation failed");
1068         return CA_STATUS_FAILED;
1069     }
1070
1071     CAEndpoint_t* ep = CACloneEndpoint(endpoint);
1072     if (!ep)
1073     {
1074         OIC_LOG(ERROR, TAG, "endpoint clone failed");
1075         OICFree(cadata);
1076         return CA_STATUS_FAILED;
1077     }
1078
1079     cadata->remoteEndpoint = ep;
1080     cadata->eventInfo = event;
1081     cadata->dataType = dataType;
1082
1083     CAQueueingThreadAddData(&g_sendThread, cadata, sizeof(CAData_t));
1084 #endif
1085
1086     return CA_STATUS_OK;
1087 }
1088
1089 CAResult_t CADetachSendMessage(const CAEndpoint_t *endpoint, const void *sendMsg,
1090                                CADataType_t dataType)
1091 {
1092     VERIFY_NON_NULL(endpoint, TAG, "endpoint");
1093     VERIFY_NON_NULL(sendMsg, TAG, "sendMsg");
1094
1095     if (false == CAIsSelectedNetworkAvailable())
1096     {
1097         return CA_STATUS_FAILED;
1098     }
1099
1100 #ifdef ARDUINO
1101     // If max retransmission queue is reached, then don't handle new request
1102     if (CA_MAX_RT_ARRAY_SIZE == u_arraylist_length(g_retransmissionContext.dataList))
1103     {
1104         OIC_LOG(ERROR, TAG, "max RT queue size reached!");
1105         return CA_SEND_FAILED;
1106     }
1107 #endif // ARDUINO
1108
1109     CAData_t *data = CAPrepareSendData(endpoint, sendMsg, dataType);
1110     if(!data)
1111     {
1112         OIC_LOG(ERROR, TAG, "CAPrepareSendData failed");
1113         return CA_MEMORY_ALLOC_FAILED;
1114     }
1115
1116     OIC_LOG_V(INFO_PRIVATE, TAG, "DID of endpoint of this message is %s", endpoint->remoteId);
1117
1118 #ifdef SINGLE_THREAD
1119     CAResult_t result = CAProcessSendData(data);
1120     if (CA_STATUS_OK != result)
1121     {
1122         OIC_LOG(ERROR, TAG, "CAProcessSendData failed");
1123         OICFree(data);
1124         return result;
1125     }
1126
1127     OICFree(data);
1128
1129 #else
1130 #ifdef WITH_BWT
1131     if (CAIsSupportedBlockwiseTransfer(endpoint->adapter))
1132     {
1133         CACheckAndDeleteTimedOutBlockData();
1134         // send block data
1135         CAResult_t res = CASendBlockWiseData(data);
1136         if (CA_NOT_SUPPORTED == res)
1137         {
1138             OIC_LOG(DEBUG, TAG, "normal msg will be sent");
1139             CAQueueingThreadAddData(&g_sendThread, data, sizeof(CAData_t));
1140             return CA_STATUS_OK;
1141         }
1142         else
1143         {
1144             CADestroyData(data, sizeof(CAData_t));
1145         }
1146
1147         return res;
1148     }
1149     else
1150 #endif // WITH_BWT
1151     {
1152         CAQueueingThreadAddData(&g_sendThread, data, sizeof(CAData_t));
1153     }
1154 #endif // SINGLE_THREAD
1155
1156     return CA_STATUS_OK;
1157 }
1158
1159 void CASetInterfaceCallbacks(CARequestCallback ReqHandler, CAResponseCallback RespHandler,
1160                              CAErrorCallback errorHandler)
1161 {
1162     g_requestHandler = ReqHandler;
1163     g_responseHandler = RespHandler;
1164     g_errorHandler = errorHandler;
1165 }
1166
1167 void CASetNetworkMonitorCallback(CANetworkMonitorCallback nwMonitorHandler)
1168 {
1169     g_nwMonitorHandler = nwMonitorHandler;
1170 }
1171
1172 CAResult_t CAInitializeMessageHandler(CATransportAdapter_t transportType)
1173 {
1174     CASetPacketReceivedCallback(CAReceivedPacketCallback);
1175     CASetErrorHandleCallback(CAErrorHandler);
1176
1177 #ifndef SINGLE_THREAD
1178     // create thread pool
1179     CAResult_t res = ca_thread_pool_init(MAX_THREAD_POOL_SIZE, &g_threadPoolHandle);
1180     if (CA_STATUS_OK != res)
1181     {
1182         OIC_LOG(ERROR, TAG, "thread pool initialize error.");
1183         return res;
1184     }
1185
1186     // send thread initialize
1187     res = CAQueueingThreadInitialize(&g_sendThread, g_threadPoolHandle,
1188                                      CASendThreadProcess, CADestroyData);
1189     if (CA_STATUS_OK != res)
1190     {
1191         OIC_LOG(ERROR, TAG, "Failed to Initialize send queue thread");
1192         return res;
1193     }
1194
1195     // start send thread
1196 #ifndef __TIZENRT__
1197     res = CAQueueingThreadStart(&g_sendThread);
1198 #else
1199     res = CAQueueingThreadStart(&g_sendThread, "IoT_MessageHandlerQueue");
1200 #endif
1201     if (CA_STATUS_OK != res)
1202     {
1203         OIC_LOG(ERROR, TAG, "thread start error(send thread).");
1204         return res;
1205     }
1206
1207     // receive thread initialize
1208     res = CAQueueingThreadInitialize(&g_receiveThread, g_threadPoolHandle,
1209                                      CAReceiveThreadProcess, CADestroyData);
1210     if (CA_STATUS_OK != res)
1211     {
1212         OIC_LOG(ERROR, TAG, "Failed to Initialize receive queue thread");
1213         return res;
1214     }
1215
1216 #ifndef SINGLE_HANDLE // This will be enabled when RI supports multi threading
1217     // start receive thread
1218     res = CAQueueingThreadStart(&g_receiveThread);
1219     if (CA_STATUS_OK != res)
1220     {
1221         OIC_LOG(ERROR, TAG, "thread start error(receive thread).");
1222         return res;
1223     }
1224 #endif // SINGLE_HANDLE
1225
1226     // retransmission initialize
1227     res = CARetransmissionInitialize(&g_retransmissionContext, g_threadPoolHandle,
1228                                      CASendUnicastData, CATimeoutCallback, NULL);
1229     if (CA_STATUS_OK != res)
1230     {
1231         OIC_LOG(ERROR, TAG, "Failed to Initialize Retransmission.");
1232         return res;
1233     }
1234
1235 #ifdef WITH_BWT
1236     // block-wise transfer initialize
1237     res = CAInitializeBlockWiseTransfer(CAAddDataToSendThread, CAAddDataToReceiveThread);
1238     if (CA_STATUS_OK != res)
1239     {
1240         OIC_LOG(ERROR, TAG, "Failed to Initialize BlockWiseTransfer.");
1241         return res;
1242     }
1243 #endif
1244
1245     // start retransmission
1246     res = CARetransmissionStart(&g_retransmissionContext);
1247     if (CA_STATUS_OK != res)
1248     {
1249         OIC_LOG(ERROR, TAG, "thread start error(retransmission thread).");
1250         return res;
1251     }
1252
1253     // initialize interface adapters by controller
1254     CAInitializeAdapters(g_threadPoolHandle, transportType);
1255     CASetNetworkMonitorCallbacks(CAAdapterStateChangedCallback, CAConnectionStateChangedCallback);
1256 #else
1257     // retransmission initialize
1258     CAResult_t res = CARetransmissionInitialize(&g_retransmissionContext, NULL, CASendUnicastData,
1259                                                 CATimeoutCallback, NULL);
1260     if (CA_STATUS_OK != res)
1261     {
1262         OIC_LOG(ERROR, TAG, "Failed to Initialize Retransmission.");
1263         return res;
1264     }
1265
1266     CAInitializeAdapters();
1267 #endif // SINGLE_THREAD
1268
1269     return CA_STATUS_OK;
1270 }
1271
1272 static bool CAClearQueueAdapterDataContext(void *data, uint32_t size, void *ctx)
1273 {
1274     if (NULL == data || NULL == ctx)
1275     {
1276         return false;
1277     }
1278
1279     CAData_t *caData = (CAData_t *)data;
1280     CATransportAdapter_t *type = (CATransportAdapter_t *)ctx;
1281
1282     if (NULL != caData && NULL != caData->remoteEndpoint
1283         && caData->remoteEndpoint->adapter == *type)
1284     {
1285         return true;
1286     }
1287     return false;
1288 }
1289
1290 void CAClearMessageHandler(CATransportAdapter_t transportType)
1291 {
1292     CATransportAdapter_t *typeCtx = &transportType;
1293
1294     CAResult_t res = CAQueueingThreadClearContextData(&g_sendThread,
1295                                                       CAClearQueueAdapterDataContext,
1296                                                       typeCtx);
1297
1298     if (res != CA_STATUS_OK)
1299     {
1300         OIC_LOG_V(ERROR, TAG, "Clear send data failed[%d]", res);
1301     }
1302
1303     res = CARetransmissionClearAdapterData(&g_retransmissionContext, transportType);
1304     if (res != CA_STATUS_OK)
1305     {
1306         OIC_LOG_V(ERROR, TAG, "Clear retransmission data failed[%d]", res);
1307     }
1308 }
1309
1310 void CATerminateMessageHandler()
1311 {
1312 #ifndef SINGLE_THREAD
1313     CATransportAdapter_t connType;
1314     u_arraylist_t *list = CAGetSelectedNetworkList();
1315     uint32_t length = u_arraylist_length(list);
1316
1317     uint32_t i = 0;
1318     for (i = 0; i < length; i++)
1319     {
1320         void* ptrType = u_arraylist_get(list, i);
1321
1322         if (NULL == ptrType)
1323         {
1324             continue;
1325         }
1326
1327         connType = *(CATransportAdapter_t *)ptrType;
1328         CAStopAdapter(connType);
1329     }
1330
1331     // stop retransmission
1332     if (NULL != g_retransmissionContext.threadMutex)
1333     {
1334         CARetransmissionStop(&g_retransmissionContext);
1335     }
1336
1337     // stop thread
1338     // delete thread data
1339     if (NULL != g_sendThread.threadMutex)
1340     {
1341         CAQueueingThreadStop(&g_sendThread);
1342     }
1343
1344     // stop thread
1345     // delete thread data
1346     if (NULL != g_receiveThread.threadMutex)
1347     {
1348 #ifndef SINGLE_HANDLE // This will be enabled when RI supports multi threading
1349         CAQueueingThreadStop(&g_receiveThread);
1350 #endif
1351     }
1352
1353     // destroy thread pool
1354     if (NULL != g_threadPoolHandle)
1355     {
1356         ca_thread_pool_free(g_threadPoolHandle);
1357         g_threadPoolHandle = NULL;
1358     }
1359
1360 #ifdef WITH_BWT
1361     CATerminateBlockWiseTransfer();
1362 #endif
1363     CARetransmissionDestroy(&g_retransmissionContext);
1364     CAQueueingThreadDestroy(&g_sendThread);
1365     CAQueueingThreadDestroy(&g_receiveThread);
1366
1367     // terminate interface adapters by controller
1368     CATerminateAdapters();
1369 #else
1370     // terminate interface adapters by controller
1371     CATerminateAdapters();
1372
1373     // stop retransmission
1374     CARetransmissionStop(&g_retransmissionContext);
1375     CARetransmissionDestroy(&g_retransmissionContext);
1376 #endif // SINGLE_THREAD
1377 }
1378
1379 static void CALogPayloadInfo(CAInfo_t *info)
1380 {
1381     if (info)
1382     {
1383         if (info->options)
1384         {
1385             for (uint32_t i = 0; i < info->numOptions; i++)
1386             {
1387                 OIC_LOG_V(DEBUG, TAG, "optionID: %u", info->options[i].optionID);
1388
1389                 OIC_LOG_V(DEBUG, TAG, "list: %s", info->options[i].optionData);
1390             }
1391         }
1392
1393         if (info->payload)
1394         {
1395             OIC_LOG_V(DEBUG, TAG, "payload: %p(%zu)", info->payload,
1396                       info->payloadSize);
1397         }
1398
1399         if (info->token)
1400         {
1401             OIC_LOG(DEBUG, TAG, "token:");
1402             OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *) info->token,
1403                            info->tokenLength);
1404         }
1405         OIC_LOG_V(DEBUG, TAG, "msgID: %u", info->messageId);
1406     }
1407     else
1408     {
1409         OIC_LOG(DEBUG, TAG, "info is NULL, cannot output log data");
1410     }
1411 }
1412
1413 void CAErrorHandler(const CAEndpoint_t *endpoint,
1414                     const void *data, uint32_t dataLen,
1415                     CAResult_t result)
1416 {
1417     OIC_LOG(DEBUG, TAG, "CAErrorHandler IN");
1418     VERIFY_NON_NULL_VOID(endpoint, TAG, "remoteEndpoint");
1419     VERIFY_NON_NULL_VOID(data, TAG, "data");
1420
1421     if (0 == dataLen)
1422     {
1423         OIC_LOG(ERROR, TAG, "dataLen is zero");
1424         return;
1425     }
1426
1427 #ifndef SINGLE_THREAD
1428     uint32_t code = CA_NOT_FOUND;
1429     //Do not free remoteEndpoint and data. Currently they will be freed in data thread
1430     //Get PDU data
1431     coap_pdu_t *pdu = (coap_pdu_t *)CAParsePDU((const char *)data, dataLen, &code, endpoint);
1432     if (NULL == pdu)
1433     {
1434         OIC_LOG(ERROR, TAG, "Parse PDU failed");
1435         return;
1436     }
1437
1438     CAData_t *cadata = CAGenerateHandlerData(endpoint, NULL, pdu, CA_ERROR_DATA);
1439     if (!cadata)
1440     {
1441         OIC_LOG(ERROR, TAG, "CAErrorHandler, CAGenerateHandlerData failed!");
1442         coap_delete_pdu(pdu);
1443         return;
1444     }
1445
1446     cadata->errorInfo->result = result;
1447
1448     CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t));
1449     coap_delete_pdu(pdu);
1450 #else
1451     (void)result;
1452 #endif
1453
1454     OIC_LOG(DEBUG, TAG, "CAErrorHandler OUT");
1455     return;
1456 }
1457
1458 static void CASendErrorInfo(const CAEndpoint_t *endpoint, const CAInfo_t *info, CAResult_t result)
1459 {
1460     OIC_LOG(DEBUG, TAG, "CASendErrorInfo IN");
1461 #ifndef SINGLE_THREAD
1462     CAData_t *cadata = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
1463     if (!cadata)
1464     {
1465         OIC_LOG(ERROR, TAG, "cadata memory allocation failed");
1466         return;
1467     }
1468
1469     CAEndpoint_t* ep = CACloneEndpoint(endpoint);
1470     if (!ep)
1471     {
1472         OIC_LOG(ERROR, TAG, "endpoint clone failed");
1473         OICFree(cadata);
1474         return;
1475     }
1476
1477     CAErrorInfo_t *errorInfo = (CAErrorInfo_t *)OICCalloc(1, sizeof (CAErrorInfo_t));
1478     if (!errorInfo)
1479     {
1480         OIC_LOG(ERROR, TAG, "errorInfo memory allocation failed");
1481         OICFree(cadata);
1482         CAFreeEndpoint(ep);
1483         return;
1484     }
1485
1486     CAResult_t res = CACloneInfo(info, &errorInfo->info);
1487     if (CA_STATUS_OK != res)
1488     {
1489         OIC_LOG(ERROR, TAG, "info clone failed");
1490         OICFree(cadata);
1491         OICFree(errorInfo);
1492         CAFreeEndpoint(ep);
1493         return;
1494     }
1495
1496     errorInfo->result = result;
1497     cadata->remoteEndpoint = ep;
1498     cadata->errorInfo = errorInfo;
1499     cadata->dataType = CA_ERROR_DATA;
1500
1501     CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t));
1502 #endif
1503     OIC_LOG(DEBUG, TAG, "CASendErrorInfo OUT");
1504 }
1505
1506
1507
1508 #ifndef ARDUINO
1509 #ifdef __TIZENRT__
1510 static void CALogPDUInfo(const CAData_t *data, const coap_pdu_t *pdu)
1511 {
1512
1513         if(data == NULL || pdu == NULL)
1514         {
1515                 printf("INVALID INPUT, CALogPDUInfo FAIL\n");
1516         }
1517
1518         char type[30] = "";
1519
1520         switch(data->dataType)
1521         {
1522                 case CA_REQUEST_DATA:
1523                         strncpy(type, "\e[32mREQUEST  <<<<\e[m", 30);
1524                         break;
1525                 case CA_RESPONSE_DATA:
1526                         strncpy(type, "\e[36mRESPONSE >>>>\e[m", 30);
1527                         break;
1528                 case CA_ERROR_DATA:
1529                         strncpy(type, "ERROR", 30);
1530                         break;
1531                 case CA_RESPONSE_FOR_RES:
1532                         strncpy(type, "RESP_RES >>>>", 30);
1533                         break;
1534                 default:
1535                         snprintf(type, 30, "Type : %d", data->dataType);
1536                         break;
1537         }
1538
1539
1540         char method[20] = "";
1541         const CAInfo_t *info = NULL;
1542         if (NULL != data->requestInfo)
1543         {
1544                 switch(data->requestInfo->method)
1545                 {
1546                         case CA_GET:
1547                                 strncpy(method, "GET", 20);
1548                                 break;
1549                         case CA_POST:
1550                                 strncpy(method, "POST", 20);
1551                                 break;
1552                         case CA_PUT:
1553                                 strncpy(method, "PUT", 20);
1554                                 break;
1555                         case CA_DELETE:
1556                                 strncpy(method, "DEL", 20);
1557                                 break;
1558                         default:
1559                                 sprintf(method, "Method : %d", data->requestInfo->method);
1560                                 break;
1561                 }
1562                 info = &data->requestInfo->info;
1563         }
1564
1565         if(NULL != data->responseInfo)
1566         {
1567
1568                 sprintf(method, "result : %d", data->responseInfo->result);
1569                 info = &data->responseInfo->info;
1570         }
1571
1572
1573         char log_buffer[1024] = "";
1574         sprintf(log_buffer, "CA_LOG [%5d] | %-13s | %-12s | msg size : %4d | %s", pdu->transport_hdr->udp.id , type, method, pdu->length, info->resourceUri);
1575
1576         puts(log_buffer);
1577 }
1578
1579
1580 #else
1581
1582 static void CALogPDUInfo(const CAData_t *data, const coap_pdu_t *pdu)
1583 {
1584     OIC_LOG(DEBUG, TAG, "CALogPDUInfo");
1585
1586     VERIFY_NON_NULL_VOID(data, TAG, "data");
1587     VERIFY_NON_NULL_VOID(pdu, TAG, "pdu");
1588     OIC_TRACE_BEGIN(%s:CALogPDUInfo, TAG);
1589
1590     OIC_LOG(INFO, ANALYZER_TAG, "=================================================");
1591     if(SEND_TYPE_MULTICAST == data->type)
1592     {
1593         OIC_LOG(INFO, ANALYZER_TAG, "Is Multicast = true");
1594     }
1595     else
1596     {
1597         OIC_LOG(INFO, ANALYZER_TAG, "Is Multicast = false");
1598     }
1599
1600     if (NULL != data->remoteEndpoint)
1601     {
1602         CALogAdapterTypeInfo(data->remoteEndpoint->adapter);
1603         OIC_LOG_V(INFO, ANALYZER_TAG, "Address = [%s]:[%d]", data->remoteEndpoint->addr,
1604                   data->remoteEndpoint->port);
1605     }
1606
1607     switch(data->dataType)
1608     {
1609         case CA_REQUEST_DATA:
1610             OIC_LOG(INFO, ANALYZER_TAG, "Data Type = [CA_REQUEST_DATA]");
1611             break;
1612         case CA_RESPONSE_DATA:
1613             OIC_LOG(INFO, ANALYZER_TAG, "Data Type = [CA_RESPONSE_DATA]");
1614             break;
1615         case CA_ERROR_DATA:
1616             OIC_LOG(INFO, ANALYZER_TAG, "Data Type = [CA_ERROR_DATA]");
1617             break;
1618         case CA_RESPONSE_FOR_RES:
1619             OIC_LOG(INFO, ANALYZER_TAG, "Data Type = [CA_RESPONSE_FOR_RES]");
1620             break;
1621         default:
1622             OIC_LOG_V(INFO, ANALYZER_TAG, "Data Type = [%d]", data->dataType);
1623             break;
1624     }
1625
1626     const CAInfo_t *info = NULL;
1627     if (NULL != data->requestInfo)
1628     {
1629         switch(data->requestInfo->method)
1630         {
1631             case CA_GET:
1632                 OIC_LOG(INFO, ANALYZER_TAG, "Method = [GET]");
1633                 break;
1634             case CA_POST:
1635                 OIC_LOG(INFO, ANALYZER_TAG, "Method = [POST]");
1636                 break;
1637             case CA_PUT:
1638                 OIC_LOG(INFO, ANALYZER_TAG, "Method = [PUT]");
1639                 break;
1640             case CA_DELETE:
1641                 OIC_LOG(INFO, ANALYZER_TAG, "Method = [DELETE]");
1642                 break;
1643             default:
1644                 OIC_LOG_V(INFO, ANALYZER_TAG, "Method = [%d]", data->requestInfo->method);
1645                 break;
1646         }
1647         info = &data->requestInfo->info;
1648     }
1649
1650     if (NULL != data->responseInfo)
1651     {
1652         OIC_LOG_V(INFO, ANALYZER_TAG, "result code = [%d]", data->responseInfo->result);
1653         info = &data->responseInfo->info;
1654     }
1655
1656     if (pdu->transport_hdr)
1657     {
1658         OIC_LOG_V(INFO, ANALYZER_TAG, "Msg ID = [%d]", pdu->transport_hdr->udp.id);
1659     }
1660
1661     if (info)
1662     {
1663         OIC_LOG(INFO, ANALYZER_TAG, "Coap Token");
1664         OIC_LOG_BUFFER(INFO, ANALYZER_TAG, (const uint8_t *) info->token, info->tokenLength);
1665         OIC_TRACE_BUFFER("OIC_CA_MSG_HANDLE:CALogPDUInfo:token",
1666                          (const uint8_t *) info->token, info->tokenLength);
1667         OIC_LOG_V(INFO, ANALYZER_TAG, "Res URI = [%s]", info->resourceUri);
1668         OIC_TRACE_MARK(%s:CALogPDUInfo:uri:%s, TAG, info->resourceUri);
1669
1670         if (CA_FORMAT_APPLICATION_CBOR == info->payloadFormat)
1671         {
1672             OIC_LOG(INFO, ANALYZER_TAG, "Payload Format = [CA_FORMAT_APPLICATION_CBOR]");
1673         }
1674         else
1675         {
1676             OIC_LOG_V(INFO, ANALYZER_TAG, "Payload Format = [%d]", info->payloadFormat);
1677         }
1678     }
1679
1680     size_t payloadLen = (pdu->data) ? (unsigned char *) pdu->hdr + pdu->length - pdu->data : 0;
1681     OIC_LOG_V(INFO, ANALYZER_TAG, "CoAP Message Full Size = [%lu]", pdu->length);
1682     OIC_LOG(INFO, ANALYZER_TAG, "CoAP Header (+ 0xFF)");
1683     OIC_LOG_BUFFER(INFO, ANALYZER_TAG,  (const uint8_t *) pdu->transport_hdr,
1684                    pdu->length - payloadLen);
1685     OIC_LOG_V(INFO, ANALYZER_TAG, "CoAP Header size = [%lu]", pdu->length - payloadLen);
1686
1687     OIC_LOG_V(INFO, ANALYZER_TAG, "CoAP Payload");
1688     OIC_LOG_BUFFER(INFO_PRIVATE, ANALYZER_TAG, pdu->data, payloadLen);
1689     OIC_LOG_V(INFO, ANALYZER_TAG, "CoAP Payload Size = [%lu]", payloadLen);
1690     OIC_LOG(INFO, ANALYZER_TAG, "=================================================");
1691
1692     // samsung log
1693     CASamsungLogMessage(data, pdu);
1694     OIC_TRACE_END();
1695 }
1696
1697 static void CASamsungLogMessage(const CAData_t *data, const coap_pdu_t *pdu)
1698 {
1699     OIC_LOG(INFO, TAG, "CASamsungLogMessage");
1700     VERIFY_NON_NULL_VOID(data, TAG, "data");
1701     VERIFY_NON_NULL_VOID(pdu, TAG, "pdu");
1702     VERIFY_NON_NULL_VOID(data->remoteEndpoint, TAG, "data->remoteEndpoint");
1703
1704     const CAInfo_t *info = NULL;
1705     if (NULL != data->requestInfo)
1706     {
1707         info = &data->requestInfo->info;
1708     }
1709
1710     if (NULL != data->responseInfo)
1711     {
1712         info = &data->responseInfo->info;
1713     }
1714
1715     VERIFY_NON_NULL_VOID(info, TAG, "info");
1716
1717     memset(g_headerBuffer, 0, MAX_LOG_BUFFER_SIZE);
1718     g_headerIndex = 0;
1719
1720     g_headerBuffer[g_headerIndex++] = data->dataType;
1721     g_headerBuffer[g_headerIndex++] = '|';
1722     g_headerBuffer[g_headerIndex++] = data->remoteEndpoint->adapter;
1723     g_headerBuffer[g_headerIndex++] = '|';
1724     g_headerBuffer[g_headerIndex++] = data->type;
1725     g_headerBuffer[g_headerIndex++] = '|';
1726
1727     if (NULL != data->remoteEndpoint)
1728     {
1729         int i = 0;
1730         while (NULL != data->remoteEndpoint->addr[i])
1731         {
1732             g_headerBuffer[g_headerIndex++] = data->remoteEndpoint->addr[i];
1733             i++;
1734         }
1735         g_headerBuffer[g_headerIndex++] = ':';
1736         g_headerBuffer[g_headerIndex++] = (data->remoteEndpoint->port >> 8) & 0x0000ff;
1737         g_headerBuffer[g_headerIndex++] = data->remoteEndpoint->port & 0x000000ff;
1738     }
1739
1740     g_headerBuffer[g_headerIndex++] = '|';
1741     if (data->requestInfo)
1742     {
1743         g_headerBuffer[g_headerIndex++] = data->requestInfo->method;
1744     }
1745     else
1746     {
1747         g_headerBuffer[g_headerIndex++] = 0;
1748     }
1749
1750     g_headerBuffer[g_headerIndex++] = '|';
1751     if (data->responseInfo)
1752     {
1753         g_headerBuffer[g_headerIndex++] = data->responseInfo->result;
1754     }
1755     else
1756     {
1757         g_headerBuffer[g_headerIndex++] = 0;
1758     }
1759     g_headerBuffer[g_headerIndex++] = '|';
1760
1761     if (pdu->transport_hdr)
1762     {
1763         g_headerBuffer[g_headerIndex++] = (pdu->transport_hdr->udp.id >> 8) & 0x0000ff;
1764         g_headerBuffer[g_headerIndex++] = pdu->transport_hdr->udp.id & 0x000000ff;
1765     }
1766     else
1767     {
1768         g_headerBuffer[g_headerIndex++] = 0;
1769         g_headerBuffer[g_headerIndex++] = 0;
1770     }
1771     g_headerBuffer[g_headerIndex++] = '|';
1772
1773     if (info->token && info->tokenLength > 0)
1774     {
1775         for (size_t i = 0; i < info->tokenLength; i++)
1776         {
1777             g_headerBuffer[g_headerIndex++] = info->token[i];
1778         }
1779         g_headerBuffer[g_headerIndex++] = '|';
1780     }
1781
1782     if (info->resourceUri)
1783     {
1784         size_t i = 0;
1785         while (NULL != info->resourceUri[i])
1786         {
1787             g_headerBuffer[g_headerIndex++] = info->resourceUri[i];
1788             i++;
1789         }
1790         g_headerBuffer[g_headerIndex++] = '|';
1791     }
1792
1793     OIC_LOG_CA_BUFFER(INFO, TAG, (uint8_t *) g_headerBuffer, g_headerIndex, 1);
1794     size_t payloadLen = (unsigned char *) pdu->hdr + pdu->length - pdu->data;
1795     OIC_LOG_CA_BUFFER(INFO_PRIVATE, TAG, pdu->data, payloadLen, 0);
1796 }
1797 #endif
1798
1799 #else
1800 static void CALogPDUInfo(const CAData_t *data, const coap_pdu_t *pdu)
1801 {
1802     VERIFY_NON_NULL_VOID(pdu, TAG, "pdu");
1803     (void)data;
1804
1805     OIC_LOG_V(DEBUG, TAG, "PDU Maker - payload : %s", pdu->data);
1806     OIC_LOG_V(DEBUG, TAG, "PDU Maker - type : %d", pdu->transport_hdr->udp.type);
1807     OIC_LOG_V(DEBUG, TAG, "PDU Maker - code : %d", pdu->transport_hdr->udp.code);
1808     OIC_LOG(DEBUG, TAG, "PDU Maker - token :");
1809     OIC_LOG_BUFFER(DEBUG, TAG, pdu->transport_hdr->udp.token,
1810                    pdu->transport_hdr->udp.token_length);
1811 }
1812 #endif