OSDN Git Service

Use native code to convert IP addresses to strings.
authorLorenzo Colitti <lorenzo@google.com>
Thu, 17 Sep 2009 22:01:47 +0000 (15:01 -0700)
committerLorenzo Colitti <lorenzo@google.com>
Fri, 18 Sep 2009 20:41:06 +0000 (13:41 -0700)
- Add a byteArrayToIpString method to the INetworkSystem interface and implement
  it in native code
- Fix the native code so it does better error reporting
- Change InetAddress's getHostAddress, getHostName and getCanonicalHostName
  methods to use it and remove the IPv4-only Java implementations
- Remove Inet6Util.createIPAddrStringFromByteArray
- Fix InetAddress so getByAddress(null) throws UnknownHostException instead of
  NullPointerException for compatibility with the RI.

Change-Id: I26548922e9eed63b295173456183c4ab3ce20718

libcore/luni/src/main/java/java/net/Inet4Address.java
libcore/luni/src/main/java/java/net/Inet6Address.java
libcore/luni/src/main/java/java/net/InetAddress.java
libcore/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
libcore/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java
libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp

index 5e1a420..b467b64 100644 (file)
@@ -217,22 +217,10 @@ public final class Inet4Address extends InetAddress {
         return prefix >= 0xEFC0 && prefix <= 0xEFC3;
     }
 
-    /**
-     * Returns a textual representation of this IP address.
-     * 
-     * @return the textual representation of this host address.
-     */
-    @Override
-    public String getHostAddress() {
-        String hostAddress = ""; //$NON-NLS-1$
-        for (int i = 0; i < 4; i++) {
-            hostAddress += ipaddress[i] & 255;
-            if (i != 3) {
-                hostAddress += "."; //$NON-NLS-1$
-            }
-        }
-        return hostAddress;
-    }
+    // BEGIN android-removed
+    // public String getHostAddress() {
+    // }
+    // END android-removed
 
     // BEGIN android-removed
     // public int hashCode() {
index 91ec48e..f333770 100644 (file)
@@ -362,15 +362,10 @@ public final class Inet6Address extends InetAddress {
         return (ipaddress[0] == -1) && (ipaddress[1] & 15) == 8;
     }
 
