#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
-// Temporary hack to fix the sim build until bionic is updated.
-#ifdef HAVE_ANDROID_OS
-#include <netinet/in6.h>
-#else
-#define ipv6mr_ifindex ipv6mr_interface
-#endif
#include <netinet/tcp.h>
#include <netdb.h>
#include <sys/time.h>
struct CachedFields {
jfieldID fd_descriptor;
jclass iaddr_class;
- jmethodID iaddr_class_init;
jmethodID iaddr_getbyaddress;
+ jclass i4addr_class;
+ jmethodID i4addr_class_init;
jfieldID iaddr_ipaddress;
jclass genericipmreq_class;
jclass integer_class;
jfieldID byte_class_value;
jclass string_class;
jmethodID string_class_init;
+ jclass socketimpl_class;
jfieldID socketimpl_address;
jfieldID socketimpl_port;
jclass dpack_class;
* @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);
}
/**
}
/**
- * 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.
}
/**
+ * 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.
*
* @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;
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;
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;
memset(&ipv6Request, 0, requestLength);
ipv6Request.ipv6mr_multiaddr =
((struct sockaddr_in6 *) &sockaddrP)->sin6_addr;
- ipv6Request.ipv6mr_ifindex = interfaceIndex;
+ ipv6Request.ipv6mr_interface = interfaceIndex;
multicastRequest = &ipv6Request;
level = IPPROTO_IPV6;
break;
}
memset(&gCachedFields, 0, sizeof(gCachedFields));
-
- // initializing InetAddress
-
- jclass iaddrclass = env->FindClass("java/net/InetAddress");
-
- if (iaddrclass == NULL) {
- jniThrowException(env, "java/lang/ClassNotFoundException",
- "java.net.InetAddress");
- return;
- }
-
- gCachedFields.iaddr_class = (jclass) env->NewGlobalRef(iaddrclass);
-
- jmethodID iaddrclassinit = env->GetMethodID(iaddrclass, "<init>", "()V");
-
- if (iaddrclassinit == NULL) {
- jniThrowException(env, "java/lang/NoSuchMethodError", "InetAddress.<init>()");
- return;
- }
-
- gCachedFields.iaddr_class_init = iaddrclassinit;
-
- jmethodID iaddrgetbyaddress = env->GetStaticMethodID(iaddrclass,
- "getByAddress", "([B)Ljava/net/InetAddress;");
-
- if (iaddrgetbyaddress == NULL) {
- jniThrowException(env, "java/lang/NoSuchMethodError",
- "InetAddress.getByAddress(byte[] val)");
- return;
- }
-
- gCachedFields.iaddr_getbyaddress = iaddrgetbyaddress;
-
- jfieldID iaddripaddress = env->GetFieldID(iaddrclass, "ipaddress", "[B");
-
- if (iaddripaddress == NULL) {
- jniThrowException(env, "java/lang/NoSuchFieldError",
- "Can't find field InetAddress.ipaddress");
- return;
- }
-
- gCachedFields.iaddr_ipaddress = iaddripaddress;
-
- // get the GenericIPMreq class
-
- jclass genericipmreqclass = env->FindClass("org/apache/harmony/luni/net/GenericIPMreq");
-
- if (genericipmreqclass == NULL) {
- jniThrowException(env, "java/lang/ClassNotFoundException",
- "org.apache.harmony.luni.net.GenericIPMreq");
- return;
- }
-
- gCachedFields.genericipmreq_class = (jclass) env->NewGlobalRef(genericipmreqclass);
-
- // initializing Integer
-
- jclass integerclass = env->FindClass("java/lang/Integer");
-
- if (integerclass == NULL) {
- jniThrowException(env, "java/lang/ClassNotFoundException",
- "java.lang.Integer");
- return;
- }
-
- jmethodID integerclassinit = env->GetMethodID(integerclass, "<init>", "(I)V");
-
- if (integerclassinit == NULL) {
- jniThrowException(env, "java/lang/NoSuchMethodError",
- "Integer.<init>(int val)");
- return;
- }
-
- jfieldID integerclassvalue = env->GetFieldID(integerclass, "value", "I");
-
- if (integerclassvalue == NULL) {
- jniThrowException(env, "java/lang/NoSuchMethodError", "Integer.value");
- return;
- }
-
- gCachedFields.integer_class = (jclass) env->NewGlobalRef(integerclass);
- gCachedFields.integer_class_init = integerclassinit;
- gCachedFields.integer_class_value = integerclassvalue;
-
- // initializing Boolean
-
- jclass booleanclass = env->FindClass("java/lang/Boolean");
-
- if (booleanclass == NULL) {
- jniThrowException(env, "java/lang/ClassNotFoundException",
- "java.lang.Boolean");
- return;
- }
-
- jmethodID booleanclassinit = env->GetMethodID(booleanclass, "<init>", "(Z)V");
-
- if (booleanclassinit == NULL) {
- jniThrowException(env, "java/lang/NoSuchMethodError",
- "Boolean.<init>(boolean val)");
- return;
- }
-
- jfieldID booleanclassvalue = env->GetFieldID(booleanclass, "value", "Z");
-
- if (booleanclassvalue == NULL) {
- jniThrowException(env, "java/lang/NoSuchMethodError", "Boolean.value");
- return;
- }
-
- gCachedFields.boolean_class = (jclass) env->NewGlobalRef(booleanclass);
- gCachedFields.boolean_class_init = booleanclassinit;
- gCachedFields.boolean_class_value = booleanclassvalue;
-
- // initializing Byte
-
- jclass byteclass = env->FindClass("java/lang/Byte");
-
- if (byteclass == NULL) {
- jniThrowException(env, "java/lang/ClassNotFoundException",
- "java.lang.Byte");
- return;
- }
-
- jmethodID byteclassinit = env->GetMethodID(byteclass, "<init>", "(B)V");
-
- if (byteclassinit == NULL) {
- jniThrowException(env, "java/lang/NoSuchMethodError",
- "Byte.<init>(byte val)");
- return;
- }
-
- jfieldID byteclassvalue = env->GetFieldID(byteclass, "value", "B");
-
- if (byteclassvalue == NULL) {
- jniThrowException(env, "java/lang/NoSuchMethodError", "Byte.value");
- return;
- }
-
- gCachedFields.byte_class = (jclass) env->NewGlobalRef(byteclass);
- gCachedFields.byte_class_init = byteclassinit;
- gCachedFields.byte_class_value = byteclassvalue;
-
- // initializing String
-
- jclass stringclass = env->FindClass("java/lang/String");
-
- if (stringclass == NULL) {
- jniThrowException(env, "java/lang/ClassNotFoundException",
- "java.lang.String");
- return;
- }
-
- jmethodID stringclassinit = env->GetMethodID(stringclass, "<init>", "([B)V");
-
- if (stringclassinit == NULL) {
- jniThrowException(env, "java/lang/NoSuchMethodError",
- "String.<init>(byte[] val)");
- return;
- }
-
- gCachedFields.string_class = (jclass) env->NewGlobalRef(stringclass);
- gCachedFields.string_class_init = stringclassinit;
-
- // initializing ScoketImpl
-
- jclass socketimplclass = env->FindClass("java/net/SocketImpl");
-
- if (socketimplclass == NULL) {
- jniThrowException(env, "java/lang/ClassNotFoundException",
- "java.net.SocketImpl");
- return;
- }
-
- jfieldID socketimplport = env->GetFieldID(socketimplclass, "port", "I");
-
- if (socketimplport == NULL) {
- jniThrowException(env, "java/lang/NoSuchFieldError", "SocketImpl.port");
- return;
- }
-
- jfieldID socketimpladdress = env->GetFieldID(socketimplclass, "address",
- "Ljava/net/InetAddress;");
-
- if (socketimpladdress == NULL) {
- jniThrowException(env, "java/lang/NoSuchFieldError",
- "SocketImpl.address");
- return;
- }
-
- gCachedFields.socketimpl_address = socketimpladdress;
- gCachedFields.socketimpl_port = socketimplport;
-
- gCachedFields.dpack_class = env->FindClass("java/net/DatagramPacket");
- if (gCachedFields.dpack_class == NULL) {
- jniThrowException(env, "java/lang/ClassNotFoundException",
- "java.net.DatagramPacket");
- return;
- }
-
- gCachedFields.dpack_address = env->GetFieldID(gCachedFields.dpack_class,
- "address", "Ljava/net/InetAddress;");
- if (gCachedFields.dpack_address == NULL) {
- jniThrowException(env, "java/lang/NoSuchFieldError",
- "DatagramPacket.address");
- return;
- }
-
- gCachedFields.dpack_port = env->GetFieldID(gCachedFields.dpack_class,
- "port", "I");
- if (gCachedFields.dpack_port == NULL) {
- jniThrowException(env, "java/lang/NoSuchFieldError",
- "DatagramPacket.port");
- return;
- }
-
- gCachedFields.dpack_length = env->GetFieldID(gCachedFields.dpack_class,
- "length", "I");
- if (gCachedFields.dpack_length == NULL) {
- jniThrowException(env, "java/lang/NoSuchFieldError",
- "DatagramPacket.length");
- return;
+ struct CachedFields *c = &gCachedFields;
+
+ struct classInfo {
+ jclass *clazz;
+ const char *name;
+ } classes[] = {
+ {&c->iaddr_class, "java/net/InetAddress"},
+ {&c->i4addr_class, "java/net/Inet4Address"},
+ {&c->genericipmreq_class, "org/apache/harmony/luni/net/GenericIPMreq"},
+ {&c->integer_class, "java/lang/Integer"},
+ {&c->boolean_class, "java/lang/Boolean"},
+ {&c->byte_class, "java/lang/Byte"},
+ {&c->string_class, "java/lang/String"},
+ {&c->socketimpl_class, "java/net/SocketImpl"},
+ {&c->dpack_class, "java/net/DatagramPacket"}
+ };
+ for (unsigned i = 0; i < sizeof(classes) / sizeof(classes[0]); i++) {
+ classInfo c = classes[i];
+ jclass tempClass = env->FindClass(c.name);
+ if (tempClass == NULL) return;
+ *c.clazz = (jclass) env->NewGlobalRef(tempClass);
+ }
+
+ struct methodInfo {
+ jmethodID *method;
+ jclass clazz;
+ const char *name;
+ const char *signature;
+ bool isStatic;
+ } methods[] = {
+ {&c->i4addr_class_init, c->i4addr_class, "<init>", "([B)V", false},
+ {&c->integer_class_init, c->integer_class, "<init>", "(I)V", false},
+ {&c->boolean_class_init, c->boolean_class, "<init>", "(Z)V", false},
+ {&c->byte_class_init, c->byte_class, "<init>", "(B)V", false},
+ {&c->string_class_init, c->string_class, "<init>", "([B)V", false},
+ {&c->iaddr_getbyaddress, c->iaddr_class, "getByAddress",
+ "([B)Ljava/net/InetAddress;", true}
+ };
+ for (unsigned i = 0; i < sizeof(methods) / sizeof(methods[0]); i++) {
+ methodInfo m = methods[i];
+ if (m.isStatic) {
+ *m.method = env->GetStaticMethodID(m.clazz, m.name, m.signature);
+ } else {
+ *m.method = env->GetMethodID(m.clazz, m.name, m.signature);
+ }
+ if (*m.method == NULL) return;
+ }
+
+ struct fieldInfo {
+ jfieldID *field;
+ jclass clazz;
+ const char *name;
+ const char *type;
+ } fields[] = {
+ {&c->iaddr_ipaddress, c->iaddr_class, "ipaddress", "[B"},
+ {&c->integer_class_value, c->integer_class, "value", "I"},
+ {&c->boolean_class_value, c->boolean_class, "value", "Z"},
+ {&c->byte_class_value, c->byte_class, "value", "B"},
+ {&c->socketimpl_port, c->socketimpl_class, "port", "I"},
+ {&c->socketimpl_address, c->socketimpl_class, "address",
+ "Ljava/net/InetAddress;"},
+ {&c->dpack_address, c->dpack_class, "address",
+ "Ljava/net/InetAddress;"},
+ {&c->dpack_port, c->dpack_class, "port", "I"},
+ {&c->dpack_length, c->dpack_class, "length", "I"}
+ };
+ for (unsigned i = 0; i < sizeof(fields) / sizeof(fields[0]); i++) {
+ fieldInfo f = fields[i];
+ *f.field = env->GetFieldID(f.clazz, f.name, f.type);
+ if (*f.field == NULL) return;
}
-
}
/**
*
* @param fileDescriptor the file descriptor to bind the socket to
* @param type the socket type to create, e.g., SOCK_STREAM
+ * @throws SocketException an error occurred when creating the socket
*
- * @return the socket file descriptor, or -1 on failure
+ * @return the socket file descriptor. On failure, an exception is thrown and
+ * a negative value is returned.
*
*/
static int createSocketFileDescriptor(JNIEnv* env, jobject fileDescriptor,
if (sock < 0) {
int err = convertError(errno);
throwSocketException(env, err);
+ return sock;
}
jniSetFileDescriptorOfFD(env, fileDescriptor, sock);
return sock;
}
-static void osNetworkSystem_createSocketImpl(JNIEnv* env, jclass clazz,
+static void osNetworkSystem_createStreamSocketImpl(JNIEnv* env, jclass clazz,
jobject fileDescriptor, jboolean preferIPv4Stack) {
// LOGD("ENTER createSocketImpl");
createSocketFileDescriptor(env, fileDescriptor, SOCK_STREAM);
}
}
-static jboolean osNetworkSystem_socketBindImpl2(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jint port, jboolean bindToDevice,
- jobject inetAddress) {
- // LOGD("ENTER socketBindImpl2");
-
- struct sockaddr_storage sockaddress;
- int ret;
- int handle;
-
- ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddress);
- if (ret < 0) // Exception has already been thrown.
- return 0;
-
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADDESC);
- return 0;
- }
-
- ret = doBind(handle, &sockaddress);
- if (ret < 0) {
- int err = convertError(errno);
- jniThrowException(env, "java/net/BindException", netLookupErrorString(err));
- return 0;
- }
-
- return 0;
-}
-
static jint osNetworkSystem_peekDatagramImpl(JNIEnv* env, jclass clazz,
jobject fd, jobject sender, jint receiveTimeout) {
// LOGD("ENTER peekDatagramImpl");
setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
}
-static void osNetworkSystem_createMulticastSocketImpl(JNIEnv* env,
- jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) {
- // LOGD("ENTER createMulticastSocketImpl");
-
- int handle = createSocketFileDescriptor(env, fileDescriptor, SOCK_DGRAM);
- if (handle < 0)
- return;
-
- int value = 1;
- // setsockopt(handle, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(jbyte));
- setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
-}
-
/*
* @param timeout in milliseconds. If zero, block until data received
*/
close(handle);
}
-static jobject osNetworkSystem_getHostByAddrImpl(JNIEnv* env, jclass clazz,
- jbyteArray addrStr) {
- // LOGD("ENTER getHostByAddrImpl");
-
- if (addrStr == NULL) {
- throwNullPointerException(env);
- return JNI_FALSE;
- }
-
- jstring address = (jstring)newJavaLangString(env, addrStr);
- jstring result;
- const char* addr = env->GetStringUTFChars(address, NULL);
-
- struct hostent* ent = gethostbyaddr(addr, strlen(addr), AF_INET);
-
- if (ent != NULL && ent->h_name != NULL) {
- result = env->NewStringUTF(ent->h_name);
- } else {
- result = NULL;
- }
-
- env->ReleaseStringUTFChars(address, addr);
-
- return result;
-}
-
-static jobject osNetworkSystem_getHostByNameImpl(JNIEnv* env, jclass clazz,
- jstring nameStr, jboolean preferIPv6Addresses) {
- // LOGD("ENTER getHostByNameImpl");
-
- if (nameStr == NULL) {
- throwNullPointerException(env);
- return NULL;
- }
-
- const char* name = env->GetStringUTFChars(nameStr, NULL);
-
- if (useAdbNetworking) {
-
- union {
- struct in_addr a;
- jbyte j[4];
- } outaddr;
-
- // LOGD("ADB networking: +gethostbyname '%s'", name);
- int err;
- err = adb_networking_gethostbyname(name, &(outaddr.a));
-
- env->ReleaseStringUTFChars(nameStr, name);
-#if 0
- LOGD("ADB networking: -gethostbyname err %d addr 0x%08x %u.%u.%u.%u",
- err, (unsigned int)outaddr.a.s_addr,
- outaddr.j[0],outaddr.j[1],
- outaddr.j[2],outaddr.j[3]);
-#endif
-
- if (err < 0) {
- return NULL;
- } else {
- jbyteArray addr = env->NewByteArray(4);
- env->SetByteArrayRegion(addr, 0, 4, outaddr.j);
- return addr;
- }
- } else {
-
- // normal case...no adb networking
- struct hostent* ent = gethostbyname(name);
-
- env->ReleaseStringUTFChars(nameStr, name);
-
- if (ent != NULL && ent->h_length > 0) {
- jbyteArray addr = env->NewByteArray(4);
- jbyte v[4];
- memcpy(v, ent->h_addr, 4);
- env->SetByteArrayRegion(addr, 0, 4, v);
- return addr;
- } else {
- return NULL;
- }
- }
-}
-
static void osNetworkSystem_setInetAddressImpl(JNIEnv* env, jobject obj,
jobject sender, jbyteArray address) {
// LOGD("ENTER setInetAddressImpl");
ntohs(local_addr.sin_port));
// new and set remote addr
- addr_object = env->NewObject(gCachedFields.iaddr_class,
- gCachedFields.iaddr_class_init);
+ addr_array = env->NewByteArray((jsize)4);
+ env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
+ addr_object = env->NewObject(gCachedFields.i4addr_class,
+ gCachedFields.i4addr_class_init, addr_array);
if (NULL == addr_object) {
goto clean;
}
if (NULL == socketaddr_object) {
goto clean;
}
- addr_field = env->GetFieldID(socketaddr_class, "addr",
- "Ljava/net/InetAddress;");
- env->SetObjectField(socketaddr_object, addr_field, addr_object);
- addr_array = env->NewByteArray((jsize)4);
- env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
- env->SetObjectField(addr_object, gCachedFields.iaddr_ipaddress,
- addr_array);
// localAddr
socketaddr_class = env->FindClass("java/net/InetSocketAddress");
socketaddr_field);
localAddr_field = env->GetFieldID(channel_class, "localAddress",
- "Ljava/net/InetAddress;");
- localAddr_object = env->NewObject(gCachedFields.iaddr_class,
- gCachedFields.iaddr_class_init);
+ "Ljava/net/Inet4Address;");
+ addr_array = env->NewByteArray((jsize)4);
+ env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, localAddr);
+ localAddr_object = env->NewObject(gCachedFields.i4addr_class,
+ gCachedFields.i4addr_class_init, addr_array);
jfieldID socketaddr_field = env->GetFieldID(channel_class,
"connectAddress", "Ljava/net/InetSocketAddress;");
jobject socketaddr_object = env->GetObjectField(channel_object,
if (NULL == localAddr_object) {
goto clean;
}
- addr_array = env->NewByteArray((jsize)4);
- env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, localAddr);
- env->SetObjectField(localAddr_object, gCachedFields.iaddr_ipaddress,
- addr_array);
// set port
goto clean;
}
+ addr_array = env->NewByteArray((jsize)4);
localAddr_field = env->GetFieldID(channel_class, "localAddress",
"Ljava/net/InetAddress;");
- localAddr_object = env->NewObject(gCachedFields.iaddr_class,
- gCachedFields.iaddr_class_init);
+ memset(address, 0, 4);
+ env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
+ localAddr_object = env->NewObject(gCachedFields.i4addr_class,
+ gCachedFields.i4addr_class_init, addr_array);
if (NULL == localAddr_object) {
goto clean;
}
env->SetIntField(channel_object, port_field, ntohs(local_addr.sin_port));
// new and set remote addr
+ addr_array = env->NewByteArray((jsize)4);
+ env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
addr_object = env->NewObject(gCachedFields.iaddr_class,
- gCachedFields.iaddr_class_init);
+ gCachedFields.i4addr_class_init, addr_array);
if (NULL == addr_object) {
goto clean;
}
if (NULL == socketaddr_object) {
goto clean;
}
- addr_field = env->GetFieldID(socketaddr_class, "addr",
- "Ljava/net/InetAddress;");
- env->SetObjectField(socketaddr_object, addr_field, addr_object);
- addr_array = env->NewByteArray((jsize)4);
- env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
- env->SetObjectField(addr_object, gCachedFields.iaddr_ipaddress, addr_array);
// set bound
if (0 != local_addr.sin_port) {
static JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "oneTimeInitializationImpl", "(Z)V", (void*) osNetworkSystem_oneTimeInitializationImpl },
- { "createSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createSocketImpl },
+ { "createStreamSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createStreamSocketImpl },
{ "createDatagramSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createDatagramSocketImpl },
{ "readSocketImpl", "(Ljava/io/FileDescriptor;[BIII)I", (void*) osNetworkSystem_readSocketImpl },
{ "readSocketDirectImpl", "(Ljava/io/FileDescriptor;IIII)I", (void*) osNetworkSystem_readSocketDirectImpl },
{ "sendUrgentDataImpl", "(Ljava/io/FileDescriptor;B)V", (void*) osNetworkSystem_sendUrgentDataImpl },
{ "connectDatagramImpl2", "(Ljava/io/FileDescriptor;IILjava/net/InetAddress;)V", (void*) osNetworkSystem_connectDatagramImpl2 },
{ "disconnectDatagramImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_disconnectDatagramImpl },
- { "socketBindImpl2", "(Ljava/io/FileDescriptor;IZLjava/net/InetAddress;)Z", (void*) osNetworkSystem_socketBindImpl2 },
{ "peekDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)I", (void*) osNetworkSystem_peekDatagramImpl },
{ "receiveDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;[BIIIZ)I", (void*) osNetworkSystem_receiveDatagramImpl },
{ "receiveDatagramDirectImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;IIIIZ)I", (void*) osNetworkSystem_receiveDatagramDirectImpl },
{ "sendConnectedDatagramImpl", "(Ljava/io/FileDescriptor;[BIIZ)I", (void*) osNetworkSystem_sendConnectedDatagramImpl },
{ "sendConnectedDatagramDirectImpl", "(Ljava/io/FileDescriptor;IIIZ)I", (void*) osNetworkSystem_sendConnectedDatagramDirectImpl },
{ "createServerStreamSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createServerStreamSocketImpl },
- { "createMulticastSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createMulticastSocketImpl },
{ "receiveStreamImpl", "(Ljava/io/FileDescriptor;[BIII)I", (void*) osNetworkSystem_receiveStreamImpl },
{ "sendStreamImpl", "(Ljava/io/FileDescriptor;[BII)I", (void*) osNetworkSystem_sendStreamImpl },
{ "shutdownInputImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_shutdownInputImpl },
{ "setSocketOptionImpl", "(Ljava/io/FileDescriptor;ILjava/lang/Object;)V", (void*) osNetworkSystem_setSocketOptionImpl },
{ "getSocketFlagsImpl", "()I", (void*) osNetworkSystem_getSocketFlagsImpl },
{ "socketCloseImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_socketCloseImpl },
- { "getHostByAddrImpl", "([B)Ljava/net/InetAddress;", (void*) osNetworkSystem_getHostByAddrImpl },
- { "getHostByNameImpl", "(Ljava/lang/String;Z)Ljava/net/InetAddress;", (void*) osNetworkSystem_getHostByNameImpl },
{ "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) {