Implementation of connectivity abstraction feature Release v0.5
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / wifi_adapter / linux / cawifinwmonitor.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 "cawifiinterface.h"
22
23 #include <string.h>
24 #include <ifaddrs.h>
25 #include <netdb.h>
26
27 #include "caadapterutils.h"
28 #include "umutex.h"
29 #include "logger.h"
30 #include "oic_malloc.h"
31
32 #define WIFI_MONITOR_TAG "WIFI_MONITOR"
33
34 /**
35  * @var nwConnectivityStatus
36  * @brief  Maintains network status.
37  */
38 static CANetworkStatus_t nwConnectivityStatus;
39
40 /**
41  * @var gWifiNetInfoMutex
42  * @brief  Mutex for synchronizing access to cached interface and IP address information.
43  */
44 static u_mutex gWifiNetInfoMutex = NULL;
45
46 /**
47  * @var gWifiInterfaceName
48  * @brief  Maintains interface name.
49  */
50 static char *gWifiInterfaceName = NULL;
51
52 /**
53  * @var gWifiIPAddress
54  * @brief  Maintains interface IP address.
55  */
56 static char *gWifiIPAddress = NULL;
57
58 /**
59  * @var gThreadPool
60  * @brief ThreadPool for storing u_thread_pool_t handle passed from adapter
61  */
62 static u_thread_pool_t gThreadPool = NULL;
63
64 /**
65  * @var gStopNetworkMonitor
66  * @brief Flag to control the Network Monitor Thread
67  */
68 static bool gStopNetworkMonitor = false;
69
70 /**
71  * @var gNetworkChangeCb
72  * @brief  Maintains network connection state change callback.
73  */
74 static CAWiFiConnectionStateChangeCallback gNetworkChangeCb = NULL;
75
76 /**
77  * @fn CAWiFiGetInterfaceInformation
78  * @brief This methods gets local interface name and IP address information.
79  */
80 static void CAWiFiGetInterfaceInformation(char **interfaceName, char **ipAddress);
81
82 static void CANetworkMonitorThread(void* threadData);
83
84 CAResult_t CAWiFiInitializeNetworkMonitor(const u_thread_pool_t threadPool)
85 {
86     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "IN");
87
88     gThreadPool = threadPool;
89
90     if (!gWifiNetInfoMutex)
91     {
92         gWifiNetInfoMutex = u_mutex_new();
93     }
94
95     u_mutex_lock(gWifiNetInfoMutex);
96     CAWiFiGetInterfaceInformation(&gWifiInterfaceName, &gWifiIPAddress);
97     u_mutex_unlock(gWifiNetInfoMutex);
98
99     nwConnectivityStatus = (gWifiIPAddress) ? CA_INTERFACE_UP : CA_INTERFACE_DOWN;
100
101     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "OUT");
102     return CA_STATUS_OK;
103 }
104
105 void CAWiFiTerminateNetworkMonitor(void)
106 {
107     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "IN");
108
109     gThreadPool = NULL;
110
111     if (gWifiInterfaceName)
112     {
113         OICFree(gWifiInterfaceName);
114         gWifiInterfaceName = NULL;
115     }
116
117     if (gWifiIPAddress)
118     {
119         OICFree(gWifiIPAddress);
120         gWifiIPAddress = NULL;
121     }
122
123     if (gWifiNetInfoMutex)
124     {
125         u_mutex_free(gWifiNetInfoMutex);
126         gWifiNetInfoMutex = NULL;
127     }
128
129     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "OUT");
130 }
131
132 CAResult_t CAWiFiStartNetworkMonitor(void)
133 {
134     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "IN");
135
136     u_mutex_lock(gWifiNetInfoMutex);
137     gStopNetworkMonitor = false;
138     u_mutex_unlock(gWifiNetInfoMutex);
139
140     if (gStopNetworkMonitor)
141     {
142         OIC_LOG_V(ERROR, WIFI_MONITOR_TAG, "Network Monitor Thread is already running!");
143         return CA_SERVER_STARTED_ALREADY;
144     }
145
146     if (CA_STATUS_OK != u_thread_pool_add_task(gThreadPool, (void *) CANetworkMonitorThread,
147             (void *)NULL))
148     {
149         OIC_LOG(ERROR, WIFI_MONITOR_TAG, "[ThreadPool] thread_pool_add_task failed!");
150         return CA_STATUS_FAILED;
151     }
152
153     OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "OUT");
154     return CA_STATUS_OK;
155 }
156
157 CAResult_t CAWiFiStopNetworkMonitor(void)
158 {
159     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "IN");
160
161     if (gStopNetworkMonitor)
162     {
163         OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "CAWiFiStopNetworkMonitor, already stopped");
164
165         return CA_STATUS_OK;
166     }
167
168     u_mutex_lock(gWifiNetInfoMutex);
169     gStopNetworkMonitor = true;
170     u_mutex_unlock(gWifiNetInfoMutex);
171
172     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "OUT");
173     return CA_STATUS_OK;
174 }
175
176 CAResult_t CAWiFiGetInterfaceInfo(char **interfaceName, char **ipAddress)
177 {
178     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "IN");
179
180     VERIFY_NON_NULL(interfaceName, WIFI_MONITOR_TAG, "interface name holder is NULL");
181     VERIFY_NON_NULL(ipAddress, WIFI_MONITOR_TAG, "IP address holder is NULL");
182
183     u_mutex_lock(gWifiNetInfoMutex);
184
185     if (gWifiInterfaceName && strlen(gWifiInterfaceName))
186     {
187         *interfaceName = (gWifiInterfaceName) ? strndup(gWifiInterfaceName, strlen(gWifiInterfaceName)) :
188                                 NULL;
189     }
190
191     if (gWifiIPAddress && strlen(gWifiIPAddress))
192     {
193         *ipAddress = (gWifiIPAddress) ? strndup(gWifiIPAddress, strlen(gWifiIPAddress)) :
194                                 NULL;
195     }
196
197     u_mutex_unlock(gWifiNetInfoMutex);
198
199     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "OUT");
200     return CA_STATUS_OK;
201 }
202
203 bool CAWiFiIsConnected(void)
204 {
205     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "IN");
206
207     if (nwConnectivityStatus == CA_INTERFACE_DOWN)
208         return false;
209
210     return true;
211 }
212
213 void CAWiFiSetConnectionStateChangeCallback(CAWiFiConnectionStateChangeCallback callback)
214 {
215     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "IN");
216
217     gNetworkChangeCb = callback;
218 }
219
220 void CAWiFiGetInterfaceInformation(char **interfaceName, char **ipAddress)
221 {
222     struct ifaddrs *ifa = NULL;
223     struct ifaddrs *ifp = NULL;
224
225     if (getifaddrs(&ifp) < 0)
226     {
227         OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "Get network interface list error");
228     }
229
230     for (ifa = ifp; ifa; ifa = ifa->ifa_next)
231     {
232         char localIPAddress[CA_IPADDR_SIZE];
233         socklen_t len;
234
235         if (ifa->ifa_addr == NULL)
236             continue;
237
238         if (ifa->ifa_addr->sa_family == AF_INET)
239             len = sizeof(struct sockaddr_in);
240         else if (ifa->ifa_addr->sa_family == AF_INET6)
241             continue;
242         else
243             continue;
244
245         if (getnameinfo(ifa->ifa_addr, len, localIPAddress,
246                         sizeof(localIPAddress), NULL, 0, NI_NUMERICHOST) < 0)
247         {
248             OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "Get IPAddress fail");
249         }
250
251         // except loopback address
252         if (strcmp(localIPAddress, "127.0.0.1") == 0)
253             continue;
254
255         // set interface name
256         *interfaceName = strndup(ifa->ifa_name, strlen(ifa->ifa_name));
257
258         // set local ip address
259         *ipAddress = strndup(localIPAddress, strlen(localIPAddress));
260     }
261
262     freeifaddrs(ifp);
263 }
264
265 void CANetworkMonitorThread(void* threadData)
266 {
267     while (!gStopNetworkMonitor)
268     {
269         if (gStopNetworkMonitor)
270         {
271             OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "Stop Network Monitor Thread is called");
272             break;
273         }
274
275         // Get network information
276         CANetworkStatus_t currNetworkStatus;
277         char *interfaceName = NULL;
278         char *ipAddress = NULL;
279         CAWiFiGetInterfaceInformation(&interfaceName, &ipAddress);
280
281         // check current network status
282         currNetworkStatus = (ipAddress) ? CA_INTERFACE_UP : CA_INTERFACE_DOWN;
283
284         // if network status is changed
285         if (currNetworkStatus != nwConnectivityStatus)
286         {
287             // set current network information
288             u_mutex_lock(gWifiNetInfoMutex);
289
290             nwConnectivityStatus = currNetworkStatus;
291
292             OICFree(gWifiInterfaceName);
293             OICFree(gWifiIPAddress);
294             gWifiInterfaceName = (interfaceName) ? strndup(interfaceName, strlen(interfaceName)) : NULL;
295             gWifiIPAddress = (ipAddress) ? strndup(ipAddress, strlen(ipAddress)) : NULL;
296
297             u_mutex_unlock(gWifiNetInfoMutex);
298
299             if (gNetworkChangeCb)
300             {
301                 gNetworkChangeCb(gWifiIPAddress, nwConnectivityStatus);
302             }
303         }
304         OICFree(interfaceName);
305         OICFree(ipAddress);
306     }
307 }