3a9878a9861533b0761a0e7a6d0e9fee1f445d8c
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / wifi_adapter / android / 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 <arpa/inet.h>
26 #include <linux/if.h>
27 #include <netdb.h>
28
29 #include "caadapterutils.h"
30 #include "umutex.h"
31 #include "logger.h"
32 #include "oic_malloc.h"
33 #include "com_iotivity_jar_CAWiFiInterface.h"
34
35 #define WIFI_MONITOR_TAG "WIFI_MONITOR"
36
37 /**
38  * @var nwConnectivityStatus
39  * @brief  Maintains network status.
40  */
41 static CANetworkStatus_t nwConnectivityStatus;
42
43 /**
44  * @var gWifiNetInfoMutex
45  * @brief  Mutex for synchronizing access to cached interface and IP address information.
46  */
47 static u_mutex gWifiNetInfoMutex = NULL;
48
49 /**
50  * @var gWifiInterfaceName
51  * @brief  Maintains interface name.
52  */
53 static char *gWifiInterfaceName = NULL;
54
55 /**
56  * @var gWifiIPAddress
57  * @brief  Maintains interface IP address.
58  */
59 static char *gWifiIPAddress = NULL;
60
61 /**
62  * @var gThreadPool
63  * @brief ThreadPool for storing u_thread_pool_t handle passed from adapter
64  */
65 static u_thread_pool_t gThreadPool = NULL;
66
67 /**
68  * @var gStopNetworkMonitor
69  * @brief Flag to control the Network Monitor Thread
70  */
71 static bool gStopNetworkMonitor = false;
72
73 /**
74  * @var g_jvm
75  * @brief pointer to store JavaVM
76  */
77 static JavaVM *g_jvm = NULL;
78
79 /**
80  * @var g_context
81  * @brief pointer to store Application Context
82  */
83 static jobject g_context = NULL;
84
85 /**
86  * @var gNetworkChangeCb
87  * @brief  Maintains network connection state change callback.
88  */
89 static CAWiFiConnectionStateChangeCallback gNetworkChangeCb = NULL;
90
91 /**
92  * @fn CAWiFiGetInterfaceInformation
93  * @brief Gets local interface name and IP address information.
94  */
95 static void CAWiFiGetInterfaceInformation(char **interfaceName, char **ipAddress);
96
97 /**
98  * @fn CACreateWiFiJNIInterfaceObject
99  * @brief creates new instance of CAWiFiInterface through JNI
100  */
101 static void CACreateWiFiJNIInterfaceObject(jobject context);
102
103 /**
104  * @fn CASendNetworkChangeCallback
105  * @brief updates network status to wifi adapter
106  */
107 void CASendNetworkChangeCallback(CANetworkStatus_t currNetworkStatus);
108
109 CAResult_t CAWiFiInitializeNetworkMonitor(const u_thread_pool_t threadPool)
110 {
111     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "IN");
112
113     gThreadPool = threadPool;
114
115     if (!gWifiNetInfoMutex)
116     {
117         gWifiNetInfoMutex = u_mutex_new();
118     }
119
120     CACreateWiFiJNIInterfaceObject(g_context);
121
122     u_mutex_lock(gWifiNetInfoMutex);
123     CAWiFiGetInterfaceInformation(&gWifiInterfaceName, &gWifiIPAddress);
124     u_mutex_unlock(gWifiNetInfoMutex);
125
126     nwConnectivityStatus = (gWifiIPAddress) ? CA_INTERFACE_UP : CA_INTERFACE_DOWN;
127
128     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "OUT");
129     return CA_STATUS_OK;
130 }
131
132 void CAWiFiTerminateNetworkMonitor(void)
133 {
134     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "IN");
135
136     gThreadPool = NULL;
137
138     if (gWifiInterfaceName)
139     {
140         OICFree(gWifiInterfaceName);
141         gWifiInterfaceName = NULL;
142     }
143
144     if (gWifiIPAddress)
145     {
146         OICFree(gWifiIPAddress);
147         gWifiIPAddress = NULL;
148     }
149
150     if (gWifiNetInfoMutex)
151     {
152         u_mutex_free(gWifiNetInfoMutex);
153         gWifiNetInfoMutex = NULL;
154     }
155
156     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "OUT");
157 }
158
159 CAResult_t CAWiFiStartNetworkMonitor(void)
160 {
161     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "IN");
162
163     u_mutex_lock(gWifiNetInfoMutex);
164     gStopNetworkMonitor = false;
165     u_mutex_unlock(gWifiNetInfoMutex);
166
167     if (gStopNetworkMonitor)
168     {
169         OIC_LOG_V(ERROR, WIFI_MONITOR_TAG, "Network Monitor Thread is already running!");
170         return CA_SERVER_STARTED_ALREADY;
171     }
172
173     OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "OUT");
174     return CA_STATUS_OK;
175 }
176
177 CAResult_t CAWiFiStopNetworkMonitor(void)
178 {
179     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "IN");
180
181     if (gStopNetworkMonitor)
182     {
183         OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "CAWiFiStopNetworkMonitor, already stopped");
184
185         return CA_STATUS_OK;
186     }
187
188     u_mutex_lock(gWifiNetInfoMutex);
189     gStopNetworkMonitor = true;
190     u_mutex_unlock(gWifiNetInfoMutex);
191
192     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "OUT");
193     return CA_STATUS_OK;
194 }
195
196 CAResult_t CAWiFiGetInterfaceInfo(char **interfaceName, char **ipAddress)
197 {
198     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "IN");
199
200     u_mutex_lock(gWifiNetInfoMutex);
201
202     if (gWifiInterfaceName && strlen(gWifiInterfaceName))
203     {
204         *interfaceName = (gWifiInterfaceName) ? strndup(gWifiInterfaceName, strlen(gWifiInterfaceName)) :
205                                 NULL;
206     }
207
208     if (gWifiIPAddress && strlen(gWifiIPAddress))
209     {
210         *ipAddress = (gWifiIPAddress) ? strndup(gWifiIPAddress, strlen(gWifiIPAddress)) :
211                                 NULL;
212     }
213
214     u_mutex_unlock(gWifiNetInfoMutex);
215
216     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "OUT");
217     return CA_STATUS_OK;
218 }
219
220 bool CAWiFiIsConnected(void)
221 {
222     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "IN");
223
224     if (nwConnectivityStatus == CA_INTERFACE_DOWN)
225         return false;
226
227     return true;
228 }
229
230 void CAWiFiSetConnectionStateChangeCallback(CAWiFiConnectionStateChangeCallback callback)
231 {
232     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "IN");
233
234     gNetworkChangeCb = callback;
235 }
236
237 void CAWiFiGetInterfaceInformation(char **interfaceName, char **ipAddress)
238 {
239     char buf[1024] =  { 0, };
240     struct ifconf ifc;
241     struct ifreq* ifr;
242     struct ifreq* item;
243     int32_t sck;
244     int32_t interfaces;
245     int32_t i;
246
247     /* Get a socket handle. */
248     sck = socket(AF_INET, SOCK_DGRAM, 0);
249     if (sck < 0)
250     {
251         return;
252     }
253
254     /* Query available interfaces. */
255     ifc.ifc_len = sizeof(buf);
256     ifc.ifc_buf = buf;
257
258     if (ioctl(sck, SIOCGIFCONF, &ifc) < 0)
259     {
260         close(sck);
261         return;
262     }
263
264     /* Iterate through the list of interfaces. */
265     ifr = ifc.ifc_req;
266     interfaces = ifc.ifc_len / sizeof(struct ifreq);
267
268     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "CAWiFiGetInterfaceInformation : %d", interfaces);
269
270     for (i = 0; i < interfaces; i++)
271     {
272         struct ifreq temp_ifr;
273         struct ifreq* item = &ifr[i];
274
275         memset(&temp_ifr, 0, sizeof(temp_ifr));
276         strcpy(temp_ifr.ifr_name, item->ifr_name);
277
278         if (ioctl((int)sck, SIOCGIFFLAGS, &temp_ifr))
279         {
280             OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "CAWiFiGetInterfaceInformation, SIOCGIFFLAGS Failed");
281             continue;
282         }
283
284         if (!((temp_ifr.ifr_flags & IFF_UP) && (temp_ifr.ifr_flags & IFF_RUNNING)))
285         {
286             continue;
287         }
288
289         if(((struct sockaddr_in*) &item->ifr_addr)->sin_family != AF_INET)
290         {
291             continue;
292         }
293
294         char* ip = inet_ntoa(((struct sockaddr_in*) &item->ifr_addr)->sin_addr);
295
296         if(strcmp(ip, "127.0.0.1") == 0)
297         {
298             continue;
299         }
300
301         // set interface name
302         *interfaceName = strndup(item->ifr_name, strlen(item->ifr_name));
303
304         // set local ip address
305         *ipAddress = strndup(ip, strlen(ip));
306
307        OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "ipAddress : %s, interfaceName : %s", *ipAddress, *interfaceName);
308        break;
309     }
310
311     close(sck);
312     return;
313 }
314
315 void CAWiFiJniInit(JavaVM* jvm)
316 {
317     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "[WIFICore] CAWiFiJniInit");
318     g_jvm = jvm;
319 }
320
321 void CAJniSetContext(jobject context)
322 {
323     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "caWifiSetObject");
324         g_context = context;
325 }
326
327 void CACreateWiFiJNIInterfaceObject(jobject context)
328 {
329     JNIEnv* env;
330     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "[WIFICore] CACreateWiFiJNIInterfaceObject");
331
332     if ((*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
333     {
334         OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "[WIFICore] Could not get JNIEnv pointer");
335         return;
336     }
337
338     //getApplicationContext
339     jclass contextClass = (*env)->FindClass(env, "android/content/Context");
340     if (contextClass == 0)
341     {
342         OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "[WIFICore] Could not get context object class");
343         return;
344     }
345
346     jmethodID getApplicationContextMethod = (*env)->GetMethodID(env, contextClass,
347             "getApplicationContext", "()Landroid/content/Context;");
348     if (getApplicationContextMethod == 0)
349     {
350         OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "[WIFICore] Could not get getApplicationContext method");
351         return;
352     }
353
354     jobject gApplicationContext = (*env)->CallObjectMethod(env, context, getApplicationContextMethod);
355     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "[WIFICore] Saving Android application context object %p", gApplicationContext);
356
357    //Create WiFiInterface instance
358     jclass WiFiJniInterface = (*env)->FindClass(env, "com/iotivity/jar/CAWiFiInterface");
359     if (!WiFiJniInterface)
360     {
361         OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "[WIFICore] Could not get CAWiFiInterface class");
362         return;
363     }
364
365     jmethodID WiFiInterfaceConstructorMethod = (*env)->GetMethodID(env,
366                 WiFiJniInterface, "<init>", "(Landroid/content/Context;)V");
367     if (!WiFiInterfaceConstructorMethod)
368     {
369         OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "[WIFICore] Could not get CAWiFiInterface constructor method");
370         return;
371     }
372
373     (*env)->NewObject(env, WiFiJniInterface, WiFiInterfaceConstructorMethod, gApplicationContext);
374     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "[WIFICore]Create CAWiFiInterface instance");
375     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "[WIFICore] NewObject Successs");
376
377 }
378
379 void CASendNetworkChangeCallback(CANetworkStatus_t currNetworkStatus)
380 {
381     // Get network information
382     char *interfaceName = NULL;
383     char *ipAddress = NULL;
384
385     if (gStopNetworkMonitor)
386     {
387         OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "Stop Network Monitor Thread is called");
388         return;
389     }
390
391     if(NULL == gNetworkChangeCb)
392     {
393         OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "[WiFiCore] gNetworkChangeCb is NULL");
394         return;
395     }
396
397     // if network status is changed
398     if (currNetworkStatus != nwConnectivityStatus)
399     {
400         CAWiFiGetInterfaceInformation(&interfaceName, &ipAddress);
401
402         // set current network information
403         u_mutex_lock(gWifiNetInfoMutex);
404
405         nwConnectivityStatus = currNetworkStatus;
406
407         gWifiInterfaceName = (interfaceName) ? strndup(interfaceName, strlen(interfaceName)) : NULL;
408         gWifiIPAddress = (ipAddress) ? strndup(ipAddress, strlen(ipAddress)) : NULL;
409
410         u_mutex_unlock(gWifiNetInfoMutex);
411
412         gNetworkChangeCb(gWifiIPAddress, nwConnectivityStatus);
413     }
414     OICFree(interfaceName);
415     OICFree(ipAddress);
416 }
417
418 JNIEXPORT void JNICALL Java_com_iotivity_jar_CAWiFiInterface_CAWiFiStateEnabled
419   (JNIEnv *env, jclass class)
420 {
421     CALocalConnectivity_t info;
422
423     CANetworkStatus_t currNetworkStatus = CA_INTERFACE_UP;
424     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "[WiFiCore] CAWiFiStateEnabled");
425
426     CASendNetworkChangeCallback(currNetworkStatus);
427     return;
428 }
429
430
431 JNIEXPORT void JNICALL Java_com_iotivity_jar_CAWiFiInterface_CAWiFiStateDisabled
432   (JNIEnv *env, jclass class)
433 {
434     CALocalConnectivity_t info;
435
436     CANetworkStatus_t currNetworkStatus = CA_INTERFACE_DOWN;
437     OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "[WiFiCore] CAWiFiStateDisabled");
438
439     CASendNetworkChangeCallback(currNetworkStatus);
440     return;
441 }
442