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