1 /******************************************************************
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************/
21 #include "caipinterface.h"
25 #include "caadapterutils.h"
28 #include "oic_malloc.h"
29 #include "oic_string.h"
31 #define IP_MONITOR_TAG "IP_MONITOR"
34 * @var g_networkMonitorContextMutex
35 * @brief Mutex for synchronizing access to cached interface and IP address information.
37 static ca_mutex g_networkMonitorContextMutex = NULL;
40 * @struct CAIPNwMonitorContext
41 * @brief Used for storing network monitor context information.
45 u_arraylist_t *netInterfaceList;
46 ca_thread_pool_t threadPool;
47 CANetworkStatus_t nwConnectivityStatus;
48 CAIPConnectionStateChangeCallback networkChangeCb;
49 } CAIPNetworkMonitorContext;
52 * @var g_networkMonitorContext
53 * @brief network monitor context.
55 static CAIPNetworkMonitorContext *g_networkMonitorContext = NULL;
57 static void CARemoveInterfaceInfo()
59 ca_mutex_lock(g_networkMonitorContextMutex);
60 if (!g_networkMonitorContext->netInterfaceList)
62 OIC_LOG(ERROR, IP_MONITOR_TAG,
63 "netInterfaceList is empty");
64 ca_mutex_unlock(g_networkMonitorContextMutex);
68 uint32_t list_index = 0;
69 uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
70 for (list_index = 0; list_index < list_length; list_index++)
72 CANetInfo_t *netInfo = (CANetInfo_t *)u_arraylist_get(
73 g_networkMonitorContext->netInterfaceList, list_index);
79 if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, list_index))
81 if (g_networkMonitorContext->networkChangeCb)
83 g_networkMonitorContext->networkChangeCb(netInfo->ipAddress,
89 OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed");
95 u_arraylist_free(&g_networkMonitorContext->netInterfaceList);
97 ca_mutex_unlock(g_networkMonitorContextMutex);
100 static bool CACheckIsInterfaceInfoChanged(const CANetInfo_t *info)
102 VERIFY_NON_NULL_RET(info, IP_MONITOR_TAG, "info is null", false);
104 ca_mutex_lock(g_networkMonitorContextMutex);
105 uint32_t list_index = 0;
106 uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
107 for (list_index = 0; list_index < list_length; list_index++)
109 CANetInfo_t *netInfo = (CANetInfo_t *)u_arraylist_get(
110 g_networkMonitorContext->netInterfaceList, list_index);
116 if (strncmp(netInfo->interfaceName, info->interfaceName, strlen(info->interfaceName)) == 0)
118 if (strncmp(netInfo->ipAddress, info->ipAddress, strlen(info->ipAddress)) == 0)
120 ca_mutex_unlock(g_networkMonitorContextMutex);
125 OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network interface info changed");
126 if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, list_index))
128 if (g_networkMonitorContext->networkChangeCb)
130 g_networkMonitorContext->networkChangeCb(netInfo->ipAddress,
137 OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed");
144 CANetInfo_t *newNetInfo = (CANetInfo_t *)OICMalloc(sizeof(CANetInfo_t));
147 OIC_LOG(ERROR, IP_MONITOR_TAG, "newNetInfo malloc failed");
148 ca_mutex_unlock(g_networkMonitorContextMutex);
153 OIC_LOG(DEBUG, IP_MONITOR_TAG, "New Interface found");
155 CAResult_t result = u_arraylist_add(g_networkMonitorContext->netInterfaceList,
157 if (CA_STATUS_OK != result)
159 OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
161 ca_mutex_unlock(g_networkMonitorContextMutex);
164 ca_mutex_unlock(g_networkMonitorContextMutex);
166 /*Callback will be unset only at the time of termination. By that time, all the threads will be
167 stopped gracefully. This callback is properly protected*/
168 if (g_networkMonitorContext->networkChangeCb)
170 g_networkMonitorContext->networkChangeCb(newNetInfo->ipAddress, CA_INTERFACE_UP);
176 void CAWiFiGetInterfaceInformation(char **interfaceName, char **ipAddress, char **subnetMask)
178 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
180 int ret = WIFI_ERROR_NONE;
182 if (!interfaceName || !ipAddress || !subnetMask)
184 OIC_LOG(ERROR, IP_MONITOR_TAG, "Invalid input: interface/ipaddress holder is NULL!");
188 // Get wifi interface name
189 if (WIFI_ERROR_NONE != (ret = wifi_get_network_interface_name(interfaceName)))
191 OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get interface name! error num [%d]", ret);
195 // Get wifi connected IP address
196 wifi_ap_h accessPoint = NULL;
197 if (WIFI_ERROR_NONE != (ret = wifi_get_connected_ap(&accessPoint)))
199 OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get access point! error num [%d]",
202 OICFree(*interfaceName);
203 *interfaceName = NULL;
207 if (WIFI_ERROR_NONE != (ret = wifi_ap_get_ip_address(accessPoint, WIFI_ADDRESS_FAMILY_IPV4,
210 OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get interface address! error num [%d]",
212 OICFree(*interfaceName);
213 *interfaceName = NULL;
217 if (WIFI_ERROR_NONE != (ret = wifi_ap_get_subnet_mask(accessPoint, WIFI_ADDRESS_FAMILY_IPV4,
220 OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get interface address! error num [%d]",
223 OICFree(*interfaceName);
225 *interfaceName = NULL;
229 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
232 static void CAIPGetInterfaceInformation(u_arraylist_t **netInterfaceList)
234 VERIFY_NON_NULL_VOID(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null");
236 // Get wifi network information
237 char *interfaceName = NULL;
238 char *ipAddress = NULL;
239 char *subnetMask = NULL;
240 ///TODO: currently we are filling single interface. Once found the proper tizen apis for
241 // getting multiple interfaces, then this function will be updated.
242 CAWiFiGetInterfaceInformation(&interfaceName, &ipAddress, &subnetMask);
244 if (!interfaceName || !ipAddress || !subnetMask)
246 OIC_LOG(ERROR, IP_MONITOR_TAG, "interface/ipaddress/subnetmask is NULL!");
250 CANetInfo_t *netInfo = (CANetInfo_t *)OICCalloc(1, sizeof(CANetInfo_t));
253 OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed");
254 OICFree(interfaceName);
260 // set interface name
261 OICStrcpy(netInfo->interfaceName, sizeof(netInfo->interfaceName), interfaceName);
263 // set local ip address
264 OICStrcpy(netInfo->ipAddress, sizeof(netInfo->ipAddress), ipAddress);
267 OICStrcpy(netInfo->subnetMask, sizeof(netInfo->subnetMask), subnetMask);
269 CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)netInfo);
270 if (CA_STATUS_OK != result)
272 OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
274 OICFree(interfaceName);
280 void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap,
283 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
285 if (WIFI_CONNECTION_STATE_ASSOCIATION == state
286 || WIFI_CONNECTION_STATE_CONFIGURATION == state)
288 OIC_LOG(DEBUG, IP_MONITOR_TAG, "Connection is in Association State");
292 // If Wifi is connected, then get the latest IP from the WIFI Interface
293 if (WIFI_CONNECTION_STATE_CONNECTED == state)
295 // Get network information
296 char *interfaceName = NULL;
297 char *ipAddress = NULL;
298 char *subnetMask = NULL;
299 CAWiFiGetInterfaceInformation(&interfaceName, &ipAddress, &subnetMask);
301 CANetInfo_t *netInfo = (CANetInfo_t *)OICCalloc(1, sizeof(CANetInfo_t));
304 OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed");
305 OICFree(interfaceName);
311 // set interface name
312 OICStrcpy(netInfo->interfaceName, sizeof(netInfo->interfaceName), interfaceName);
314 // set local ip address
315 OICStrcpy(netInfo->ipAddress, sizeof(netInfo->ipAddress), ipAddress);
318 OICStrcpy(netInfo->subnetMask, sizeof(netInfo->subnetMask), subnetMask);
320 bool ret = CACheckIsInterfaceInfoChanged(netInfo);
323 OIC_LOG(DEBUG, IP_MONITOR_TAG, "CACheckIsInterfaceInfoChanged true");
327 OICFree(interfaceName);
333 CARemoveInterfaceInfo();
336 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
339 void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData)
341 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
343 if (WIFI_DEVICE_STATE_ACTIVATED == state)
345 OIC_LOG(DEBUG, IP_MONITOR_TAG, "Wifi is in Activated State");
349 CAWIFIConnectionStateChangedCb(WIFI_CONNECTION_STATE_DISCONNECTED, NULL, NULL);
350 OIC_LOG(DEBUG, IP_MONITOR_TAG, "Wifi is in Deactivated State");
353 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
356 static CAResult_t CAInitializeNetworkMonitorMutexes()
358 if (!g_networkMonitorContextMutex)
360 g_networkMonitorContextMutex = ca_mutex_new();
361 if (!g_networkMonitorContextMutex)
363 OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContextMutex Malloc failed");
364 return CA_MEMORY_ALLOC_FAILED;
371 static void CADestroyNetworkMonitorMutexes()
373 ca_mutex_free(g_networkMonitorContextMutex);
374 g_networkMonitorContextMutex = NULL;
377 CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool)
379 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
381 VERIFY_NON_NULL(threadPool, IP_MONITOR_TAG, "threadPool is null");
383 CAResult_t ret = CAInitializeNetworkMonitorMutexes();
385 if (CA_STATUS_OK != ret)
387 OIC_LOG(ERROR, IP_MONITOR_TAG, "CAInitializeNetworkMonitorMutexes failed");
388 return CA_STATUS_FAILED;
390 ca_mutex_lock(g_networkMonitorContextMutex);
392 // Initialize Wifi service
393 wifi_error_e retValue = wifi_initialize();
394 if (WIFI_ERROR_NONE != retValue)
396 OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_initialize failed");
397 return CA_STATUS_FAILED;
400 g_networkMonitorContext = (CAIPNetworkMonitorContext *)OICCalloc(1,
401 sizeof(*g_networkMonitorContext));
402 if (!g_networkMonitorContext)
404 OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext Malloc failed");
405 ca_mutex_unlock(g_networkMonitorContextMutex);
406 CADestroyNetworkMonitorMutexes();
407 return CA_MEMORY_ALLOC_FAILED;
410 g_networkMonitorContext->netInterfaceList = u_arraylist_create();
411 if (!g_networkMonitorContext->netInterfaceList)
413 OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_create failed");
414 OICFree(g_networkMonitorContext);
415 ca_mutex_unlock(g_networkMonitorContextMutex);
416 CADestroyNetworkMonitorMutexes();
417 return CA_MEMORY_ALLOC_FAILED;
420 CAIPGetInterfaceInformation(&g_networkMonitorContext->netInterfaceList);
422 ca_mutex_unlock(g_networkMonitorContextMutex);
424 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
428 void CAIPTerminateNetworkMonitor()
430 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
432 ca_mutex_lock(g_networkMonitorContextMutex);
434 // Deinitialize Wifi service
435 wifi_error_e ret = wifi_deinitialize();
436 if (WIFI_ERROR_NONE != ret)
438 OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_deinitialize failed");
441 CAClearNetInterfaceInfoList(g_networkMonitorContext->netInterfaceList);
443 g_networkMonitorContext->netInterfaceList = NULL;
444 g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN;
445 g_networkMonitorContext->networkChangeCb = NULL;
447 OICFree(g_networkMonitorContext);
448 g_networkMonitorContext = NULL;
450 ca_mutex_unlock(g_networkMonitorContextMutex);
452 CADestroyNetworkMonitorMutexes();
454 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
457 CAResult_t CAIPStartNetworkMonitor()
459 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
461 // Set callback for receiving state changes
462 wifi_error_e ret = wifi_set_device_state_changed_cb(CAWIFIDeviceStateChangedCb, NULL);
463 if (WIFI_ERROR_NONE != ret)
465 OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_set_device_state_changed_cb failed");
466 return CA_STATUS_FAILED;
469 // Set callback for receiving connection state changes
470 ret = wifi_set_connection_state_changed_cb(CAWIFIConnectionStateChangedCb, NULL);
471 if (WIFI_ERROR_NONE != ret)
473 OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_set_connection_state_changed_cb failed");
474 return CA_STATUS_FAILED;
477 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
481 CAResult_t CAIPStopNetworkMonitor()
483 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
485 // Reset callback for receiving state changes
486 wifi_error_e ret = wifi_unset_device_state_changed_cb();
487 if (WIFI_ERROR_NONE != ret)
489 OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_unset_device_state_changed_cb failed");
492 // Reset callback for receiving connection state changes
493 ret = wifi_unset_connection_state_changed_cb();
494 if (WIFI_ERROR_NONE != ret)
496 OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_unset_connection_state_changed_cb failed");
499 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
503 CAResult_t CAIPGetInterfaceInfo(u_arraylist_t **netInterfaceList)
505 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
507 VERIFY_NON_NULL(netInterfaceList, IP_MONITOR_TAG, "u_array_list is null");
508 VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG,
509 "g_networkMonitorContext is null");
510 VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG,
511 "g_networkMonitorContextMutex is null");
513 // Get the interface and ipaddress information from cache
514 ca_mutex_lock(g_networkMonitorContextMutex);
515 if (!g_networkMonitorContext->netInterfaceList
516 || !(u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
518 OIC_LOG(ERROR, IP_MONITOR_TAG, "Network not enabled");
519 ca_mutex_unlock(g_networkMonitorContextMutex);
520 return CA_ADAPTER_NOT_ENABLED;
523 uint32_t list_index = 0;
524 uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
525 OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo list length [%d]",
527 for (list_index = 0; list_index < list_length; list_index++)
529 CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(
530 g_networkMonitorContext->netInterfaceList, list_index);
535 OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo ip [%s]",
537 CANetInfo_t *newNetinfo = (CANetInfo_t *) OICMalloc(sizeof(CANetInfo_t));
540 OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed!");
541 ca_mutex_unlock(g_networkMonitorContextMutex);
542 return CA_MEMORY_ALLOC_FAILED;
547 CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)newNetinfo);
548 if (CA_STATUS_OK != result)
550 OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
551 ca_mutex_unlock(g_networkMonitorContextMutex);
552 return CA_STATUS_FAILED;
556 ca_mutex_unlock(g_networkMonitorContextMutex);
558 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
562 CAResult_t CAIPGetInterfaceSubnetMask(const char *ipAddress, char **subnetMask)
564 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
566 VERIFY_NON_NULL(subnetMask, IP_MONITOR_TAG, "subnet mask");
567 VERIFY_NON_NULL(ipAddress, IP_MONITOR_TAG, "ipAddress is null");
568 VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG,
569 "g_networkMonitorContext is null");
570 VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG,
571 "g_networkMonitorContextMutex is null");
573 // Get the interface and ipaddress information from cache
574 ca_mutex_lock(g_networkMonitorContextMutex);
575 if (!g_networkMonitorContext->netInterfaceList
576 || !(u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
578 OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network not enabled");
579 ca_mutex_unlock(g_networkMonitorContextMutex);
580 return CA_ADAPTER_NOT_ENABLED;
583 uint32_t list_index = 0;
584 uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
585 OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "list lenght [%d]", list_length);
586 for (list_index = 0; list_index < list_length; list_index++)
588 CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(
589 g_networkMonitorContext->netInterfaceList, list_index);
595 if (strncmp(info->ipAddress, ipAddress, strlen(ipAddress)) == 0)
597 OIC_LOG_V(DEBUG, IP_MONITOR_TAG,
598 "CAIPGetInterfaceSubnetMask subnetmask is %s", info->subnetMask);
599 *subnetMask = OICStrdup(info->subnetMask);
603 ca_mutex_unlock(g_networkMonitorContextMutex);
605 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
609 bool CAIPIsConnected()
611 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
613 wifi_connection_state_e connection_state;
614 wifi_error_e ret = wifi_get_connection_state(&connection_state);
615 if (WIFI_ERROR_NONE != ret)
617 OIC_LOG(ERROR, IP_MONITOR_TAG, "Failed to get the Connection State");
621 if (WIFI_CONNECTION_STATE_DISCONNECTED == connection_state)
623 OIC_LOG(DEBUG, IP_MONITOR_TAG, "WIFI is not Connected");
627 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
631 void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback)
633 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
634 if (!g_networkMonitorContextMutex || !g_networkMonitorContext)
636 OIC_LOG(ERROR, IP_MONITOR_TAG, "CAIPSetConnectionStateChangeCallback failed");
639 ca_mutex_lock(g_networkMonitorContextMutex);
641 g_networkMonitorContext->networkChangeCb = callback;
643 ca_mutex_unlock(g_networkMonitorContextMutex);
645 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");