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