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");
326 OICFree(interfaceName);
332 CARemoveInterfaceInfo();
335 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
338 void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData)
340 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
342 if (WIFI_DEVICE_STATE_ACTIVATED == state)
344 OIC_LOG(DEBUG, IP_MONITOR_TAG, "Wifi is in Activated State");
348 CAWIFIConnectionStateChangedCb(WIFI_CONNECTION_STATE_DISCONNECTED, NULL, NULL);
349 OIC_LOG(DEBUG, IP_MONITOR_TAG, "Wifi is in Deactivated State");
352 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
355 static CAResult_t CAInitializeNetworkMonitorMutexes()
357 if (!g_networkMonitorContextMutex)
359 g_networkMonitorContextMutex = ca_mutex_new();
360 if (!g_networkMonitorContextMutex)
362 OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContextMutex Malloc failed");
363 return CA_MEMORY_ALLOC_FAILED;
370 static void CADestroyNetworkMonitorMutexes()
372 ca_mutex_free(g_networkMonitorContextMutex);
373 g_networkMonitorContextMutex = NULL;
376 CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool)
378 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
380 VERIFY_NON_NULL(threadPool, IP_MONITOR_TAG, "threadPool is null");
382 CAResult_t ret = CAInitializeNetworkMonitorMutexes();
384 if (CA_STATUS_OK != ret)
386 OIC_LOG(ERROR, IP_MONITOR_TAG, "CAInitializeNetworkMonitorMutexes failed");
387 return CA_STATUS_FAILED;
389 ca_mutex_lock(g_networkMonitorContextMutex);
391 // Initialize Wifi service
392 wifi_error_e retValue = wifi_initialize();
393 if (WIFI_ERROR_NONE != retValue)
395 OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_initialize failed");
396 return CA_STATUS_FAILED;
399 g_networkMonitorContext = (CAIPNetworkMonitorContext *)OICCalloc(1,
400 sizeof(*g_networkMonitorContext));
401 if (!g_networkMonitorContext)
403 OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext Malloc failed");
404 ca_mutex_unlock(g_networkMonitorContextMutex);
405 CADestroyNetworkMonitorMutexes();
406 return CA_MEMORY_ALLOC_FAILED;
409 g_networkMonitorContext->netInterfaceList = u_arraylist_create();
410 if (!g_networkMonitorContext->netInterfaceList)
412 OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_create failed");
413 OICFree(g_networkMonitorContext);
414 ca_mutex_unlock(g_networkMonitorContextMutex);
415 CADestroyNetworkMonitorMutexes();
416 return CA_MEMORY_ALLOC_FAILED;
419 CAIPGetInterfaceInformation(&g_networkMonitorContext->netInterfaceList);
421 ca_mutex_unlock(g_networkMonitorContextMutex);
423 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
427 void CAIPTerminateNetworkMonitor()
429 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
431 ca_mutex_lock(g_networkMonitorContextMutex);
433 // Deinitialize Wifi service
434 wifi_error_e ret = wifi_deinitialize();
435 if (WIFI_ERROR_NONE != ret)
437 OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_deinitialize failed");
440 CAClearNetInterfaceInfoList(g_networkMonitorContext->netInterfaceList);
442 g_networkMonitorContext->netInterfaceList = NULL;
443 g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN;
444 g_networkMonitorContext->networkChangeCb = NULL;
446 OICFree(g_networkMonitorContext);
447 g_networkMonitorContext = NULL;
449 ca_mutex_unlock(g_networkMonitorContextMutex);
451 CADestroyNetworkMonitorMutexes();
453 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
456 CAResult_t CAIPStartNetworkMonitor()
458 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
460 // Set callback for receiving state changes
461 wifi_error_e ret = wifi_set_device_state_changed_cb(CAWIFIDeviceStateChangedCb, NULL);
462 if (WIFI_ERROR_NONE != ret)
464 OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_set_device_state_changed_cb failed");
465 return CA_STATUS_FAILED;
468 // Set callback for receiving connection state changes
469 ret = wifi_set_connection_state_changed_cb(CAWIFIConnectionStateChangedCb, NULL);
470 if (WIFI_ERROR_NONE != ret)
472 OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_set_connection_state_changed_cb failed");
473 return CA_STATUS_FAILED;
476 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
480 CAResult_t CAIPStopNetworkMonitor()
482 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
484 // Reset callback for receiving state changes
485 wifi_error_e ret = wifi_unset_device_state_changed_cb();
486 if (WIFI_ERROR_NONE != ret)
488 OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_unset_device_state_changed_cb failed");
491 // Reset callback for receiving connection state changes
492 ret = wifi_unset_connection_state_changed_cb();
493 if (WIFI_ERROR_NONE != ret)
495 OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_unset_connection_state_changed_cb failed");
498 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
502 CAResult_t CAIPGetInterfaceInfo(u_arraylist_t **netInterfaceList)
504 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
506 VERIFY_NON_NULL(netInterfaceList, IP_MONITOR_TAG, "u_array_list is null");
507 VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG,
508 "g_networkMonitorContext is null");
509 VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG,
510 "g_networkMonitorContextMutex is null");
512 // Get the interface and ipaddress information from cache
513 ca_mutex_lock(g_networkMonitorContextMutex);
514 if (!g_networkMonitorContext->netInterfaceList
515 || !(u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
517 OIC_LOG(ERROR, IP_MONITOR_TAG, "Network not enabled");
518 ca_mutex_unlock(g_networkMonitorContextMutex);
519 return CA_ADAPTER_NOT_ENABLED;
522 uint32_t list_index = 0;
523 uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
524 OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo list length [%d]",
526 for (list_index = 0; list_index < list_length; list_index++)
528 CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(
529 g_networkMonitorContext->netInterfaceList, list_index);
534 OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo ip [%s]",
536 CANetInfo_t *newNetinfo = (CANetInfo_t *) OICMalloc(sizeof(CANetInfo_t));
539 OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed!");
540 ca_mutex_unlock(g_networkMonitorContextMutex);
541 return CA_MEMORY_ALLOC_FAILED;
546 CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)newNetinfo);
547 if (CA_STATUS_OK != result)
549 OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
550 ca_mutex_unlock(g_networkMonitorContextMutex);
551 return CA_STATUS_FAILED;
555 ca_mutex_unlock(g_networkMonitorContextMutex);
557 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
561 CAResult_t CAIPGetInterfaceSubnetMask(const char *ipAddress, char **subnetMask)
563 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
565 VERIFY_NON_NULL(subnetMask, IP_MONITOR_TAG, "subnet mask");
566 VERIFY_NON_NULL(ipAddress, IP_MONITOR_TAG, "ipAddress is null");
567 VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG,
568 "g_networkMonitorContext is null");
569 VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG,
570 "g_networkMonitorContextMutex is null");
572 // Get the interface and ipaddress information from cache
573 ca_mutex_lock(g_networkMonitorContextMutex);
574 if (!g_networkMonitorContext->netInterfaceList
575 || !(u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
577 OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network not enabled");
578 ca_mutex_unlock(g_networkMonitorContextMutex);
579 return CA_ADAPTER_NOT_ENABLED;
582 uint32_t list_index = 0;
583 uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
584 OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "list lenght [%d]", list_length);
585 for (list_index = 0; list_index < list_length; list_index++)
587 CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(
588 g_networkMonitorContext->netInterfaceList, list_index);
594 if (strncmp(info->ipAddress, ipAddress, strlen(ipAddress)) == 0)
596 OIC_LOG_V(DEBUG, IP_MONITOR_TAG,
597 "CAIPGetInterfaceSubnetMask subnetmask is %s", info->subnetMask);
598 *subnetMask = OICStrdup(info->subnetMask);
602 ca_mutex_unlock(g_networkMonitorContextMutex);
604 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
608 bool CAIPIsConnected()
610 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
612 wifi_connection_state_e connection_state;
613 wifi_error_e ret = wifi_get_connection_state(&connection_state);
614 if (WIFI_ERROR_NONE != ret)
616 OIC_LOG(ERROR, IP_MONITOR_TAG, "Failed to get the Connection State");
620 if (WIFI_CONNECTION_STATE_DISCONNECTED == connection_state)
622 OIC_LOG(DEBUG, IP_MONITOR_TAG, "WIFI is not Connected");
626 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
630 void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback)
632 OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
633 if (!g_networkMonitorContextMutex || !g_networkMonitorContext)
635 OIC_LOG(ERROR, IP_MONITOR_TAG, "CAIPSetConnectionStateChangeCallback failed");
638 ca_mutex_lock(g_networkMonitorContextMutex);
640 g_networkMonitorContext->networkChangeCb = callback;
642 ca_mutex_unlock(g_networkMonitorContextMutex);
644 OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");