[Jira] IOT-529, Fix to support multiple IP networks in Android
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ip_adapter / android / caipnwmonitor.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 "caipinterface.h"
22
23 #include <string.h>
24 #include <sys/ioctl.h>
25 #include <arpa/inet.h>
26 #include <linux/if.h>
27 #include <netdb.h>
28 #include <errno.h>
29 #include <unistd.h>
30
31 #include "caadapterutils.h"
32 #include "camutex.h"
33 #include "logger.h"
34 #include "oic_malloc.h"
35 #include "oic_string.h"
36 #include "org_iotivity_ca_CaIpInterface.h"
37
38 #define IP_MONITOR_TAG "IP_MONITOR"
39 #define MAX_INTERFACE_INFO_LENGTH (1024)
40
41 /**
42  * @var g_stopNetworkMonitor
43  * @brief  Used to stop the network monitor thread.
44  */
45 static bool g_stopNetworkMonitor = false;
46
47 /**
48  * @var g_stopNetworkMonitorMutex
49  * @brief  Mutex for synchronizing access to g_stopNetworkMonitor flag.
50  */
51 static ca_mutex g_stopNetworkMonitorMutex = NULL;
52
53 /**
54  * @struct CAIPNwMonitorContext
55  * @brief  Used for storing network monitor context information.
56  */
57 typedef struct
58 {
59     u_arraylist_t *netInterfaceList;
60     ca_thread_pool_t threadPool;
61     CANetworkStatus_t nwConnectivityStatus;
62     CAIPConnectionStateChangeCallback networkChangeCb;
63 } CAIPNetworkMonitorContext;
64
65 /**
66  * @var g_networkMonitorContext
67  * @brief  network monitor context.
68  */
69 static CAIPNetworkMonitorContext *g_networkMonitorContext = NULL;
70
71 /**
72  * @var g_networkMonitorContextMutex
73  * @brief  Mutex for synchronizing access to cached interface and IP address information.
74  */
75 static ca_mutex g_networkMonitorContextMutex = NULL;
76
77 /**
78  * @var g_jvm
79  * @brief pointer to store JavaVM
80  */
81 static JavaVM *g_jvm = NULL;
82
83 /**
84  * @var g_context
85  * @brief pointer to store Application Context
86  */
87 static jobject g_context = NULL;
88
89 /**
90  * @fn CAIPUpdateInterfaceInformation
91  * @brief This methods gets local interface name and IP address information.
92  */
93 static CAResult_t CAIPUpdateInterfaceInformation(u_arraylist_t **netInterfaceList);
94 /**
95  * @fn CACreateIPJNIInterfaceObject
96  * @brief creates new instance of caipinterface through JNI
97  */
98 static CAResult_t CACreateIPJNIInterfaceObject(jobject context);
99
100 /**
101  * @fn CAIPSendNetworkChangeCallback
102  * @brief updates network status to IP adapter
103  */
104 static void CAIPSendNetworkChangeCallback(CANetworkStatus_t currNetworkStatus);
105
106 CAResult_t CAIPJniInit()
107 {
108     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
109
110     OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPJniInit");
111     g_jvm = CANativeJNIGetJavaVM();
112
113     if (!g_jvm)
114     {
115         OIC_LOG(ERROR, IP_MONITOR_TAG, "JNI initialize error");
116         return CA_STATUS_FAILED;
117     }
118
119     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
120     return CA_STATUS_OK;
121 }
122
123 CAResult_t CAIPJniSetContext()
124 {
125     OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPJniSetContext");
126     g_context = (jobject) CANativeJNIGetContext();
127
128     if (!g_context)
129     {
130         OIC_LOG(ERROR, IP_MONITOR_TAG, "unable to get application context");
131         return CA_STATUS_FAILED;
132     }
133
134     return CA_STATUS_OK;
135 }
136
137 CAResult_t CACreateIPJNIInterfaceObject(jobject context)
138 {
139     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
140
141     OIC_LOG(DEBUG, IP_MONITOR_TAG, "CACreateIPJNIInterfaceObject");
142
143     VERIFY_NON_NULL(context, IP_MONITOR_TAG, "context");
144
145     JNIEnv* env;
146
147     if ((*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
148     {
149         OIC_LOG(ERROR, IP_MONITOR_TAG, "Could not get JNIEnv pointer");
150         return CA_STATUS_FAILED;
151     }
152
153     //getApplicationContext
154     jclass contextClass = (*env)->FindClass(env, "android/content/Context");
155     if (!contextClass)
156     {
157         OIC_LOG(ERROR, IP_MONITOR_TAG, "Could not get context object class");
158         return CA_STATUS_FAILED;
159     }
160
161     jmethodID getApplicationContextMethod = (*env)->GetMethodID(env, contextClass,
162                                                                 "getApplicationContext",
163                                                                 "()Landroid/content/Context;");
164     if (!getApplicationContextMethod)
165     {
166         OIC_LOG(ERROR, IP_MONITOR_TAG, "Could not get getApplicationContext method");
167         return CA_STATUS_FAILED;
168     }
169
170     jobject gApplicationContext = (*env)->CallObjectMethod(env, context,
171                                                            getApplicationContextMethod);
172     if (!getApplicationContextMethod)
173     {
174         OIC_LOG(ERROR, IP_MONITOR_TAG, "Could not get getApplicationContext");
175         return CA_STATUS_FAILED;
176     }
177
178     //Create caipinterface jni instance
179     jclass IPJniInterface = (*env)->FindClass(env, "org/iotivity/ca/CaIpInterface");
180     if (!IPJniInterface)
181     {
182         OIC_LOG(ERROR, IP_MONITOR_TAG, "Could not get caipinterface class");
183         return CA_STATUS_FAILED;
184     }
185
186     jmethodID IPInterfaceConstructorMethod = (*env)->GetMethodID(env, IPJniInterface, "<init>",
187                                                                    "(Landroid/content/Context;)V");
188     if (!IPInterfaceConstructorMethod)
189     {
190         OIC_LOG(ERROR, IP_MONITOR_TAG, "Could not get caipinterface constructor method");
191         return CA_STATUS_FAILED;
192     }
193
194     (*env)->NewObject(env, IPJniInterface, IPInterfaceConstructorMethod, gApplicationContext);
195     OIC_LOG(DEBUG, IP_MONITOR_TAG, "Create caipinterface instance, success");
196
197     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
198     return CA_STATUS_OK;
199 }
200
201 static CAResult_t CAIPUpdateInterfaceInformation(u_arraylist_t **netInterfaceList)
202 {
203     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
204
205     VERIFY_NON_NULL(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null");
206
207     /* Get a socket handle. */
208     int sck = -1;
209 #ifdef SOCK_CLOEXEC
210     sck = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
211 #endif
212
213     if ( -1 == sck)
214     {
215         sck=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
216     }
217
218     if (sck < 0)
219     {
220         OIC_LOG(ERROR, IP_MONITOR_TAG, "Error in socket creation");
221         return CA_STATUS_FAILED;
222     }
223
224     char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 };
225     struct ifconf ifc;
226
227     /* Query available interfaces. */
228     ifc.ifc_len = MAX_INTERFACE_INFO_LENGTH;
229     ifc.ifc_buf = buf;
230
231     if (ioctl(sck, SIOCGIFCONF, &ifc) < 0)
232     {
233         close(sck);
234         OIC_LOG(ERROR, IP_MONITOR_TAG, "Failed to get interface info");
235         return CA_STATUS_FAILED;
236     }
237
238     /* Iterate through the list of interfaces. */
239     struct ifreq* ifr = ifc.ifc_req;
240     int32_t interfaces = ifc.ifc_len / sizeof(struct ifreq);
241
242     OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPUpdateInterfaceInformation : %d", interfaces);
243
244     if(0 == interfaces)
245     {
246         OIC_LOG(ERROR, IP_MONITOR_TAG, "no interfaces");
247         return CA_STATUS_FAILED;
248     }
249
250     for (int32_t i = 0; i < interfaces; i++)
251     {
252         struct ifreq temp_ifr = { 0 };
253         struct ifreq* item = &ifr[i];
254
255         char interfaceAddress[CA_IPADDR_SIZE] = { 0 };
256         char interfaceSubnetMask[CA_IPADDR_SIZE] = { 0 };
257         socklen_t len = sizeof(struct sockaddr_in);
258
259         strcpy(temp_ifr.ifr_name, item->ifr_name);
260
261         if (ioctl(sck, SIOCGIFFLAGS, &temp_ifr))
262         {
263             OIC_LOG(ERROR, IP_MONITOR_TAG,
264                     "CAIPUpdateInterfaceInformation, SIOCGIFFLAGS Failed");
265             close(sck);
266             return CA_STATUS_FAILED;
267         }
268
269         if ((temp_ifr.ifr_flags & IFF_LOOPBACK)
270             || !(temp_ifr.ifr_flags & IFF_UP) || !(temp_ifr.ifr_flags & IFF_RUNNING))
271         {
272             OIC_LOG_V(ERROR, IP_MONITOR_TAG,
273                       "interface is not up or not running or loopback = %x", temp_ifr.ifr_flags);
274             continue;
275         }
276
277         if (AF_INET != ((struct sockaddr_in*) &item->ifr_addr)->sin_family)
278         {
279             continue;
280         }
281
282         //get the interface ip address
283         if (0 != getnameinfo(&item->ifr_addr, len, interfaceAddress, sizeof(interfaceAddress),
284                              NULL, 0, NI_NUMERICHOST))
285         {
286             OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get IPAddress, Error code: %s",
287                     strerror(errno));
288             close(sck);
289             return CA_STATUS_FAILED;
290         }
291
292         if (ioctl((int) sck, SIOCGIFNETMASK, item) < 0)
293         {
294             OIC_LOG(ERROR, IP_MONITOR_TAG,
295                     "CAIPUpdateInterfaceInformation, SIOCGIFNETMASK Failed");
296             close(sck);
297             return CA_STATUS_FAILED;
298         }
299
300         // get the interface subnet mask
301         if (0 != getnameinfo(&item->ifr_netmask, len, interfaceSubnetMask,
302                              sizeof(interfaceSubnetMask), NULL, 0, NI_NUMERICHOST))
303         {
304             OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get subnet mask, Error code: %s",
305                     strerror(errno));
306             close(sck);
307             return CA_STATUS_FAILED;
308         }
309
310         CANetInfo_t *netInfo = (CANetInfo_t *) OICCalloc(1, sizeof(CANetInfo_t));
311         if (!netInfo)
312         {
313             OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed");
314             close(sck);
315             return CA_MEMORY_ALLOC_FAILED;
316         }
317
318         // set interface name
319         strncpy(netInfo->interfaceName, item->ifr_name, strlen(item->ifr_name));
320
321         // set local ip address
322         strncpy(netInfo->ipAddress, interfaceAddress, strlen(interfaceAddress));
323
324         // set subnet mask
325         strncpy(netInfo->subnetMask, interfaceSubnetMask, strlen(interfaceSubnetMask));
326
327         CAResult_t result = u_arraylist_add(*netInterfaceList, (void *) netInfo);
328         if (CA_STATUS_OK != result)
329         {
330             OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!Thread exiting.");
331             close(sck);
332             return CA_STATUS_FAILED;
333         }
334
335         OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "ipAddress : %s, interfaceName : %s, subnetmask : %s",
336                 netInfo->ipAddress, netInfo->interfaceName, netInfo->subnetMask);
337     }
338
339     close(sck);
340     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
341     return CA_STATUS_OK;
342 }
343
344 static bool CACheckIsAnyInterfaceDown(const u_arraylist_t *netInterfaceList,
345                                       const CANetInfo_t *info)
346 {
347     VERIFY_NON_NULL_RET(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null", false);
348     VERIFY_NON_NULL_RET(info, IP_MONITOR_TAG, "info is null", false);
349
350     uint32_t list_length = u_arraylist_length(netInterfaceList);
351     for (uint32_t list_index = 0; list_index < list_length; list_index++)
352     {
353         CANetInfo_t *netInfo = (CANetInfo_t *) u_arraylist_get(netInterfaceList, list_index);
354         if (!netInfo)
355         {
356             continue;
357         }
358         if (strncmp(netInfo->interfaceName, info->interfaceName, strlen(info->interfaceName)) == 0)
359         {
360             return false;
361         }
362     }
363     OIC_LOG(DEBUG, IP_MONITOR_TAG, "Interface is down");
364     return true;
365 }
366
367 static bool CACheckIsInterfaceInfoChanged(const CANetInfo_t *info)
368 {
369     VERIFY_NON_NULL_RET(info, IP_MONITOR_TAG, "info is null", false);
370
371     ca_mutex_lock(g_networkMonitorContextMutex);
372
373     uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
374     for (uint32_t list_index = 0; list_index < list_length; list_index++)
375     {
376         CANetInfo_t *netInfo = (CANetInfo_t *) u_arraylist_get(
377                                g_networkMonitorContext->netInterfaceList, list_index);
378         if (!netInfo)
379         {
380             continue;
381         }
382         if (strncmp(netInfo->interfaceName, info->interfaceName, strlen(info->interfaceName)) == 0)
383         {
384             if (strncmp(netInfo->ipAddress, info->ipAddress, strlen(info->ipAddress)) == 0)
385             {
386                 ca_mutex_unlock(g_networkMonitorContextMutex);
387                 return false;
388             }
389             else
390             {
391                 OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network interface info changed");
392                 if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, list_index))
393                 {
394                     if (g_networkMonitorContext->networkChangeCb)
395                     {
396                         g_networkMonitorContext->networkChangeCb(netInfo->ipAddress,
397                                                                  CA_INTERFACE_DOWN);
398                     }
399                     OICFree(netInfo);
400                 }
401                 else
402                 {
403                     OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed");
404                 }
405                 break;
406             }
407         }
408     }
409
410     CANetInfo_t *newNetInfo = (CANetInfo_t *) OICMalloc(sizeof(CANetInfo_t));
411     if (!newNetInfo)
412     {
413         OIC_LOG(ERROR, IP_MONITOR_TAG, "newNetInfo malloc failed");
414         ca_mutex_unlock(g_networkMonitorContextMutex);
415         return false;
416     }
417     memcpy(newNetInfo, info, sizeof(*newNetInfo));
418
419     OIC_LOG(DEBUG, IP_MONITOR_TAG, "New Interface found");
420
421     CAResult_t result = u_arraylist_add(g_networkMonitorContext->netInterfaceList,
422                                         (void *) newNetInfo);
423     if (CA_STATUS_OK != result)
424     {
425         OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
426         OICFree(newNetInfo);
427         ca_mutex_unlock(g_networkMonitorContextMutex);
428         return false;
429     }
430     ca_mutex_unlock(g_networkMonitorContextMutex);
431
432     /*Callback will be unset only at the time of termination. By that time, all the threads will be
433       stopped gracefully. This callback is properly protected*/
434     if (g_networkMonitorContext->networkChangeCb)
435     {
436         g_networkMonitorContext->networkChangeCb(newNetInfo->ipAddress, CA_INTERFACE_UP);
437     }
438
439     return true;
440 }
441
442 static CAResult_t CAInitializeNetworkMonitorMutexes()
443 {
444     if (!g_networkMonitorContextMutex)
445     {
446         g_networkMonitorContextMutex = ca_mutex_new();
447         if (!g_networkMonitorContextMutex)
448         {
449             OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContextMutex Malloc  failed");
450             return CA_MEMORY_ALLOC_FAILED;
451         }
452     }
453
454     if (!g_stopNetworkMonitorMutex)
455     {
456         g_stopNetworkMonitorMutex = ca_mutex_new();
457         if (!g_stopNetworkMonitorMutex)
458         {
459             OIC_LOG(ERROR, IP_MONITOR_TAG, "g_stopNetworkMonitorMutex Malloc  failed");
460             ca_mutex_free(g_networkMonitorContextMutex);
461             return CA_MEMORY_ALLOC_FAILED;
462         }
463     }
464     return CA_STATUS_OK;
465 }
466
467 static void CADestroyNetworkMonitorMutexes()
468 {
469     ca_mutex_free(g_networkMonitorContextMutex);
470     g_networkMonitorContextMutex = NULL;
471
472     ca_mutex_free(g_stopNetworkMonitorMutex);
473     g_stopNetworkMonitorMutex = NULL;
474 }
475
476 CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool)
477 {
478     OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPInitializeNetworkMonitor IN");
479
480     VERIFY_NON_NULL(threadPool, IP_MONITOR_TAG, "threadPool is null");
481
482     CAResult_t ret = CAIPJniInit();
483     if (CA_STATUS_OK != ret)
484     {
485         OIC_LOG(ERROR, IP_MONITOR_TAG, "Initialization failed");
486         return ret;
487     }
488
489     ret = CAIPJniSetContext();
490     if (CA_STATUS_OK != ret)
491     {
492         OIC_LOG(ERROR, IP_MONITOR_TAG, "CAIPJniSetContext failed");
493         return ret;
494     }
495
496     ret = CACreateIPJNIInterfaceObject(g_context);
497     if (CA_STATUS_OK != ret)
498     {
499         OIC_LOG(ERROR, IP_MONITOR_TAG, "unable to create caipinterface instance");
500         return ret;
501     }
502
503     ret = CAInitializeNetworkMonitorMutexes();
504
505     if (CA_STATUS_OK != ret)
506     {
507         OIC_LOG(ERROR, IP_MONITOR_TAG, "CAInitializeNetworkMonitorMutexes failed");
508         return CA_STATUS_FAILED;
509     }
510
511     ca_mutex_lock(g_networkMonitorContextMutex);
512
513     g_networkMonitorContext = (CAIPNetworkMonitorContext *) OICCalloc(
514             1, sizeof(*g_networkMonitorContext));
515     if (!g_networkMonitorContext)
516     {
517         OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext Malloc  failed");
518         ca_mutex_unlock(g_networkMonitorContextMutex);
519         CADestroyNetworkMonitorMutexes();
520         return CA_MEMORY_ALLOC_FAILED;
521     }
522     g_networkMonitorContext->threadPool = threadPool;
523
524     g_networkMonitorContext->netInterfaceList = u_arraylist_create();
525     if (!g_networkMonitorContext->netInterfaceList)
526     {
527         OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_create failed");
528         OICFree(g_networkMonitorContext);
529         ca_mutex_unlock(g_networkMonitorContextMutex);
530         CADestroyNetworkMonitorMutexes();
531         return CA_MEMORY_ALLOC_FAILED;
532     }
533
534     CAIPUpdateInterfaceInformation(&g_networkMonitorContext->netInterfaceList);
535
536     if (u_arraylist_length(g_networkMonitorContext->netInterfaceList))
537     {
538         g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_UP;
539     }
540     else
541     {
542         g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN;
543     }
544
545     ca_mutex_unlock(g_networkMonitorContextMutex);
546
547     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
548     return CA_STATUS_OK;
549 }
550
551 void CAIPTerminateNetworkMonitor()
552 {
553     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
554
555     ca_mutex_lock(g_networkMonitorContextMutex);
556     g_networkMonitorContext->threadPool = NULL;
557
558     CAClearNetInterfaceInfoList(g_networkMonitorContext->netInterfaceList);
559
560     g_networkMonitorContext->netInterfaceList = NULL;
561     g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN;
562     g_networkMonitorContext->networkChangeCb = NULL;
563     g_networkMonitorContext->threadPool = NULL;
564
565     OICFree(g_networkMonitorContext);
566     g_networkMonitorContext = NULL;
567
568     ca_mutex_unlock(g_networkMonitorContextMutex);
569
570     ca_mutex_lock(g_stopNetworkMonitorMutex);
571     g_stopNetworkMonitor = true;
572     ca_mutex_unlock(g_stopNetworkMonitorMutex);
573
574     CADestroyNetworkMonitorMutexes();
575
576     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
577 }
578
579 CAResult_t CAIPStartNetworkMonitor()
580 {
581     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
582
583     ca_mutex_lock(g_stopNetworkMonitorMutex);
584     g_stopNetworkMonitor = false;
585     ca_mutex_unlock(g_stopNetworkMonitorMutex);
586
587     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
588     return CA_STATUS_OK;
589 }
590
591 CAResult_t CAIPStopNetworkMonitor()
592 {
593     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
594
595     ca_mutex_lock(g_networkMonitorContextMutex);
596     if (!g_networkMonitorContext)
597     {
598         OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext is null");
599         ca_mutex_unlock(g_networkMonitorContextMutex);
600         return CA_STATUS_FAILED;
601     }
602
603     ca_mutex_unlock(g_networkMonitorContextMutex);
604
605     ca_mutex_lock(g_stopNetworkMonitorMutex);
606     if (!g_stopNetworkMonitor)
607     {
608         g_stopNetworkMonitor = true;
609     }
610     else
611     {
612         OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPStopNetworkMonitor, already stopped!");
613     }
614     ca_mutex_unlock(g_stopNetworkMonitorMutex);
615
616     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
617     return CA_STATUS_OK;
618 }
619
620 CAResult_t CAIPGetInterfaceInfo(u_arraylist_t **netInterfaceList)
621 {
622     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
623
624     VERIFY_NON_NULL(netInterfaceList, IP_MONITOR_TAG, "u_array_list is null");
625     VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG, "g_networkMonitorContext is null");
626     VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG,
627                     "g_networkMonitorContextMutex is null");
628
629     // Get the interface and ipaddress information from cache
630     ca_mutex_lock(g_networkMonitorContextMutex);
631     if (!g_networkMonitorContext->netInterfaceList
632         || !(u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
633     {
634         OIC_LOG(ERROR, IP_MONITOR_TAG, "Network not enabled");
635         ca_mutex_unlock(g_networkMonitorContextMutex);
636         return CA_ADAPTER_NOT_ENABLED;
637     }
638
639     uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
640     OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo list length [%d]",
641             list_length);
642     for (uint32_t list_index = 0; list_index < list_length; list_index++)
643     {
644         CANetInfo_t *info = (CANetInfo_t *) u_arraylist_get(
645                 g_networkMonitorContext->netInterfaceList, list_index);
646         if (!info)
647         {
648             continue;
649         }
650         OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo ip [%s]",
651                   info->ipAddress);
652         CANetInfo_t *newNetinfo = (CANetInfo_t *) OICMalloc(sizeof(CANetInfo_t));
653         if (!newNetinfo)
654         {
655             OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed!");
656             ca_mutex_unlock(g_networkMonitorContextMutex);
657             return CA_MEMORY_ALLOC_FAILED;
658         }
659
660         memcpy(newNetinfo, info, sizeof(*info));
661
662         CAResult_t result = u_arraylist_add(*netInterfaceList, (void *) newNetinfo);
663         if (CA_STATUS_OK != result)
664         {
665             OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
666             ca_mutex_unlock(g_networkMonitorContextMutex);
667             return CA_STATUS_FAILED;
668         }
669     }
670
671     ca_mutex_unlock(g_networkMonitorContextMutex);
672
673     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
674     return CA_STATUS_OK;
675 }
676
677 CAResult_t CAIPGetInterfaceSubnetMask(const char *ipAddress, char **subnetMask)
678 {
679     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
680
681     VERIFY_NON_NULL(subnetMask, IP_MONITOR_TAG, "subnet mask");
682     VERIFY_NON_NULL(ipAddress, IP_MONITOR_TAG, "ipAddress is null");
683     VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG, "g_networkMonitorContext is null");
684     VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG,
685                     "g_networkMonitorContextMutex is null");
686
687     // Get the interface and ipaddress information from cache
688     ca_mutex_lock(g_networkMonitorContextMutex);
689     if (!g_networkMonitorContext->netInterfaceList
690         || (0 == u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
691     {
692         OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network not enabled");
693         ca_mutex_unlock(g_networkMonitorContextMutex);
694         return CA_ADAPTER_NOT_ENABLED;
695     }
696
697     uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
698     OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "list lenght [%d]", list_length);
699     for (uint32_t list_index = 0; list_index < list_length; list_index++)
700     {
701         CANetInfo_t *info = (CANetInfo_t *) u_arraylist_get(
702                 g_networkMonitorContext->netInterfaceList, list_index);
703         if (!info)
704         {
705             continue;
706         }
707
708         if (strncmp(info->ipAddress, ipAddress, strlen(ipAddress)) == 0)
709         {
710             OIC_LOG_V(DEBUG, IP_MONITOR_TAG,
711                       "CAIPGetInterfaceSubnetMask subnetmask is %s", info->subnetMask);
712             *subnetMask = OICStrdup(info->subnetMask);
713             break;
714         }
715     }
716     ca_mutex_unlock(g_networkMonitorContextMutex);
717
718     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
719     return CA_STATUS_OK;
720 }
721
722 bool CAIPIsConnected()
723 {
724     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
725     if (!g_networkMonitorContextMutex || !g_networkMonitorContext)
726     {
727         OIC_LOG(ERROR, IP_MONITOR_TAG, "IP is not connected");
728         return false;
729     }
730
731     ca_mutex_lock(g_networkMonitorContextMutex);
732     if (0 == u_arraylist_length(g_networkMonitorContext->netInterfaceList))
733     {
734         OIC_LOG(ERROR, IP_MONITOR_TAG, "IP is not connected");
735         ca_mutex_unlock(g_networkMonitorContextMutex);
736         return false;
737     }
738     ca_mutex_unlock(g_networkMonitorContextMutex);
739
740     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
741     return true;
742 }
743
744 void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback)
745 {
746     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
747     if (!g_networkMonitorContextMutex || !g_networkMonitorContext)
748     {
749         OIC_LOG(ERROR, IP_MONITOR_TAG, "CAIPSetConnectionStateChangeCallback failed");
750         return;
751     }
752     ca_mutex_lock(g_networkMonitorContextMutex);
753
754     g_networkMonitorContext->networkChangeCb = callback;
755
756     ca_mutex_unlock(g_networkMonitorContextMutex);
757
758     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
759 }
760
761 void CAIPSendNetworkChangeCallback(CANetworkStatus_t currNetworkStatus)
762 {
763     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
764     ca_mutex_lock(g_stopNetworkMonitorMutex);
765
766     if (g_stopNetworkMonitor)
767     {
768         OIC_LOG(DEBUG, IP_MONITOR_TAG, "Stop Network Monitor Thread is called");
769         ca_mutex_unlock(g_stopNetworkMonitorMutex);
770         return;
771     }
772     ca_mutex_unlock(g_stopNetworkMonitorMutex);
773     ca_mutex_lock(g_networkMonitorContextMutex);
774     if(!g_networkMonitorContext)
775     {
776         OIC_LOG(DEBUG, IP_MONITOR_TAG, "g_networkChangeCb is NULL");
777         ca_mutex_unlock(g_networkMonitorContextMutex);
778         return;
779     }
780     if (!g_networkMonitorContext->networkChangeCb)
781     {    
782         OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkChangeCb->networkChangeCb is NULL");
783         ca_mutex_unlock(g_networkMonitorContextMutex);
784         return;
785     }
786
787     ca_mutex_unlock(g_networkMonitorContextMutex);
788   
789     u_arraylist_t *netInterfaceList = u_arraylist_create();
790
791     VERIFY_NON_NULL_VOID(netInterfaceList, IP_MONITOR_TAG,
792                          "memory allocation failed for netInterfaceList");
793
794     // if network status is changed
795     CAResult_t ret = CAIPUpdateInterfaceInformation(&netInterfaceList);
796     if (CA_STATUS_OK != ret)
797     {
798         OIC_LOG(ERROR, IP_MONITOR_TAG, "could not update interface information");
799     }
800
801     ca_mutex_lock(g_networkMonitorContextMutex);
802     if (!g_networkMonitorContext->netInterfaceList)
803     {
804         OIC_LOG(ERROR, IP_MONITOR_TAG,
805                 "u_arraylist_create failed. Network Monitor thread stopped");
806         CAClearNetInterfaceInfoList(netInterfaceList);
807         ca_mutex_unlock(g_networkMonitorContextMutex);
808         return;
809     }
810
811     uint32_t listLength = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
812     for (uint32_t listIndex = 0; listIndex < listLength;)
813     {
814         CANetInfo_t *info = (CANetInfo_t *) u_arraylist_get(
815                 g_networkMonitorContext->netInterfaceList, listIndex);
816         if (!info)
817         {
818             listIndex++;
819             continue;
820         }
821
822         bool ret = CACheckIsAnyInterfaceDown(netInterfaceList, info);
823         if (ret)
824         {
825             OIC_LOG(DEBUG, IP_MONITOR_TAG, "Interface is down");
826             if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, listIndex))
827             {
828                 OIC_LOG(DEBUG, IP_MONITOR_TAG, "u_arraylist_remove success");
829                 if (g_networkMonitorContext->networkChangeCb)
830                 {
831                     g_networkMonitorContext->networkChangeCb(info->ipAddress, CA_INTERFACE_DOWN);
832                 }
833                 OICFree(info);
834                 listLength--;
835             }
836             else
837             {
838                 OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed");
839                 break;
840             }
841         }
842         else
843         {
844             listIndex++;
845         }
846     }
847
848     ca_mutex_unlock(g_networkMonitorContextMutex);
849
850     listLength = u_arraylist_length(netInterfaceList);
851     for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
852     {
853         CANetInfo_t *info = (CANetInfo_t *) u_arraylist_get(netInterfaceList, listIndex);
854         if (!info)
855         {
856             continue;
857         }
858         bool ret = CACheckIsInterfaceInfoChanged(info);
859         if (ret)
860         {
861             OIC_LOG(DEBUG, IP_MONITOR_TAG, "CACheckIsInterfaceInfoChanged true");
862         }
863     }
864
865     CAClearNetInterfaceInfoList(netInterfaceList);
866     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
867 }
868
869 JNIEXPORT void JNICALL Java_org_iotivity_ca_CaIpInterface_stateEnabled
870   (JNIEnv *env, jclass clazz)
871 {
872     CANetworkStatus_t currNetworkStatus = CA_INTERFACE_UP;
873     OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPStateEnabled");
874
875     CAIPSendNetworkChangeCallback(currNetworkStatus);
876 }
877
878 JNIEXPORT void JNICALL Java_org_iotivity_ca_CaIpInterface_stateDisabled
879   (JNIEnv *env, jclass clazz)
880 {
881     CANetworkStatus_t currNetworkStatus = CA_INTERFACE_DOWN;
882     OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPStateDisabled");
883
884     CAIPSendNetworkChangeCallback(currNetworkStatus);
885 }
886