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