-    /**
-     * Gets the textual representation of this IP address.
-     * 
-     * @return the as a dotted string formatted IP address.
-     */
-    @Override
-    public String getHostAddress() {
-        return Inet6Util.createIPAddrStringFromByteArray(ipaddress);
-    }
+    // BEGIN android-removed
+    // public String getHostAddress() {
+    // }
+    // END android-removed
 
     /**
      * Gets the scope id as a number if this address is linked to an interface.
index a7ea3f6..0fa4796 100644 (file)
@@ -301,14 +301,31 @@ public class InetAddress extends Object implements Serializable {
         return getAllByNameImpl(host, false)[0];
     }
 
+    /*
+     * Convenience method to convert a byte array to a string, converting
+     * exceptions to runtime exceptions. This is used when passing in byte
+     * arrays that have been verified to be correct and is necessary because
+     * some methods, such as getHostName(), are not allowed to throw exceptions
+     * but are implemented using byteArrayToIpString(), which throws
+     * UnknownHostException. Exceptions should never occur when the address is
+     * valid, but they cannot be simply ignored because they could be due to
+     * runtime errors such as out-of-memory conditions.
+     */
+    private static String ipAddressToString(byte[] ipaddress) {
+        try {
+            return NETIMPL.byteArrayToIpString(ipaddress);
+        } catch(UnknownHostException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
     /**
      * Gets the textual representation of this IP address.
      *
-     * @return the textual representation of this host address in form of a
-     *         dotted string.
+     * @return the textual representation of host's IP address.
      */
     public String getHostAddress() {
-        return inetNtoaImpl(bytesToInt(ipaddress, 0));
+        return ipAddressToString(ipaddress);
     }
 
     /**
@@ -325,18 +342,17 @@ public class InetAddress extends Object implements Serializable {
                 if (ipaddress.length == 4) {
                     address = bytesToInt(ipaddress, 0);
                     if (address == 0) {
-                        return hostName = inetNtoaImpl(address);
+                        return hostName = ipAddressToString(ipaddress);
                     }
                 }
                 hostName = getHostByAddrImpl(ipaddress).hostName;
                 if (hostName.equals("localhost") && ipaddress.length == 4 //$NON-NLS-1$
                         && address != 0x7f000001) {
-                    return hostName = inetNtoaImpl(address);
+                    return hostName = ipAddressToString(ipaddress);
                 }
             }
         } catch (UnknownHostException e) {
-            return hostName = Inet6Util
-                    .createIPAddrStringFromByteArray(ipaddress);
+            return hostName = ipAddressToString(ipaddress);
         }
         SecurityManager security = System.getSecurityManager();
         try {
@@ -345,7 +361,7 @@ public class InetAddress extends Object implements Serializable {
                 security.checkConnect(hostName, -1);
             }
         } catch (SecurityException e) {
-            return Inet6Util.createIPAddrStringFromByteArray(ipaddress);
+            return ipAddressToString(ipaddress);
         }
         return hostName;
     }
@@ -365,12 +381,12 @@ public class InetAddress extends Object implements Serializable {
             if (ipaddress.length == 4) {
                 address = bytesToInt(ipaddress, 0);
                 if (address == 0) {
-                    return inetNtoaImpl(address);
+                    return ipAddressToString(ipaddress);
                 }
             }
             canonicalName = getHostByAddrImpl(ipaddress).hostName;
         } catch (UnknownHostException e) {
-            return Inet6Util.createIPAddrStringFromByteArray(ipaddress);
+            return ipAddressToString(ipaddress);
         }
         SecurityManager security = System.getSecurityManager();
         try {
@@ -379,7 +395,7 @@ public class InetAddress extends Object implements Serializable {
                 security.checkConnect(canonicalName, -1);
             }
         } catch (SecurityException e) {
-            return Inet6Util.createIPAddrStringFromByteArray(ipaddress);
+            return ipAddressToString(ipaddress);
         }
         return canonicalName;
     }
@@ -550,10 +566,9 @@ public class InetAddress extends Object implements Serializable {
     private static native String gethostbyaddr(byte[] addr);
     // END android-changed
 
-    static int inetAddr(String host) throws UnknownHostException {
-        return (host.equals("255.255.255.255")) ? 0xFFFFFFFF //$NON-NLS-1$
-                : inetAddrImpl(host);
-    }
+    // BEGIN android-removed
+    // static int inetAddr(String host) throws UnknownHostException
+    // END android-removed
 
     /**
      * Convert a string containing an IPv4 Internet Protocol dotted address into
@@ -561,41 +576,17 @@ public class InetAddress extends Object implements Serializable {
      * exception, so this value should not be used as an argument. See also
      * inetAddr(String).
      */
-    // BEGIN android-changed
+    // BEGIN android-removed
     // static native int inetAddrImpl(String host) throws UnknownHostException;
-    static int inetAddrImpl(String host) throws UnknownHostException {
-        // TODO Probably not exactly what we want, and also inefficient. Provide native later.
-        try {
-            String[] args = host.split("\\.");
-
-            int a = Integer.parseInt(args[0]) << 24;
-            int b = Integer.parseInt(args[1]) << 16;
-            int c = Integer.parseInt(args[2]) <<  8;
-            int d = Integer.parseInt(args[3])      ;
-
-            return a | b | c | d;
-        } catch (Exception ex) {
-            throw new UnknownHostException(host);
-        }
-    }
-    // END android-changed
+    // END android-removed
 
     /**
      * Convert a binary address into a string containing an Ipv4 Internet
      * Protocol dotted address.
      */
-    // BEGIN android-changed
+    // BEGIN android-removed
     // static native String inetNtoaImpl(int hipAddr);
-    static String inetNtoaImpl(int hipAddr) {
-        // TODO Inefficient and probably wrong. Provide proper (native?) implementation later.
-        int a = (hipAddr >> 24) & 0xFF;
-        int b = (hipAddr >> 16) & 0xFF;
-        int c = (hipAddr >>  8) & 0xFF;
-        int d = (hipAddr      ) & 0xFF;
-
-        return "" + a + "." + b + "." + c + "." + d;
-    }
-    // END android-changed
+    // END android-removed
 
     // BEGIN android-removed
     /**
@@ -1223,7 +1214,11 @@ public class InetAddress extends Object implements Serializable {
     static InetAddress getByAddressInternal(String hostName, byte[] ipAddress,
             int scope_id) throws UnknownHostException {
         if (ipAddress == null) {
-            throw new NullPointerException();
+            // We don't throw NullPointerException here for RI compatibility,
+            // but we do say "address is null" (K0331), instead of "addr is of
+            // illegal length".
+            throw new UnknownHostException(
+                Msg.getString("K0331", hostName)); //$NON-NLS-1$
         }
         switch (ipAddress.length) {
             case 4:
index eae5261..1345341 100644 (file)
@@ -217,7 +217,10 @@ public interface INetworkSystem {
             throws UnknownHostException;
 
     public void setInetAddress(InetAddress sender, byte[] address);
-    
+
+    public String byteArrayToIpString(byte[] address)
+            throws UnknownHostException;
+
     // BEGIN android-removed
     // public boolean isReachableByICMP(InetAddress dest,InetAddress source,int ttl,int timeout);
     // END android-removed
index 70432a6..0fa25ea 100644 (file)
@@ -239,6 +239,9 @@ final class OSNetworkSystem implements INetworkSystem {
         return getSocketFlagsImpl();
     }
 
+    public native String byteArrayToIpString(byte[] address)
+            throws UnknownHostException;
+
     static native int getSocketFlagsImpl();
 
     public InetAddress getSocketLocalAddress(FileDescriptor fd,
index d8b261d..4dae1c3 100644 (file)
@@ -144,55 +144,6 @@ public class Inet6Util {
 
        }
 
-    // BEGIN android-changed
-    static char[] hexCharacters = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
-            '9', 'a', 'b', 'c', 'd', 'e', 'f'};
-    // END android-changed
-
-       public static String createIPAddrStringFromByteArray(byte ipByteArray[]) {
-               if (ipByteArray.length == 4) {
-                       return addressToString(bytesToInt(ipByteArray, 0));
-               }
-
-               if (ipByteArray.length == 16) {
-                       if (isIPv4MappedAddress(ipByteArray)) {
-                               byte ipv4ByteArray[] = new byte[4];
-                               for (int i = 0; i < 4; i++) {
-                                       ipv4ByteArray[i] = ipByteArray[i + 12];
-                               }
-                               return addressToString(bytesToInt(ipv4ByteArray, 0));
-                       }
-            StringBuilder buffer = new StringBuilder();
-            // BEGIN android-changed
-            for (int i = 0; i < 8; i++) { // ipByteArray.length / 2
-
-                int num = (ipByteArray[2 * i] & 0xff) << 8;
-                num ^= ipByteArray[2 * i + 1] & 0xff;
-
-                // count the digits to display without leading 0
-                int count = 1, j = num;
-                while ((j >>>= 4) != 0) {
-                    count++;
-                }
-
-                char[] buf = new char[count];
-                do {
-                    int t = num & 0x0f;
-                    buf[--count] = hexCharacters[t];
-                    num >>>= 4;
-                } while (count > 0);
-
-                buffer.append(buf);
-                if ((i + 1) < 8) { // ipByteArray.length / 2
-                    buffer.append(":");
-                }
-            }
-            // END android-changed
-            return buffer.toString();
-               }
-               return null;
-       }
-
        /** Converts a 4 character hex word into a 2 byte word equivalent */
        public static void convertToBytes(String hexWord, byte ipByteArray[],
                        int byteIndex) {
index d689fc7..909f211 100644 (file)
@@ -333,53 +333,151 @@ static jobject socketAddressToInetAddress(JNIEnv *env,
  * @param port the port number
  * @param sockaddress the sockaddr_storage structure to write to
  *
- * @return 0 on success, -1 on failure
+ * @return 0 on success, a system error code on failure
  *
  * @exception SocketError if the address family is unknown
  */
-static int inetAddressToSocketAddress(JNIEnv *env,
-        jobject inetaddress, int port, struct sockaddr_storage *sockaddress) {
-
-    // Get the byte array that stores the IP address bytes in the InetAddress.
-    jbyteArray addressByteArray;
-    addressByteArray = (jbyteArray)env->GetObjectField(inetaddress,
-            gCachedFields.iaddr_ipaddress);
+static int byteArrayToSocketAddress(JNIEnv *env,
+        jbyteArray addressByteArray, int port, sockaddr_storage *sockaddress) {
     if (addressByteArray == NULL) {
       throwNullPointerException(env);
-      return -1;
+      return EFAULT;
     }
-
-    // Get the raw IP address bytes.
-    jbyte *addressBytes = env->GetByteArrayElements(addressByteArray, NULL);
-    if (addressBytes == NULL) {
-      throwNullPointerException(env);
-      return -1;
-    }
-
     // Convert the IP address bytes to the proper IP address type.
     size_t addressLength = env->GetArrayLength(addressByteArray);
-    int result = 0;
     if (addressLength == 4) {
         // IPv4 address.
-        struct sockaddr_in *sin = (struct sockaddr_in *) sockaddress;
-        memset(sin, 0, sizeof(struct sockaddr_in));
+        sockaddr_in *sin = (sockaddr_in *) sockaddress;
+        memset(sin, 0, sizeof(sockaddr_in));
         sin->sin_family = AF_INET;
         sin->sin_port = htons(port);
-        memcpy(&sin->sin_addr.s_addr, addressBytes, 4);
+        jbyte *rawBytes = (jbyte *) &sin->sin_addr.s_addr;
+        env->GetByteArrayRegion(addressByteArray, 0, 4, rawBytes);
     } else if (addressLength == 16) {
         // IPv6 address.
-        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sockaddress;
-        memset(sin6, 0, sizeof(struct sockaddr_in6));
+        sockaddr_in6 *sin6 = (sockaddr_in6 *) sockaddress;
+        memset(sin6, 0, sizeof(sockaddr_in6));
         sin6->sin6_family = AF_INET6;
         sin6->sin6_port = htons(port);
-        memcpy(&sin6->sin6_addr.s6_addr, addressBytes, 16);
+        jbyte *rawBytes = (jbyte *) &sin6->sin6_addr.s6_addr;
+        env->GetByteArrayRegion(addressByteArray, 0, 16, rawBytes);
     } else {
         // Unknown address family.
         throwSocketException(env, SOCKERR_BADAF);
-        result = -1;
+        return EAFNOSUPPORT;
     }
-    env->ReleaseByteArrayElements(addressByteArray, addressBytes, 0);
-    return result;
+    return 0;
+}
+
+/**
+ * Converts an InetAddress object and port number to a native address structure.
+ * Throws a NullPointerException or a SocketException in case of
+ * error. This is signaled by a return value of -1. The normal
+ * return value is 0.
+ *
+ * @param inetaddress the InetAddress object to convert
+ * @param port the port number
+ * @param sockaddress the sockaddr_storage structure to write to
+ *
+ * @return 0 on success, -1 on failure
+ * @throw UnknownHostException if any error occurs
+ *
+ * @exception SocketError if the address family is unknown
+ */
+static int inetAddressToSocketAddress(JNIEnv *env,
+        jobject inetaddress, int port, sockaddr_storage *sockaddress) {
+
+    // Get the byte array that stores the IP address bytes in the InetAddress.
+    jbyteArray addressByteArray;
+    addressByteArray = (jbyteArray)env->GetObjectField(inetaddress,
+            gCachedFields.iaddr_ipaddress);
+
+    return byteArrayToSocketAddress(env, addressByteArray, port, sockaddress);
+}
+
+/**
+ * Convert a sockaddr_storage structure to a Java string.
+ *
+ * @param address pointer to sockaddr_storage structure to convert.
+ * @param withPort whether to include the port number in the output as well.
+ *
+ * @return 0 on success, a getnameinfo return code on failure.
+ *
+ * @throws SocketException the address family was unknown.
+ */
+static int socketAddressToString(sockaddr_storage *address, char *ipString,
+        int len, bool withPort) {
+    // TODO: getnameinfo seems to want its length parameter to be exactly
+    // sizeof(sockaddr_in) for an IPv4 address and sizeof (sockaddr_in6) for an
+    // IPv6 address. Fix getnameinfo so it accepts sizeof(sockaddr_storage), and
+    // then remove this hack.
+    int size;
+    if (address->ss_family == AF_INET) {
+        size = sizeof(sockaddr_in);
+    } else if (address->ss_family == AF_INET6) {
+        size = sizeof(sockaddr_in6);
+    } else {
+        errno = EAFNOSUPPORT;
+        return EAI_SYSTEM;
+    }
+
+    char tmp[INET6_ADDRSTRLEN];
+    int result = getnameinfo((sockaddr *)address, size, tmp, sizeof(tmp), NULL,
+            0, NI_NUMERICHOST);
+    if (result != 0) {
+        return result;
+    }
+
+    int port;
+    if (withPort) {
+        if (address->ss_family == AF_INET6) {
+            sockaddr_in6 *sin6 = (sockaddr_in6 *) address;
+            port = ntohs(sin6->sin6_port);
+            snprintf(ipString, len, "[%s]:%d", tmp, port);
+        } else {
+            sockaddr_in *sin = (sockaddr_in *) address;
+            port = ntohs(sin->sin_port);
+            snprintf(ipString, len, "%s:%d", tmp, port);
+        }
+    } else {
+        strncpy(ipString, tmp, len);
+    }
+    return 0;
+}
+
+/**
+ * Convert a Java byte array representing an IP address to a Java string.
+ *
+ * @param addressByteArray the byte array to convert.
+ *
+ * @return a string with the textual representation of the address.
+ *
+ * @throws SocketException the address family was unknown.
+ */
+static jstring osNetworkSystem_byteArrayToIpString(JNIEnv *env, jclass clazz,
+        jbyteArray byteArray) {
+    // For compatibility, ensure that an UnknownHostException is thrown if the
+    // address is null.
+    if (byteArray == NULL) {
+        jniThrowException(env, "java/net/UnknownHostException",
+                strerror(EFAULT));
+        return NULL;
+    }
+    struct sockaddr_storage ss;
+    int ret = byteArrayToSocketAddress(env, byteArray, 0, &ss);
+    if (ret) {
+        jniThrowException(env, "java/net/UnknownHostException", strerror(ret));
+        return NULL;
+    }
+    char ipString[INET6_ADDRSTRLEN];
+    ret = socketAddressToString(&ss, ipString, sizeof(ipString), false);
+    if (ret) {
+        env->ExceptionClear();
+        jniThrowException(env, "java/net/UnknownHostException",
+                gai_strerror(ret));
+        return NULL;
+    }
+    return env->NewStringUTF(ipString);
 }
 
 /**
@@ -507,49 +605,6 @@ static bool useAdbNetworkingForAddress(struct sockaddr_storage *address) {
 }
 
 /**
- * Convert a sockaddr_storage structure to a string for logging purposes.
- *
- * @param address pointer to sockaddr_storage structure to print
- *
- * @return a string with the textual representation of the address.
- *
- * @note Returns a statically allocated buffer, so is not thread-safe.
- */
-static char *socketAddressToString(struct sockaddr_storage *address) {
-    static char invalidString[] = "<invalid>";
-    static char ipString[INET6_ADDRSTRLEN + sizeof("[]:65535")];
-
-    char tmp[INET6_ADDRSTRLEN];
-    int port;
-    // TODO: getnameinfo seems to want its length parameter to be exactly
-    // sizeof(sockaddr_in) for an IPv4 address and sizeof (sockaddr_in6) for an
-    // IPv6 address. Fix getnameinfo so it accepts sizeof(sockaddr_storage), and
-    // then remove this hack.
-    int size = (address->ss_family == AF_INET) ?
-            sizeof(sockaddr_in) : sizeof(sockaddr_in6);
-    int result = getnameinfo((struct sockaddr *)address,
-            size, tmp, sizeof(tmp), NULL, 0,
-            NI_NUMERICHOST);
-
-    if (result != 0)
-        return invalidString;
-
-    if (address->ss_family == AF_INET6) {
-        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address;
-        port = ntohs(sin6->sin6_port);
-        sprintf(ipString, "[%s]:%d", tmp, port);
-        return ipString;
-    } else if (address->ss_family == AF_INET) {
-        struct sockaddr_in *sin = (struct sockaddr_in *) address;
-        port = ntohs(sin->sin_port);
-        sprintf(ipString, "%s:%d", tmp, port);
-        return ipString;
-    } else {
-        return invalidString;
-    }
-}
-
-/**
  * Answer the errorString corresponding to the errorNumber, if available.
  * This function will answer a default error string, if the errorNumber is not
  * recognized.
@@ -930,6 +985,23 @@ unsigned short ip_checksum(unsigned short* buffer, int size) {
 }
 
 /**
+ * Converts an IPv4-mapped IPv6 address to an IPv4 address. Performs no error
+ * checking.
+ *
+ * @param address the address to convert. Must contain an IPv4-mapped address.
+ * @param outputAddress the converted address. Will contain an IPv4 address.
+ */
+static void convertMappedToIpv4(sockaddr_storage *address,
+        sockaddr_storage *outputAddress) {
+  memset(outputAddress, 0, sizeof(sockaddr_in));
+  const sockaddr_in6 *sin6 = ((sockaddr_in6 *) address);
+  sockaddr_in *sin = ((sockaddr_in *) outputAddress);
+  sin->sin_family = AF_INET;
+  sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
+  sin->sin_port = sin6->sin6_port;
+}
+
+/**
  * Converts an IPv4 address to an IPv4-mapped IPv6 address. Performs no error
  * checking.
  *
@@ -937,9 +1009,9 @@ unsigned short ip_checksum(unsigned short* buffer, int size) {
  * @param outputAddress the converted address. Will contain an IPv6 address.
  * @param mapUnspecified if true, convert 0.0.0.0 to ::ffff:0:0; if false, to ::
  */
-static void ipv4ToMappedAddress(struct sockaddr_storage *address,
+static void convertIpv4ToMapped(struct sockaddr_storage *address,
         struct sockaddr_storage *outputAddress, bool mapUnspecified) {
-  memset(outputAddress, 0, sizeof(struct sockaddr_storage));
+  memset(outputAddress, 0, sizeof(struct sockaddr_in6));
   const struct sockaddr_in *sin = ((struct sockaddr_in *) address);
   struct sockaddr_in6 *sin6 = ((struct sockaddr_in6 *) outputAddress);
   sin6->sin6_family = AF_INET6;
@@ -962,7 +1034,7 @@ static int doConnect(int socket, struct sockaddr_storage *socketAddress) {
     struct sockaddr_storage *realAddress;
     if (socketAddress->ss_family == AF_INET &&
         getSocketAddressFamily(socket) == AF_INET6) {
-        ipv4ToMappedAddress(socketAddress, &mappedAddress, true);
+        convertIpv4ToMapped(socketAddress, &mappedAddress, true);
         realAddress = &mappedAddress;
     } else {
         realAddress = socketAddress;
@@ -987,7 +1059,7 @@ static int doBind(int socket, struct sockaddr_storage *socketAddress) {
     struct sockaddr_storage *realAddress;
     if (socketAddress->ss_family == AF_INET &&
         getSocketAddressFamily(socket) == AF_INET6) {
-        ipv4ToMappedAddress(socketAddress, &mappedAddress, false);
+        convertIpv4ToMapped(socketAddress, &mappedAddress, false);
         realAddress = &mappedAddress;
     } else {
         realAddress = socketAddress;
@@ -3610,6 +3682,7 @@ static JNINativeMethod gMethods[] = {
     { "socketCloseImpl",                   "(Ljava/io/FileDescriptor;)V",                                              (void*) osNetworkSystem_socketCloseImpl                    },
     { "setInetAddressImpl",                "(Ljava/net/InetAddress;[B)V",                                              (void*) osNetworkSystem_setInetAddressImpl                 },
     { "inheritedChannelImpl",              "()Ljava/nio/channels/Channel;",                                            (void*) osNetworkSystem_inheritedChannelImpl               },
+    { "byteArrayToIpString",               "([B)Ljava/lang/String;",                                                   (void*) osNetworkSystem_byteArrayToIpString                },
 };
 
 int register_org_apache_harmony_luni_platform_OSNetworkSystem(JNIEnv* env) {