prevent defects resolved (removed not useful code)
[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     for (int32_t i = 0; i < interfaces; i++)
245     {
246         struct ifreq temp_ifr = { 0 };
247         struct ifreq* item = &ifr[i];
248
249         char interfaceAddress[CA_IPADDR_SIZE] = { 0 };
250         char interfaceSubnetMask[CA_IPADDR_SIZE] = { 0 };
251         socklen_t len = sizeof(struct sockaddr_in);
252
253         strcpy(temp_ifr.ifr_name, item->ifr_name);
254
255         if (ioctl(sck, SIOCGIFFLAGS, &temp_ifr))
256         {
257             OIC_LOG(ERROR, IP_MONITOR_TAG,
258                     "CAIPUpdateInterfaceInformation, SIOCGIFFLAGS Failed");
259             close(sck);
260             return CA_STATUS_FAILED;
261         }
262
263         if ((temp_ifr.ifr_flags & IFF_LOOPBACK)
264             || !(temp_ifr.ifr_flags & IFF_UP) || !(temp_ifr.ifr_flags & IFF_RUNNING))
265         {
266             continue;
267         }
268
269         if (AF_INET != ((struct sockaddr_in*) &item->ifr_addr)->sin_family)
270         {
271             continue;
272         }
273
274         //get the interface ip address
275         if (0 != getnameinfo(&item->ifr_addr, len, interfaceAddress, sizeof(interfaceAddress),
276                              NULL, 0, NI_NUMERICHOST))
277         {
278             OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get IPAddress, Error code: %s",
279                     strerror(errno));
280             close(sck);
281             return CA_STATUS_FAILED;
282         }
283
284         if (ioctl((int) sck, SIOCGIFNETMASK, item) < 0)
285         {
286             OIC_LOG(ERROR, IP_MONITOR_TAG,
287                     "CAIPUpdateInterfaceInformation, SIOCGIFNETMASK Failed");
288             close(sck);
289             return CA_STATUS_FAILED;
290         }
291
292         // get the interface subnet mask
293         if (0 != getnameinfo(&item->ifr_netmask, len, interfaceSubnetMask,
294                              sizeof(interfaceSubnetMask), NULL, 0, NI_NUMERICHOST))
295         {
296             OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get subnet mask, Error code: %s",
297                     strerror(errno));
298             close(sck);
299             return CA_STATUS_FAILED;
300         }
301
302         CANetInfo_t *netInfo = (CANetInfo_t *) OICCalloc(1, sizeof(CANetInfo_t));
303         if (!netInfo)
304         {
305             OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed");
306             close(sck);
307             return CA_MEMORY_ALLOC_FAILED;
308         }
309
310         // set interface name
311         strncpy(netInfo->interfaceName, item->ifr_name, strlen(item->ifr_name));
312
313         // set local ip address
314         strncpy(netInfo->ipAddress, interfaceAddress, strlen(interfaceAddress));
315
316         // set subnet mask
317         strncpy(netInfo->subnetMask, interfaceSubnetMask, strlen(interfaceSubnetMask));
318
319         CAResult_t result = u_arraylist_add(*netInterfaceList, (void *) netInfo);
320         if (CA_STATUS_OK != result)
321         {
322             OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!Thread exiting.");
323             close(sck);
324             return CA_STATUS_FAILED;
325         }
326
327         OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "ipAddress : %s, interfaceName : %s, subnetmask : %s",
328                 netInfo->ipAddress, netInfo->interfaceName, netInfo->subnetMask);
329         close(sck);
330         return CA_STATUS_OK;
331
332         break;
333     }
334
335     close(sck);
336     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
337     return CA_STATUS_FAILED;
338 }
339
340 static bool CACheckIsAnyInterfaceDown(const u_arraylist_t *netInterfaceList,
341                                       const CANetInfo_t *info)
342 {
343     VERIFY_NON_NULL_RET(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null", false);
344     VERIFY_NON_NULL_RET(info, IP_MONITOR_TAG, "info is null", false);
345
346     uint32_t list_length = u_arraylist_length(netInterfaceList);
347     for (uint32_t list_index = 0; list_index < list_length; list_index++)
348     {
349         CANetInfo_t *netInfo = (CANetInfo_t *) u_arraylist_get(netInterfaceList, list_index);
350         if (!netInfo)
351         {
352             continue;
353         }
354         if (strncmp(netInfo->interfaceName, info->interfaceName, strlen(info->interfaceName)) == 0)
355         {
356             return false;
357         }
358     }
359     OIC_LOG(DEBUG, IP_MONITOR_TAG, "Interface is down");
360     return true;
361 }
362
363 static bool CACheckIsInterfaceInfoChanged(const CANetInfo_t *info)
364 {
365     VERIFY_NON_NULL_RET(info, IP_MONITOR_TAG, "info is null", false);
366
367     ca_mutex_lock(g_networkMonitorContextMutex);
368
369     uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
370     for (uint32_t list_index = 0; list_index < list_length; list_index++)
371     {
372         CANetInfo_t *netInfo = (CANetInfo_t *) u_arraylist_get(
373                                g_networkMonitorContext->netInterfaceList, list_index);
374         if (!netInfo)
375         {
376             continue;
377         }
378         if (strncmp(netInfo->interfaceName, info->interfaceName, strlen(info->interfaceName)) == 0)
379         {
380             if (strncmp(netInfo->ipAddress, info->ipAddress, strlen(info->ipAddress)) == 0)
381             {
382                 ca_mutex_unlock(g_networkMonitorContextMutex);
383                 return false;
384             }
385             else
386             {
387                 OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network interface info changed");
388                 if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, list_index))
389                 {
390                     if (g_networkMonitorContext->networkChangeCb)
391                     {
392                         g_networkMonitorContext->networkChangeCb(netInfo->ipAddress,
393                                                                  CA_INTERFACE_DOWN);
394                     }
395                     OICFree(netInfo);
396                 }
397                 else
398                 {
399                     OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed");
400                 }
401                 break;
402             }
403         }
404     }
405
406     CANetInfo_t *newNetInfo = (CANetInfo_t *) OICMalloc(sizeof(CANetInfo_t));
407     if (!newNetInfo)
408     {
409         OIC_LOG(ERROR, IP_MONITOR_TAG, "newNetInfo malloc failed");
410         ca_mutex_unlock(g_networkMonitorContextMutex);
411         return false;
412     }
413     memcpy(newNetInfo, info, sizeof(*newNetInfo));
414
415     OIC_LOG(DEBUG, IP_MONITOR_TAG, "New Interface found");
416
417     CAResult_t result = u_arraylist_add(g_networkMonitorContext->netInterfaceList,
418                                         (void *) newNetInfo);
419     if (CA_STATUS_OK != result)
420     {
421         OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
422         OICFree(newNetInfo);
423         ca_mutex_unlock(g_networkMonitorContextMutex);
424         return false;
425     }
426     ca_mutex_unlock(g_networkMonitorContextMutex);
427
428     /*Callback will be unset only at the time of termination. By that time, all the threads will be
429       stopped gracefully. This callback is properly protected*/
430     if (g_networkMonitorContext->networkChangeCb)
431     {
432         g_networkMonitorContext->networkChangeCb(newNetInfo->ipAddress, CA_INTERFACE_UP);
433     }
434
435     return true;
436 }
437
438 static CAResult_t CAInitializeNetworkMonitorMutexes()
439 {
440     if (!g_networkMonitorContextMutex)
441     {
442         g_networkMonitorContextMutex = ca_mutex_new();
443         if (!g_networkMonitorContextMutex)
444         {
445             OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContextMutex Malloc  failed");
446             return CA_MEMORY_ALLOC_FAILED;
447         }
448     }
449
450     if (!g_stopNetworkMonitorMutex)
451     {
452         g_stopNetworkMonitorMutex = ca_mutex_new();
453         if (!g_stopNetworkMonitorMutex)
454         {
455             OIC_LOG(ERROR, IP_MONITOR_TAG, "g_stopNetworkMonitorMutex Malloc  failed");
456             ca_mutex_free(g_networkMonitorContextMutex);
457             return CA_MEMORY_ALLOC_FAILED;
458         }
459     }
460     return CA_STATUS_OK;
461 }
462
463 static void CADestroyNetworkMonitorMutexes()
464 {
465     ca_mutex_free(g_networkMonitorContextMutex);
466     g_networkMonitorContextMutex = NULL;
467
468     ca_mutex_free(g_stopNetworkMonitorMutex);
469     g_stopNetworkMonitorMutex = NULL;
470 }
471
472 CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool)
473 {
474     OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPInitializeNetworkMonitor IN");
475
476     VERIFY_NON_NULL(threadPool, IP_MONITOR_TAG, "threadPool is null");
477
478     CAResult_t ret = CAIPJniInit();
479     if (CA_STATUS_OK != ret)
480     {
481         OIC_LOG(ERROR, IP_MONITOR_TAG, "Initialization failed");
482         return ret;
483     }
484
485     ret = CAIPJniSetContext();
486     if (CA_STATUS_OK != ret)
487     {
488         OIC_LOG(ERROR, IP_MONITOR_TAG, "CAIPJniSetContext failed");
489         return ret;
490     }
491
492     ret = CACreateIPJNIInterfaceObject(g_context);
493     if (CA_STATUS_OK != ret)
494     {
495         OIC_LOG(ERROR, IP_MONITOR_TAG, "unable to create caipinterface instance");
496         return ret;
497     }
498
499     ret = CAInitializeNetworkMonitorMutexes();
500
501     if (CA_STATUS_OK != ret)
502     {
503         OIC_LOG(ERROR, IP_MONITOR_TAG, "CAInitializeNetworkMonitorMutexes failed");
504         return CA_STATUS_FAILED;
505     }
506
507     ca_mutex_lock(g_networkMonitorContextMutex);
508
509     g_networkMonitorContext = (CAIPNetworkMonitorContext *) OICCalloc(
510             1, sizeof(*g_networkMonitorContext));
511     if (!g_networkMonitorContext)
512     {
513         OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext Malloc  failed");
514         ca_mutex_unlock(g_networkMonitorContextMutex);
515         CADestroyNetworkMonitorMutexes();
516         return CA_MEMORY_ALLOC_FAILED;
517     }
518     g_networkMonitorContext->threadPool = threadPool;
519
520     g_networkMonitorContext->netInterfaceList = u_arraylist_create();
521     if (!g_networkMonitorContext->netInterfaceList)
522     {
523         OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_create failed");
524         OICFree(g_networkMonitorContext);
525         ca_mutex_unlock(g_networkMonitorContextMutex);
526         CADestroyNetworkMonitorMutexes();
527         return CA_MEMORY_ALLOC_FAILED;
528     }
529
530     CAIPUpdateInterfaceInformation(&g_networkMonitorContext->netInterfaceList);
531
532     if (u_arraylist_length(g_networkMonitorContext->netInterfaceList))
533     {
534         g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_UP;
535     }
536     else
537     {
538         g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN;
539     }
540
541     ca_mutex_unlock(g_networkMonitorContextMutex);
542
543     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
544     return CA_STATUS_OK;
545 }
546
547 void CAIPTerminateNetworkMonitor()
548 {
549     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
550
551     ca_mutex_lock(g_networkMonitorContextMutex);
552     g_networkMonitorContext->threadPool = NULL;
553
554     CAClearNetInterfaceInfoList(g_networkMonitorContext->netInterfaceList);
555
556     g_networkMonitorContext->netInterfaceList = NULL;
557     g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN;
558     g_networkMonitorContext->networkChangeCb = NULL;
559     g_networkMonitorContext->threadPool = NULL;
560
561     OICFree(g_networkMonitorContext);
562     g_networkMonitorContext = NULL;
563
564     ca_mutex_unlock(g_networkMonitorContextMutex);
565
566     ca_mutex_lock(g_stopNetworkMonitorMutex);
567     g_stopNetworkMonitor = true;
568     ca_mutex_unlock(g_stopNetworkMonitorMutex);
569
570     CADestroyNetworkMonitorMutexes();
571
572     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
573 }
574
575 CAResult_t CAIPStartNetworkMonitor()
576 {
577     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
578
579     ca_mutex_lock(g_stopNetworkMonitorMutex);
580     g_stopNetworkMonitor = false;
581     ca_mutex_unlock(g_stopNetworkMonitorMutex);
582
583     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
584     return CA_STATUS_OK;
585 }
586
587 CAResult_t CAIPStopNetworkMonitor()
588 {
589     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
590
591     ca_mutex_lock(g_networkMonitorContextMutex);
592     if (!g_networkMonitorContext)
593     {
594         OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext is null");
595         ca_mutex_unlock(g_networkMonitorContextMutex);
596         return CA_STATUS_FAILED;
597     }
598
599     ca_mutex_unlock(g_networkMonitorContextMutex);
600
601     ca_mutex_lock(g_stopNetworkMonitorMutex);
602     if (!g_stopNetworkMonitor)
603     {
604         g_stopNetworkMonitor = true;
605     }
606     else
607     {
608         OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPStopNetworkMonitor, already stopped!");
609     }
610     ca_mutex_unlock(g_stopNetworkMonitorMutex);
611
612     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
613     return CA_STATUS_OK;
614 }
615
616 CAResult_t CAIPGetInterfaceInfo(u_arraylist_t **netInterfaceList)
617 {
618     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
619
620     VERIFY_NON_NULL(netInterfaceList, IP_MONITOR_TAG, "u_array_list is null");
621     VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG, "g_networkMonitorContext is null");
622     VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG,
623                     "g_networkMonitorContextMutex is null");
624
625     // Get the interface and ipaddress information from cache
626     ca_mutex_lock(g_networkMonitorContextMutex);
627     if (!g_networkMonitorContext->netInterfaceList
628         || !(u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
629     {
630         OIC_LOG(ERROR, IP_MONITOR_TAG, "Network not enabled");
631         ca_mutex_unlock(g_networkMonitorContextMutex);
632         return CA_ADAPTER_NOT_ENABLED;
633     }
634
635     uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
636     OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo list length [%d]",
637             list_length);
638     for (uint32_t list_index = 0; list_index < list_length; list_index++)
639     {
640         CANetInfo_t *info = (CANetInfo_t *) u_arraylist_get(
641                 g_networkMonitorContext->netInterfaceList, list_index);
642         if (!info)
643         {
644             continue;
645         }
646         OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo ip [%s]",
647                   info->ipAddress);
648         CANetInfo_t *newNetinfo = (CANetInfo_t *) OICMalloc(sizeof(CANetInfo_t));
649         if (!newNetinfo)
650         {
651             OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed!");
652             ca_mutex_unlock(g_networkMonitorContextMutex);
653             return CA_MEMORY_ALLOC_FAILED;
654         }
655
656         memcpy(newNetinfo, info, sizeof(*info));
657
658         CAResult_t result = u_arraylist_add(*netInterfaceList, (void *) newNetinfo);
659         if (CA_STATUS_OK != result)
660         {
661             OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
662             ca_mutex_unlock(g_networkMonitorContextMutex);
663             return CA_STATUS_FAILED;
664         }
665     }
666
667     ca_mutex_unlock(g_networkMonitorContextMutex);
668
669     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
670     return CA_STATUS_OK;
671 }
672
673 CAResult_t CAIPGetInterfaceSubnetMask(const char *ipAddress, char **subnetMask)
674 {
675     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
676
677     VERIFY_NON_NULL(subnetMask, IP_MONITOR_TAG, "subnet mask");
678     VERIFY_NON_NULL(ipAddress, IP_MONITOR_TAG, "ipAddress is null");
679     VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG, "g_networkMonitorContext is null");
680     VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG,
681                     "g_networkMonitorContextMutex is null");
682
683     // Get the interface and ipaddress information from cache
684     ca_mutex_lock(g_networkMonitorContextMutex);
685     if (!g_networkMonitorContext->netInterfaceList
686         || (0 == u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
687     {
688         OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network not enabled");
689         ca_mutex_unlock(g_networkMonitorContextMutex);
690         return CA_ADAPTER_NOT_ENABLED;
691     }
692
693     uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
694     OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "list lenght [%d]", list_length);
695     for (uint32_t list_index = 0; list_index < list_length; list_index++)
696     {
697         CANetInfo_t *info = (CANetInfo_t *) u_arraylist_get(
698                 g_networkMonitorContext->netInterfaceList, list_index);
699         if (!info)
700         {
701             continue;
702         }
703
704         if (strncmp(info->ipAddress, ipAddress, strlen(ipAddress)) == 0)
705         {
706             OIC_LOG_V(DEBUG, IP_MONITOR_TAG,
707                       "CAIPGetInterfaceSubnetMask subnetmask is %s", info->subnetMask);
708             *subnetMask = OICStrdup(info->subnetMask);
709             break;
710         }
711     }
712     ca_mutex_unlock(g_networkMonitorContextMutex);
713
714     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
715     return CA_STATUS_OK;
716 }
717
718 bool CAIPIsConnected()
719 {
720     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
721     if (!g_networkMonitorContextMutex || !g_networkMonitorContext)
722     {
723         OIC_LOG(ERROR, IP_MONITOR_TAG, "IP is not connected");
724         return false;
725     }
726
727     ca_mutex_lock(g_networkMonitorContextMutex);
728     if (0 == u_arraylist_length(g_networkMonitorContext->netInterfaceList))
729     {
730         OIC_LOG(ERROR, IP_MONITOR_TAG, "IP is not connected");
731         ca_mutex_unlock(g_networkMonitorContextMutex);
732         return false;
733     }
734     ca_mutex_unlock(g_networkMonitorContextMutex);
735
736     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
737     return true;
738 }
739
740 void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback)
741 {
742     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
743     if (!g_networkMonitorContextMutex || !g_networkMonitorContext)
744     {
745         OIC_LOG(ERROR, IP_MONITOR_TAG, "CAIPSetConnectionStateChangeCallback failed");
746         return;
747     }
748     ca_mutex_lock(g_networkMonitorContextMutex);
749
750     g_networkMonitorContext->networkChangeCb = callback;
751
752     ca_mutex_unlock(g_networkMonitorContextMutex);
753
754     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
755 }
756
757 void CAIPSendNetworkChangeCallback(CANetworkStatus_t currNetworkStatus)
758 {
759     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
760     ca_mutex_lock(g_stopNetworkMonitorMutex);
761
762     if (g_stopNetworkMonitor)
763     {
764         OIC_LOG(DEBUG, IP_MONITOR_TAG, "Stop Network Monitor Thread is called");
765         ca_mutex_unlock(g_stopNetworkMonitorMutex);
766         return;
767     }
768     ca_mutex_unlock(g_stopNetworkMonitorMutex);
769     ca_mutex_lock(g_networkMonitorContextMutex);
770     if(!g_networkMonitorContext)
771     {
772         OIC_LOG(DEBUG, IP_MONITOR_TAG, "g_networkChangeCb is NULL");
773         ca_mutex_unlock(g_networkMonitorContextMutex);
774         return;
775     }
776     if (!g_networkMonitorContext->networkChangeCb)
777     {    
778         OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkChangeCb->networkChangeCb is NULL");
779         ca_mutex_unlock(g_networkMonitorContextMutex);
780         return;
781     }
782
783     ca_mutex_unlock(g_networkMonitorContextMutex);
784   
785     u_arraylist_t *netInterfaceList = u_arraylist_create();
786
787     VERIFY_NON_NULL_VOID(netInterfaceList, IP_MONITOR_TAG,
788                          "memory allocation failed for netInterfaceList");
789
790     // if network status is changed
791     CAResult_t ret = CAIPUpdateInterfaceInformation(&netInterfaceList);
792     if (CA_STATUS_OK != ret)
793     {
794         OIC_LOG(ERROR, IP_MONITOR_TAG, "could not update interface information");
795     }
796
797     ca_mutex_lock(g_networkMonitorContextMutex);
798     if (!g_networkMonitorContext->netInterfaceList)
799     {
800         OIC_LOG(ERROR, IP_MONITOR_TAG,
801                 "u_arraylist_create failed. Network Monitor thread stopped");
802         CAClearNetInterfaceInfoList(netInterfaceList);
803         ca_mutex_unlock(g_networkMonitorContextMutex);
804         return;
805     }
806
807     uint32_t listLength = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
808     for (uint32_t listIndex = 0; listIndex < listLength;)
809     {
810         CANetInfo_t *info = (CANetInfo_t *) u_arraylist_get(
811                 g_networkMonitorContext->netInterfaceList, listIndex);
812         if (!info)
813         {
814             listIndex++;
815             continue;
816         }
817
818         bool ret = CACheckIsAnyInterfaceDown(netInterfaceList, info);
819         if (ret)
820         {
821             OIC_LOG(DEBUG, IP_MONITOR_TAG, "Interface is down");
822             if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, listIndex))
823             {
824                 OIC_LOG(DEBUG, IP_MONITOR_TAG, "u_arraylist_remove success");
825                 if (g_networkMonitorContext->networkChangeCb)
826                 {
827                     g_networkMonitorContext->networkChangeCb(info->ipAddress, CA_INTERFACE_DOWN);
828                 }
829                 OICFree(info);
830                 listLength--;
831             }
832             else
833             {
834                 OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed");
835                 break;
836             }
837         }
838         else
839         {
840             listIndex++;
841         }
842     }
843
844     ca_mutex_unlock(g_networkMonitorContextMutex);
845
846     listLength = u_arraylist_length(netInterfaceList);
847     for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
848     {
849         CANetInfo_t *info = (CANetInfo_t *) u_arraylist_get(netInterfaceList, listIndex);
850         if (!info)
851         {
852             continue;
853         }
854         bool ret = CACheckIsInterfaceInfoChanged(info);
855         if (ret)
856         {
857             OIC_LOG(DEBUG, IP_MONITOR_TAG, "CACheckIsInterfaceInfoChanged true");
858         }
859     }
860
861     CAClearNetInterfaceInfoList(netInterfaceList);
862     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
863 }
864
865 JNIEXPORT void JNICALL Java_org_iotivity_ca_CaIpInterface_stateEnabled
866   (JNIEnv *env, jclass clazz)
867 {
868     CANetworkStatus_t currNetworkStatus = CA_INTERFACE_UP;
869     OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPStateEnabled");
870
871     CAIPSendNetworkChangeCallback(currNetworkStatus);
872 }
873
874 JNIEXPORT void JNICALL Java_org_iotivity_ca_CaIpInterface_stateDisabled
875   (JNIEnv *env, jclass clazz)
876 {
877     CANetworkStatus_t currNetworkStatus = CA_INTERFACE_DOWN;
878     OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPStateDisabled");
879
880     CAIPSendNetworkChangeCallback(currNetworkStatus);
881 }
882