/jni/OSNetworkSystem.cpp
C++ | 3670 lines | 2373 code | 615 blank | 682 comment | 576 complexity | da45757e245a55287e2e260bd4d1362e MD5 | raw file
Possible License(s): GPL-3.0, BSD-3-Clause
Large files files are truncated, but you can click here to view the full file
- /*
- * Copyright (C) 2009 The Sipdroid Open Source Project
- * Copyright (C) 2007 The Android Open Source Project
- *
- * This file is part of Sipdroid (http://www.sipdroid.org)
- *
- * Sipdroid is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This source code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this source code; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
- #define LOG_TAG "OSNetworkSystem"
-
- //#include "JNIHelp.h"
- #include "jni.h"
- #include "errno.h"
-
- #include <unistd.h>
- #include <stdio.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netinet/tcp.h>
- #include <netdb.h>
- #include <sys/time.h>
- #include <stdlib.h>
- #include <sys/ioctl.h>
- #include <sys/un.h>
-
- //#include <cutils/properties.h>
- //#include <cutils/adb_networking.h>
- //#include <utils/LogSocket.h>
- //#include "AndroidSystemNatives.h"
-
- /**
- * @name Socket Errors
- * Error codes for socket operations
- *
- * @internal SOCKERR* range from -200 to -299 avoid overlap
- */
- #define SOCKERR_BADSOCKET -200 /* generic error */
- #define SOCKERR_NOTINITIALIZED -201 /* socket library uninitialized */
- #define SOCKERR_BADAF -202 /* bad address family */
- #define SOCKERR_BADPROTO -203 /* bad protocol */
- #define SOCKERR_BADTYPE -204 /* bad type */
- #define SOCKERR_SYSTEMBUSY -205 /* system busy handling requests */
- #define SOCKERR_SYSTEMFULL -206 /* too many sockets */
- #define SOCKERR_NOTCONNECTED -207 /* socket is not connected */
- #define SOCKERR_INTERRUPTED -208 /* the call was cancelled */
- #define SOCKERR_TIMEOUT -209 /* the operation timed out */
- #define SOCKERR_CONNRESET -210 /* the connection was reset */
- #define SOCKERR_WOULDBLOCK -211 /* the socket is marked as nonblocking operation would block */
- #define SOCKERR_ADDRNOTAVAIL -212 /* address not available */
- #define SOCKERR_ADDRINUSE -213 /* address already in use */
- #define SOCKERR_NOTBOUND -214 /* the socket is not bound */
- #define SOCKERR_UNKNOWNSOCKET -215 /* resolution of fileDescriptor to socket failed */
- #define SOCKERR_INVALIDTIMEOUT -216 /* the specified timeout is invalid */
- #define SOCKERR_FDSETFULL -217 /* Unable to create an FDSET */
- #define SOCKERR_TIMEVALFULL -218 /* Unable to create a TIMEVAL */
- #define SOCKERR_REMSOCKSHUTDOWN -219 /* The remote socket has shutdown gracefully */
- #define SOCKERR_NOTLISTENING -220 /* listen() was not invoked prior to accept() */
- #define SOCKERR_NOTSTREAMSOCK -221 /* The socket does not support connection-oriented service */
- #define SOCKERR_ALREADYBOUND -222 /* The socket is already bound to an address */
- #define SOCKERR_NBWITHLINGER -223 /* The socket is marked non-blocking & SO_LINGER is non-zero */
- #define SOCKERR_ISCONNECTED -224 /* The socket is already connected */
- #define SOCKERR_NOBUFFERS -225 /* No buffer space is available */
- #define SOCKERR_HOSTNOTFOUND -226 /* Authoritative Answer Host not found */
- #define SOCKERR_NODATA -227 /* Valid name, no data record of requested type */
- #define SOCKERR_BOUNDORCONN -228 /* The socket has not been bound or is already connected */
- #define SOCKERR_OPNOTSUPP -229 /* The socket does not support the operation */
- #define SOCKERR_OPTUNSUPP -230 /* The socket option is not supported */
- #define SOCKERR_OPTARGSINVALID -231 /* The socket option arguments are invalid */
- #define SOCKERR_SOCKLEVELINVALID -232 /* The socket level is invalid */
- #define SOCKERR_TIMEOUTFAILURE -233
- #define SOCKERR_SOCKADDRALLOCFAIL -234 /* Unable to allocate the sockaddr structure */
- #define SOCKERR_FDSET_SIZEBAD -235 /* The calculated maximum size of the file descriptor set is bad */
- #define SOCKERR_UNKNOWNFLAG -236 /* The flag is unknown */
- #define SOCKERR_MSGSIZE -237 /* The datagram was too big to fit the specified buffer & was truncated. */
- #define SOCKERR_NORECOVERY -238 /* The operation failed with no recovery possible */
- #define SOCKERR_ARGSINVALID -239 /* The arguments are invalid */
- #define SOCKERR_BADDESC -240 /* The socket argument is not a valid file descriptor */
- #define SOCKERR_NOTSOCK -241 /* The socket argument is not a socket */
- #define SOCKERR_HOSTENTALLOCFAIL -242 /* Unable to allocate the hostent structure */
- #define SOCKERR_TIMEVALALLOCFAIL -243 /* Unable to allocate the timeval structure */
- #define SOCKERR_LINGERALLOCFAIL -244 /* Unable to allocate the linger structure */
- #define SOCKERR_IPMREQALLOCFAIL -245 /* Unable to allocate the ipmreq structure */
- #define SOCKERR_FDSETALLOCFAIL -246 /* Unable to allocate the fdset structure */
- #define SOCKERR_OPFAILED -247 /* Operation failed */
- #define SOCKERR_VALUE_NULL -248 /* The value indexed was NULL */
- #define SOCKERR_CONNECTION_REFUSED -249 /* connection was refused */
- #define SOCKERR_ENETUNREACH -250 /* network is not reachable */
- #define SOCKERR_EACCES -251 /* permissions do not allow action on socket */
- #define SOCKERR_EHOSTUNREACH -252 /* no route to host */
- #define SOCKERR_EPIPE -253 /* broken pipe */
-
- #define JAVASOCKOPT_TCP_NODELAY 1
- #define JAVASOCKOPT_IP_TOS 3
- #define JAVASOCKOPT_SO_REUSEADDR 4
- #define JAVASOCKOPT_SO_KEEPALIVE 8
- #define JAVASOCKOPT_MCAST_TIME_TO_LIVE 10 /* Currently unused */
- #define JAVASOCKOPT_SO_BINDADDR 15
- #define JAVASOCKOPT_MCAST_INTERFACE 16
- #define JAVASOCKOPT_MCAST_TTL 17
- #define JAVASOCKOPT_IP_MULTICAST_LOOP 18
- #define JAVASOCKOPT_MCAST_ADD_MEMBERSHIP 19
- #define JAVASOCKOPT_MCAST_DROP_MEMBERSHIP 20
- #define JAVASOCKOPT_IP_MULTICAST_IF2 31
- #define JAVASOCKOPT_SO_BROADCAST 32
- #define JAVASOCKOPT_SO_LINGER 128
- #define JAVASOCKOPT_REUSEADDR_AND_REUSEPORT 10001
- #define JAVASOCKOPT_SO_SNDBUF 4097
- #define JAVASOCKOPT_SO_RCVBUF 4098
- #define JAVASOCKOPT_SO_RCVTIMEOUT 4102
- #define JAVASOCKOPT_SO_OOBINLINE 4099
-
- /* constants for calling multi-call functions */
- #define SOCKET_STEP_START 10
- #define SOCKET_STEP_CHECK 20
- #define SOCKET_STEP_DONE 30
-
- #define BROKEN_MULTICAST_IF 1
- #define BROKEN_MULTICAST_TTL 2
- #define BROKEN_TCP_NODELAY 4
-
- #define SOCKET_CONNECT_STEP_START 0
- #define SOCKET_CONNECT_STEP_CHECK 1
-
- #define SOCKET_OP_NONE 0
- #define SOCKET_OP_READ 1
- #define SOCKET_OP_WRITE 2
- #define SOCKET_READ_WRITE 3
-
- #define SOCKET_MSG_PEEK 1
- #define SOCKET_MSG_OOB 2
-
- #define SOCKET_NOFLAGS 0
-
- #undef BUFFERSIZE
- #define BUFFERSIZE 2048
-
- // wait for 500000 usec = 0.5 second
- #define SEND_RETRY_TIME 500000
-
-
- struct CachedFields {
- jfieldID fd_descriptor;
- jclass iaddr_class;
- jmethodID iaddr_class_init;
- jmethodID iaddr_getbyaddress;
- jfieldID iaddr_ipaddress;
- jclass genericipmreq_class;
- jclass integer_class;
- jmethodID integer_class_init;
- jfieldID integer_class_value;
- jclass boolean_class;
- jmethodID boolean_class_init;
- jfieldID boolean_class_value;
- jclass byte_class;
- jmethodID byte_class_init;
- jfieldID byte_class_value;
- jclass string_class;
- jmethodID string_class_init;
- jfieldID socketimpl_address;
- jfieldID socketimpl_port;
- jclass dpack_class;
- jfieldID dpack_address;
- jfieldID dpack_port;
- jfieldID dpack_length;
- jclass fd_class;
- jfieldID descriptor;
- } gCachedFields;
-
- static int useAdbNetworking = 0;
-
- /* needed for connecting with timeout */
- typedef struct selectFDSet {
- int nfds;
- int sock;
- fd_set writeSet;
- fd_set readSet;
- fd_set exceptionSet;
- } selectFDSet;
-
- static const char * netLookupErrorString(int anErrorNum);
-
- #define log_socket_close(a,b)
- #define log_socket_connect(a,b,c)
- #define add_send_stats(a,b)
- #define add_recv_stats(a,b)
- #define adb_networking_connect_fd(a,b) 0
- #define adb_networking_gethostbyname(a,b) 0
- #define PROPERTY_VALUE_MAX 1
- #define property_get(a,b,c)
- #define assert(a)
- /*
- * Throw an exception with the specified class and an optional message.
- */
- int jniThrowException(JNIEnv* env, const char* className, const char* msg)
- {
- jclass exceptionClass;
-
- exceptionClass = env->FindClass(className);
- if (exceptionClass == NULL) {
- // LOGE("Unable to find exception class %s\n", className);
- assert(0); /* fatal during dev; should always be fatal? */
- return -1;
- }
-
- if (env->ThrowNew(exceptionClass, msg) != JNI_OK) {
- // LOGE("Failed throwing '%s' '%s'\n", className, msg);
- assert(!"failed to throw");
- }
- return 0;
- }
-
- /*
- * Internal helper function.
- *
- * Get the file descriptor.
- */
- static inline int getFd(JNIEnv* env, jobject obj)
- {
- return env->GetIntField(obj, gCachedFields.descriptor);
- }
-
- /*
- * Internal helper function.
- *
- * Set the file descriptor.
- */
- static inline void setFd(JNIEnv* env, jobject obj, jint value)
- {
- env->SetIntField(obj, gCachedFields.descriptor, value);
- }
-
- /*
- * For JNIHelp.c
- * Get an int file descriptor from a java.io.FileDescriptor
- */
-
- static int jniGetFDFromFileDescriptor (JNIEnv* env, jobject fileDescriptor) {
-
- return getFd(env, fileDescriptor);
- }
-
- /*
- * For JNIHelp.c
- * Set the descriptor of a java.io.FileDescriptor
- */
-
- static void jniSetFileDescriptorOfFD (JNIEnv* env, jobject fileDescriptor, int value) {
-
- setFd(env, fileDescriptor, value);
- }
-
- /**
- * Throws an SocketException with the message affiliated with the errorCode.
- */
- static void throwSocketException(JNIEnv *env, int errorCode) {
- jniThrowException(env, "java/net/SocketException",
- netLookupErrorString(errorCode));
- }
-
- /**
- * Throws an IOException with the given message.
- */
- static void throwIOExceptionStr(JNIEnv *env, const char *message) {
- jniThrowException(env, "java/io/IOException", message);
- }
-
- /**
- * Throws a NullPointerException.
- */
- static void throwNullPointerException(JNIEnv *env) {
- jniThrowException(env, "java/lang/NullPointerException", NULL);
- }
-
- /**
- * Converts a 4-byte array to a native address structure. Throws a
- * NullPointerException or an IOException in case of error. This is
- * signaled by a return value of -1. The normal return value is 0.
- */
- static int javaAddressToStructIn(
- JNIEnv *env, jbyteArray java_address, struct in_addr *address) {
-
- memset(address, 0, sizeof(address));
-
- if (java_address == NULL) {
- return -1;
- }
-
- if (env->GetArrayLength(java_address) != sizeof(address->s_addr)) {
- return -1;
- }
-
- jbyte * java_address_bytes
- = env->GetByteArrayElements(java_address, NULL);
-
- memcpy(&(address->s_addr),
- java_address_bytes,
- sizeof(address->s_addr));
-
- env->ReleaseByteArrayElements(java_address, java_address_bytes, JNI_ABORT);
-
- return 0;
- }
-
- /**
- * Converts a native address structure to a 4-byte array. Throws a
- * NullPointerException or an IOException in case of error. This is
- * signaled by a return value of -1. The normal return value is 0.
- */
- static int structInToJavaAddress(
- JNIEnv *env, struct in_addr *address, jbyteArray java_address) {
-
- if (java_address == NULL) {
- return -1;
- }
-
- if (env->GetArrayLength(java_address) != sizeof(address->s_addr)) {
- return -1;
- }
-
- jbyte *java_address_bytes;
-
- java_address_bytes = env->GetByteArrayElements(java_address, NULL);
-
- memcpy(java_address_bytes, &(address->s_addr), sizeof(address->s_addr));
-
- env->ReleaseByteArrayElements(java_address, java_address_bytes, 0);
-
- return 0;
- }
-
- /**
- * Converts a native address structure to an InetAddress object.
- * Throws a NullPointerException or an IOException in case of
- * error. This is signaled by a return value of -1. The normal
- * return value is 0.
- */
- static int socketAddressToInetAddress(JNIEnv *env,
- struct sockaddr_in *sockaddress, jobject inetaddress, int *port) {
-
- jbyteArray ipaddress;
- int result;
-
- ipaddress = (jbyteArray)env->GetObjectField(inetaddress,
- gCachedFields.iaddr_ipaddress);
-
- if (structInToJavaAddress(env, &sockaddress->sin_addr, ipaddress) < 0) {
- return -1;
- }
-
- *port = ntohs(sockaddress->sin_port);
-
- return 0;
- }
-
- /**
- * Converts an InetAddress object to a native address structure.
- * Throws a NullPointerException or an IOException in case of
- * error. This is signaled by a return value of -1. The normal
- * return value is 0.
- */
- static int inetAddressToSocketAddress(JNIEnv *env,
- jobject inetaddress, int port, struct sockaddr_in *sockaddress) {
-
- jbyteArray ipaddress;
- int result;
-
- ipaddress = (jbyteArray)env->GetObjectField(inetaddress,
- gCachedFields.iaddr_ipaddress);
-
- memset(sockaddress, 0, sizeof(sockaddress));
-
- sockaddress->sin_family = AF_INET;
- sockaddress->sin_port = htons(port);
-
- if (javaAddressToStructIn(env, ipaddress, &(sockaddress->sin_addr)) < 0) {
- return -1;
- }
-
- return 0;
- }
-
- static jobject structInToInetAddress(JNIEnv *env, struct in_addr *address) {
- jbyteArray bytes;
- int success;
-
- bytes = env->NewByteArray(4);
-
- if (bytes == NULL) {
- return NULL;
- }
-
- if (structInToJavaAddress(env, address, bytes) < 0) {
- return NULL;
- }
-
- return env->CallStaticObjectMethod(gCachedFields.iaddr_class,
- gCachedFields.iaddr_getbyaddress, bytes);
- }
-
- /**
- * Answer a new java.lang.Boolean object.
- *
- * @param env pointer to the JNI library
- * @param anInt the Boolean constructor argument
- *
- * @return the new Boolean
- */
-
- static jobject newJavaLangBoolean(JNIEnv * env, jint anInt) {
- jclass tempClass;
- jmethodID tempMethod;
-
- tempClass = gCachedFields.boolean_class;
- tempMethod = gCachedFields.boolean_class_init;
- return env->NewObject(tempClass, tempMethod, (jboolean) (anInt != 0));
- }
-
- /**
- * Answer a new java.lang.Byte object.
- *
- * @param env pointer to the JNI library
- * @param anInt the Byte constructor argument
- *
- * @return the new Byte
- */
-
- static jobject newJavaLangByte(JNIEnv * env, jbyte val) {
- jclass tempClass;
- jmethodID tempMethod;
-
- tempClass = gCachedFields.byte_class;
- tempMethod = gCachedFields.byte_class_init;
- return env->NewObject(tempClass, tempMethod, val);
- }
-
- /**
- * Answer a new java.lang.Integer object.
- *
- * @param env pointer to the JNI library
- * @param anInt the Integer constructor argument
- *
- * @return the new Integer
- */
-
- static jobject newJavaLangInteger(JNIEnv * env, jint anInt) {
- jclass tempClass;
- jmethodID tempMethod;
-
- tempClass = gCachedFields.integer_class;
- tempMethod = gCachedFields.integer_class_init;
- return env->NewObject(tempClass, tempMethod, anInt);
- }
-
- /**
- * Answer a new java.lang.String object.
- *
- * @param env pointer to the JNI library
- * @param anInt the byte[] constructor argument
- *
- * @return the new String
- */
-
- static jobject newJavaLangString(JNIEnv * env, jbyteArray bytes) {
- jclass tempClass;
- jmethodID tempMethod;
-
- tempClass = gCachedFields.string_class;
- tempMethod = gCachedFields.string_class_init;
- return env->NewObject(tempClass, tempMethod, (jbyteArray) bytes);
- }
-
- /**
- * Query OS for timestamp.
- * Retrieve the current value of system clock and convert to milliseconds.
- *
- * @param[in] portLibrary The port library.
- *
- * @return 0 on failure, time value in milliseconds on success.
- * @deprecated Use @ref time_hires_clock and @ref time_hires_delta
- *
- * technically, this should return I_64 since both timeval.tv_sec and
- * timeval.tv_usec are long
- */
-
- static int time_msec_clock() {
- struct timeval tp;
- struct timezone tzp;
-
- gettimeofday(&tp, &tzp);
- return (tp.tv_sec * 1000) + (tp.tv_usec / 1000);
- }
-
- /**
- * check if the passed sockaddr_in struct contains a localhost address
- *
- * @param[in] address pointer to the address to check
- *
- * @return 0 if the passed address isn't a localhost address
- */
- static int isLocalhost(struct sockaddr_in *address) {
- // return address == 127.0.0.1
- return (unsigned int) address->sin_addr.s_addr == 16777343;
- }
-
- /**
- * Answer the errorString corresponding to the errorNumber, if available.
- * This function will answer a default error string, if the errorNumber is not
- * recognized.
- *
- * This function will have to be reworked to handle internationalization
- * properly, removing the explicit strings.
- *
- * @param anErrorNum the error code to resolve to a human readable string
- *
- * @return a human readable error string
- */
-
- static const char * netLookupErrorString(int anErrorNum) {
- switch (anErrorNum) {
- case SOCKERR_BADSOCKET:
- return "Bad socket";
- case SOCKERR_NOTINITIALIZED:
- return "Socket library uninitialized";
- case SOCKERR_BADAF:
- return "Bad address family";
- case SOCKERR_BADPROTO:
- return "Bad protocol";
- case SOCKERR_BADTYPE:
- return "Bad type";
- case SOCKERR_SYSTEMBUSY:
- return "System busy handling requests";
- case SOCKERR_SYSTEMFULL:
- return "Too many sockets allocated";
- case SOCKERR_NOTCONNECTED:
- return "Socket is not connected";
- case SOCKERR_INTERRUPTED:
- return "The system call was cancelled";
- case SOCKERR_TIMEOUT:
- return "The operation timed out";
- case SOCKERR_CONNRESET:
- return "The connection was reset";
- case SOCKERR_WOULDBLOCK:
- return "The nonblocking operation would block";
- case SOCKERR_ADDRNOTAVAIL:
- return "The address is not available";
- case SOCKERR_ADDRINUSE:
- return "The address is already in use";
- case SOCKERR_NOTBOUND:
- return "The socket is not bound";
- case SOCKERR_UNKNOWNSOCKET:
- return "Resolution of the FileDescriptor to socket failed";
- case SOCKERR_INVALIDTIMEOUT:
- return "The specified timeout is invalid";
- case SOCKERR_FDSETFULL:
- return "Unable to create an FDSET";
- case SOCKERR_TIMEVALFULL:
- return "Unable to create a TIMEVAL";
- case SOCKERR_REMSOCKSHUTDOWN:
- return "The remote socket has shutdown gracefully";
- case SOCKERR_NOTLISTENING:
- return "Listen() was not invoked prior to accept()";
- case SOCKERR_NOTSTREAMSOCK:
- return "The socket does not support connection-oriented service";
- case SOCKERR_ALREADYBOUND:
- return "The socket is already bound to an address";
- case SOCKERR_NBWITHLINGER:
- return "The socket is marked non-blocking & SO_LINGER is non-zero";
- case SOCKERR_ISCONNECTED:
- return "The socket is already connected";
- case SOCKERR_NOBUFFERS:
- return "No buffer space is available";
- case SOCKERR_HOSTNOTFOUND:
- return "Authoritative Answer Host not found";
- case SOCKERR_NODATA:
- return "Valid name, no data record of requested type";
- case SOCKERR_BOUNDORCONN:
- return "The socket has not been bound or is already connected";
- case SOCKERR_OPNOTSUPP:
- return "The socket does not support the operation";
- case SOCKERR_OPTUNSUPP:
- return "The socket option is not supported";
- case SOCKERR_OPTARGSINVALID:
- return "The socket option arguments are invalid";
- case SOCKERR_SOCKLEVELINVALID:
- return "The socket level is invalid";
- case SOCKERR_TIMEOUTFAILURE:
- return "The timeout operation failed";
- case SOCKERR_SOCKADDRALLOCFAIL:
- return "Failed to allocate address structure";
- case SOCKERR_FDSET_SIZEBAD:
- return "The calculated maximum size of the file descriptor set is bad";
- case SOCKERR_UNKNOWNFLAG:
- return "The flag is unknown";
- case SOCKERR_MSGSIZE:
- return "The datagram was too big to fit the specified buffer, so truncated";
- case SOCKERR_NORECOVERY:
- return "The operation failed with no recovery possible";
- case SOCKERR_ARGSINVALID:
- return "The arguments are invalid";
- case SOCKERR_BADDESC:
- return "The socket argument is not a valid file descriptor";
- case SOCKERR_NOTSOCK:
- return "The socket argument is not a socket";
- case SOCKERR_HOSTENTALLOCFAIL:
- return "Unable to allocate the hostent structure";
- case SOCKERR_TIMEVALALLOCFAIL:
- return "Unable to allocate the timeval structure";
- case SOCKERR_LINGERALLOCFAIL:
- return "Unable to allocate the linger structure";
- case SOCKERR_IPMREQALLOCFAIL:
- return "Unable to allocate the ipmreq structure";
- case SOCKERR_FDSETALLOCFAIL:
- return "Unable to allocate the fdset structure";
- case SOCKERR_OPFAILED:
- return "Operation failed";
- case SOCKERR_CONNECTION_REFUSED:
- return "Connection refused";
- case SOCKERR_ENETUNREACH:
- return "Network unreachable";
- case SOCKERR_EHOSTUNREACH:
- return "No route to host";
- case SOCKERR_EPIPE:
- return "Broken pipe";
- case SOCKERR_EACCES:
- return "Permission denied (maybe missing INTERNET permission)";
-
- default:
- // LOGE("unknown socket error %d", anErrorNum);
- return "unknown error";
- }
- }
-
- static int convertError(int errorCode) {
- switch (errorCode) {
- case EBADF:
- return SOCKERR_BADDESC;
- case ENOBUFS:
- return SOCKERR_NOBUFFERS;
- case EOPNOTSUPP:
- return SOCKERR_OPNOTSUPP;
- case ENOPROTOOPT:
- return SOCKERR_OPTUNSUPP;
- case EINVAL:
- return SOCKERR_SOCKLEVELINVALID;
- case ENOTSOCK:
- return SOCKERR_NOTSOCK;
- case EINTR:
- return SOCKERR_INTERRUPTED;
- case ENOTCONN:
- return SOCKERR_NOTCONNECTED;
- case EAFNOSUPPORT:
- return SOCKERR_BADAF;
- /* note: CONNRESET not included because it has the same
- * value as ECONNRESET and they both map to SOCKERR_CONNRESET */
- case ECONNRESET:
- return SOCKERR_CONNRESET;
- case EAGAIN:
- return SOCKERR_WOULDBLOCK;
- case EPROTONOSUPPORT:
- return SOCKERR_BADPROTO;
- case EFAULT:
- return SOCKERR_ARGSINVALID;
- case ETIMEDOUT:
- return SOCKERR_TIMEOUT;
- case ECONNREFUSED:
- return SOCKERR_CONNECTION_REFUSED;
- case ENETUNREACH:
- return SOCKERR_ENETUNREACH;
- case EACCES:
- return SOCKERR_EACCES;
- case EPIPE:
- return SOCKERR_EPIPE;
- case EHOSTUNREACH:
- return SOCKERR_EHOSTUNREACH;
- case EADDRINUSE:
- return SOCKERR_ADDRINUSE;
- case EADDRNOTAVAIL:
- return SOCKERR_ADDRNOTAVAIL;
- case EMSGSIZE:
- return SOCKERR_MSGSIZE;
- default:
- // LOGE("unclassified errno %d (%s)", errorCode, strerror(errorCode));
- return SOCKERR_OPFAILED;
- }
- }
-
- static int sockSelect(int nfds, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds, struct timeval *timeout) {
-
- int result = select(nfds, readfds, writefds, exceptfds, timeout);
-
- if (result < 0) {
- if (errno == EINTR) {
- result = SOCKERR_INTERRUPTED;
- } else {
- result = SOCKERR_OPFAILED;
- }
- } else if (result == 0) {
- result = SOCKERR_TIMEOUT;
- }
- return result;
- }
-
- #define SELECT_READ_TYPE 0
- #define SELECT_WRITE_TYPE 1
-
- static int selectWait(int handle, int uSecTime, int type) {
- fd_set fdset;
- struct timeval time, *timePtr;
- int result = 0;
- int size = handle + 1;
-
- FD_ZERO(&fdset);
- FD_SET(handle, &fdset);
-
- if (0 <= uSecTime) {
- /* Use a timeout if uSecTime >= 0 */
- memset(&time, 0, sizeof(time));
- time.tv_usec = uSecTime;
- timePtr = &time;
- } else {
- /* Infinite timeout if uSecTime < 0 */
- timePtr = NULL;
- }
-
- if (type == SELECT_READ_TYPE) {
- result = sockSelect(size, &fdset, NULL, NULL, timePtr);
- } else {
- result = sockSelect(size, NULL, &fdset, NULL, timePtr);
- }
- return result;
- }
-
- static int pollSelectWait(JNIEnv *env, jobject fileDescriptor, int timeout, int type) {
- /* now try reading the socket for the timespan timeout.
- * if timeout is 0 try forever until the soclets gets ready or until an
- * exception occurs.
- */
- int pollTimeoutUSec = 100000, pollMsec = 100;
- int finishTime = 0;
- int timeLeft = timeout;
- int hasTimeout = timeout > 0 ? 1 : 0;
- int result = 0;
- int handle;
-
- if (hasTimeout) {
- finishTime = time_msec_clock() + timeout;
- }
-
- int poll = 1;
-
- while (poll) { /* begin polling loop */
-
- /*
- * Fetch the handle every time in case the socket is closed.
- */
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_INTERRUPTED);
- return -1;
- }
-
- if (hasTimeout) {
-
- if (timeLeft - 10 < pollMsec) {
- pollTimeoutUSec = timeLeft <= 0 ? 0 : (timeLeft * 1000);
- }
-
- result = selectWait(handle, pollTimeoutUSec, type);
-
- /*
- * because we are polling at a time smaller than timeout
- * (presumably) lets treat an interrupt and timeout the same - go
- * see if we're done timewise, and then just try again if not.
- */
- if (SOCKERR_TIMEOUT == result ||
- SOCKERR_INTERRUPTED == result) {
-
- timeLeft = finishTime - time_msec_clock();
-
- if (timeLeft <= 0) {
- /*
- * Always throw the "timeout" message because that is
- * effectively what has happened, even if we happen to
- * have been interrupted.
- */
- jniThrowException(env, "java/net/SocketTimeoutException",
- netLookupErrorString(SOCKERR_TIMEOUT));
- } else {
- continue; // try again
- }
-
- } else if (0 > result) {
- log_socket_close(handle, result);
- throwSocketException(env, result);
- }
- poll = 0;
-
- } else { /* polling with no timeout (why would you do this?)*/
-
- result = selectWait(handle, pollTimeoutUSec, type);
-
- /*
- * if interrupted (or a timeout) just retry
- */
- if (SOCKERR_TIMEOUT == result ||
- SOCKERR_INTERRUPTED == result) {
-
- continue; // try again
- } else if (0 > result) {
- log_socket_close(handle, result);
- throwSocketException(env, result);
- }
- poll = 0;
- }
- } /* end polling loop */
-
- return result;
- }
-
- /**
- * A helper method, to set the connect context to a Long object.
- *
- * @param env pointer to the JNI library
- * @param longclass Java Long Object
- */
- void setConnectContext(JNIEnv *env,jobject longclass,jbyte * context) {
- jclass descriptorCLS;
- jfieldID descriptorFID;
- descriptorCLS = env->FindClass("java/lang/Long");
- descriptorFID = env->GetFieldID(descriptorCLS, "value", "J");
- env->SetLongField(longclass, descriptorFID, (jlong)((jint)context));
- };
-
- /**
- * A helper method, to get the connect context.
- *
- * @param env pointer to the JNI library
- * @param longclass Java Long Object
- */
- jbyte *getConnectContext(JNIEnv *env, jobject longclass) {
- jclass descriptorCLS;
- jfieldID descriptorFID;
- descriptorCLS = env->FindClass("java/lang/Long");
- descriptorFID = env->GetFieldID(descriptorCLS, "value", "J");
- return (jbyte*) ((jint)env->GetLongField(longclass, descriptorFID));
- };
-
- // typical ip checksum
- unsigned short ip_checksum(unsigned short* buffer, int size) {
- register unsigned short * buf = buffer;
- register int bufleft = size;
- register unsigned long sum = 0;
-
- while (bufleft > 1) {
- sum = sum + (*buf++);
- bufleft = bufleft - sizeof(unsigned short );
- }
- if (bufleft) {
- sum = sum + (*(unsigned char*)buf);
- }
- sum = (sum >> 16) + (sum & 0xffff);
- sum += (sum >> 16);
-
- return (unsigned short )(~sum);
- }
-
- /**
- * Establish a connection to a peer with a timeout. This function is called
- * repeatedly in order to carry out the connect and to allow other tasks to
- * proceed on certain platforms. The caller must first call with
- * step = SOCKET_STEP_START, if the result is SOCKERR_NOTCONNECTED it will then
- * call it with step = CHECK until either another error or 0 is returned to
- * indicate the connect is complete. Each time the function should sleep for no
- * more than timeout milliseconds. If the connect succeeds or an error occurs,
- * the caller must always end the process by calling the function with
- * step = SOCKET_STEP_DONE
- *
- * @param[in] portLibrary The port library.
- * @param[in] sock pointer to the unconnected local socket.
- * @param[in] addr pointer to the sockaddr, specifying remote host/port.
- * @param[in] timeout the timeout in milliseconds. If timeout is negative,
- * perform a block operation.
- * @param[in,out] pointer to context pointer. Filled in on first call and then
- * to be passed into each subsequent call.
- *
- * @return 0, if no errors occurred, otherwise the (negative) error code.
- */
- static int sockConnectWithTimeout(int handle, struct sockaddr_in addr,
- unsigned int timeout, unsigned int step, jbyte *ctxt) {
- int rc = 0;
- struct timeval passedTimeout;
- int errorVal;
- socklen_t errorValLen = sizeof(int);
- struct selectFDSet *context = NULL;
-
- if (SOCKET_STEP_START == step) {
-
- context = (struct selectFDSet *) ctxt;
-
- context->sock = handle;
- context->nfds = handle + 1;
-
- if (useAdbNetworking && !isLocalhost(&addr)) {
-
- // LOGD("+connect to address 0x%08x (via adb)",
- // addr.sin_addr.s_addr);
- rc = adb_networking_connect_fd(handle, &addr);
- // LOGD("-connect ret %d errno %d (via adb)", rc, errno);
-
- } else {
- log_socket_connect(handle, ntohl(addr.sin_addr.s_addr),
- ntohs(addr.sin_port));
- /* set the socket to non-blocking */
- int block = JNI_TRUE;
- rc = ioctl(handle, FIONBIO, &block);
- if (0 != rc) {
- return convertError(rc);
- }
-
- // LOGD("+connect to address 0x%08x (via normal) on handle %d",
- // addr.sin_addr.s_addr, handle);
- do {
- rc = connect(handle, (struct sockaddr *) &addr,
- sizeof(struct sockaddr));
- } while (rc < 0 && errno == EINTR);
- // LOGD("-connect to address 0x%08x (via normal) returned %d",
- // addr.sin_addr.s_addr, (int) rc);
-
- }
-
- if (rc == -1) {
- rc = errno;
- switch (rc) {
- case EINTR:
- return SOCKERR_ALREADYBOUND;
- case EAGAIN:
- case EINPROGRESS:
- return SOCKERR_NOTCONNECTED;
- default:
- return convertError(rc);
- }
- }
-
- /* we connected right off the bat so just return */
- return rc;
-
- } else if (SOCKET_STEP_CHECK == step) {
- /* now check if we have connected yet */
-
- context = (struct selectFDSet *) ctxt;
-
- /*
- * set the timeout value to be used. Because on some unix platforms we
- * don't get notified when a socket is closed we only sleep for 100ms
- * at a time
- */
- passedTimeout.tv_sec = 0;
- if (timeout > 100) {
- passedTimeout.tv_usec = 100 * 1000;
- } else if ((int)timeout >= 0) {
- passedTimeout.tv_usec = timeout * 1000;
- }
-
- /* initialize the FD sets for the select */
- FD_ZERO(&(context->exceptionSet));
- FD_ZERO(&(context->writeSet));
- FD_ZERO(&(context->readSet));
- FD_SET(context->sock, &(context->writeSet));
- FD_SET(context->sock, &(context->readSet));
- FD_SET(context->sock, &(context->exceptionSet));
-
- rc = select(context->nfds,
- &(context->readSet),
- &(context->writeSet),
- &(context->exceptionSet),
- (int)timeout >= 0 ? &passedTimeout : NULL);
-
- /* if there is at least one descriptor ready to be checked */
- if (0 < rc) {
- /* if the descriptor is in the write set we connected or failed */
- if (FD_ISSET(context->sock, &(context->writeSet))) {
-
- if (!FD_ISSET(context->sock, &(context->readSet))) {
- /* ok we have connected ok */
- return 0;
- } else {
- /* ok we have more work to do to figure it out */
- if (getsockopt(context->sock, SOL_SOCKET, SO_ERROR,
- &errorVal, &errorValLen) >= 0) {
- return errorVal ? convertError(errorVal) : 0;
- } else {
- return convertError(errno);
- }
- }
- }
-
- /* if the descriptor is in the exception set the connect failed */
- if (FD_ISSET(context->sock, &(context->exceptionSet))) {
- if (getsockopt(context->sock, SOL_SOCKET, SO_ERROR, &errorVal,
- &errorValLen) >= 0) {
- return errorVal ? convertError(errorVal) : 0;
- }
- rc = errno;
- return convertError(rc);
- }
-
- } else if (rc < 0) {
- /* something went wrong with the select call */
- rc = errno;
-
- /* if it was EINTR we can just try again. Return not connected */
- if (EINTR == rc) {
- return SOCKERR_NOTCONNECTED;
- }
-
- /* some other error occured so look it up and return */
- return convertError(rc);
- }
-
- /*
- * if we get here the timeout expired or the connect had not yet
- * completed just indicate that the connect is not yet complete
- */
- return SOCKERR_NOTCONNECTED;
- } else if (SOCKET_STEP_DONE == step) {
- /* we are done the connect or an error occured so clean up */
- if (handle != -1) {
- int block = JNI_FALSE;
- ioctl(handle, FIONBIO, &block);
- }
- return 0;
- }
- return SOCKERR_ARGSINVALID;
- }
-
- /**
- * Join/Leave the nominated multicast group on the specified socket.
- * Implemented by setting the multicast 'add membership'/'drop membership'
- * option at the HY_IPPROTO_IP level on the socket.
- *
- * Implementation note for multicast sockets in general:
- *
- * - This code is untested, because at the time of this writing multicast can't
- * be properly tested on Android due to GSM routing restrictions. So it might
- * or might not work.
- *
- * - The REUSEPORT socket option that Harmony employs is not supported on Linux
- * and thus also not supported on Android. It's is not needed for multicast
- * to work anyway (REUSEADDR should suffice).
- *
- * @param env pointer to the JNI library.
- * @param socketP pointer to the hysocket to join/leave on.
- * @param optVal pointer to the InetAddress, the multicast group to join/drop.
- *
- * @exception SocketException if an error occurs during the call
- */
- static void mcastAddDropMembership (JNIEnv * env, int handle, jobject optVal,
- int ignoreIF, int setSockOptVal) {
- int result;
- struct ip_mreq ipmreqP;
- struct sockaddr_in sockaddrP;
- int length = sizeof(struct ip_mreq);
- socklen_t lengthIF = sizeof(struct sockaddr_in);
-
- /*
- * JNI objects needed to access the information in the optVal oject
- * passed in. The object passed in is a GenericIPMreq object
- */
- jclass cls;
- jfieldID multiaddrID;
- jfieldID interfaceAddrID;
- jobject multiaddr;
- jobject interfaceAddr;
-
- /*
- * check whether we are getting an InetAddress or an Generic IPMreq, for now
- * we support both so that we will not break the tests
- */
- if (env->IsInstanceOf (optVal, gCachedFields.iaddr_class)) {
-
- ipmreqP.imr_interface.s_addr = htonl(INADDR_ANY);
- if (!ignoreIF) {
-
- result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, &sockaddrP,
- &lengthIF);
-
- if (0 != result) {
- throwSocketException (env, convertError(errno));
- return;
- }
-
- memcpy(&(ipmreqP.imr_interface.s_addr), &(sockaddrP.sin_addr), 4);
- }
-
- result = inetAddressToSocketAddress(env, optVal, 0, &sockaddrP);
-
- if (result < 0) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return;
- }
-
- memcpy(&(ipmreqP.imr_multiaddr.s_addr), &(sockaddrP.sin_addr), 4);
-
- result = setsockopt(handle, IPPROTO_IP, setSockOptVal, &ipmreqP, length);
- if (0 != result) {
- throwSocketException (env, convertError(errno));
- return;
- }
-
- } else {
-
- /* we need the multicast address regardless of the type of address */
- cls = env->GetObjectClass(optVal);
- multiaddrID = env->GetFieldID(cls, "multiaddr", "Ljava/net/InetAddress;");
- multiaddr = env->GetObjectField(optVal, multiaddrID);
-
- result = inetAddressToSocketAddress(env, multiaddr, 0, &sockaddrP);
-
- if (result < 0) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return;
- }
-
- memcpy(&(ipmreqP.imr_multiaddr.s_addr), &(sockaddrP.sin_addr), 4);
-
- /* we need to use an IP_MREQ as it is an IPV4 address */
- interfaceAddrID = env->GetFieldID(cls, "interfaceAddr",
- "Ljava/net/InetAddress;");
- interfaceAddr = env->GetObjectField(optVal, interfaceAddrID);
-
- ipmreqP.imr_interface.s_addr = htonl(INADDR_ANY);
-
- /*
- * if an interfaceAddr was passed then use that value, otherwise set the
- * interface to all 0 to indicate the system should select the interface
- * used
- */
- if (!ignoreIF) {
- if (NULL != interfaceAddr) {
-
- result = inetAddressToSocketAddress(env, interfaceAddr, 0,
- &sockaddrP);
-
- if (result < 0) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return;
- }
-
- memcpy(&(ipmreqP.imr_interface.s_addr), &(sockaddrP.sin_addr), 4);
-
- }
- }
-
- /* join/drop the multicast address */
- result = setsockopt(handle, IPPROTO_IP, setSockOptVal, &ipmreqP, length);
- if (0 != result) {
- throwSocketException (env, convertError(errno));
- return;
- }
- }
- }
-
- extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_oneTimeInitializationImpl(JNIEnv* env, jobject obj,
- jboolean jcl_supports_ipv6) {
- // LOGD("ENTER oneTimeInitializationImpl of OSNetworkSystem");
-
- char useAdbNetworkingProperty[PROPERTY_VALUE_MAX];
- char adbConnectedProperty[PROPERTY_VALUE_MAX];
-
- property_get("android.net.use-adb-networking", useAdbNetworkingProperty, "");
- property_get("adb.connected", adbConnectedProperty, "");
-
- if (strlen((char *)useAdbNetworkingProperty) > 0
- && strlen((char *)adbConnectedProperty) > 0) {
- useAdbNetworking = 1;
- }
-
- 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;
- }
-
- gCachedFields.fd_class = env->FindClass("java/io/FileDescriptor");
- if (gCachedFields.fd_class == NULL) {
- jniThrowException(env, "java/lang/ClassNotFoundException",
- "java.io.FileDescriptor");
- return;
- }
- gCachedFields.descriptor = env->GetFieldID(gCachedFields.fd_class, "descriptor", "I");
- if (gCachedFields.descriptor == NULL) {
- jniThrowException(env, "java/lang/NoSuchFieldError",
- "FileDescriptor.descriptor");
- return;
- }
-
- }
-
- extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_createSocketImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jboolean preferIPv4Stack) {
- // LOGD("ENTER createSocketImpl");
-
- int ret = socket(PF_INET, SOCK_STREAM, 0);
-
- if (ret < 0) {
- int err = convertError(errno);
- throwSocketException(env, err);
- return;
- }
-
- jniSetFileDescriptorOfFD(env, fileDescriptor, ret);
-
- return;
- }
-
- extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_createDatagramSocketImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jboolean preferIPv4Stack) {
- // LOGD("ENTER createDatagramSocketImpl");
-
- int ret = socket(PF_INET, SOCK_DGRAM, 0);
…
Large files files are truncated, but you can click here to view the full file