1ad9b3385788d91cdbe6fe704ac896552a015db3
[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, size_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 #ifdef WITH_BWT
102 void CAAddDataToSendThread(CAData_t *data)
103 {
104     VERIFY_NON_NULL_VOID(data, TAG, "data");
105
106     // add thread
107     CAQueueingThreadAddData(&g_sendThread, data, sizeof(CAData_t));
108 }
109
110 void CAAddDataToReceiveThread(CAData_t *data)
111 {
112     VERIFY_NON_NULL_VOID(data, TAG, "data");
113
114     // add thread
115     CAQueueingThreadAddData(&g_receiveThread, data, sizeof(CAData_t));
116 }
117 #endif
118
119 static bool CAIsSelectedNetworkAvailable()
120 {
121     u_arraylist_t *list = CAGetSelectedNetworkList();
122     if (!list || u_arraylist_length(list) == 0)
123     {
124         OIC_LOG(ERROR, TAG, "No selected network");
125         return false;
126     }
127
128     return true;
129 }
130
131 static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint,
132                                        const CARemoteId_t *identity,
133                                        const void *data, CADataType_t dataType)
134 {
135     OIC_LOG(DEBUG, TAG, "CAGenerateHandlerData IN");
136     CAInfo_t *info = NULL;
137     CAData_t *cadata = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
138     if (!cadata)
139     {
140         OIC_LOG(ERROR, TAG, "memory allocation failed");
141         return NULL;
142     }
143 #ifdef SINGLE_THREAD
144     CAEndpoint_t* ep = endpoint;
145 #else
146     CAEndpoint_t* ep = CACloneEndpoint(endpoint);
147     if (!ep)
148     {
149         OIC_LOG(ERROR, TAG, "endpoint clone failed");
150         goto exit;
151     }
152 #endif
153
154     OIC_LOG_V(DEBUG, TAG, "address : %s", ep->addr);
155
156     if (CA_RESPONSE_DATA == dataType)
157     {
158         CAResponseInfo_t* resInfo = (CAResponseInfo_t*)OICCalloc(1, sizeof(CAResponseInfo_t));
159         if (!resInfo)
160         {
161             OIC_LOG(ERROR, TAG, "memory allocation failed");
162             goto exit;
163         }
164
165         CAResult_t result = CAGetResponseInfoFromPDU(data, resInfo, endpoint);
166         if (CA_STATUS_OK != result)
167         {
168             OIC_LOG(ERROR, TAG, "CAGetResponseInfoFromPDU Failed");
169             CADestroyResponseInfoInternal(resInfo);
170             goto exit;
171         }
172         cadata->responseInfo = resInfo;
173         info = &resInfo->info;
174         if (identity)
175         {
176             info->identity = *identity;
177         }
178         OIC_LOG(DEBUG, TAG, "Response Info :");
179         CALogPayloadInfo(info);
180     }
181     else if (CA_REQUEST_DATA == dataType)
182     {
183         CARequestInfo_t* reqInfo = (CARequestInfo_t*)OICCalloc(1, sizeof(CARequestInfo_t));
184         if (!reqInfo)
185         {
186             OIC_LOG(ERROR, TAG, "memory allocation failed");
187             goto exit;
188         }
189
190         CAResult_t result = CAGetRequestInfoFromPDU(data, endpoint, reqInfo);
191         if (CA_STATUS_OK != result)
192         {
193             OIC_LOG(ERROR, TAG, "CAGetRequestInfoFromPDU failed");
194             CADestroyRequestInfoInternal(reqInfo);
195             goto exit;
196         }
197
198         if (CADropSecondMessage(&caglobals.ca.requestHistory, endpoint, reqInfo->info.messageId,
199                                 reqInfo->info.token, reqInfo->info.tokenLength))
200         {
201             OIC_LOG(INFO, TAG, "Second Request with same Token, Drop it");
202             CADestroyRequestInfoInternal(reqInfo);
203             goto exit;
204         }
205
206         cadata->requestInfo = reqInfo;
207         info = &reqInfo->info;
208         if (identity)
209         {
210             info->identity = *identity;
211         }
212         OIC_LOG(DEBUG, TAG, "Request Info :");
213         CALogPayloadInfo(info);
214    }
215     else if (CA_ERROR_DATA == dataType)
216     {
217         CAErrorInfo_t *errorInfo = (CAErrorInfo_t *)OICCalloc(1, sizeof (CAErrorInfo_t));
218         if (!errorInfo)
219         {
220             OIC_LOG(ERROR, TAG, "Memory allocation failed!");
221             goto exit;
222         }
223
224         CAResult_t result = CAGetErrorInfoFromPDU(data, endpoint, errorInfo);
225         if (CA_STATUS_OK != result)
226         {
227             OIC_LOG(ERROR, TAG, "CAGetErrorInfoFromPDU failed");
228             OICFree(errorInfo);
229             goto exit;
230         }
231
232         cadata->errorInfo = errorInfo;
233         info = &errorInfo->info;
234         if (identity)
235         {
236             info->identity = *identity;
237         }
238         OIC_LOG(DEBUG, TAG, "error Info :");
239         CALogPayloadInfo(info);
240     }
241
242     cadata->remoteEndpoint = ep;
243     cadata->dataType = dataType;
244
245     OIC_LOG(DEBUG, TAG, "CAGenerateHandlerData OUT");
246     return cadata;
247
248 exit:
249     OICFree(cadata);
250 #ifndef SINGLE_THREAD
251     CAFreeEndpoint(ep);
252 #endif
253     return NULL;
254 }
255
256 static void CATimeoutCallback(const CAEndpoint_t *endpoint, const void *pdu, uint32_t size)
257 {
258     VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint");
259     VERIFY_NON_NULL_VOID(pdu, TAG, "pdu");
260 #ifdef SINGLE_THREAD
261     CAEndpoint_t* ep = endpoint;
262 #else
263     CAEndpoint_t* ep = CACloneEndpoint(endpoint);
264     if (!ep)
265     {
266         OIC_LOG(ERROR, TAG, "clone failed");
267         return;
268     }
269 #endif
270
271     CAResponseInfo_t* resInfo = (CAResponseInfo_t*)OICCalloc(1, sizeof(CAResponseInfo_t));
272
273     if (!resInfo)
274     {
275         OIC_LOG(ERROR, TAG, "calloc failed");
276 #ifndef SINGLE_THREAD
277         CAFreeEndpoint(ep);
278 #endif
279         return;
280     }
281
282     resInfo->result = CA_RETRANSMIT_TIMEOUT;
283     resInfo->info.type = CAGetMessageTypeFromPduBinaryData(pdu, size);
284     resInfo->info.messageId = CAGetMessageIdFromPduBinaryData(pdu, size);
285
286     CAResult_t res = CAGetTokenFromPDU((const coap_hdr_transport_t *) pdu, &(resInfo->info),
287                                        endpoint);
288     if (CA_STATUS_OK != res)
289     {
290         OIC_LOG(ERROR, TAG, "fail to get Token from retransmission list");
291         CADestroyResponseInfoInternal(resInfo);
292 #ifndef SINGLE_THREAD
293         CAFreeEndpoint(ep);
294 #endif
295         return;
296     }
297
298     CAData_t *cadata = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
299     if (NULL == cadata)
300     {
301         OIC_LOG(ERROR, TAG, "memory allocation failed !");
302 #ifndef SINGLE_THREAD
303         CAFreeEndpoint(ep);
304 #endif
305         CADestroyResponseInfoInternal(resInfo);
306         return;
307     }
308
309     cadata->type = SEND_TYPE_UNICAST;
310     cadata->remoteEndpoint = ep;
311     cadata->requestInfo = NULL;
312     cadata->responseInfo = resInfo;
313
314 #ifdef WITH_BWT
315     if (CAIsSupportedBlockwiseTransfer(endpoint->adapter))
316     {
317         res = CARemoveBlockDataFromListWithSeed(resInfo->info.token, resInfo->info.tokenLength,
318                                                 endpoint->addr, endpoint->port);
319         if (CA_STATUS_OK != res)
320         {
321             OIC_LOG(ERROR, TAG, "CARemoveBlockDataFromListWithSeed failed");
322         }
323     }
324 #endif // WITH_BWT
325
326 #ifdef SINGLE_THREAD
327     CAProcessReceivedData(cadata);
328 #else
329     CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t));
330 #endif
331 }
332
333 static void CADestroyData(void *data, uint32_t size)
334 {
335     OIC_LOG(DEBUG, TAG, "CADestroyData IN");
336     if ((size_t)size < sizeof(CAData_t))
337     {
338         OIC_LOG_V(ERROR, TAG, "Destroy data too small %p %d", data, size);
339     }
340     CAData_t *cadata = (CAData_t *) data;
341
342     if (NULL == cadata)
343     {
344         OIC_LOG(ERROR, TAG, "cadata is NULL");
345         return;
346     }
347 #ifndef SINGLE_THREAD
348     if (NULL != cadata->remoteEndpoint)
349     {
350         CAFreeEndpoint(cadata->remoteEndpoint);
351     }
352 #endif
353
354     if (NULL != cadata->requestInfo)
355     {
356         CADestroyRequestInfoInternal((CARequestInfo_t *) cadata->requestInfo);
357     }
358
359     if (NULL != cadata->responseInfo)
360     {
361         CADestroyResponseInfoInternal((CAResponseInfo_t *) cadata->responseInfo);
362     }
363
364     if (NULL != cadata->errorInfo)
365     {
366         CADestroyErrorInfoInternal(cadata->errorInfo);
367     }
368
369     OICFree(cadata);
370     OIC_LOG(DEBUG, TAG, "CADestroyData OUT");
371 }
372
373 #ifdef SINGLE_THREAD
374 static void CAProcessReceivedData(CAData_t *data)
375 {
376     OIC_LOG(DEBUG, TAG, "CAProcessReceivedData IN");
377     if (!data)
378     {
379         OIC_LOG(ERROR, TAG, "thread data error!!");
380         return;
381     }
382
383     // parse the data and call the callbacks.
384     // #1 parse the data
385     // #2 get endpoint
386     CAEndpoint_t *rep = (CAEndpoint_t *)(data->remoteEndpoint);
387     if (!rep)
388     {
389         OIC_LOG(ERROR, TAG, "remoteEndpoint error!!");
390         return;
391     }
392
393     if (data->requestInfo && g_requestHandler)
394     {
395         g_requestHandler(rep, data->requestInfo);
396     }
397     else if (data->responseInfo && g_responseHandler)
398     {
399         g_responseHandler(rep, data->responseInfo);
400     }
401     else if (data->errorInfo && g_errorHandler)
402     {
403         g_errorHandler(rep, data->errorInfo);
404     }
405
406     CADestroyData(data, sizeof(CAData_t));
407
408     OIC_LOG(DEBUG, TAG, "CAProcessReceivedData OUT");
409 }
410 #endif
411
412 #ifndef SINGLE_THREAD
413 static void CAReceiveThreadProcess(void *threadData)
414 {
415 #ifndef SINGLE_HANDLE
416     CAData_t *data = (CAData_t *) threadData;
417     CAProcessReceivedData(data);
418 #else
419     (void)threadData;
420 #endif
421 }
422 #endif // SINGLE_THREAD
423
424 static CAResult_t CAProcessMulticastData(const CAData_t *data)
425 {
426     VERIFY_NON_NULL(data, TAG, "data");
427     VERIFY_NON_NULL(data->remoteEndpoint, TAG, "remoteEndpoint");
428
429     coap_pdu_t *pdu = NULL;
430     CAInfo_t *info = NULL;
431     coap_list_t *options = NULL;
432     coap_transport_t transport = COAP_UDP;
433     CAResult_t res = CA_SEND_FAILED;
434
435     if (!data->requestInfo && !data->responseInfo)
436     {
437         OIC_LOG(ERROR, TAG, "request or response info is empty");
438         return res;
439     }
440
441     if (data->requestInfo)
442     {
443         OIC_LOG(DEBUG, TAG, "requestInfo is available..");
444
445         info = &data->requestInfo->info;
446         pdu = CAGeneratePDU(CA_GET, info, data->remoteEndpoint, &options, &transport);
447     }
448     else if (data->responseInfo)
449     {
450         OIC_LOG(DEBUG, TAG, "responseInfo is available..");
451
452         info = &data->responseInfo->info;
453         pdu = CAGeneratePDU(data->responseInfo->result, info, data->remoteEndpoint,
454                             &options, &transport);
455     }
456
457     if (!pdu)
458     {
459         OIC_LOG(ERROR,TAG,"Failed to generate multicast PDU");
460         CASendErrorInfo(data->remoteEndpoint, info, CA_SEND_FAILED);
461         coap_delete_list(options);
462         return res;
463     }
464
465 #ifdef WITH_BWT
466     if (CAIsSupportedBlockwiseTransfer(data->remoteEndpoint->adapter))
467     {
468         // Blockwise transfer
469         res = CAAddBlockOption(&pdu, info, data->remoteEndpoint, &options);
470         if (CA_STATUS_OK != res)
471         {
472             OIC_LOG(DEBUG, TAG, "CAAddBlockOption has failed");
473             goto exit;
474         }
475     }
476 #endif // WITH_BWT
477
478     CALogPDUInfo(data, pdu);
479
480     res = CASendMulticastData(data->remoteEndpoint, pdu->transport_hdr, pdu->length, data->dataType);
481     if (CA_STATUS_OK != res)
482     {
483         OIC_LOG_V(ERROR, TAG, "send failed:%d", res);
484         goto exit;
485     }
486
487     coap_delete_list(options);
488     coap_delete_pdu(pdu);
489     return res;
490
491 exit:
492     CAErrorHandler(data->remoteEndpoint, pdu->transport_hdr, pdu->length, res);
493     coap_delete_list(options);
494     coap_delete_pdu(pdu);
495     return res;
496 }
497
498 static CAResult_t CAProcessSendData(const CAData_t *data)
499 {
500     VERIFY_NON_NULL(data, TAG, "data");
501     VERIFY_NON_NULL(data->remoteEndpoint, TAG, "remoteEndpoint");
502
503     OIC_TRACE_BEGIN(%s:CAProcessSendData, TAG);
504
505     CAResult_t res = CA_STATUS_FAILED;
506
507     CASendDataType_t type = data->type;
508
509     coap_pdu_t *pdu = NULL;
510     CAInfo_t *info = NULL;
511     coap_list_t *options = NULL;
512     coap_transport_t transport = COAP_UDP;
513
514     if (SEND_TYPE_UNICAST == type)
515     {
516         OIC_LOG(DEBUG,TAG,"Unicast message");
517
518 #ifdef ROUTING_GATEWAY
519         /*
520          * When forwarding a packet, do not attempt retransmission as its the responsibility of
521          * packet originator node
522          */
523         bool skipRetransmission = false;
524 #endif
525
526         if (NULL != data->requestInfo)
527         {
528             OIC_LOG(DEBUG, TAG, "requestInfo is available..");
529
530             info = &data->requestInfo->info;
531 #ifdef ROUTING_GATEWAY
532             skipRetransmission = data->requestInfo->info.skipRetransmission;
533 #endif
534             pdu = CAGeneratePDU(data->requestInfo->method, info, data->remoteEndpoint,
535                                 &options, &transport);
536         }
537         else if (NULL != data->responseInfo)
538         {
539             OIC_LOG(DEBUG, TAG, "responseInfo is available..");
540
541             info = &data->responseInfo->info;
542 #ifdef ROUTING_GATEWAY
543             skipRetransmission = data->responseInfo->info.skipRetransmission;
544 #endif
545             pdu = CAGeneratePDU(data->responseInfo->result, info, data->remoteEndpoint,
546                                 &options, &transport);
547         }
548         else
549         {
550             OIC_LOG(DEBUG, TAG, "request info, response info is empty");
551             OIC_TRACE_END();
552             return CA_STATUS_INVALID_PARAM;
553         }
554
555         // interface controller function call.
556         if (NULL != pdu)
557         {
558 #ifdef WITH_BWT
559             if (CAIsSupportedBlockwiseTransfer(data->remoteEndpoint->adapter))
560             {
561                 // Blockwise transfer
562                 if (NULL != info)
563                 {
564                     CAResult_t res = CAAddBlockOption(&pdu, info,
565                                                       data->remoteEndpoint,
566                                                       &options);
567                     if (CA_STATUS_OK != res)
568                     {
569                         OIC_LOG(INFO, TAG, "to write block option has failed");
570                         CAErrorHandler(data->remoteEndpoint, pdu->transport_hdr, pdu->length, res);
571                         coap_delete_list(options);
572                         coap_delete_pdu(pdu);
573                         OIC_TRACE_END();
574                         return res;
575                     }
576                 }
577             }
578 #endif // WITH_BWT
579             CALogPDUInfo(data, pdu);
580
581             OIC_LOG_V(INFO, TAG, "CASendUnicastData type : %d", data->dataType);
582             res = CASendUnicastData(data->remoteEndpoint, pdu->transport_hdr, pdu->length, data->dataType);
583             if (CA_STATUS_OK != res)
584             {
585                 OIC_LOG_V(ERROR, TAG, "send failed:%d", res);
586                 CAErrorHandler(data->remoteEndpoint, pdu->transport_hdr, pdu->length, res);
587                 coap_delete_list(options);
588                 coap_delete_pdu(pdu);
589                 OIC_TRACE_END();
590                 return res;
591             }
592
593 #ifdef WITH_TCP
594             if (CAIsSupportedCoAPOverTCP(data->remoteEndpoint->adapter))
595             {
596                 OIC_LOG(INFO, TAG, "retransmission will be not worked");
597             }
598             else
599 #endif
600 #ifdef ROUTING_GATEWAY
601             if (!skipRetransmission)
602 #endif
603             {
604                 // for retransmission
605                 res = CARetransmissionSentData(&g_retransmissionContext,
606                                                data->remoteEndpoint,
607                                                data->dataType,
608                                                pdu->transport_hdr, pdu->length);
609                 if ((CA_STATUS_OK != res) && (CA_NOT_SUPPORTED != res))
610                 {
611                     //when retransmission not supported this will return CA_NOT_SUPPORTED, ignore
612                     OIC_LOG_V(INFO, TAG, "retransmission is not enabled due to error, res : %d", res);
613                     coap_delete_list(options);
614                     coap_delete_pdu(pdu);
615                     OIC_TRACE_END();
616                     return res;
617                 }
618             }
619
620             coap_delete_list(options);
621             coap_delete_pdu(pdu);
622         }
623         else
624         {
625             OIC_LOG(ERROR,TAG,"Failed to generate unicast PDU");
626             CASendErrorInfo(data->remoteEndpoint, info, CA_SEND_FAILED);
627             OIC_TRACE_END();
628             return CA_SEND_FAILED;
629         }
630     }
631     else if (SEND_TYPE_MULTICAST == type)
632     {
633         OIC_LOG(DEBUG,TAG,"Multicast message");
634 #ifdef WITH_TCP
635         /*
636          * If CoAP over TCP is enabled, the CoAP pdu wont be same for IP and other adapters.
637          * That's why we need to generate two pdu's, one for IP and second for other transports.
638          * Two possible cases we might have to split: a) when adapter is CA_DEFAULT_ADAPTER
639          * b) when one of the adapter is IP adapter(ex: CA_ADAPTER_IP | CA_ADAPTER_GATT_BTLE)
640          */
641         if (data->remoteEndpoint->adapter == CA_DEFAULT_ADAPTER ||
642                 (CA_ADAPTER_IP & data->remoteEndpoint->adapter &&
643                     CA_ADAPTER_IP != data->remoteEndpoint->adapter))
644         {
645             if (data->remoteEndpoint->adapter == CA_DEFAULT_ADAPTER)
646             {
647                 data->remoteEndpoint->adapter = CA_ALL_ADAPTERS ^ CA_ADAPTER_IP;
648             }
649             else
650             {
651                 data->remoteEndpoint->adapter = data->remoteEndpoint->adapter ^ CA_ADAPTER_IP;
652             }
653             CAProcessMulticastData(data);
654             data->remoteEndpoint->adapter = CA_ADAPTER_IP;
655             CAProcessMulticastData(data);
656         }
657         else
658         {
659             CAProcessMulticastData(data);
660         }
661 #else
662         CAProcessMulticastData(data);
663 #endif
664     }
665     OIC_TRACE_END();
666     return CA_STATUS_OK;
667 }
668
669 #ifndef SINGLE_THREAD
670 static void CASendThreadProcess(void *threadData)
671 {
672     CAData_t *data = (CAData_t *) threadData;
673     CAProcessSendData(data);
674 }
675 #endif
676
677 /*
678  * If a second message arrives with the same message ID, token and the other address
679  * family, drop it.  Typically, IPv6 beats IPv4, so the IPv4 message is dropped.
680  */
681 static bool CADropSecondMessage(CAHistory_t *history, const CAEndpoint_t *ep, uint16_t id,
682                                 CAToken_t token, uint8_t tokenLength)
683 {
684     if (!ep)
685     {
686         return true;
687     }
688     if (ep->adapter != CA_ADAPTER_IP)
689     {
690         return false;
691     }
692     if (!caglobals.ip.dualstack)
693     {
694         return false;
695     }
696
697     if (tokenLength > CA_MAX_TOKEN_LEN)
698     {
699         /*
700          * If token length is more than CA_MAX_TOKEN_LEN,
701          * we compare the first CA_MAX_TOKEN_LEN bytes only.
702          */
703         tokenLength = CA_MAX_TOKEN_LEN;
704     }
705
706     bool ret = false;
707     CATransportFlags_t familyFlags = ep->flags & CA_IPFAMILY_MASK;
708
709     for (size_t i = 0; i < sizeof(history->items) / sizeof(history->items[0]); i++)
710     {
711         CAHistoryItem_t *item = &(history->items[i]);
712         if (id == item->messageId && tokenLength == item->tokenLength
713             && ep->ifindex == item->ifindex && memcmp(item->token, token, tokenLength) == 0)
714         {
715             OIC_LOG_V(INFO, TAG, "IPv%c duplicate message ignored",
716                       familyFlags & CA_IPV6 ? '6' : '4');
717             ret = true;
718             break;
719         }
720     }
721
722     history->items[history->nextIndex].flags = familyFlags;
723     history->items[history->nextIndex].messageId = id;
724     history->items[history->nextIndex].ifindex = ep->ifindex;
725     if (token && tokenLength)
726     {
727         memcpy(history->items[history->nextIndex].token, token, tokenLength);
728         history->items[history->nextIndex].tokenLength = tokenLength;
729     }
730
731     if (++history->nextIndex >= HISTORYSIZE)
732     {
733         history->nextIndex = 0;
734     }
735
736     return ret;
737 }
738
739 static void CAReceivedPacketCallback(const CASecureEndpoint_t *sep,
740                                      const void *data, size_t dataLen)
741 {
742     VERIFY_NON_NULL_VOID(sep, TAG, "remoteEndpoint");
743     VERIFY_NON_NULL_VOID(data, TAG, "data");
744
745     OIC_TRACE_BEGIN(%s:CAReceivedPacketCallback, TAG);
746
747     if (0 == dataLen)
748     {
749         OIC_LOG(ERROR, TAG, "dataLen is zero");
750         OIC_TRACE_END();
751         return;
752     }
753
754     uint32_t code = CA_NOT_FOUND;
755     CAData_t *cadata = NULL;
756
757     coap_pdu_t *pdu = (coap_pdu_t *) CAParsePDU((const char *) data, dataLen, &code,
758                                                 &(sep->endpoint));
759     if (NULL == pdu)
760     {
761         OIC_LOG(ERROR, TAG, "Parse PDU failed");
762         goto exit;
763     }
764
765     OIC_LOG_V(DEBUG, TAG, "code = %d", code);
766     if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code)
767     {
768         cadata = CAGenerateHandlerData(&(sep->endpoint), &(sep->identity), pdu, CA_REQUEST_DATA);
769         if (!cadata)
770         {
771             OIC_LOG(ERROR, TAG, "CAReceivedPacketCallback, CAGenerateHandlerData failed!");
772             coap_delete_pdu(pdu);
773             goto exit;
774         }
775     }
776     else
777     {
778         cadata = CAGenerateHandlerData(&(sep->endpoint), &(sep->identity), pdu, CA_RESPONSE_DATA);
779         if (!cadata)
780         {
781             OIC_LOG(ERROR, TAG, "CAReceivedPacketCallback, CAGenerateHandlerData failed!");
782             coap_delete_pdu(pdu);
783             goto exit;
784         }
785
786 #ifdef WITH_TCP
787         if (CAIsSupportedCoAPOverTCP(sep->endpoint.adapter))
788         {
789             OIC_LOG(INFO, TAG, "retransmission is not supported");
790         }
791         else
792 #endif
793         {
794             // for retransmission
795             void *retransmissionPdu = NULL;
796             CARetransmissionReceivedData(&g_retransmissionContext, cadata->remoteEndpoint, pdu->transport_hdr,
797                                          pdu->length, &retransmissionPdu);
798
799             // get token from saved data in retransmission list
800             if (retransmissionPdu && CA_EMPTY == code)
801             {
802                 if (cadata->responseInfo)
803                 {
804                     CAInfo_t *info = &cadata->responseInfo->info;
805                     CAResult_t res = CAGetTokenFromPDU((const coap_hdr_transport_t *)retransmissionPdu,
806                                                        info, &(sep->endpoint));
807                     if (CA_STATUS_OK != res)
808                     {
809                         OIC_LOG(ERROR, TAG, "fail to get Token from retransmission list");
810                         OICFree(info->token);
811                         info->tokenLength = 0;
812                     }
813                 }
814             }
815             OICFree(retransmissionPdu);
816         }
817     }
818
819     cadata->type = SEND_TYPE_UNICAST;
820
821     CALogPDUInfo(cadata, pdu);
822
823 #ifdef SINGLE_THREAD
824     CAProcessReceivedData(cadata);
825 #else
826 #ifdef WITH_BWT
827     if (CAIsSupportedBlockwiseTransfer(sep->endpoint.adapter))
828     {
829         CAResult_t res = CAReceiveBlockWiseData(pdu, &(sep->endpoint), cadata, dataLen);
830         if (CA_NOT_SUPPORTED == res || CA_REQUEST_TIMEOUT == res)
831         {
832             OIC_LOG(DEBUG, TAG, "this message does not have block option");
833             CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t));
834         }
835         else
836         {
837             CADestroyData(cadata, sizeof(CAData_t));
838         }
839     }
840     else
841 #endif
842     {
843         CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t));
844     }
845 #endif // SINGLE_THREAD
846
847     coap_delete_pdu(pdu);
848
849 exit:
850     OIC_LOG(DEBUG, TAG, "received pdu data :");
851     OIC_LOG_BUFFER(DEBUG, TAG,  data, dataLen);
852
853     OIC_TRACE_END();
854 }
855
856 void CAHandleRequestResponseCallbacks()
857 {
858 #ifdef SINGLE_THREAD
859     CAReadData();
860     CARetransmissionBaseRoutine((void *)&g_retransmissionContext);
861 #else
862 #ifdef SINGLE_HANDLE
863     // parse the data and call the callbacks.
864     // #1 parse the data
865     // #2 get endpoint
866
867     oc_mutex_lock(g_receiveThread.threadMutex);
868
869     u_queue_message_t *item = u_queue_get_element(g_receiveThread.dataQueue);
870
871     oc_mutex_unlock(g_receiveThread.threadMutex);
872
873     if (NULL == item || NULL == item->msg)
874     {
875         return;
876     }
877
878     // get endpoint
879     CAData_t *td = (CAData_t *) item->msg;
880
881     if (td->requestInfo && g_requestHandler)
882     {
883         OIC_LOG_V(DEBUG, TAG, "request callback : %d", td->requestInfo->info.numOptions);
884         g_requestHandler(td->remoteEndpoint, td->requestInfo);
885     }
886     else if (td->responseInfo && g_responseHandler)
887     {
888         OIC_LOG_V(DEBUG, TAG, "response callback : %d", td->responseInfo->info.numOptions);
889         g_responseHandler(td->remoteEndpoint, td->responseInfo);
890     }
891     else if (td->errorInfo && g_errorHandler)
892     {
893         OIC_LOG_V(DEBUG, TAG, "error callback error: %d", td->errorInfo->result);
894         g_errorHandler(td->remoteEndpoint, td->errorInfo);
895     }
896
897     CADestroyData(item->msg, sizeof(CAData_t));
898     OICFree(item);
899
900 #endif // SINGLE_HANDLE
901 #endif // SINGLE_THREAD
902 }
903
904 static CAData_t* CAPrepareSendData(const CAEndpoint_t *endpoint, const void *sendData,
905                                    CADataType_t dataType)
906 {
907     OIC_LOG(DEBUG, TAG, "CAPrepareSendData IN");
908
909     CAData_t *cadata = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
910     if (!cadata)
911     {
912         OIC_LOG(ERROR, TAG, "memory allocation failed");
913         return NULL;
914     }
915
916     if (CA_REQUEST_DATA == dataType)
917     {
918 #ifdef SINGLE_THREAD
919         CARequestInfo_t *request = (CARequestInfo_t *)sendData;
920 #else
921         // clone request info
922         CARequestInfo_t *request = CACloneRequestInfo((CARequestInfo_t *)sendData);
923         if (!request)
924         {
925             OIC_LOG(ERROR, TAG, "CACloneRequestInfo failed");
926             goto exit;
927         }
928 #endif
929         cadata->type = request->isMulticast ? SEND_TYPE_MULTICAST : SEND_TYPE_UNICAST;
930         cadata->requestInfo =  request;
931     }
932     else if (CA_RESPONSE_DATA == dataType || CA_RESPONSE_FOR_RES == dataType)
933     {
934 #ifdef SINGLE_THREAD
935         CAResponseInfo_t *response = (CAResponseInfo_t *)sendData;
936 #else
937         // clone response info
938         CAResponseInfo_t *response = CACloneResponseInfo((CAResponseInfo_t *)sendData);
939         if(!response)
940         {
941             OIC_LOG(ERROR, TAG, "CACloneResponseInfo failed");
942             goto exit;
943         }
944 #endif
945         cadata->type = response->isMulticast ? SEND_TYPE_MULTICAST : SEND_TYPE_UNICAST;
946         cadata->responseInfo = response;
947     }
948     else
949     {
950         OIC_LOG(ERROR, TAG, "CAPrepareSendData unknown data type");
951         goto exit;
952     }
953
954 #ifdef SINGLE_THREAD
955     CAEndpoint_t* ep = endpoint;
956 #else
957     CAEndpoint_t* ep = CACloneEndpoint(endpoint);
958     if (!ep)
959     {
960         OIC_LOG(ERROR, TAG, "endpoint clone failed");
961         goto exit;
962     }
963 #endif
964     cadata->remoteEndpoint = ep;
965     cadata->dataType = dataType;
966     return cadata;
967
968 exit:
969 #ifndef SINGLE_THREAD
970     CADestroyData(cadata, sizeof(CAData_t));
971 #else
972     OICFree(cadata);
973 #endif
974     return NULL;
975 }
976
977 CAResult_t CADetachSendMessage(const CAEndpoint_t *endpoint, const void *sendMsg,
978                                CADataType_t dataType)
979 {
980     VERIFY_NON_NULL(endpoint, TAG, "endpoint");
981     VERIFY_NON_NULL(sendMsg, TAG, "sendMsg");
982
983     if (false == CAIsSelectedNetworkAvailable())
984     {
985         return CA_STATUS_FAILED;
986     }
987
988 #ifdef ARDUINO
989     // If max retransmission queue is reached, then don't handle new request
990     if (CA_MAX_RT_ARRAY_SIZE == u_arraylist_length(g_retransmissionContext.dataList))
991     {
992         OIC_LOG(ERROR, TAG, "max RT queue size reached!");
993         return CA_SEND_FAILED;
994     }
995 #endif // ARDUINO
996
997     CAData_t *data = CAPrepareSendData(endpoint, sendMsg, dataType);
998     if(!data)
999     {
1000         OIC_LOG(ERROR, TAG, "CAPrepareSendData failed");
1001         return CA_MEMORY_ALLOC_FAILED;
1002     }
1003
1004     OIC_LOG_V(DEBUG, TAG, "device ID of endpoint of this message is %s", endpoint->remoteId);
1005
1006 #ifdef SINGLE_THREAD
1007     CAResult_t result = CAProcessSendData(data);
1008     if (CA_STATUS_OK != result)
1009     {
1010         OIC_LOG(ERROR, TAG, "CAProcessSendData failed");
1011         OICFree(data);
1012         return result;
1013     }
1014
1015     OICFree(data);
1016
1017 #else
1018     if (SEND_TYPE_UNICAST == data->type && CAIsLocalEndpoint(data->remoteEndpoint))
1019     {
1020         OIC_LOG(DEBUG, TAG,
1021                 "This is a loopback message. Transfer it to the receive queue directly");
1022         CAQueueingThreadAddData(&g_receiveThread, data, sizeof(CAData_t));
1023         return CA_STATUS_OK;
1024     }
1025 #ifdef WITH_BWT
1026     if (CAIsSupportedBlockwiseTransfer(endpoint->adapter))
1027     {
1028         // send block data
1029         CAResult_t res = CASendBlockWiseData(data);
1030         if (CA_NOT_SUPPORTED == res)
1031         {
1032             OIC_LOG(DEBUG, TAG, "normal msg will be sent");
1033             CAQueueingThreadAddData(&g_sendThread, data, sizeof(CAData_t));
1034             return CA_STATUS_OK;
1035         }
1036         else
1037         {
1038             CADestroyData(data, sizeof(CAData_t));
1039         }
1040         return res;
1041     }
1042     else
1043 #endif // WITH_BWT
1044     {
1045         CAQueueingThreadAddData(&g_sendThread, data, sizeof(CAData_t));
1046     }
1047 #endif // SINGLE_THREAD
1048
1049     return CA_STATUS_OK;
1050 }
1051
1052 void CASetInterfaceCallbacks(CARequestCallback ReqHandler, CAResponseCallback RespHandler,
1053                              CAErrorCallback errorHandler)
1054 {
1055     g_requestHandler = ReqHandler;
1056     g_responseHandler = RespHandler;
1057     g_errorHandler = errorHandler;
1058 }
1059
1060 void CASetNetworkMonitorCallback(CANetworkMonitorCallback nwMonitorHandler)
1061 {
1062     g_nwMonitorHandler = nwMonitorHandler;
1063 }
1064
1065 CAResult_t CAInitializeMessageHandler(CATransportAdapter_t transportType)
1066 {
1067     CASetPacketReceivedCallback(CAReceivedPacketCallback);
1068     CASetErrorHandleCallback(CAErrorHandler);
1069
1070 #ifndef SINGLE_THREAD
1071     // create thread pool
1072     CAResult_t res = ca_thread_pool_init(MAX_THREAD_POOL_SIZE, &g_threadPoolHandle);
1073     if (CA_STATUS_OK != res)
1074     {
1075         OIC_LOG(ERROR, TAG, "thread pool initialize error.");
1076         return res;
1077     }
1078
1079     // send thread initialize
1080     res = CAQueueingThreadInitialize(&g_sendThread, g_threadPoolHandle,
1081                                      CASendThreadProcess, CADestroyData);
1082     if (CA_STATUS_OK != res)
1083     {
1084         OIC_LOG(ERROR, TAG, "Failed to Initialize send queue thread");
1085         return res;
1086     }
1087
1088     // start send thread
1089     res = CAQueueingThreadStart(&g_sendThread);
1090     if (CA_STATUS_OK != res)
1091     {
1092         OIC_LOG(ERROR, TAG, "thread start error(send thread).");
1093         return res;
1094     }
1095
1096     // receive thread initialize
1097     res = CAQueueingThreadInitialize(&g_receiveThread, g_threadPoolHandle,
1098                                      CAReceiveThreadProcess, CADestroyData);
1099     if (CA_STATUS_OK != res)
1100     {
1101         OIC_LOG(ERROR, TAG, "Failed to Initialize receive queue thread");
1102         return res;
1103     }
1104
1105 #ifndef SINGLE_HANDLE // This will be enabled when RI supports multi threading
1106     // start receive thread
1107     res = CAQueueingThreadStart(&g_receiveThread);
1108     if (CA_STATUS_OK != res)
1109     {
1110         OIC_LOG(ERROR, TAG, "thread start error(receive thread).");
1111         return res;
1112     }
1113 #endif // SINGLE_HANDLE
1114
1115     // retransmission initialize
1116     res = CARetransmissionInitialize(&g_retransmissionContext, g_threadPoolHandle,
1117                                      CASendUnicastData, CATimeoutCallback, NULL);
1118     if (CA_STATUS_OK != res)
1119     {
1120         OIC_LOG(ERROR, TAG, "Failed to Initialize Retransmission.");
1121         return res;
1122     }
1123
1124 #ifdef WITH_BWT
1125     // block-wise transfer initialize
1126     res = CAInitializeBlockWiseTransfer(CAAddDataToSendThread, CAAddDataToReceiveThread);
1127     if (CA_STATUS_OK != res)
1128     {
1129         OIC_LOG(ERROR, TAG, "Failed to Initialize BlockWiseTransfer.");
1130         return res;
1131     }
1132 #endif
1133
1134     // start retransmission
1135     res = CARetransmissionStart(&g_retransmissionContext);
1136     if (CA_STATUS_OK != res)
1137     {
1138         OIC_LOG(ERROR, TAG, "thread start error(retransmission thread).");
1139         return res;
1140     }
1141
1142     // initialize interface adapters by controller
1143     CAInitializeAdapters(g_threadPoolHandle, transportType);
1144 #else
1145     // retransmission initialize
1146     CAResult_t res = CARetransmissionInitialize(&g_retransmissionContext, NULL, CASendUnicastData,
1147                                                 CATimeoutCallback, NULL);
1148     if (CA_STATUS_OK != res)
1149     {
1150         OIC_LOG(ERROR, TAG, "Failed to Initialize Retransmission.");
1151         return res;
1152     }
1153
1154     CAInitializeAdapters();
1155 #endif // SINGLE_THREAD
1156
1157     return CA_STATUS_OK;
1158 }
1159
1160 void CATerminateMessageHandler()
1161 {
1162 #ifndef SINGLE_THREAD
1163     CATransportAdapter_t connType;
1164     u_arraylist_t *list = CAGetSelectedNetworkList();
1165     uint32_t length = u_arraylist_length(list);
1166
1167     uint32_t i = 0;
1168     for (i = 0; i < length; i++)
1169     {
1170         void* ptrType = u_arraylist_get(list, i);
1171
1172         if (NULL == ptrType)
1173         {
1174             continue;
1175         }
1176
1177         connType = *(CATransportAdapter_t *)ptrType;
1178         CAStopAdapter(connType);
1179     }
1180
1181     // stop retransmission
1182     if (NULL != g_retransmissionContext.threadMutex)
1183     {
1184         CARetransmissionStop(&g_retransmissionContext);
1185     }
1186
1187     // stop thread
1188     // delete thread data
1189     if (NULL != g_sendThread.threadMutex)
1190     {
1191         CAQueueingThreadStop(&g_sendThread);
1192     }
1193
1194     // stop thread
1195     // delete thread data
1196     if (NULL != g_receiveThread.threadMutex)
1197     {
1198 #ifndef SINGLE_HANDLE // This will be enabled when RI supports multi threading
1199         CAQueueingThreadStop(&g_receiveThread);
1200 #endif
1201     }
1202
1203     // destroy thread pool
1204     if (NULL != g_threadPoolHandle)
1205     {
1206         ca_thread_pool_free(g_threadPoolHandle);
1207         g_threadPoolHandle = NULL;
1208     }
1209
1210 #ifdef WITH_BWT
1211     CATerminateBlockWiseTransfer();
1212 #endif
1213     CARetransmissionDestroy(&g_retransmissionContext);
1214     CAQueueingThreadDestroy(&g_sendThread);
1215     CAQueueingThreadDestroy(&g_receiveThread);
1216
1217     // terminate interface adapters by controller
1218     CATerminateAdapters();
1219 #else
1220     // terminate interface adapters by controller
1221     CATerminateAdapters();
1222
1223     // stop retransmission
1224     CARetransmissionStop(&g_retransmissionContext);
1225     CARetransmissionDestroy(&g_retransmissionContext);
1226 #endif // SINGLE_THREAD
1227 }
1228
1229 static void CALogPayloadInfo(CAInfo_t *info)
1230 {
1231     if (info)
1232     {
1233         if (info->options)
1234         {
1235             for (uint32_t i = 0; i < info->numOptions; i++)
1236             {
1237                 OIC_LOG_V(DEBUG, TAG, "optionID: %u", info->options[i].optionID);
1238
1239                 OIC_LOG_V(DEBUG, TAG, "list: %s", info->options[i].optionData);
1240             }
1241         }
1242
1243         if (info->payload)
1244         {
1245             OIC_LOG_V(DEBUG, TAG, "payload: %p(%zu)", info->payload,
1246                       info->payloadSize);
1247         }
1248
1249         if (info->token)
1250         {
1251             OIC_LOG(DEBUG, TAG, "token:");
1252             OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *) info->token,
1253                            info->tokenLength);
1254         }
1255         OIC_LOG_V(DEBUG, TAG, "msgID: %u", info->messageId);
1256     }
1257     else
1258     {
1259         OIC_LOG(DEBUG, TAG, "info is NULL, cannot output log data");
1260     }
1261 }
1262
1263 void CAErrorHandler(const CAEndpoint_t *endpoint,
1264                     const void *data, size_t dataLen,
1265                     CAResult_t result)
1266 {
1267     OIC_LOG(DEBUG, TAG, "CAErrorHandler IN");
1268     VERIFY_NON_NULL_VOID(endpoint, TAG, "remoteEndpoint");
1269     VERIFY_NON_NULL_VOID(data, TAG, "data");
1270
1271     if (0 == dataLen)
1272     {
1273         OIC_LOG(ERROR, TAG, "dataLen is zero");
1274         return;
1275     }
1276
1277 #ifndef SINGLE_THREAD
1278     uint32_t code = CA_NOT_FOUND;
1279     //Do not free remoteEndpoint and data. Currently they will be freed in data thread
1280     //Get PDU data
1281     coap_pdu_t *pdu = (coap_pdu_t *)CAParsePDU((const char *)data, dataLen, &code, endpoint);
1282     if (NULL == pdu)
1283     {
1284         OIC_LOG(ERROR, TAG, "Parse PDU failed");
1285         return;
1286     }
1287
1288     CAData_t *cadata = CAGenerateHandlerData(endpoint, NULL, pdu, CA_ERROR_DATA);
1289     if (!cadata)
1290     {
1291         OIC_LOG(ERROR, TAG, "CAErrorHandler, CAGenerateHandlerData failed!");
1292         coap_delete_pdu(pdu);
1293         return;
1294     }
1295
1296     cadata->errorInfo->result = result;
1297
1298     CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t));
1299     coap_delete_pdu(pdu);
1300 #else
1301     (void)result;
1302 #endif
1303
1304     OIC_LOG(DEBUG, TAG, "CAErrorHandler OUT");
1305     return;
1306 }
1307
1308 static void CASendErrorInfo(const CAEndpoint_t *endpoint, const CAInfo_t *info, CAResult_t result)
1309 {
1310     OIC_LOG(DEBUG, TAG, "CASendErrorInfo IN");
1311 #ifndef SINGLE_THREAD
1312     CAData_t *cadata = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
1313     if (!cadata)
1314     {
1315         OIC_LOG(ERROR, TAG, "cadata memory allocation failed");
1316         return;
1317     }
1318
1319     CAEndpoint_t* ep = CACloneEndpoint(endpoint);
1320     if (!ep)
1321     {
1322         OIC_LOG(ERROR, TAG, "endpoint clone failed");
1323         OICFree(cadata);
1324         return;
1325     }
1326
1327     CAErrorInfo_t *errorInfo = (CAErrorInfo_t *)OICCalloc(1, sizeof (CAErrorInfo_t));
1328     if (!errorInfo)
1329     {
1330         OIC_LOG(ERROR, TAG, "errorInfo memory allocation failed");
1331         OICFree(cadata);
1332         CAFreeEndpoint(ep);
1333         return;
1334     }
1335
1336     CAResult_t res = CACloneInfo(info, &errorInfo->info);
1337     if (CA_STATUS_OK != res)
1338     {
1339         OIC_LOG(ERROR, TAG, "info clone failed");
1340         OICFree(cadata);
1341         OICFree(errorInfo);
1342         CAFreeEndpoint(ep);
1343         return;
1344     }
1345
1346     errorInfo->result = result;
1347     cadata->remoteEndpoint = ep;
1348     cadata->errorInfo = errorInfo;
1349     cadata->dataType = CA_ERROR_DATA;
1350
1351     CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t));
1352 #endif
1353     OIC_LOG(DEBUG, TAG, "CASendErrorInfo OUT");
1354 }
1355
1356 #ifndef ARDUINO
1357 static void CALogPDUInfo(const CAData_t *data, const coap_pdu_t *pdu)
1358 {
1359     OIC_LOG(DEBUG, TAG, "CALogPDUInfo");
1360
1361     VERIFY_NON_NULL_VOID(data, TAG, "data");
1362     VERIFY_NON_NULL_VOID(pdu, TAG, "pdu");
1363
1364     OIC_LOG(DEBUG, ANALYZER_TAG, "=================================================");
1365     if(SEND_TYPE_MULTICAST == data->type)
1366     {
1367         OIC_LOG(DEBUG, ANALYZER_TAG, "Is Multicast = true");
1368     }
1369     else
1370     {
1371         OIC_LOG(DEBUG, ANALYZER_TAG, "Is Multicast = false");
1372     }
1373
1374     if (NULL != data->remoteEndpoint)
1375     {
1376         CALogAdapterTypeInfo(data->remoteEndpoint->adapter);
1377         OIC_LOG(DEBUG, ANALYZER_TAG, "-------------------------------------------------");
1378         OIC_LOG_V(DEBUG, ANALYZER_TAG, "Address = [%s]:[%d]", data->remoteEndpoint->addr,
1379                   data->remoteEndpoint->port);
1380         OIC_LOG(DEBUG, ANALYZER_TAG, "-------------------------------------------------");
1381     }
1382
1383     switch(data->dataType)
1384     {
1385         case CA_REQUEST_DATA:
1386             OIC_LOG(DEBUG, ANALYZER_TAG, "Data Type = [CA_REQUEST_DATA]");
1387             break;
1388         case CA_RESPONSE_DATA:
1389             OIC_LOG(DEBUG, ANALYZER_TAG, "Data Type = [CA_RESPONSE_DATA]");
1390             break;
1391         case CA_ERROR_DATA:
1392             OIC_LOG(DEBUG, ANALYZER_TAG, "Data Type = [CA_ERROR_DATA]");
1393             break;
1394         case CA_RESPONSE_FOR_RES:
1395             OIC_LOG(DEBUG, ANALYZER_TAG, "Data Type = [CA_RESPONSE_FOR_RES]");
1396             break;
1397         default:
1398             OIC_LOG_V(DEBUG, ANALYZER_TAG, "Data Type = [%d]", data->dataType);
1399             break;
1400     }
1401     OIC_LOG(DEBUG, ANALYZER_TAG, "-------------------------------------------------");
1402
1403     const CAInfo_t *info = NULL;
1404     if (NULL != data->requestInfo)
1405     {
1406         switch(data->requestInfo->method)
1407         {
1408             case CA_GET:
1409                 OIC_LOG(DEBUG, ANALYZER_TAG, "Method = [GET]");
1410                 break;
1411             case CA_POST:
1412                 OIC_LOG(DEBUG, ANALYZER_TAG, "Method = [POST]");
1413                 break;
1414             case CA_PUT:
1415                 OIC_LOG(DEBUG, ANALYZER_TAG, "Method = [PUT]");
1416                 break;
1417             case CA_DELETE:
1418                 OIC_LOG(DEBUG, ANALYZER_TAG, "Method = [DELETE]");
1419                 break;
1420             default:
1421                 OIC_LOG_V(DEBUG, ANALYZER_TAG, "Method = [%d]", data->requestInfo->method);
1422                 break;
1423         }
1424         info = &data->requestInfo->info;
1425     }
1426
1427     if (NULL != data->responseInfo)
1428     {
1429         OIC_LOG_V(DEBUG, ANALYZER_TAG, "result code = [%d]", data->responseInfo->result);
1430         info = &data->responseInfo->info;
1431     }
1432
1433     if (pdu->transport_hdr)
1434     {
1435         OIC_LOG_V(DEBUG, ANALYZER_TAG, "Msg ID = [%d]", pdu->transport_hdr->udp.id);
1436     }
1437
1438     if (info)
1439     {
1440         OIC_LOG(DEBUG, ANALYZER_TAG, "Coap Token");
1441         OIC_LOG_BUFFER(DEBUG, ANALYZER_TAG, (const uint8_t *) info->token, info->tokenLength);
1442         OIC_LOG_V(DEBUG, ANALYZER_TAG, "Res URI = [%s]", info->resourceUri);
1443         OIC_LOG(DEBUG, ANALYZER_TAG, "-------------------------------------------------");
1444
1445         if (CA_FORMAT_APPLICATION_CBOR == info->payloadFormat)
1446         {
1447             OIC_LOG(DEBUG, ANALYZER_TAG, "Payload Format = [CA_FORMAT_APPLICATION_CBOR]");
1448         }
1449         else
1450         {
1451             OIC_LOG_V(DEBUG, ANALYZER_TAG, "Payload Format = [%d]", info->payloadFormat);
1452         }
1453     }
1454
1455     size_t payloadLen = (pdu->data) ? (unsigned char *) pdu->hdr + pdu->length - pdu->data : 0;
1456     OIC_LOG_V(DEBUG, ANALYZER_TAG, "CoAP Message Full Size = [%lu]", pdu->length);
1457     OIC_LOG(DEBUG, ANALYZER_TAG, "CoAP Header (+ 0xFF)");
1458     OIC_LOG_BUFFER(DEBUG, ANALYZER_TAG,  (const uint8_t *) pdu->transport_hdr,
1459                    pdu->length - payloadLen);
1460     OIC_LOG_V(DEBUG, ANALYZER_TAG, "CoAP Header size = [%lu]", pdu->length - payloadLen);
1461
1462     OIC_LOG_V(DEBUG, ANALYZER_TAG, "CoAP Payload");
1463     OIC_LOG_BUFFER(DEBUG, ANALYZER_TAG, pdu->data, payloadLen);
1464     OIC_LOG_V(DEBUG, ANALYZER_TAG, "CoAP Payload Size = [%lu]", payloadLen);
1465     OIC_LOG(DEBUG, ANALYZER_TAG, "=================================================");
1466 }
1467 #else
1468 static void CALogPDUInfo(const CAData_t *data, const coap_pdu_t *pdu)
1469 {
1470     VERIFY_NON_NULL_VOID(pdu, TAG, "pdu");
1471     (void)data;
1472
1473     OIC_LOG_V(DEBUG, TAG, "PDU Maker - payload : %s", pdu->data);
1474     OIC_LOG_V(DEBUG, TAG, "PDU Maker - type : %d", pdu->transport_hdr->udp.type);
1475     OIC_LOG_V(DEBUG, TAG, "PDU Maker - code : %d", pdu->transport_hdr->udp.code);
1476     OIC_LOG(DEBUG, TAG, "PDU Maker - token :");
1477     OIC_LOG_BUFFER(DEBUG, TAG, pdu->transport_hdr->udp.token,
1478                    pdu->transport_hdr->udp.token_length);
1479 }
1480 #endif