9e6fa2dff768f7bb4f8c4bdb42f480934abfe01d
[iotivity.git] / resource / csdk / connectivity / src / cainterfacecontroller.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 <inttypes.h>
25
26 #include "platform_features.h"
27 #include "experimental/logger.h"
28 #include "oic_malloc.h"
29 #include "caadapterutils.h"
30 #include "canetworkconfigurator.h"
31 #include "cainterfacecontroller.h"
32 #include "caedradapter.h"
33 #include "caleadapter.h"
34 #include "canfcadapter.h"
35 #include "caremotehandler.h"
36 #include "cathreadpool.h"
37 #include "caipadapter.h"
38 #include "cainterface.h"
39 #include <coap/utlist.h>
40
41 #ifndef SINGLE_THREAD
42 #include <assert.h>
43 #include "caqueueingthread.h"
44 #endif
45
46 #ifdef RA_ADAPTER
47 #include "caraadapter.h"
48 #endif
49
50 #ifdef TCP_ADAPTER
51 #include "catcpadapter.h"
52 #endif
53
54 #define TAG "OIC_CA_INF_CTR"
55
56 #if defined(TCP_ADAPTER) || defined(EDR_ADAPTER) || defined(LE_ADAPTER)
57 #define STATEFUL_PROTOCOL_SUPPORTED
58 #endif
59
60 #define CA_MEMORY_ALLOC_CHECK(arg) {if (arg == NULL) \
61     {OIC_LOG(ERROR, TAG, "memory error");goto memory_error_exit;} }
62
63 static CAConnectivityHandler_t *g_adapterHandler = NULL;
64
65 static size_t g_numberOfAdapters = 0;
66
67 static CANetworkPacketReceivedCallback g_networkPacketReceivedCallback = NULL;
68
69 static CAErrorHandleCallback g_errorHandleCallback = NULL;
70
71 static struct CANetworkCallback_t *g_networkChangeCallbackList = NULL;
72
73 #ifndef SINGLE_THREAD
74 static CAQueueingThread_t g_networkChangeCallbackThread;
75 #endif
76
77 /**
78  * network callback structure is handling
79  * for adapter state changed and connection state changed event.
80  */
81 typedef struct CANetworkCallback_t
82 {
83
84     /** Linked list; for multiple callback list.*/
85     struct CANetworkCallback_t *next;
86
87     /** Adapter state changed event callback. */
88     CAAdapterStateChangedCB adapter;
89
90     /** Connection state changed event callback. */
91     CAConnectionStateChangedCB conn;
92
93 } CANetworkCallback_t;
94
95 #ifndef SINGLE_THREAD
96 /**
97  * struct to wrap the network change callback info.
98  */
99 typedef struct CANetworkCallbackThreadInfo_t
100 {
101     CAAdapterStateChangedCB adapterCB;
102     CATransportAdapter_t adapter;
103     bool isInterfaceUp;
104
105 #ifdef STATEFUL_PROTOCOL_SUPPORTED
106     CAConnectionStateChangedCB connectionCB;
107     CAEndpoint_t *endpoint;
108     bool isConnected;
109 #endif
110 } CANetworkCallbackThreadInfo_t;
111
112 static void CANetworkChangeCallbackThreadProcess(void *threadData)
113 {
114     assert(threadData);
115
116     CANetworkCallbackThreadInfo_t *info = (CANetworkCallbackThreadInfo_t *) threadData;
117     if (info->adapterCB)
118     {
119         info->adapterCB(info->adapter, info->isInterfaceUp);
120     }
121 #ifdef STATEFUL_PROTOCOL_SUPPORTED
122     else if(info->connectionCB)
123     {
124         info->connectionCB(info->endpoint, info->isConnected);
125     }
126 #endif
127 }
128
129 static void CADestroyNetworkChangeCallbackData(void *data, uint32_t size)
130 {
131     assert(data);
132     OC_UNUSED(size);
133
134     CANetworkCallbackThreadInfo_t *info = (CANetworkCallbackThreadInfo_t *) data;
135 #ifdef STATEFUL_PROTOCOL_SUPPORTED
136     if (info->endpoint)
137     {
138         CAFreeEndpoint(info->endpoint);
139         info->endpoint = NULL;
140     }
141 #endif
142     OICFree(info);
143     info = NULL;
144 }
145 #endif // SINGLE_THREAD
146
147 static CAResult_t CAGetAdapterIndex(CATransportAdapter_t cType, size_t *adapterIndex)
148 {
149     for (size_t index = 0 ; index < g_numberOfAdapters ; index++)
150     {
151         if (cType == g_adapterHandler[index].cType )
152         {
153             *adapterIndex = index;
154             return CA_STATUS_OK;
155         }
156     }
157     return CA_STATUS_FAILED;
158 }
159
160 static void CARegisterCallback(CAConnectivityHandler_t handler)
161 {
162     if (handler.startAdapter == NULL ||
163         handler.startListenServer == NULL ||
164         handler.stopListenServer == NULL ||
165         handler.startDiscoveryServer == NULL ||
166         handler.sendData == NULL ||
167         handler.sendDataToAll == NULL ||
168         handler.GetnetInfo == NULL ||
169         handler.readData == NULL ||
170         handler.stopAdapter == NULL ||
171         handler.terminate == NULL)
172     {
173         OIC_LOG(ERROR, TAG, "connectivity handler is not enough to be used!");
174         return;
175     }
176     size_t numberofAdapters = g_numberOfAdapters + 1;
177     CAConnectivityHandler_t *adapterHandler = OICRealloc(g_adapterHandler,
178             (numberofAdapters) * sizeof(*adapterHandler));
179     if (NULL == adapterHandler)
180     {
181         OIC_LOG(ERROR, TAG, "Memory allocation failed during registration");
182         return;
183     }
184     g_adapterHandler = adapterHandler;
185     g_numberOfAdapters = numberofAdapters;
186     g_adapterHandler[g_numberOfAdapters - 1] = handler;
187
188     OIC_LOG_V(DEBUG, TAG, "%d type adapter, register complete!", handler.cType);
189 }
190
191 /**
192  * Add a network callback from caller to the network callback list
193  *
194  * @param adapterCB  adapter state changed callback
195  * @param connCB     connection state changed callback
196  *
197  * @return
198  *     CAResult_t
199  */
200 static CAResult_t AddNetworkStateChangedCallback(CAAdapterStateChangedCB adapterCB,
201         CAConnectionStateChangedCB connCB)
202 {
203     OIC_LOG(DEBUG, TAG, "Add NetworkStateChanged Callback");
204
205     if (!adapterCB)
206     {
207         OIC_LOG(ERROR, TAG, "adapterCB is null");
208         return CA_STATUS_INVALID_PARAM;
209     }
210
211 #ifdef STATEFUL_PROTOCOL_SUPPORTED
212     if (!connCB)
213     {
214         OIC_LOG(ERROR, TAG, "connCB is null");
215         return CA_STATUS_INVALID_PARAM;
216     }
217 #endif
218
219     CANetworkCallback_t *callback = NULL;
220     LL_FOREACH(g_networkChangeCallbackList, callback)
221     {
222         if (callback && adapterCB == callback->adapter && connCB == callback->conn)
223         {
224             OIC_LOG(DEBUG, TAG, "this callback is already added");
225             return CA_STATUS_OK;
226         }
227     }
228
229     callback = (CANetworkCallback_t *) OICCalloc(1, sizeof(CANetworkCallback_t));
230     if (NULL == callback)
231     {
232         OIC_LOG(ERROR, TAG, "Memory allocation failed during registration");
233         return CA_MEMORY_ALLOC_FAILED;
234     }
235
236     callback->adapter = adapterCB;
237 #ifdef STATEFUL_PROTOCOL_SUPPORTED
238     // Since IP adapter(UDP) is the Connectionless Protocol, it doesn't need.
239     callback->conn = connCB;
240 #endif
241     LL_APPEND(g_networkChangeCallbackList, callback);
242     return CA_STATUS_OK;
243 }
244
245 /**
246  * Remove a network callback from the network callback list
247  *
248  * @param adapterCB  adapter state changed callback
249  * @param connCB     connection state changed callback
250  *
251  * @return
252  *     CAResult_t
253  */
254 static CAResult_t RemoveNetworkStateChangedCallback(CAAdapterStateChangedCB adapterCB,
255         CAConnectionStateChangedCB connCB)
256 {
257     OIC_LOG(DEBUG, TAG, "Remove NetworkStateChanged Callback");
258
259     CANetworkCallback_t *callback = NULL;
260     LL_FOREACH(g_networkChangeCallbackList, callback)
261     {
262         if (callback && adapterCB == callback->adapter && connCB == callback->conn)
263         {
264             OIC_LOG(DEBUG, TAG, "remove specific callback");
265             LL_DELETE(g_networkChangeCallbackList, callback);
266             OICFree(callback);
267             callback = NULL;
268             return CA_STATUS_OK;
269         }
270     }
271     return CA_STATUS_OK;
272 }
273
274 /**
275  * Remove all network callback from the network callback list
276  */
277 static void RemoveAllNetworkStateChangedCallback()
278 {
279     OIC_LOG(DEBUG, TAG, "Remove All NetworkStateChanged Callback");
280
281     CANetworkCallback_t *callback = NULL;
282     CANetworkCallback_t *tmp = NULL;
283     LL_FOREACH_SAFE(g_networkChangeCallbackList, callback, tmp)
284     {
285         LL_DELETE(g_networkChangeCallbackList, callback);
286         OICFree(callback);
287         callback = NULL;
288     }
289     g_networkChangeCallbackList = NULL;
290 }
291
292 #ifdef RA_ADAPTER
293 CAResult_t CASetAdapterRAInfo(const CARAInfo_t *caraInfo)
294 {
295     return CASetRAInfo(caraInfo);
296 }
297 #endif
298
299 static void CAReceivedPacketCallback(const CASecureEndpoint_t *sep,
300                                      const void *data, size_t dataLen)
301 {
302     if (g_networkPacketReceivedCallback != NULL)
303     {
304         g_networkPacketReceivedCallback(sep, data, dataLen);
305     }
306     else
307     {
308         OIC_LOG(ERROR, TAG, "network packet received callback is NULL!");
309     }
310 }
311
312 static void CAAdapterChangedCallback(CATransportAdapter_t adapter, CANetworkStatus_t status)
313 {
314     OIC_LOG_V(DEBUG, TAG, "[%d] adapter state is changed to [%d]", adapter, status);
315
316     // Call the callback.
317     CANetworkCallback_t *callback  = NULL;
318     LL_FOREACH(g_networkChangeCallbackList, callback)
319     {
320         if (callback && callback->adapter)
321         {
322 #ifndef SINGLE_THREAD
323             CANetworkCallbackThreadInfo_t *info = (CANetworkCallbackThreadInfo_t *)
324                                         OICCalloc(1, sizeof(CANetworkCallbackThreadInfo_t));
325             if (!info)
326             {
327                 OIC_LOG(ERROR, TAG, "OICCalloc to info failed!");
328                 return;
329             }
330
331             info->adapterCB = callback->adapter;
332             info->adapter = adapter;
333             info->isInterfaceUp = (CA_INTERFACE_UP == status);
334
335             CAQueueingThreadAddData(&g_networkChangeCallbackThread, info,
336                                     sizeof(CANetworkCallbackThreadInfo_t));
337 #else
338             if (CA_INTERFACE_UP == status)
339             {
340                 callback->adapter(adapter, true);
341             }
342             else if (CA_INTERFACE_DOWN == status)
343             {
344                 callback->adapter(adapter, false);
345             }
346 #endif //SINGLE_THREAD
347         }
348     }
349 }
350
351 #ifdef STATEFUL_PROTOCOL_SUPPORTED
352 static void CAConnectionChangedCallback(const CAEndpoint_t *endpoint, bool isConnected)
353 {
354     OIC_LOG_V(DEBUG, TAG, "[%s] connection state is changed to [%d]", endpoint->addr, isConnected);
355
356     // Call the callback.
357     CANetworkCallback_t *callback = NULL;
358     LL_FOREACH(g_networkChangeCallbackList, callback)
359     {
360         if (callback && callback->conn)
361         {
362 #ifndef SINGLE_THREAD
363             CANetworkCallbackThreadInfo_t *info = (CANetworkCallbackThreadInfo_t *)
364                                         OICCalloc(1, sizeof(CANetworkCallbackThreadInfo_t));
365             if (!info)
366             {
367                 OIC_LOG(ERROR, TAG, "OICCalloc to info failed!");
368                 return;
369             }
370
371             CAEndpoint_t *cloneEp = CACloneEndpoint(endpoint);
372             if (!cloneEp)
373             {
374                 OIC_LOG(ERROR, TAG, "CACloneEndpoint failed!");
375                 OICFree(info);
376                 return;
377             }
378
379             info->connectionCB = callback->conn;
380             info->endpoint = cloneEp;
381             info->isConnected = isConnected;
382
383             CAQueueingThreadAddData(&g_networkChangeCallbackThread, info,
384                                     sizeof(CANetworkCallbackThreadInfo_t));
385 #else
386             callback->conn(endpoint, isConnected);
387 #endif //SINGLE_THREAD
388         }
389     }
390 }
391 #endif //STATEFUL_PROTOCOL_SUPPORTED
392
393 static void CAAdapterErrorHandleCallback(const CAEndpoint_t *endpoint,
394         const void *data, size_t dataLen,
395         CAResult_t result)
396 {
397     OIC_LOG(DEBUG, TAG, "received error from adapter in interfacecontroller");
398
399     // Call the callback.
400     if (g_errorHandleCallback != NULL)
401     {
402         g_errorHandleCallback(endpoint, data, dataLen, result);
403     }
404 }
405
406 CAResult_t CAInitializeAdapters(ca_thread_pool_t handle, CATransportAdapter_t transportType)
407 {
408     OIC_LOG_V(DEBUG, TAG, "initialize adapters %d", transportType);
409
410     // Initialize adapters and register callback.
411 #ifdef IP_ADAPTER
412     if ((transportType & CA_ADAPTER_IP) || (CA_DEFAULT_ADAPTER == transportType)
413         || (transportType == CA_ALL_ADAPTERS))
414     {
415         CAInitializeIP(CARegisterCallback, CAReceivedPacketCallback, CAAdapterChangedCallback,
416                        CAAdapterErrorHandleCallback, handle);
417     }
418 #endif /* IP_ADAPTER */
419
420 #ifdef EDR_ADAPTER
421     if ((transportType & CA_ADAPTER_RFCOMM_BTEDR) || (CA_DEFAULT_ADAPTER == transportType))
422     {
423         CAInitializeEDR(CARegisterCallback, CAReceivedPacketCallback, CAAdapterChangedCallback,
424                         CAConnectionChangedCallback, CAAdapterErrorHandleCallback, handle);
425     }
426 #endif /* EDR_ADAPTER */
427
428 #ifdef LE_ADAPTER
429     if ((transportType & CA_ADAPTER_GATT_BTLE) || (CA_DEFAULT_ADAPTER == transportType))
430     {
431         CAInitializeLE(CARegisterCallback, CAReceivedPacketCallback, CAAdapterChangedCallback,
432                        CAConnectionChangedCallback, CAAdapterErrorHandleCallback, handle);
433     }
434 #endif /* LE_ADAPTER */
435
436 #ifdef RA_ADAPTER
437     if ((transportType & CA_ADAPTER_REMOTE_ACCESS) || (CA_DEFAULT_ADAPTER == transportType))
438     {
439         CAInitializeRA(CARegisterCallback, CAReceivedPacketCallback, CAAdapterChangedCallback,
440                        handle);
441     }
442 #endif /* RA_ADAPTER */
443
444 #ifdef TCP_ADAPTER
445     if ((transportType & CA_ADAPTER_TCP) || (CA_DEFAULT_ADAPTER == transportType))
446     {
447         CAInitializeTCP(CARegisterCallback, CAReceivedPacketCallback, CAAdapterChangedCallback,
448                         CAConnectionChangedCallback, CAAdapterErrorHandleCallback, handle);
449     }
450 #endif /* TCP_ADAPTER */
451
452 #ifdef NFC_ADAPTER
453     if ((transportType & CA_ADAPTER_NFC) || (CA_DEFAULT_ADAPTER == transportType))
454     {
455         CAInitializeNFC(CARegisterCallback, CAReceivedPacketCallback, CAAdapterChangedCallback,
456                         CAAdapterErrorHandleCallback, handle);
457     }
458 #endif /* NFC_ADAPTER */
459
460 #ifndef SINGLE_THREAD
461     CAResult_t res = CA_STATUS_OK;
462
463     // Initialize & Start network-change-callback-thread.
464     res = CAQueueingThreadInitialize(&g_networkChangeCallbackThread, handle,
465                                      CANetworkChangeCallbackThreadProcess,
466                                      CADestroyNetworkChangeCallbackData);
467     if (CA_STATUS_OK != res)
468     {
469         OIC_LOG(ERROR, TAG, "Failed to Initialize callback queue thread");
470         return res;
471     }
472
473     res = CAQueueingThreadStart(&g_networkChangeCallbackThread);
474     if (CA_STATUS_OK != res)
475     {
476         OIC_LOG(ERROR, TAG, "thread start error(callback thread).");
477         return res;
478     }
479 #endif //SINGLE_THREAD
480
481     return CA_STATUS_OK;
482 }
483
484 void CASetPacketReceivedCallback(CANetworkPacketReceivedCallback callback)
485 {
486     OIC_LOG(DEBUG, TAG, "Set Receiver handle callback");
487
488     g_networkPacketReceivedCallback = callback;
489 }
490
491 CAResult_t CASetNetworkMonitorCallbacks(CAAdapterStateChangedCB adapterCB,
492                                         CAConnectionStateChangedCB connCB)
493 {
494     OIC_LOG(DEBUG, TAG, "Set network monitoring callback");
495     CAResult_t res = AddNetworkStateChangedCallback(adapterCB, connCB);
496     if (CA_STATUS_OK != res)
497     {
498         OIC_LOG(ERROR, TAG, "AddNetworkStateChangedCallback has failed");
499         return CA_STATUS_FAILED;
500     }
501     return CA_STATUS_OK;
502 }
503
504 CAResult_t CAUnsetNetworkMonitorCallbacks(CAAdapterStateChangedCB adapterCB,
505         CAConnectionStateChangedCB connCB)
506 {
507     OIC_LOG(DEBUG, TAG, "Unset network monitoring callback");
508     CAResult_t res = RemoveNetworkStateChangedCallback(adapterCB, connCB);
509     if (CA_STATUS_OK != res)
510     {
511         OIC_LOG(ERROR, TAG, "RemoveNetworkStateChangedCallback has failed");
512         return CA_STATUS_FAILED;
513     }
514     return CA_STATUS_OK;
515 }
516
517 void CASetErrorHandleCallback(CAErrorHandleCallback errorCallback)
518 {
519     OIC_LOG(DEBUG, TAG, "Set error handle callback");
520     g_errorHandleCallback = errorCallback;
521 }
522
523 CAResult_t CAStartAdapter(CATransportAdapter_t transportType)
524 {
525     size_t index = 0;
526     CAResult_t res = CA_STATUS_FAILED;
527
528     OIC_LOG_V(DEBUG, TAG, "Start the adapter of CAConnectivityType[%d]", transportType);
529
530     res = CAGetAdapterIndex(transportType, &index);
531     if (CA_STATUS_OK != res)
532     {
533         OIC_LOG(ERROR, TAG, "unknown connectivity type!");
534         return CA_STATUS_FAILED;
535     }
536
537     if (g_adapterHandler[index].startAdapter != NULL)
538     {
539         res = g_adapterHandler[index].startAdapter();
540     }
541
542     return res;
543 }
544
545 void CAStopAdapter(CATransportAdapter_t transportType)
546 {
547     size_t index = 0;
548     CAResult_t res = CA_STATUS_FAILED;
549
550     OIC_LOG_V(DEBUG, TAG, "Stop the adapter of CATransportType[%d]", transportType);
551
552     res = CAGetAdapterIndex(transportType, &index);
553     if (CA_STATUS_OK != res)
554     {
555         OIC_LOG(ERROR, TAG, "unknown transport type!");
556         return;
557     }
558
559     if (g_adapterHandler[index].stopAdapter != NULL)
560     {
561         g_adapterHandler[index].stopAdapter();
562     }
563 }
564
565 #ifndef SINGLE_THREAD
566 void CAStopAdapters()
567 {
568     CATransportAdapter_t connType;
569     u_arraylist_t *list = CAGetSelectedNetworkList();
570     size_t length = u_arraylist_length(list);
571
572     for (size_t i = 0; i < length; i++)
573     {
574         void* ptrType = u_arraylist_get(list, i);
575
576         if (NULL == ptrType)
577         {
578             continue;
579         }
580
581         connType = *(CATransportAdapter_t *)ptrType;
582         CAStopAdapter(connType);
583     }
584
585     CAQueueingThreadStop(&g_networkChangeCallbackThread);
586 }
587 #endif //SINGLE_THREAD
588
589 CAResult_t CAGetNetworkInfo(CAEndpoint_t **info, size_t *size)
590 {
591     VERIFY_NON_NULL(info, TAG, "info is null");
592     VERIFY_NON_NULL(size, TAG, "size is null");
593
594     CAEndpoint_t **tempInfo = (CAEndpoint_t **) OICCalloc(g_numberOfAdapters, sizeof(*tempInfo));
595     if (!tempInfo)
596     {
597         OIC_LOG(ERROR, TAG, "Out of memory!");
598         return CA_MEMORY_ALLOC_FAILED;
599     }
600     size_t *tempSize = (size_t *)OICCalloc(g_numberOfAdapters, sizeof(*tempSize));
601     if (!tempSize)
602     {
603         OIC_LOG(ERROR, TAG, "Out of memory!");
604         OICFree(tempInfo);
605         return CA_MEMORY_ALLOC_FAILED;
606     }
607
608     CAResult_t res = CA_STATUS_FAILED;
609     size_t resSize = 0;
610     for (size_t index = 0; index < g_numberOfAdapters; index++)
611     {
612         if (g_adapterHandler[index].GetnetInfo != NULL)
613         {
614             // #1. get information for each adapter
615             res = g_adapterHandler[index].GetnetInfo(&tempInfo[index],
616                     &tempSize[index]);
617
618             // #2. total size
619             if (res == CA_STATUS_OK)
620             {
621                 resSize += tempSize[index];
622             }
623
624             OIC_LOG_V(DEBUG,
625                       TAG,
626                       "%" PRIuPTR " adapter network info size is %" PRIuPTR " res:%u",
627                       index,
628                       tempSize[index],
629                       res);
630         }
631     }
632
633     OIC_LOG_V(DEBUG, TAG, "network info total size is %" PRIuPTR "!", resSize);
634
635     if (resSize == 0)
636     {
637         OICFree(tempInfo);
638         OICFree(tempSize);
639         return res;
640     }
641
642     // #3. add data into result
643     // memory allocation
644     CAEndpoint_t *resInfo = (CAEndpoint_t *) OICCalloc(resSize, sizeof (*resInfo));
645     CA_MEMORY_ALLOC_CHECK(resInfo);
646
647     // #4. save data
648     *info = resInfo;
649     *size = resSize;
650
651     for (size_t index = 0; index < g_numberOfAdapters; index++)
652     {
653         // check information
654         if (tempSize[index] == 0)
655         {
656             continue;
657         }
658
659         memcpy(resInfo,
660                tempInfo[index],
661                sizeof(*resInfo) * tempSize[index]);
662
663         resInfo += tempSize[index];
664
665         // free adapter data
666         OICFree(tempInfo[index]);
667         tempInfo[index] = NULL;
668     }
669     OICFree(tempInfo);
670     OICFree(tempSize);
671
672     OIC_LOG(DEBUG, TAG, "each network info save success!");
673     return CA_STATUS_OK;
674
675     // memory error label.
676 memory_error_exit:
677
678     for (size_t index = 0; index < g_numberOfAdapters; index++)
679     {
680         OICFree(tempInfo[index]);
681         tempInfo[index] = NULL;
682     }
683     OICFree(tempInfo);
684     OICFree(tempSize);
685
686     return CA_MEMORY_ALLOC_FAILED;
687 }
688
689 CAResult_t CASendUnicastData(const CAEndpoint_t *endpoint, const void *data, uint32_t length,
690                              CADataType_t dataType)
691 {
692     size_t index = 0;
693     CAResult_t res = CA_STATUS_FAILED;
694
695     VERIFY_NON_NULL(endpoint, TAG, "endpoint is null");
696
697     u_arraylist_t *list = CAGetSelectedNetworkList();
698     if (!list)
699     {
700         OIC_LOG(ERROR, TAG, "No selected network");
701         return CA_SEND_FAILED;
702     }
703     CATransportAdapter_t requestedAdapter = endpoint->adapter ? endpoint->adapter : CA_ALL_ADAPTERS;
704
705     for (size_t i = 0; i < u_arraylist_length(list); i++)
706     {
707         void *ptrType = u_arraylist_get(list, i);
708
709         if (NULL == ptrType)
710         {
711             continue;
712         }
713
714         CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType;
715         if (0 == (connType & requestedAdapter))
716         {
717             continue;
718         }
719
720         res = CAGetAdapterIndex(connType, &index);
721         if (CA_STATUS_OK != res)
722         {
723             OIC_LOG(ERROR, TAG, "unknown transport type!");
724             return CA_STATUS_INVALID_PARAM;
725         }
726
727         int32_t sentDataLen = 0;
728
729         if (NULL != g_adapterHandler[index].sendData)
730         {
731             OIC_LOG(DEBUG, TAG, "unicast message to adapter");
732             sentDataLen = g_adapterHandler[index].sendData(endpoint, data, length, dataType);
733         }
734
735         if ((0 > sentDataLen) || ((uint32_t)sentDataLen != length))
736         {
737             OIC_LOG(ERROR, TAG, "Error sending data. The error will be reported in adapter.");
738 #ifdef SINGLE_THREAD
739             //in case of single thread, no error handler. Report error immediately
740             return CA_SEND_FAILED;
741 #endif
742         }
743
744     }
745
746     return CA_STATUS_OK;
747 }
748
749 CAResult_t CASendMulticastData(const CAEndpoint_t *endpoint, const void *data, uint32_t length,
750                                CADataType_t dataType)
751 {
752     size_t index = 0;
753     CAResult_t res = CA_STATUS_FAILED;
754
755     VERIFY_NON_NULL(endpoint, TAG, "endpoint is null");
756
757     u_arraylist_t *list = CAGetSelectedNetworkList();
758     if (!list)
759     {
760         OIC_LOG(DEBUG, TAG, "No selected network");
761         return CA_SEND_FAILED;
762     }
763
764     CATransportAdapter_t requestedAdapter = endpoint->adapter ? endpoint->adapter : CA_ALL_ADAPTERS;
765     size_t selectedLength = u_arraylist_length(list);
766     for (size_t i = 0; i < selectedLength; i++)
767     {
768         void *ptrType = u_arraylist_get(list, i);
769
770         if (NULL == ptrType)
771         {
772             continue;
773         }
774
775         CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType;
776         if (0 == (connType & requestedAdapter))
777         {
778             continue;
779         }
780
781         res = CAGetAdapterIndex(connType, &index);
782         if (CA_STATUS_OK != res)
783         {
784             OIC_LOG(ERROR, TAG, "unknown connectivity type!");
785             continue;
786         }
787
788         uint32_t sentDataLen = 0;
789
790         if (NULL != g_adapterHandler[index].sendDataToAll)
791         {
792             void *payload = (void *) OICMalloc(length);
793             if (!payload)
794             {
795                 OIC_LOG(ERROR, TAG, "Out of memory!");
796                 return CA_MEMORY_ALLOC_FAILED;
797             }
798             memcpy(payload, data, length);
799             sentDataLen = g_adapterHandler[index].sendDataToAll(endpoint, payload, length, dataType);
800             OICFree(payload);
801         }
802
803         if (sentDataLen != length)
804         {
805             OIC_LOG(ERROR, TAG, "sendDataToAll failed! Error will be reported from adapter");
806 #ifdef SINGLE_THREAD
807             //in case of single thread, no error handler. Report error immediately
808             return CA_SEND_FAILED;
809 #endif
810         }
811     }
812
813     return CA_STATUS_OK;
814 }
815
816 CAResult_t CAStartListeningServerAdapters()
817 {
818     size_t index = 0;
819     CAResult_t result = CA_STATUS_FAILED;
820
821     u_arraylist_t *list = CAGetSelectedNetworkList();
822     if (!list)
823     {
824         OIC_LOG(ERROR, TAG, "No selected network");
825         return result;
826     }
827
828     size_t length = u_arraylist_length(list);
829     for (size_t i = 0; i < length; i++)
830     {
831         void *ptrType = u_arraylist_get(list, i);
832
833         if (ptrType == NULL)
834         {
835             continue;
836         }
837
838         CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType;
839
840         if (CA_STATUS_OK != CAGetAdapterIndex(connType, &index))
841         {
842             OIC_LOG(ERROR, TAG, "unknown connectivity type!");
843             continue;
844         }
845
846         if (g_adapterHandler[index].startListenServer != NULL)
847         {
848             const CAResult_t tmp =
849                 g_adapterHandler[index].startListenServer();
850
851             // Successful listen if at least one adapter started.
852             if (CA_STATUS_OK == tmp)
853             {
854                 result = tmp;
855             }
856         }
857     }
858
859     return result;
860 }
861
862 CAResult_t CAStopListeningServerAdapters()
863 {
864     size_t index = 0;
865     CAResult_t res = CA_STATUS_FAILED;
866     u_arraylist_t *list = CAGetSelectedNetworkList();
867     if (!list)
868     {
869         OIC_LOG(ERROR, TAG, "No selected network");
870         return CA_STATUS_FAILED;
871     }
872
873     size_t length = u_arraylist_length(list);
874     for (size_t i = 0; i < length; i++)
875     {
876         void *ptrType = u_arraylist_get(list, i);
877         if (ptrType == NULL)
878         {
879             continue;
880         }
881
882         CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType;
883
884         res = CAGetAdapterIndex(connType, &index);
885         if (CA_STATUS_OK != res)
886         {
887             OIC_LOG(ERROR, TAG, "unknown connectivity type!");
888             continue;
889         }
890
891         if (g_adapterHandler[index].stopListenServer != NULL)
892         {
893             g_adapterHandler[index].stopListenServer();
894         }
895     }
896
897     return CA_STATUS_OK;
898 }
899
900 CAResult_t CAStartDiscoveryServerAdapters()
901 {
902     size_t index = 0;
903     CAResult_t result = CA_STATUS_FAILED;
904
905     u_arraylist_t *list = CAGetSelectedNetworkList();
906
907     if (!list)
908     {
909         OIC_LOG(ERROR, TAG, "No selected network");
910         return result;
911     }
912
913     size_t length = u_arraylist_length(list);
914     for (size_t i = 0; i < length; i++)
915     {
916         void *ptrType = u_arraylist_get(list, i);
917
918         if (ptrType == NULL)
919         {
920             continue;
921         }
922
923         CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType;
924
925         if (CA_STATUS_OK != CAGetAdapterIndex(connType, &index))
926         {
927             OIC_LOG(DEBUG, TAG, "unknown connectivity type!");
928             continue;
929         }
930
931         if (g_adapterHandler[index].startDiscoveryServer != NULL)
932         {
933             const CAResult_t tmp =
934                 g_adapterHandler[index].startDiscoveryServer();
935
936             // Successful discovery if at least one adapter started.
937             if (CA_STATUS_OK == tmp)
938             {
939                 result = tmp;
940             }
941         }
942     }
943
944     return result;
945 }
946
947 bool CAIsLocalEndpoint(const CAEndpoint_t *ep)
948 {
949     VERIFY_NON_NULL_RET(ep, TAG, "ep is null", false);
950
951 #ifdef IP_ADAPTER
952     if (ep->adapter & CA_ADAPTER_IP)
953     {
954         return CAIPIsLocalEndpoint(ep);
955     }
956 #endif /* IP_ADAPTER */
957
958     //TODO: implement for the other adapters(EDR/LE/NFC)
959     return false;
960 }
961
962 void CATerminateAdapters()
963 {
964     for (size_t index = 0; index < g_numberOfAdapters; index++)
965     {
966         if (g_adapterHandler[index].terminate != NULL)
967         {
968             g_adapterHandler[index].terminate();
969         }
970     }
971
972     OICFree(g_adapterHandler);
973     g_adapterHandler = NULL;
974     g_numberOfAdapters = 0;
975
976 #ifndef SINGLE_THREAD
977     CAQueueingThreadDestroy(&g_networkChangeCallbackThread);
978 #endif //SINGLE_THREAD
979
980     RemoveAllNetworkStateChangedCallback();
981 }
982
983 #ifdef SINGLE_THREAD
984 CAResult_t CAReadData()
985 {
986     size_t index = 0;
987     CAResult_t res = CA_STATUS_FAILED;
988     u_arraylist_t *list = CAGetSelectedNetworkList();
989
990     if (!list)
991     {
992         return CA_STATUS_FAILED;
993     }
994
995     size_t i = 0;
996     for (i = 0; i < u_arraylist_length(list); i++)
997     {
998         void *ptrType = u_arraylist_get(list, i);
999         if (NULL == ptrType)
1000         {
1001             OIC_LOG(ERROR, TAG, "get list fail");
1002             return CA_STATUS_FAILED;
1003         }
1004
1005         CATransportAdapter_t connType = *(CATransportAdapter_t *) ptrType;
1006
1007         res = CAGetAdapterIndex(connType, &index);
1008         if (CA_STATUS_OK != res)
1009         {
1010             OIC_LOG(DEBUG, TAG, "unknown connectivity type!");
1011             continue;
1012         }
1013
1014         if (g_adapterHandler[index].readData != NULL)
1015         {
1016             g_adapterHandler[index].readData();
1017         }
1018     }
1019
1020     return CA_STATUS_OK;
1021 }
1022 #endif