261732db241f0e80a6edfcf36a453e377cd056dc
[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 "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     {
414         CAInitializeIP(CARegisterCallback, CAReceivedPacketCallback, CAAdapterChangedCallback,
415                        CAAdapterErrorHandleCallback, handle);
416     }
417 #endif /* IP_ADAPTER */
418
419 #ifdef EDR_ADAPTER
420     if ((transportType & CA_ADAPTER_RFCOMM_BTEDR) || (CA_DEFAULT_ADAPTER == transportType))
421     {
422         CAInitializeEDR(CARegisterCallback, CAReceivedPacketCallback, CAAdapterChangedCallback,
423                         CAConnectionChangedCallback, CAAdapterErrorHandleCallback, handle);
424     }
425 #endif /* EDR_ADAPTER */
426
427 #ifdef LE_ADAPTER
428     if ((transportType & CA_ADAPTER_GATT_BTLE) || (CA_DEFAULT_ADAPTER == transportType))
429     {
430         CAInitializeLE(CARegisterCallback, CAReceivedPacketCallback, CAAdapterChangedCallback,
431                        CAConnectionChangedCallback, CAAdapterErrorHandleCallback, handle);
432     }
433 #endif /* LE_ADAPTER */
434
435 #ifdef RA_ADAPTER
436     if ((transportType & CA_ADAPTER_REMOTE_ACCESS) || (CA_DEFAULT_ADAPTER == transportType))
437     {
438         CAInitializeRA(CARegisterCallback, CAReceivedPacketCallback, CAAdapterChangedCallback,
439                        handle);
440     }
441 #endif /* RA_ADAPTER */
442
443 #ifdef TCP_ADAPTER
444     if ((transportType & CA_ADAPTER_TCP) || (CA_DEFAULT_ADAPTER == transportType))
445     {
446         CAInitializeTCP(CARegisterCallback, CAReceivedPacketCallback, CAAdapterChangedCallback,
447                         CAConnectionChangedCallback, CAAdapterErrorHandleCallback, handle);
448     }
449 #endif /* TCP_ADAPTER */
450
451 #ifdef NFC_ADAPTER
452     if ((transportType & CA_ADAPTER_NFC) || (CA_DEFAULT_ADAPTER == transportType))
453     {
454         CAInitializeNFC(CARegisterCallback, CAReceivedPacketCallback, CAAdapterChangedCallback,
455                         CAAdapterErrorHandleCallback, handle);
456     }
457 #endif /* NFC_ADAPTER */
458
459 #ifndef SINGLE_THREAD
460     CAResult_t res = CA_STATUS_OK;
461
462     // Initialize & Start network-change-callback-thread.
463     res = CAQueueingThreadInitialize(&g_networkChangeCallbackThread, handle,
464                                      CANetworkChangeCallbackThreadProcess,
465                                      CADestroyNetworkChangeCallbackData);
466     if (CA_STATUS_OK != res)
467     {
468         OIC_LOG(ERROR, TAG, "Failed to Initialize callback queue thread");
469         return res;
470     }
471
472     res = CAQueueingThreadStart(&g_networkChangeCallbackThread);
473     if (CA_STATUS_OK != res)
474     {
475         OIC_LOG(ERROR, TAG, "thread start error(callback thread).");
476         return res;
477     }
478 #endif //SINGLE_THREAD
479
480     return CA_STATUS_OK;
481 }
482
483 void CASetPacketReceivedCallback(CANetworkPacketReceivedCallback callback)
484 {
485     OIC_LOG(DEBUG, TAG, "Set Receiver handle callback");
486
487     g_networkPacketReceivedCallback = callback;
488 }
489
490 CAResult_t CASetNetworkMonitorCallbacks(CAAdapterStateChangedCB adapterCB,
491                                         CAConnectionStateChangedCB connCB)
492 {
493     OIC_LOG(DEBUG, TAG, "Set network monitoring callback");
494     CAResult_t res = AddNetworkStateChangedCallback(adapterCB, connCB);
495     if (CA_STATUS_OK != res)
496     {
497         OIC_LOG(ERROR, TAG, "AddNetworkStateChangedCallback has failed");
498         return CA_STATUS_FAILED;
499     }
500     return CA_STATUS_OK;
501 }
502
503 CAResult_t CAUnsetNetworkMonitorCallbacks(CAAdapterStateChangedCB adapterCB,
504         CAConnectionStateChangedCB connCB)
505 {
506     OIC_LOG(DEBUG, TAG, "Unset network monitoring callback");
507     CAResult_t res = RemoveNetworkStateChangedCallback(adapterCB, connCB);
508     if (CA_STATUS_OK != res)
509     {
510         OIC_LOG(ERROR, TAG, "RemoveNetworkStateChangedCallback has failed");
511         return CA_STATUS_FAILED;
512     }
513     return CA_STATUS_OK;
514 }
515
516 void CASetErrorHandleCallback(CAErrorHandleCallback errorCallback)
517 {
518     OIC_LOG(DEBUG, TAG, "Set error handle callback");
519     g_errorHandleCallback = errorCallback;
520 }
521
522 CAResult_t CAStartAdapter(CATransportAdapter_t transportType)
523 {
524     size_t index = 0;
525     CAResult_t res = CA_STATUS_FAILED;
526
527     OIC_LOG_V(DEBUG, TAG, "Start the adapter of CAConnectivityType[%d]", transportType);
528
529     res = CAGetAdapterIndex(transportType, &index);
530     if (CA_STATUS_OK != res)
531     {
532         OIC_LOG(ERROR, TAG, "unknown connectivity type!");
533         return CA_STATUS_FAILED;
534     }
535
536     if (g_adapterHandler[index].startAdapter != NULL)
537     {
538         res = g_adapterHandler[index].startAdapter();
539     }
540
541     return res;
542 }
543
544 void CAStopAdapter(CATransportAdapter_t transportType)
545 {
546     size_t index = 0;
547     CAResult_t res = CA_STATUS_FAILED;
548
549     OIC_LOG_V(DEBUG, TAG, "Stop the adapter of CATransportType[%d]", transportType);
550
551     res = CAGetAdapterIndex(transportType, &index);
552     if (CA_STATUS_OK != res)
553     {
554         OIC_LOG(ERROR, TAG, "unknown transport type!");
555         return;
556     }
557
558     if (g_adapterHandler[index].stopAdapter != NULL)
559     {
560         g_adapterHandler[index].stopAdapter();
561     }
562 }
563
564 #ifndef SINGLE_THREAD
565 void CAStopAdapters()
566 {
567     CATransportAdapter_t connType;
568     u_arraylist_t *list = CAGetSelectedNetworkList();
569     size_t length = u_arraylist_length(list);
570
571     for (size_t i = 0; i < length; i++)
572     {
573         void* ptrType = u_arraylist_get(list, i);
574
575         if (NULL == ptrType)
576         {
577             continue;
578         }
579
580         connType = *(CATransportAdapter_t *)ptrType;
581         CAStopAdapter(connType);
582     }
583
584     CAQueueingThreadStop(&g_networkChangeCallbackThread);
585 }
586 #endif //SINGLE_THREAD
587
588 CAResult_t CAGetNetworkInfo(CAEndpoint_t **info, size_t *size)
589 {
590     VERIFY_NON_NULL(info, TAG, "info is null");
591     VERIFY_NON_NULL(size, TAG, "size is null");
592
593     CAEndpoint_t **tempInfo = (CAEndpoint_t **) OICCalloc(g_numberOfAdapters, sizeof(*tempInfo));
594     if (!tempInfo)
595     {
596         OIC_LOG(ERROR, TAG, "Out of memory!");
597         return CA_MEMORY_ALLOC_FAILED;
598     }
599     size_t *tempSize = (size_t *)OICCalloc(g_numberOfAdapters, sizeof(*tempSize));
600     if (!tempSize)
601     {
602         OIC_LOG(ERROR, TAG, "Out of memory!");
603         OICFree(tempInfo);
604         return CA_MEMORY_ALLOC_FAILED;
605     }
606
607     CAResult_t res = CA_STATUS_FAILED;
608     size_t resSize = 0;
609     for (size_t index = 0; index < g_numberOfAdapters; index++)
610     {
611         if (g_adapterHandler[index].GetnetInfo != NULL)
612         {
613             // #1. get information for each adapter
614             res = g_adapterHandler[index].GetnetInfo(&tempInfo[index],
615                     &tempSize[index]);
616
617             // #2. total size
618             if (res == CA_STATUS_OK)
619             {
620                 resSize += tempSize[index];
621             }
622
623             OIC_LOG_V(DEBUG,
624                       TAG,
625                       "%" PRIu32 " adapter network info size is %" PRIu32 " res:%d",
626                       index,
627                       tempSize[index],
628                       res);
629         }
630     }
631
632     OIC_LOG_V(DEBUG, TAG, "network info total size is %" PRIuPTR "!", resSize);
633
634     if (resSize == 0)
635     {
636         OICFree(tempInfo);
637         OICFree(tempSize);
638         return res;
639     }
640
641     // #3. add data into result
642     // memory allocation
643     CAEndpoint_t *resInfo = (CAEndpoint_t *) OICCalloc(resSize, sizeof (*resInfo));
644     CA_MEMORY_ALLOC_CHECK(resInfo);
645
646     // #4. save data
647     *info = resInfo;
648     *size = resSize;
649
650     for (size_t index = 0; index < g_numberOfAdapters; index++)
651     {
652         // check information
653         if (tempSize[index] == 0)
654         {
655             continue;
656         }
657
658         memcpy(resInfo,
659                tempInfo[index],
660                sizeof(*resInfo) * tempSize[index]);
661
662         resInfo += tempSize[index];
663
664         // free adapter data
665         OICFree(tempInfo[index]);
666         tempInfo[index] = NULL;
667     }
668     OICFree(tempInfo);
669     OICFree(tempSize);
670
671     OIC_LOG(DEBUG, TAG, "each network info save success!");
672     return CA_STATUS_OK;
673
674     // memory error label.
675 memory_error_exit:
676
677     for (size_t index = 0; index < g_numberOfAdapters; index++)
678     {
679         OICFree(tempInfo[index]);
680         tempInfo[index] = NULL;
681     }
682     OICFree(tempInfo);
683     OICFree(tempSize);
684
685     return CA_MEMORY_ALLOC_FAILED;
686 }
687
688 CAResult_t CASendUnicastData(const CAEndpoint_t *endpoint, const void *data, uint32_t length,
689                              CADataType_t dataType)
690 {
691     size_t index = 0;
692     CAResult_t res = CA_STATUS_FAILED;
693
694     VERIFY_NON_NULL(endpoint, TAG, "endpoint is null");
695
696     u_arraylist_t *list = CAGetSelectedNetworkList();
697     if (!list)
698     {
699         OIC_LOG(ERROR, TAG, "No selected network");
700         return CA_SEND_FAILED;
701     }
702     CATransportAdapter_t requestedAdapter = endpoint->adapter ? endpoint->adapter : CA_ALL_ADAPTERS;
703
704     for (size_t i = 0; i < u_arraylist_length(list); i++)
705     {
706         void *ptrType = u_arraylist_get(list, i);
707
708         if (NULL == ptrType)
709         {
710             continue;
711         }
712
713         CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType;
714         if (0 == (connType & requestedAdapter))
715         {
716             continue;
717         }
718
719         res = CAGetAdapterIndex(connType, &index);
720         if (CA_STATUS_OK != res)
721         {
722             OIC_LOG(ERROR, TAG, "unknown transport type!");
723             return CA_STATUS_INVALID_PARAM;
724         }
725
726         int32_t sentDataLen = 0;
727
728         if (NULL != g_adapterHandler[index].sendData)
729         {
730             OIC_LOG(DEBUG, TAG, "unicast message to adapter");
731             sentDataLen = g_adapterHandler[index].sendData(endpoint, data, length, dataType);
732         }
733
734         if ((0 > sentDataLen) || ((uint32_t)sentDataLen != length))
735         {
736             OIC_LOG(ERROR, TAG, "Error sending data. The error will be reported in adapter.");
737 #ifdef SINGLE_THREAD
738             //in case of single thread, no error handler. Report error immediately
739             return CA_SEND_FAILED;
740 #endif
741         }
742
743     }
744
745     return CA_STATUS_OK;
746 }
747
748 CAResult_t CASendMulticastData(const CAEndpoint_t *endpoint, const void *data, uint32_t length,
749                                CADataType_t dataType)
750 {
751     size_t index = 0;
752     CAResult_t res = CA_STATUS_FAILED;
753
754     VERIFY_NON_NULL(endpoint, TAG, "endpoint is null");
755
756     u_arraylist_t *list = CAGetSelectedNetworkList();
757     if (!list)
758     {
759         OIC_LOG(DEBUG, TAG, "No selected network");
760         return CA_SEND_FAILED;
761     }
762
763     CATransportAdapter_t requestedAdapter = endpoint->adapter ? endpoint->adapter : CA_ALL_ADAPTERS;
764     size_t selectedLength = u_arraylist_length(list);
765     for (size_t i = 0; i < selectedLength; i++)
766     {
767         void *ptrType = u_arraylist_get(list, i);
768
769         if (NULL == ptrType)
770         {
771             continue;
772         }
773
774         CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType;
775         if (0 == (connType & requestedAdapter))
776         {
777             continue;
778         }
779
780         res = CAGetAdapterIndex(connType, &index);
781         if (CA_STATUS_OK != res)
782         {
783             OIC_LOG(ERROR, TAG, "unknown connectivity type!");
784             continue;
785         }
786
787         uint32_t sentDataLen = 0;
788
789         if (NULL != g_adapterHandler[index].sendDataToAll)
790         {
791             void *payload = (void *) OICMalloc(length);
792             if (!payload)
793             {
794                 OIC_LOG(ERROR, TAG, "Out of memory!");
795                 return CA_MEMORY_ALLOC_FAILED;
796             }
797             memcpy(payload, data, length);
798             sentDataLen = g_adapterHandler[index].sendDataToAll(endpoint, payload, length, dataType);
799             OICFree(payload);
800         }
801
802         if (sentDataLen != length)
803         {
804             OIC_LOG(ERROR, TAG, "sendDataToAll failed! Error will be reported from adapter");
805 #ifdef SINGLE_THREAD
806             //in case of single thread, no error handler. Report error immediately
807             return CA_SEND_FAILED;
808 #endif
809         }
810     }
811
812     return CA_STATUS_OK;
813 }
814
815 CAResult_t CAStartListeningServerAdapters()
816 {
817     size_t index = 0;
818     CAResult_t result = CA_STATUS_FAILED;
819
820     u_arraylist_t *list = CAGetSelectedNetworkList();
821     if (!list)
822     {
823         OIC_LOG(ERROR, TAG, "No selected network");
824         return result;
825     }
826
827     size_t length = u_arraylist_length(list);
828     for (size_t i = 0; i < length; i++)
829     {
830         void *ptrType = u_arraylist_get(list, i);
831
832         if (ptrType == NULL)
833         {
834             continue;
835         }
836
837         CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType;
838
839         if (CA_STATUS_OK != CAGetAdapterIndex(connType, &index))
840         {
841             OIC_LOG(ERROR, TAG, "unknown connectivity type!");
842             continue;
843         }
844
845         if (g_adapterHandler[index].startListenServer != NULL)
846         {
847             const CAResult_t tmp =
848                 g_adapterHandler[index].startListenServer();
849
850             // Successful listen if at least one adapter started.
851             if (CA_STATUS_OK == tmp)
852             {
853                 result = tmp;
854             }
855         }
856     }
857
858     return result;
859 }
860
861 CAResult_t CAStopListeningServerAdapters()
862 {
863     size_t index = 0;
864     CAResult_t res = CA_STATUS_FAILED;
865     u_arraylist_t *list = CAGetSelectedNetworkList();
866     if (!list)
867     {
868         OIC_LOG(ERROR, TAG, "No selected network");
869         return CA_STATUS_FAILED;
870     }
871
872     size_t length = u_arraylist_length(list);
873     for (size_t i = 0; i < length; i++)
874     {
875         void *ptrType = u_arraylist_get(list, i);
876         if (ptrType == NULL)
877         {
878             continue;
879         }
880
881         CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType;
882
883         res = CAGetAdapterIndex(connType, &index);
884         if (CA_STATUS_OK != res)
885         {
886             OIC_LOG(ERROR, TAG, "unknown connectivity type!");
887             continue;
888         }
889
890         if (g_adapterHandler[index].stopListenServer != NULL)
891         {
892             g_adapterHandler[index].stopListenServer();
893         }
894     }
895
896     return CA_STATUS_OK;
897 }
898
899 CAResult_t CAStartDiscoveryServerAdapters()
900 {
901     size_t index = 0;
902     CAResult_t result = CA_STATUS_FAILED;
903
904     u_arraylist_t *list = CAGetSelectedNetworkList();
905
906     if (!list)
907     {
908         OIC_LOG(ERROR, TAG, "No selected network");
909         return result;
910     }
911
912     size_t length = u_arraylist_length(list);
913     for (size_t i = 0; i < length; i++)
914     {
915         void *ptrType = u_arraylist_get(list, i);
916
917         if (ptrType == NULL)
918         {
919             continue;
920         }
921
922         CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType;
923
924         if (CA_STATUS_OK != CAGetAdapterIndex(connType, &index))
925         {
926             OIC_LOG(DEBUG, TAG, "unknown connectivity type!");
927             continue;
928         }
929
930         if (g_adapterHandler[index].startDiscoveryServer != NULL)
931         {
932             const CAResult_t tmp =
933                 g_adapterHandler[index].startDiscoveryServer();
934
935             // Successful discovery if at least one adapter started.
936             if (CA_STATUS_OK == tmp)
937             {
938                 result = tmp;
939             }
940         }
941     }
942
943     return result;
944 }
945
946 bool CAIsLocalEndpoint(const CAEndpoint_t *ep)
947 {
948     VERIFY_NON_NULL_RET(ep, TAG, "ep is null", false);
949
950 #ifdef IP_ADAPTER
951     if (ep->adapter & CA_ADAPTER_IP)
952     {
953         return CAIPIsLocalEndpoint(ep);
954     }
955 #endif /* IP_ADAPTER */
956
957     //TODO: implement for the other adapters(EDR/LE/NFC)
958     return false;
959 }
960
961 void CATerminateAdapters()
962 {
963     for (size_t index = 0; index < g_numberOfAdapters; index++)
964     {
965         if (g_adapterHandler[index].terminate != NULL)
966         {
967             g_adapterHandler[index].terminate();
968         }
969     }
970
971     OICFree(g_adapterHandler);
972     g_adapterHandler = NULL;
973     g_numberOfAdapters = 0;
974
975 #ifndef SINGLE_THREAD
976     CAQueueingThreadDestroy(&g_networkChangeCallbackThread);
977 #endif //SINGLE_THREAD
978
979     RemoveAllNetworkStateChangedCallback();
980 }
981
982 #ifdef SINGLE_THREAD
983 CAResult_t CAReadData()
984 {
985     size_t index = 0;
986     CAResult_t res = CA_STATUS_FAILED;
987     u_arraylist_t *list = CAGetSelectedNetworkList();
988
989     if (!list)
990     {
991         return CA_STATUS_FAILED;
992     }
993
994     size_t i = 0;
995     for (i = 0; i < u_arraylist_length(list); i++)
996     {
997         void *ptrType = u_arraylist_get(list, i);
998         if (NULL == ptrType)
999         {
1000             OIC_LOG(ERROR, TAG, "get list fail");
1001             return CA_STATUS_FAILED;
1002         }
1003
1004         CATransportAdapter_t connType = *(CATransportAdapter_t *) ptrType;
1005
1006         res = CAGetAdapterIndex(connType, &index);
1007         if (CA_STATUS_OK != res)
1008         {
1009             OIC_LOG(DEBUG, TAG, "unknown connectivity type!");
1010             continue;
1011         }
1012
1013         if (g_adapterHandler[index].readData != NULL)
1014         {
1015             g_adapterHandler[index].readData();
1016         }
1017     }
1018
1019     return CA_STATUS_OK;
1020 }
1021 #endif
1022