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