Fixed build warnings due to assert, unused function, time
[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 "config.h" /* for coap protocol */
32 #include "oic_malloc.h"
33 #include "canetworkconfigurator.h"
34 #include "caadapterutils.h"
35 #include "cainterfacecontroller.h"
36 #include "caretransmission.h"
37
38 #ifndef  SINGLE_THREAD
39 #include "uqueue.h"
40 #include "cathreadpool.h" /* for thread pool */
41 #include "caqueueingthread.h"
42
43 #define SINGLE_HANDLE
44 #define MAX_THREAD_POOL_SIZE    20
45
46 // thread pool handle
47 static ca_thread_pool_t g_threadPoolHandle = NULL;
48
49 // message handler main thread
50 static CAQueueingThread_t g_sendThread;
51 static CAQueueingThread_t g_receiveThread;
52
53 #else
54 #define CA_MAX_RT_ARRAY_SIZE    3
55 #endif  /* SINGLE_THREAD */
56
57 #define TAG "CA_MSG_HNDLR"
58
59 static CARetransmission_t g_retransmissionContext;
60
61 // handler field
62 static CARequestCallback g_requestHandler = NULL;
63 static CAResponseCallback g_responseHandler = NULL;
64 static CAErrorCallback g_errorHandler = NULL;
65
66 static void CAErrorHandler(const CAEndpoint_t *endpoint,
67                            const void *data, uint32_t dataLen,
68                            CAResult_t result);
69
70 static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint, const void *data,
71                                        CADataType_t dataType);
72
73 #ifdef SINGLE_THREAD
74 static void CAProcessReceivedData(CAData_t *data);
75 #endif
76 static void CADataDestroyer(void *data, uint32_t size);
77 static void CALogPayloadInfo(CAInfo_t *info);
78 static bool CADropSecondRequest(const CAEndpoint_t *endpoint, uint16_t messageId);
79
80 static bool CAIsSelectedNetworkAvailable()
81 {
82     u_arraylist_t *list = CAGetSelectedNetworkList();
83     if (!list || list->length == 0)
84     {
85         OIC_LOG(ERROR, TAG, "No selected network");
86         return false;
87     }
88
89     return true;
90 }
91
92 static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint, const void *data, CADataType_t dataType)
93 {
94     OIC_LOG(DEBUG, TAG, "CAGenerateHandlerData IN");
95     CAInfo_t *info = NULL;
96     CAData_t *cadata = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
97     if (!cadata)
98     {
99         OIC_LOG(ERROR, TAG, "memory allocation failed");
100         return NULL;
101     }
102
103     CAEndpoint_t* ep = CACloneEndpoint(endpoint);
104     if (!ep)
105     {
106         OIC_LOG(ERROR, TAG, "endpoint clone failed");
107         OICFree(cadata);
108         return NULL;
109     }
110
111     OIC_LOG_V(DEBUG, TAG, "address : %s", ep->addr);
112     CAResult_t result;
113
114     if(CA_RESPONSE_DATA == dataType)
115     {
116         CAResponseInfo_t* resInfo = (CAResponseInfo_t*)OICCalloc(1, sizeof(CAResponseInfo_t));
117         if (!resInfo)
118         {
119             OIC_LOG(ERROR, TAG, "memory allocation failed");
120             OICFree(cadata);
121             CAFreeEndpoint(ep);
122             return NULL;
123         }
124
125         result = CAGetResponseInfoFromPDU(data, resInfo);
126         if (CA_STATUS_OK != result)
127         {
128             OIC_LOG(ERROR, TAG, "CAGetResponseInfoFromPDU Failed");
129             CAFreeEndpoint(ep);
130             CADestroyResponseInfoInternal(resInfo);
131             OICFree(cadata);
132             return NULL;
133         }
134         cadata->responseInfo = resInfo;
135         info = &resInfo->info;
136         OIC_LOG(DEBUG, TAG, "Response Info :");
137         CALogPayloadInfo(info);
138     }
139     else if (CA_REQUEST_DATA == dataType)
140     {
141         CARequestInfo_t* reqInfo = (CARequestInfo_t*)OICCalloc(1, sizeof(CARequestInfo_t));
142         if (!reqInfo)
143         {
144             OIC_LOG(ERROR, TAG, "memory allocation failed");
145             OICFree(cadata);
146             CAFreeEndpoint(ep);
147             return NULL;
148         }
149
150         result = CAGetRequestInfoFromPDU(data, reqInfo);
151         if (CA_STATUS_OK != result)
152         {
153             OIC_LOG(ERROR, TAG, "CAGetRequestInfoFromPDU failed");
154             CAFreeEndpoint(ep);
155             CADestroyRequestInfoInternal(reqInfo);
156             OICFree(cadata);
157             return NULL;
158         }
159
160         if (CADropSecondRequest(endpoint, reqInfo->info.messageId))
161         {
162             OIC_LOG(ERROR, TAG, "Second Request with same Token, Drop it");
163             CAFreeEndpoint(ep);
164             CADestroyRequestInfoInternal(reqInfo);
165             OICFree(cadata);
166             return NULL;
167         }
168
169         cadata->requestInfo = reqInfo;
170         info = &reqInfo->info;
171         OIC_LOG(DEBUG, TAG, "Request Info :");
172         CALogPayloadInfo(info);
173    }
174     else if (CA_ERROR_DATA == dataType)
175     {
176         CAErrorInfo_t *errorInfo = (CAErrorInfo_t *)OICCalloc(1, sizeof (CAErrorInfo_t));
177         if (!errorInfo)
178         {
179             OIC_LOG(ERROR, TAG, "Memory allocation failed!");
180             OICFree(cadata);
181             CAFreeEndpoint(ep);
182             return NULL;
183         }
184
185         CAResult_t result = CAGetErrorInfoFromPDU(data, errorInfo);
186         if (CA_STATUS_OK != result)
187         {
188             OIC_LOG(ERROR, TAG, "CAGetErrorInfoFromPDU failed");
189             CAFreeEndpoint(ep);
190             OICFree(errorInfo);
191             OICFree(cadata);
192             return NULL;
193         }
194
195         cadata->errorInfo = errorInfo;
196         info = &errorInfo->info;
197         OIC_LOG(DEBUG, TAG, "error Info :");
198         CALogPayloadInfo(info);
199     }
200
201     cadata->remoteEndpoint = ep;
202     cadata->dataType = dataType;
203
204     return cadata;
205
206     OIC_LOG(DEBUG, TAG, "CAGenerateHandlerData OUT");
207 }
208
209 static void CATimeoutCallback(const CAEndpoint_t *endpoint, const void *pdu, uint32_t size)
210 {
211     OIC_LOG(DEBUG, TAG, "IN");
212     VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint");
213     VERIFY_NON_NULL_VOID(pdu, TAG, "pdu");
214
215     CAEndpoint_t* ep = CACloneEndpoint(endpoint);
216     if (!ep)
217     {
218         OIC_LOG(ERROR, TAG, "clone failed");
219         return;
220     }
221
222     CAResponseInfo_t* resInfo = (CAResponseInfo_t*)OICCalloc(1, sizeof(CAResponseInfo_t));
223
224     if (!resInfo)
225     {
226         OIC_LOG(ERROR, TAG, "calloc failed");
227         CAFreeEndpoint(ep);
228         return;
229     }
230
231     resInfo->result = CA_RETRANSMIT_TIMEOUT;
232     resInfo->info.type = CAGetMessageTypeFromPduBinaryData(pdu, size);
233     resInfo->info.messageId = CAGetMessageIdFromPduBinaryData(pdu, size);
234
235     CAResult_t res = CAGetTokenFromPDU((const coap_hdr_t *) pdu, &(resInfo->info));
236     if (CA_STATUS_OK != res)
237     {
238         OIC_LOG(ERROR, TAG, "fail to get Token from retransmission list");
239         CADestroyResponseInfoInternal(resInfo);
240         CAFreeEndpoint(ep);
241         return;
242     }
243
244     CAData_t *cadata = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
245     if (NULL == cadata)
246     {
247         OIC_LOG(ERROR, TAG, "memory allocation failed !");
248         CAFreeEndpoint(ep);
249         CADestroyResponseInfoInternal(resInfo);
250         return;
251     }
252
253     cadata->type = SEND_TYPE_UNICAST;
254     cadata->remoteEndpoint = ep;
255     cadata->requestInfo = NULL;
256     cadata->responseInfo = resInfo;
257
258 #ifdef SINGLE_THREAD
259     CAProcessReceivedData(cadata);
260 #else
261     CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t));
262 #endif
263
264     OIC_LOG(DEBUG, TAG, "OUT");
265 }
266
267 static void CADataDestroyer(void *data, uint32_t size)
268 {
269     OIC_LOG(DEBUG, TAG, "CADataDestroyer IN");
270     CAData_t *cadata = (CAData_t *) data;
271
272     if (NULL == cadata)
273     {
274         OIC_LOG(ERROR, TAG, "cadata is NULL");
275         return;
276     }
277
278     if (NULL != cadata->remoteEndpoint)
279     {
280         CAFreeEndpoint(cadata->remoteEndpoint);
281     }
282
283     if (NULL != cadata->requestInfo)
284     {
285         CADestroyRequestInfoInternal((CARequestInfo_t *) cadata->requestInfo);
286     }
287
288     if (NULL != cadata->responseInfo)
289     {
290         CADestroyResponseInfoInternal((CAResponseInfo_t *) cadata->responseInfo);
291     }
292
293     if (NULL != cadata->errorInfo)
294     {
295         CADestroyErrorInfoInternal(cadata->errorInfo);
296     }
297
298     OICFree(cadata->options);
299     OICFree(cadata);
300     OIC_LOG(DEBUG, TAG, "CADataDestroyer OUT");
301 }
302
303 #ifdef SINGLE_THREAD
304 static void CAProcessReceivedData(CAData_t *data)
305 {
306     OIC_LOG(DEBUG, TAG, "CAProcessReceivedData IN");
307     if (!data)
308     {
309         OIC_LOG(ERROR, TAG, "thread data error!!");
310         return;
311     }
312
313     // parse the data and call the callbacks.
314     // #1 parse the data
315     // #2 get endpoint
316     CAEndpoint_t *rep = (CAEndpoint_t *)(data->remoteEndpoint);
317     if (!rep)
318     {
319         OIC_LOG(ERROR, TAG, "remoteEndpoint error!!");
320         return;
321     }
322
323     if (data->requestInfo && g_requestHandler)
324     {
325         g_requestHandler(rep, data->requestInfo);
326     }
327     else if (data->responseInfo && g_responseHandler)
328     {
329         g_responseHandler(rep, data->responseInfo);
330     }
331     else if (data->errorInfo && g_errorHandler)
332     {
333         g_errorHandler(rep, data->errorInfo);
334     }
335
336     CADataDestroyer(data, sizeof(CAData_t));
337
338     OIC_LOG(DEBUG, TAG, "CAProcessReceivedData OUT");
339 }
340 #endif
341
342 #ifndef SINGLE_THREAD
343
344 static void CAReceiveThreadProcess(void *threadData)
345 {
346     OIC_LOG(DEBUG, TAG, "IN");
347 #ifndef SINGLE_HANDLE
348     CAData_t *data = (CAData_t *) threadData;
349     CAProcessReceivedData(data);
350 #endif
351     OIC_LOG(DEBUG, TAG, "OUT");
352 }
353 #endif
354
355 static void CAProcessSendData(const CAData_t *data)
356 {
357     OIC_LOG(DEBUG, TAG, "IN");
358     VERIFY_NON_NULL_VOID(data, TAG, "data");
359     VERIFY_NON_NULL_VOID(data->remoteEndpoint, TAG, "remoteEndpoint");
360
361     CAResult_t res = CA_STATUS_FAILED;
362
363     CASendDataType_t type = data->type;
364
365     coap_pdu_t *pdu = NULL;
366
367     if (SEND_TYPE_UNICAST == type)
368     {
369
370         OIC_LOG(DEBUG,TAG,"Unicast message");
371         if (NULL != data->requestInfo)
372         {
373             OIC_LOG(DEBUG, TAG, "requestInfo is available..");
374
375             pdu = CAGeneratePDU(data->requestInfo->method, &data->requestInfo->info);
376         }
377         else if (NULL != data->responseInfo)
378         {
379             OIC_LOG(DEBUG, TAG, "responseInfo is available..");
380
381             pdu = CAGeneratePDU(data->responseInfo->result, &data->responseInfo->info);
382         }
383         else
384         {
385             OIC_LOG(DEBUG, TAG, "request info, response info is empty");
386             return;
387         }
388
389         // interface controller function call.
390         if (NULL != pdu)
391         {
392             CALogPDUInfo(pdu);
393
394             res = CASendUnicastData(data->remoteEndpoint, pdu->hdr, pdu->length);
395             if (CA_STATUS_OK != res)
396             {
397                 OIC_LOG_V(ERROR, TAG, "send failed:%d", res);
398                 coap_delete_pdu(pdu);
399                 return;
400             }
401             // for retransmission
402             res = CARetransmissionSentData(&g_retransmissionContext, data->remoteEndpoint, pdu->hdr,
403                                            pdu->length);
404             if (CA_STATUS_OK != res)
405             {
406                 OIC_LOG_V(INFO, TAG, "retransmission is not enabled due to error, res : %d", res);
407                 coap_delete_pdu(pdu);
408                 return;
409             }
410
411             coap_delete_pdu(pdu);
412         }
413         else
414         {
415             OIC_LOG(ERROR,TAG,"Failed to generate unicast PDU");
416             return;
417         }
418     }
419     else if (SEND_TYPE_MULTICAST == type)
420     {
421         OIC_LOG(DEBUG,TAG,"Multicast message");
422         if (NULL != data->requestInfo)
423         {
424             OIC_LOG(DEBUG, TAG, "requestInfo is available..");
425             CAInfo_t *info = &data->requestInfo->info;
426
427             pdu = CAGeneratePDU(CA_GET, info);
428             if (NULL != pdu)
429             {
430                 CALogPDUInfo(pdu);
431
432                 res = CASendMulticastData(data->remoteEndpoint, pdu->hdr, pdu->length);
433                 if (CA_STATUS_OK != res)
434                 {
435                     OIC_LOG_V(ERROR, TAG, "send failed:%d", res);
436                     coap_delete_pdu(pdu);
437                     return;
438                 }
439
440                 coap_delete_pdu(pdu);
441             }
442             else
443             {
444                 OIC_LOG(ERROR,TAG,"Failed to generate multicast PDU");
445             }
446         }
447         else
448         {
449             OIC_LOG(ERROR, TAG, "request info is empty");
450         }
451     }
452
453     OIC_LOG(DEBUG, TAG, "OUT");
454 }
455
456 #ifndef SINGLE_THREAD
457 static void CASendThreadProcess(void *threadData)
458 {
459     CAData_t *data = (CAData_t *) threadData;
460     CAProcessSendData(data);
461 }
462
463 #endif
464
465 /*
466  * If a second message arrives with the same token and the other address
467  * family, drop it.  Typically, IPv6 beats IPv4, so the IPv4 message is dropped.
468  * This can be made more robust (for instance, another message could arrive
469  * in between), but it is good enough for now.
470  */
471 static bool CADropSecondRequest(const CAEndpoint_t *endpoint, uint16_t messageId)
472 {
473     if (!endpoint)
474     {
475         return true;
476     }
477     if (endpoint->adapter != CA_ADAPTER_IP)
478     {
479         return false;
480     }
481
482     bool ret = false;
483     CATransportFlags_t familyFlags = endpoint->flags & CA_IPFAMILY_MASK;
484
485     if (messageId == caglobals.ca.previousRequestMessageId)
486     {
487         if ((familyFlags ^ caglobals.ca.previousRequestFlags) == CA_IPFAMILY_MASK)
488         {
489             if (familyFlags & CA_IPV6)
490             {
491                 OIC_LOG(INFO, TAG, "IPv6 duplicate response ignored");
492             }
493             else
494             {
495                 OIC_LOG(INFO, TAG, "IPv4 duplicate response ignored");
496             }
497             ret = true;
498         }
499     }
500     caglobals.ca.previousRequestFlags = familyFlags;
501     caglobals.ca.previousRequestMessageId = messageId;
502     return ret;
503 }
504
505 static void CAReceivedPacketCallback(const CAEndpoint_t *remoteEndpoint, void *data, uint32_t dataLen)
506 {
507     OIC_LOG(DEBUG, TAG, "IN");
508     VERIFY_NON_NULL_VOID(remoteEndpoint, TAG, "remoteEndpoint");
509     VERIFY_NON_NULL_VOID(data, TAG, "data");
510
511     uint32_t code = CA_NOT_FOUND;
512     CAData_t *cadata = NULL;
513
514     coap_pdu_t *pdu = (coap_pdu_t *) CAParsePDU((const char *) data, dataLen, &code);
515     if (NULL == pdu)
516     {
517         OIC_LOG(ERROR, TAG, "Parse PDU failed");
518         return;
519     }
520
521     OIC_LOG_V(DEBUG, TAG, "code = %d", code);
522     if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code)
523     {
524         cadata = CAGenerateHandlerData(remoteEndpoint, pdu, CA_REQUEST_DATA);
525         if (!cadata)
526         {
527             OIC_LOG(ERROR, TAG, "CAReceivedPacketCallback, CAGenerateHandlerData failed!");
528             coap_delete_pdu(pdu);
529             return;
530         }
531     }
532     else
533     {
534         cadata = CAGenerateHandlerData(remoteEndpoint, pdu, CA_RESPONSE_DATA);
535         if (!cadata)
536         {
537             OIC_LOG(ERROR, TAG, "CAReceivedPacketCallback, CAGenerateHandlerData failed!");
538             coap_delete_pdu(pdu);
539             return;
540         }
541
542         // for retransmission
543         void *retransmissionPdu = NULL;
544         CARetransmissionReceivedData(&g_retransmissionContext, cadata->remoteEndpoint, pdu->hdr,
545                                      pdu->length, &retransmissionPdu);
546
547         // get token from saved data in retransmission list
548         if (retransmissionPdu && CA_EMPTY == code)
549         {
550             CAInfo_t *info = &cadata->responseInfo->info;
551             CAResult_t res = CAGetTokenFromPDU((const coap_hdr_t *)retransmissionPdu,
552                                                info);
553             if (CA_STATUS_OK != res)
554             {
555                 OIC_LOG(ERROR, TAG, "fail to get Token from retransmission list");
556                 OICFree(info->token);
557                 info->tokenLength = 0;
558             }
559         }
560         OICFree(retransmissionPdu);
561     }
562
563     cadata->type = SEND_TYPE_UNICAST;
564
565 #ifdef SINGLE_THREAD
566     CAProcessReceivedData(cadata);
567 #else
568     CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t));
569 #endif
570
571     coap_delete_pdu(pdu);
572
573     OIC_LOG(DEBUG, TAG, "OUT");
574 }
575
576 static void CANetworkChangedCallback(const CAEndpoint_t *info, CANetworkStatus_t status)
577 {
578     OIC_LOG(DEBUG, TAG, "IN");
579
580     OIC_LOG(DEBUG, TAG, "OUT");
581 }
582
583 void CAHandleRequestResponseCallbacks()
584 {
585     OIC_LOG(DEBUG, TAG, "CAHandleRequestResponseCallbacks IN");
586 #ifdef SINGLE_THREAD
587     CAReadData();
588     CARetransmissionBaseRoutine((void *)&g_retransmissionContext);
589 #else
590 #ifdef SINGLE_HANDLE
591     // parse the data and call the callbacks.
592     // #1 parse the data
593     // #2 get endpoint
594
595     ca_mutex_lock(g_receiveThread.threadMutex);
596
597     u_queue_message_t *item = u_queue_get_element(g_receiveThread.dataQueue);
598
599     ca_mutex_unlock(g_receiveThread.threadMutex);
600
601     if (NULL == item)
602     {
603         return;
604     }
605
606     // get values
607     void *msg = item->msg;
608
609     if (NULL == msg)
610     {
611         return;
612     }
613
614     // get endpoint
615     CAData_t *td = (CAData_t *) msg;
616
617     if (td->requestInfo && g_requestHandler)
618     {
619         OIC_LOG_V(DEBUG, TAG, "request callback : %d", td->requestInfo->info.numOptions);
620         g_requestHandler(td->remoteEndpoint, td->requestInfo);
621     }
622     else if (td->responseInfo && g_responseHandler)
623     {
624         OIC_LOG_V(DEBUG, TAG, "response callback : %d", td->responseInfo->info.numOptions);
625         g_responseHandler(td->remoteEndpoint, td->responseInfo);
626     }
627     else if (td->errorInfo && g_errorHandler)
628     {
629         OIC_LOG_V(DEBUG, TAG, "error callback error: %d", td->errorInfo->result);
630         g_errorHandler(td->remoteEndpoint, td->errorInfo);
631     }
632
633     CADataDestroyer(msg, sizeof(CAData_t));
634     OICFree(item);
635
636 #endif /* SINGLE_HANDLE */
637 #endif
638     OIC_LOG(DEBUG, TAG, "CAHandleRequestResponseCallbacks OUT");
639 }
640
641 static CAData_t* CAPrepareSendData(const CAEndpoint_t *endpoint, const void *sendData,
642                                    CADataType_t dataType)
643 {
644     OIC_LOG(DEBUG, TAG, "CAPrepareSendData IN");
645     CAInfo_t *info = NULL;
646
647     CAData_t *cadata = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
648     if (!cadata)
649     {
650         OIC_LOG(ERROR, TAG, "memory allocation failed");
651         return NULL;
652     }
653
654     if(CA_REQUEST_DATA == dataType)
655     {
656         // clone request info
657         CARequestInfo_t *request = CACloneRequestInfo((CARequestInfo_t *)sendData);
658
659         if(!request)
660         {
661             OIC_LOG(ERROR, TAG, "CACloneRequestInfo failed");
662             OICFree(cadata);
663             return NULL;
664         }
665
666         cadata->type = request->isMulticast ? SEND_TYPE_MULTICAST : SEND_TYPE_UNICAST;
667         info = &request->info;
668         cadata->requestInfo =  request;
669     }
670     else if(CA_RESPONSE_DATA == dataType)
671     {
672         // clone response info
673         CAResponseInfo_t *response = CACloneResponseInfo((CAResponseInfo_t *)sendData);
674
675         if(!response)
676         {
677             OIC_LOG(ERROR, TAG, "CACloneResponseInfo failed");
678             OICFree(cadata);
679             return NULL;
680         }
681
682         cadata->type = SEND_TYPE_UNICAST;
683         info = &response->info;
684         cadata->responseInfo = response;
685     }
686
687     if (NULL != info->options && 0 < info->numOptions)
688     {
689         uint8_t numOptions = info->numOptions;
690         // copy data
691         CAHeaderOption_t *headerOption = (CAHeaderOption_t *) OICMalloc(sizeof(CAHeaderOption_t)
692                                                                         * numOptions);
693         if(!headerOption)
694         {
695             OIC_LOG(ERROR, TAG, "memory allocation failed");
696             CADataDestroyer(cadata, sizeof(CAData_t));
697             return NULL;
698         }
699
700         memcpy(headerOption, info->options, sizeof(CAHeaderOption_t) * numOptions);
701
702         cadata->options = headerOption;
703         cadata->numOptions = numOptions;
704     }
705
706     CAEndpoint_t* ep = CACloneEndpoint(endpoint);
707     if (!ep)
708     {
709         OIC_LOG(ERROR, TAG, "endpoint clone failed");
710         CADataDestroyer(cadata, sizeof(CAData_t));
711         return NULL;
712     }
713
714     cadata->remoteEndpoint = ep;
715     return cadata;
716
717 }
718
719 CAResult_t CADetachRequestMessage(const CAEndpoint_t *object, const CARequestInfo_t *request)
720 {
721     OIC_LOG(DEBUG, TAG, "IN");
722
723     VERIFY_NON_NULL(object, TAG, "object");
724     VERIFY_NON_NULL(request, TAG, "request");
725
726     if (false == CAIsSelectedNetworkAvailable())
727     {
728         return CA_STATUS_FAILED;
729     }
730
731 #ifdef ARDUINO
732     // If max retransmission queue is reached, then don't handle new request
733     if (CA_MAX_RT_ARRAY_SIZE == u_arraylist_length(g_retransmissionContext.dataList))
734     {
735         OIC_LOG(ERROR, TAG, "max RT queue size reached!");
736         return CA_SEND_FAILED;
737     }
738 #endif /* ARDUINO */
739
740     CAData_t *data = CAPrepareSendData(object, request, CA_REQUEST_DATA);
741     if(!data)
742     {
743         OIC_LOG(ERROR, TAG, "CAPrepareSendData failed");
744         return CA_MEMORY_ALLOC_FAILED;
745     }
746
747 #ifdef SINGLE_THREAD
748     CAProcessSendData(data);
749     CADataDestroyer(data, sizeof(CAData_t));
750 #else
751     CAQueueingThreadAddData(&g_sendThread, data, sizeof(CAData_t));
752 #endif
753
754     OIC_LOG(DEBUG, TAG, "OUT");
755     return CA_STATUS_OK;
756 }
757
758 CAResult_t CADetachResponseMessage(const CAEndpoint_t *object,
759                                    const CAResponseInfo_t *response)
760 {
761     OIC_LOG(DEBUG, TAG, "IN");
762     VERIFY_NON_NULL(object, TAG, "object");
763     VERIFY_NON_NULL(response, TAG, "response");
764
765     if (false == CAIsSelectedNetworkAvailable())
766     {
767         return CA_STATUS_FAILED;
768     }
769
770     CAData_t *data = CAPrepareSendData(object, response, CA_RESPONSE_DATA);
771     if(!data)
772     {
773         OIC_LOG(ERROR, TAG, "CAPrepareSendData failed");
774         return CA_MEMORY_ALLOC_FAILED;
775     }
776
777 #ifdef SINGLE_THREAD
778     CAProcessSendData(data);
779     CADataDestroyer(data, sizeof(CAData_t));
780 #else
781     CAQueueingThreadAddData(&g_sendThread, data, sizeof(CAData_t));
782 #endif
783
784     OIC_LOG(DEBUG, TAG, "OUT");
785     return CA_STATUS_OK;
786 }
787
788 CAResult_t CADetachMessageResourceUri(const CAURI_t resourceUri, const CAToken_t token,
789                                       uint8_t tokenLength, const CAHeaderOption_t *options,
790                                       uint8_t numOptions)
791 {
792     return CA_NOT_SUPPORTED;
793 }
794
795 void CASetInterfaceCallbacks(CARequestCallback ReqHandler, CAResponseCallback RespHandler,
796                              CAErrorCallback errorHandler)
797 {
798     OIC_LOG(DEBUG, TAG, "IN");
799     g_requestHandler = ReqHandler;
800     g_responseHandler = RespHandler;
801     g_errorHandler = errorHandler;
802     OIC_LOG(DEBUG, TAG, "OUT");
803 }
804
805 CAResult_t CAInitializeMessageHandler()
806 {
807     OIC_LOG(DEBUG, TAG, "IN");
808     CASetPacketReceivedCallback(CAReceivedPacketCallback);
809
810     CASetNetworkChangeCallback(CANetworkChangedCallback);
811     CASetErrorHandleCallback(CAErrorHandler);
812
813 #ifndef SINGLE_THREAD
814     // create thread pool
815     CAResult_t res = ca_thread_pool_init(MAX_THREAD_POOL_SIZE, &g_threadPoolHandle);
816
817     if (CA_STATUS_OK != res)
818     {
819         OIC_LOG(ERROR, TAG, "thread pool initialize error.");
820         return res;
821     }
822
823     // send thread initialize
824     if (CA_STATUS_OK != CAQueueingThreadInitialize(&g_sendThread, g_threadPoolHandle,
825                                                    CASendThreadProcess, CADataDestroyer))
826     {
827         OIC_LOG(ERROR, TAG, "Failed to Initialize send queue thread");
828         return CA_STATUS_FAILED;
829     }
830
831     // start send thread
832     res = CAQueueingThreadStart(&g_sendThread);
833
834     if (CA_STATUS_OK != res)
835     {
836         OIC_LOG(ERROR, TAG, "thread start error(send thread).");
837         ca_thread_pool_free(g_threadPoolHandle);
838         g_threadPoolHandle = NULL;
839         return res;
840     }
841
842     // receive thread initialize
843     if (CA_STATUS_OK != CAQueueingThreadInitialize(&g_receiveThread, g_threadPoolHandle,
844                                                    CAReceiveThreadProcess, CADataDestroyer))
845     {
846         OIC_LOG(ERROR, TAG, "Failed to Initialize receive queue thread");
847         return CA_STATUS_FAILED;
848     }
849
850 #ifndef SINGLE_HANDLE // This will be enabled when RI supports multi threading
851     // start receive thread
852     res = CAQueueingThreadStart(&gReceiveThread);
853
854     if (res != CA_STATUS_OK)
855     {
856         OIC_LOG(ERROR, TAG, "thread start error(receive thread).");
857         return res;
858     }
859 #endif /* SINGLE_HANDLE */
860
861     // retransmission initialize
862     CARetransmissionInitialize(&g_retransmissionContext, g_threadPoolHandle, CASendUnicastData,
863                                CATimeoutCallback, NULL);
864
865     // start retransmission
866     res = CARetransmissionStart(&g_retransmissionContext);
867
868     if (CA_STATUS_OK != res)
869     {
870         OIC_LOG(ERROR, TAG, "thread start error(retransmission thread).");
871         return res;
872     }
873
874     // initialize interface adapters by controller
875     CAInitializeAdapters(g_threadPoolHandle);
876 #else
877     // retransmission initialize
878     CARetransmissionInitialize(&g_retransmissionContext, NULL, CASendUnicastData,
879                                CATimeoutCallback, NULL);
880     CAInitializeAdapters();
881 #endif
882
883     OIC_LOG(DEBUG, TAG, "OUT");
884     return CA_STATUS_OK;
885 }
886
887 void CATerminateMessageHandler()
888 {
889     OIC_LOG(DEBUG, TAG, "IN");
890 #ifndef SINGLE_THREAD
891     CATransportAdapter_t connType;
892     u_arraylist_t *list = CAGetSelectedNetworkList();
893     uint32_t length = u_arraylist_length(list);
894
895     uint32_t i = 0;
896     for (i = 0; i < length; i++)
897     {
898         void* ptrType = u_arraylist_get(list, i);
899
900         if (NULL == ptrType)
901         {
902             continue;
903         }
904
905         connType = *(CATransportAdapter_t *)ptrType;
906         CAStopAdapter(connType);
907     }
908
909     // stop retransmission
910     if (NULL != g_retransmissionContext.threadMutex)
911     {
912         CARetransmissionStop(&g_retransmissionContext);
913     }
914
915     // stop thread
916     // delete thread data
917     if (NULL != g_sendThread.threadMutex)
918     {
919         CAQueueingThreadStop(&g_sendThread);
920     }
921
922     // stop thread
923     // delete thread data
924     if (NULL != g_receiveThread.threadMutex)
925     {
926 #ifndef SINGLE_HANDLE // This will be enabled when RI supports multi threading
927         CAQueueingThreadStop(&gReceiveThread);
928 #endif /* SINGLE_HANDLE */
929     }
930
931     // destroy thread pool
932     if (NULL != g_threadPoolHandle)
933     {
934         ca_thread_pool_free(g_threadPoolHandle);
935         g_threadPoolHandle = NULL;
936     }
937
938     CARetransmissionDestroy(&g_retransmissionContext);
939     CAQueueingThreadDestroy(&g_sendThread);
940     CAQueueingThreadDestroy(&g_receiveThread);
941
942     // terminate interface adapters by controller
943     CATerminateAdapters();
944 #else
945     // terminate interface adapters by controller
946     CATerminateAdapters();
947
948     // stop retransmission
949     CARetransmissionStop(&g_retransmissionContext);
950     CARetransmissionDestroy(&g_retransmissionContext);
951 #endif
952
953     OIC_LOG(DEBUG, TAG, "OUT");
954 }
955
956 void CALogPDUInfo(coap_pdu_t *pdu)
957 {
958     VERIFY_NON_NULL_VOID(pdu, TAG, "pdu");
959
960     OIC_LOG_V(DEBUG, TAG, "PDU Maker - payload : %s", pdu->data);
961
962     OIC_LOG_V(DEBUG, TAG, "PDU Maker - type : %d", pdu->hdr->type);
963
964     OIC_LOG_V(DEBUG, TAG, "PDU Maker - code : %d", pdu->hdr->code);
965
966     OIC_LOG(DEBUG, TAG, "PDU Maker - token :");
967
968     OIC_LOG_BUFFER(DEBUG, TAG, pdu->hdr->token, pdu->hdr->token_length);
969 }
970
971 static void CALogPayloadInfo(CAInfo_t *info)
972 {
973     if(info)
974     {
975         if (!info->options)
976         {
977             for (uint32_t i = 0; i < info->numOptions; i++)
978             {
979                 OIC_LOG_V(DEBUG, TAG, "optionID: %d", info->options[i].optionID);
980
981                 OIC_LOG_V(DEBUG, TAG, "list: %s", info->options[i].optionData);
982             }
983         }
984
985         if (!info->payload)
986         {
987             OIC_LOG_V(DEBUG, TAG, "payload: %p(%u)", info->payload,
988                       info->payloadSize);
989         }
990
991         if (!info->token)
992         {
993             OIC_LOG(DEBUG, TAG, "token:");
994             OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *) info->token,
995                            info->tokenLength);
996         }
997         OIC_LOG_V(DEBUG, TAG, "msgID: %d", info->messageId);
998     }
999     else
1000     {
1001         OIC_LOG(DEBUG, TAG, "info is NULL, cannot output log data");
1002     }
1003 }
1004
1005 void CAErrorHandler(const CAEndpoint_t *endpoint,
1006                     const void *data, uint32_t dataLen,
1007                     CAResult_t result)
1008 {
1009     OIC_LOG(DEBUG, TAG, "IN");
1010
1011 #ifndef SINGLE_THREAD
1012
1013     VERIFY_NON_NULL_VOID(endpoint, TAG, "remoteEndpoint");
1014     VERIFY_NON_NULL_VOID(data, TAG, "data");
1015
1016     uint32_t code = CA_NOT_FOUND;
1017     //Do not free remoteEndpoint and data. Currently they will be freed in data thread
1018     //Get PDU data
1019     coap_pdu_t *pdu = (coap_pdu_t *)CAParsePDU((const char *)data, dataLen, &code);
1020     if (NULL == pdu)
1021     {
1022         OIC_LOG(ERROR, TAG, "Parse PDU failed");
1023         return;
1024     }
1025
1026     CAData_t *cadata = CAGenerateHandlerData(endpoint, pdu, CA_ERROR_DATA);
1027     if(!cadata)
1028     {
1029         OIC_LOG(ERROR, TAG, "CAErrorHandler, CAGenerateHandlerData failed!");
1030         coap_delete_pdu(pdu);
1031         return;
1032     }
1033
1034     cadata->errorInfo->result = result;
1035
1036     CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t));
1037     coap_delete_pdu(pdu);
1038 #endif
1039
1040     OIC_LOG(DEBUG, TAG, "OUT");
1041     return;
1042 }