/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
- /*
- * 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);
-
- if (ret < 0) {
- int err = convertError(errno);
- throwSocketException(env, err);
- return;
- }
-
- jniSetFileDescriptorOfFD(env, fileDescriptor, ret);
-
- return;
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_readSocketDirectImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jint address, jint offset, jint count,
- jint timeout) {
- // LOGD("ENTER readSocketDirectImpl");
-
- int handle;
- jbyte *message = (jbyte *)address;
- int result, ret, localCount;
-
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return 0;
- }
-
- result = selectWait(handle, timeout, SELECT_READ_TYPE);
-
- if (0 > result) {
- return 0;
- }
-
- localCount = (count < 65536) ? count : 65536;
-
- do {
- ret = recv(handle, (jbyte *) message, localCount, SOCKET_NOFLAGS);
- } while (ret < 0 && errno == EINTR);
-
- if (0 == ret) {
- return -1;
- } else if (ret == -1) {
- int err = convertError(errno);
- log_socket_close(handle, err);
- throwSocketException(env, err);
- return 0;
- }
- add_recv_stats(handle, ret);
- return ret;
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_readSocketImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jbyteArray data, jint offset, jint count,
- jint timeout) {
- // LOGD("ENTER readSocketImpl");
-
- jbyte *message;
- int result, localCount;
-
- jbyte internalBuffer[BUFFERSIZE];
-
- localCount = (count < 65536) ? count : 65536;
-
- if (localCount > BUFFERSIZE) {
- message = (jbyte*)malloc(localCount * sizeof(jbyte));
- if (message == NULL) {
- jniThrowException(env, "java/lang/OutOfMemoryError",
- "couldn't allocate enough memory for readSocket");
- return 0;
- }
- } else {
- message = (jbyte *)internalBuffer;
- }
-
- result = Java_org_sipdroid_net_impl_OSNetworkSystem_readSocketDirectImpl(env, clazz, fileDescriptor,
- (jint) message, offset, count, timeout);
-
- if (result > 0) {
- env->SetByteArrayRegion(data, offset, result, (jbyte *)message);
- }
-
- if (((jbyte *)message) != internalBuffer) {
- free(( jbyte *)message);
- }
-
- return result;
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_writeSocketDirectImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jint address, jint offset, jint count) {
- // LOGD("ENTER writeSocketDirectImpl");
-
- int handle;
- jbyte *message = (jbyte *)address;
- int result = 0, sent = 0;
-
- if (count <= 0) {
- return 0;
- }
-
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return 0;
- }
-
- result = send(handle, (jbyte *) message, (int) count, SOCKET_NOFLAGS);
- if (result < 0) {
- int err = convertError(errno);
- log_socket_close(handle, err);
-
- if (SOCKERR_WOULDBLOCK == err){
- jclass socketExClass,errorCodeExClass;
- jmethodID errorCodeExConstructor, socketExConstructor,socketExCauseMethod;
- jobject errorCodeEx, socketEx;
- const char* errorMessage = netLookupErrorString(err);
- jstring errorMessageString = env->NewStringUTF(errorMessage);
-
- errorCodeExClass = env->FindClass("org/apache/harmony/luni/util/ErrorCodeException");
- if (!errorCodeExClass){
- return 0;
- }
- errorCodeExConstructor = env->GetMethodID(errorCodeExClass,"<init>","(I)V");
- if (!errorCodeExConstructor){
- return 0;
- }
- errorCodeEx = env->NewObject(errorCodeExClass,errorCodeExConstructor,err);
-
- socketExClass = env->FindClass("java/net/SocketException");
- if (!socketExClass) {
- return 0;
- }
- socketExConstructor = env->GetMethodID(socketExClass,"<init>","(Ljava/lang/String;)V");
- if (!socketExConstructor) {
- return 0;
- }
- socketEx = env->NewObject(socketExClass, socketExConstructor, errorMessageString);
- socketExCauseMethod = env->GetMethodID(socketExClass,"initCause","(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
- env->CallObjectMethod(socketEx,socketExCauseMethod,errorCodeEx);
- env->Throw((jthrowable)socketEx);
- return 0;
- }
- throwSocketException(env, err);
- return 0;
- }
-
- add_send_stats(handle, result);
- return result;
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_writeSocketImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jbyteArray data, jint offset, jint count) {
- // LOGD("ENTER writeSocketImpl");
-
- jbyte *message;
- int sent = 0;
- jint result = 0;
-
- /* TODO: ARRAY PINNING */
- #define INTERNAL_SEND_BUFFER_MAX 512
- jbyte internalBuffer[INTERNAL_SEND_BUFFER_MAX];
-
- if (count > INTERNAL_SEND_BUFFER_MAX) {
- message = (jbyte*)malloc(count * sizeof( jbyte));
- if (message == NULL) {
- jniThrowException(env, "java/lang/OutOfMemoryError",
- "couldn't allocate enough memory for writeSocket");
- return 0;
- }
- } else {
- message = (jbyte *)internalBuffer;
- }
-
- env->GetByteArrayRegion(data, offset, count, message);
-
- result = Java_org_sipdroid_net_impl_OSNetworkSystem_writeSocketDirectImpl(env, clazz, fileDescriptor,
- (jint) message, offset, count);
-
- if (( jbyte *)message != internalBuffer) {
- free(( jbyte *)message);
- }
- #undef INTERNAL_SEND_BUFFER_MAX
- return result;
- }
-
- extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_setNonBlockingImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jboolean nonblocking) {
- // LOGD("ENTER setNonBlockingImpl");
-
- int handle;
- int result;
-
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return;
- }
-
- int block = nonblocking;
-
- result = ioctl(handle, FIONBIO, &block);
-
- if (result == -1) {
- throwSocketException(env, convertError(errno));
- }
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_connectSocketImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jint trafficClass, jobject inetAddr, jint port);
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_connectWithTimeoutSocketImpl(JNIEnv* env,
- jclass clazz, jobject fileDescriptor, jint timeout, jint trafficClass,
- jobject inetAddr, jint port, jint step, jbyteArray passContext) {
- // LOGD("ENTER connectWithTimeoutSocketImpl");
-
- int handle;
- int result = 0;
- struct sockaddr_in address;
- jbyte *context = NULL;
-
- memset(&address, 0, sizeof(address));
-
- address.sin_family = AF_INET;
-
- result = inetAddressToSocketAddress(env, inetAddr, port,
- (struct sockaddr_in *) &address);
-
- if (result < 0) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return result;
- }
-
- // Check if we're using adb networking and redirect in case it is used.
- if (useAdbNetworking && !isLocalhost(&address)) {
- return Java_org_sipdroid_net_impl_OSNetworkSystem_connectSocketImpl(env, clazz, fileDescriptor,
- trafficClass, inetAddr, port);
- }
-
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return -1;
- }
-
- address.sin_port = htons(port);
-
- context = (jbyte *)env->GetPrimitiveArrayCritical(passContext, NULL);
-
- switch (step) {
- case SOCKET_CONNECT_STEP_START:
- result = sockConnectWithTimeout(handle, address, 0,
- SOCKET_STEP_START, context);
- break;
- case SOCKET_CONNECT_STEP_CHECK:
- result = sockConnectWithTimeout(handle, address, timeout,
- SOCKET_STEP_CHECK, context);
- break;
- }
-
- env->ReleasePrimitiveArrayCritical(passContext, context, JNI_ABORT);
-
- if (0 == result) {
- /* connected , so stop here */
- sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, NULL);
- } else if (result != SOCKERR_NOTCONNECTED) {
- /* can not connect... */
- sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, NULL);
- if (result == SOCKERR_EACCES) {
- jniThrowException(env, "java/lang/SecurityException",
- netLookupErrorString(result));
- } else {
- jniThrowException(env, "java/net/ConnectException",
- netLookupErrorString(result));
- }
- }
-
- return result;
- }
-
- extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_connectStreamWithTimeoutSocketImpl(JNIEnv* env,
- jclass clazz, jobject fileDescriptor, jint remotePort, jint timeout,
- jint trafficClass, jobject inetAddr) {
- // LOGD("ENTER connectStreamWithTimeoutSocketImpl");
-
- int result = 0;
- int handle;
- struct sockaddr_in address;
- jbyte *context = NULL;
- int remainingTimeout = timeout;
- int passedTimeout = 0;
- int finishTime = 0;
- int blocking = 0;
- char hasTimeout = timeout > 0;
-
- /* if a timeout was specified calculate the finish time value */
- if (hasTimeout) {
- finishTime = time_msec_clock() + (int) timeout;
- }
-
-
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return;
- } else {
- result = inetAddressToSocketAddress(env, inetAddr, remotePort,
- (struct sockaddr_in *) &address);
-
- if (result < 0) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return;
- }
-
- // Check if we're using adb networking and redirect in case it is used.
- if (useAdbNetworking && !isLocalhost(&address)) {
- int retVal = Java_org_sipdroid_net_impl_OSNetworkSystem_connectSocketImpl(env, clazz,
- fileDescriptor, trafficClass, inetAddr, remotePort);
- if (retVal != 0) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- }
- return;
- }
-
- /*
- * we will be looping checking for when we are connected so allocate
- * the descriptor sets that we will use
- */
- context =(jbyte *) malloc(sizeof(struct selectFDSet));
-
- if (NULL == context) {
- throwSocketException(env, SOCKERR_NOBUFFERS);
- return;
- }
-
- result = sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_START, context);
- if (0 == result) {
- /* ok we connected right away so we are done */
- sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, context);
- goto bail;
- } else if (result != SOCKERR_NOTCONNECTED) {
- log_socket_close(handle, result);
- sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE,
- context);
- /* we got an error other than NOTCONNECTED so we cannot continue */
- if (SOCKERR_EACCES == result) {
- jniThrowException(env, "java/lang/SecurityException",
- netLookupErrorString(result));
- } else {
- throwSocketException(env, result);
- }
- goto bail;
- }
-
- while (SOCKERR_NOTCONNECTED == result) {
- passedTimeout = remainingTimeout;
-
- /*
- * ok now try and connect. Depending on the platform this may sleep
- * for up to passedTimeout milliseconds
- */
- result = sockConnectWithTimeout(handle, address, passedTimeout,
- SOCKET_STEP_CHECK, context);
-
- /*
- * now check if the socket is still connected.
- * Do it here as some platforms seem to think they
- * are connected if the socket is closed on them.
- */
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (handle == 0 || handle == -1) {
- sockConnectWithTimeout(handle, address, 0,
- SOCKET_STEP_DONE, context);
- throwSocketException(env, SOCKERR_BADSOCKET);
- goto bail;
- }
-
- /*
- * check if we are now connected,
- * if so we can finish the process and return
- */
- if (0 == result) {
- sockConnectWithTimeout(handle, address, 0,
- SOCKET_STEP_DONE, context);
- goto bail;
- }
-
- /*
- * if the error is SOCKERR_NOTCONNECTED then we have not yet
- * connected and we may not be done yet
- */
- if (SOCKERR_NOTCONNECTED == result) {
- /* check if the timeout has expired */
- if (hasTimeout) {
- remainingTimeout = finishTime - time_msec_clock();
- if (remainingTimeout <= 0) {
- log_socket_close(handle, result);
- sockConnectWithTimeout(handle, address, 0,
- SOCKET_STEP_DONE, context);
- jniThrowException(env,
- "java/net/SocketTimeoutException",
- netLookupErrorString(result));
- goto bail;
- }
- } else {
- remainingTimeout = 100;
- }
- } else {
- log_socket_close(handle, result);
- sockConnectWithTimeout(handle, address, remainingTimeout,
- SOCKET_STEP_DONE, context);
- if ((SOCKERR_CONNRESET == result) ||
- (SOCKERR_CONNECTION_REFUSED == result) ||
- (SOCKERR_ADDRNOTAVAIL == result) ||
- (SOCKERR_ADDRINUSE == result) ||
- (SOCKERR_ENETUNREACH == result)) {
- jniThrowException(env, "java/net/ConnectException",
- netLookupErrorString(result));
- } else if (SOCKERR_EACCES == result) {
- jniThrowException(env, "java/lang/SecurityException",
- netLookupErrorString(result));
- } else {
- throwSocketException(env, result);
- }
- goto bail;
- }
- }
- }
-
- bail:
-
- /* free the memory for the FD set */
- if (context != NULL) {
- free(context);
- }
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_connectSocketImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jint trafficClass, jobject inetAddr, jint port) {
- //LOGD("ENTER direct-call connectSocketImpl\n");
-
- struct sockaddr_in address;
- int ret;
- int handle;
- jbyteArray java_in_addr;
-
- memset(&address, 0, sizeof(address));
-
- address.sin_family = AF_INET;
-
- ret = inetAddressToSocketAddress(env, inetAddr, port,
- (struct sockaddr_in *) &address);
-
- if (ret < 0) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return ret;
- }
-
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return -1;
- }
-
- address.sin_port = htons(port);
-
- if (useAdbNetworking && !isLocalhost(&address)) {
-
- // LOGD("+connect to address 0x%08x port %d (via adb)",
- // address.sin_addr.s_addr, (int) port);
- ret = adb_networking_connect_fd(handle, &address);
- // LOGD("-connect ret %d errno %d (via adb)", ret, errno);
-
- } else {
-
- // call this method with a timeout of zero
- Java_org_sipdroid_net_impl_OSNetworkSystem_connectStreamWithTimeoutSocketImpl(env, clazz,
- fileDescriptor, port, 0, trafficClass, inetAddr);
- if (env->ExceptionOccurred() != 0) {
- return -1;
- } else {
- return 0;
- }
-
- }
-
- if (ret < 0) {
- jniThrowException(env, "java/net/ConnectException",
- netLookupErrorString(convertError(errno)));
- return ret;
- }
-
- return ret;
- }
-
- extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_socketBindImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jint port, jobject inetAddress) {
- // LOGD("ENTER socketBindImpl");
-
- struct sockaddr_in sockaddress;
- int ret;
- int handle;
-
- ret = inetAddressToSocketAddress(env, inetAddress, port,
- (struct sockaddr_in *) &sockaddress);
-
- if (ret < 0) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return;
- }
-
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return;
- }
-
- ret = bind(handle, (const sockaddr*)&sockaddress, sizeof(sockaddress));
-
- if (ret < 0) {
- jniThrowException(env, "java/net/BindException",
- netLookupErrorString(convertError(errno)));
- return;
- }
- }
-
- extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_listenStreamSocketImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jint backlog) {
- // LOGD("ENTER listenStreamSocketImpl");
-
- int ret;
- int handle;
-
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return;
- }
-
- ret = listen(handle, backlog);
-
- if (ret < 0) {
- int err = convertError(errno);
- log_socket_close(handle, err);
- throwSocketException(env, err);
- return;
- }
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_availableStreamImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor) {
- // LOGD("ENTER availableStreamImpl");
-
- int handle;
- char message[BUFFERSIZE];
-
- int result;
-
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return 0;
- }
-
- do {
- result = selectWait(handle, 1, SELECT_READ_TYPE);
-
- if (SOCKERR_TIMEOUT == result) {
- // The read operation timed out, so answer 0 bytes available
- return 0;
- } else if (SOCKERR_INTERRUPTED == result) {
- continue;
- } else if (0 > result) {
- log_socket_close(handle, result);
- throwSocketException(env, result);
- return 0;
- }
- } while (SOCKERR_INTERRUPTED == result);
-
- result = recv(handle, (jbyte *) message, BUFFERSIZE, MSG_PEEK);
-
- if (0 > result) {
- int err = convertError(errno);
- log_socket_close(handle, err);
- throwSocketException(env, err);
- return 0;
- }
- add_recv_stats(handle, result);
- return result;
- }
-
- extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_acceptSocketImpl(JNIEnv* env, jclass clazz,
- jobject fdServer, jobject newSocket, jobject fdnewSocket, jint timeout) {
- // LOGD("ENTER acceptSocketImpl");
-
- union {
- struct sockaddr address;
- struct sockaddr_in in_address;
- } sa;
-
- int ret;
- int retFD;
- int result;
- int handle;
- socklen_t addrlen;
-
- if (newSocket == NULL) {
- throwNullPointerException(env);
- return;
- }
-
- result = pollSelectWait(env, fdServer, timeout, SELECT_READ_TYPE);
-
- if (0 > result) {
- return;
- }
-
- handle = jniGetFDFromFileDescriptor(env, fdServer);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return;
- }
-
- do {
- addrlen = sizeof(sa);
- ret = accept(handle, &(sa.address), &addrlen);
- } while (ret < 0 && errno == EINTR);
-
- if (ret < 0) {
- int err = convertError(errno);
- log_socket_close(handle, err);
- throwSocketException(env, err);
- return;
- }
-
- retFD = ret;
-
- /* For AF_INET / inetOrLocal == true only: put
- * peer address and port in instance variables
- * We don't bother for UNIX domain sockets, since most peers are
- * anonymous anyway
- */
- if (sa.address.sa_family == AF_INET) {
- // inetOrLocal should also be true
-
- jobject inetAddress;
-
- inetAddress = structInToInetAddress(env, &(sa.in_address.sin_addr));
-
- if (inetAddress == NULL) {
- close(retFD);
- newSocket = NULL;
- return;
- }
-
- env->SetObjectField(newSocket,
- gCachedFields.socketimpl_address, inetAddress);
-
- env->SetIntField(newSocket, gCachedFields.socketimpl_port,
- ntohs(sa.in_address.sin_port));
- }
-
- jniSetFileDescriptorOfFD(env, fdnewSocket, retFD);
- }
-
- extern "C" jboolean Java_org_sipdroid_net_impl_OSNetworkSystem_supportsUrgentDataImpl(JNIEnv* env,
- jclass clazz, jobject fileDescriptor) {
- // LOGD("ENTER supportsUrgentDataImpl");
-
- int handle;
-
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
- if (handle == 0 || handle == -1) {
- return JNI_FALSE;
- }
-
- return JNI_TRUE;
- }
-
- extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_sendUrgentDataImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jbyte value) {
- // LOGD("ENTER sendUrgentDataImpl");
-
- int handle;
- int result;
-
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return;
- }
-
- result = send(handle, (jbyte *) &value, 1, MSG_OOB);
- if (result < 0) {
- int err = convertError(errno);
- log_socket_close(handle, err);
- throwSocketException(env, err);
- }
- }
-
- extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_connectDatagramImpl2(JNIEnv* env, jclass clazz,
- jobject fd, jint port, jint trafficClass, jobject inetAddress) {
- // LOGD("ENTER connectDatagramImpl2");
-
- int handle = jniGetFDFromFileDescriptor(env, fd);
-
- struct sockaddr_in sockAddr;
- int ret;
-
- ret = inetAddressToSocketAddress(env, inetAddress, port, &sockAddr);
-
- if (ret < 0) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return;
- }
- log_socket_connect(handle, ntohl(sockAddr.sin_addr.s_addr), port);
- int result = connect(handle, (struct sockaddr *)&sockAddr, sizeof(sockAddr));
- if (result < 0) {
- int err = convertError(errno);
- log_socket_close(handle, err);
- throwSocketException(env, err);
- }
- }
-
- extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_disconnectDatagramImpl(JNIEnv* env, jclass clazz,
- jobject fd) {
- // LOGD("ENTER disconnectDatagramImpl");
-
- int handle = jniGetFDFromFileDescriptor(env, fd);
-
- struct sockaddr_in *sockAddr;
- socklen_t sockAddrLen = sizeof(struct sockaddr_in);
- sockAddr = (struct sockaddr_in *) malloc(sockAddrLen);
- memset(sockAddr, 0, sockAddrLen);
-
- sockAddr->sin_family = AF_UNSPEC;
- int result = connect(handle, (struct sockaddr *)sockAddr, sockAddrLen);
- free(sockAddr);
-
- if (result < 0) {
- int err = convertError(errno);
- log_socket_close(handle, err);
- throwSocketException(env, err);
- }
- }
-
- extern "C" jboolean Java_org_sipdroid_net_impl_OSNetworkSystem_socketBindImpl2(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jint port, jboolean bindToDevice,
- jobject inetAddress) {
- // LOGD("ENTER socketBindImpl2");
-
- struct sockaddr_in sockaddress;
- int ret;
- int handle;
-
- ret = inetAddressToSocketAddress(env, inetAddress, port,
- (struct sockaddr_in *) &sockaddress);
-
- if (ret < 0) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return 0;
- }
-
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return 0;
- }
-
- ret = bind(handle, (const sockaddr*)&sockaddress, sizeof(sockaddress));
-
- if (ret < 0) {
- int err = convertError(errno);
- log_socket_close(handle, err);
- jniThrowException(env, "java/net/BindException", netLookupErrorString(err));
- return 0;
- }
-
- return 0;
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_peekDatagramImpl(JNIEnv* env, jclass clazz,
- jobject fd, jobject sender, jint receiveTimeout) {
- // LOGD("ENTER peekDatagramImpl");
-
- int port = -1;
-
- int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
- if (0> result) {
- return (jint) 0;
- }
-
- int handle = jniGetFDFromFileDescriptor(env, fd);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return 0;
- }
-
- struct sockaddr_in sockAddr;
- socklen_t sockAddrLen = sizeof(sockAddr);
-
- int length = recvfrom(handle, NULL, 0, MSG_PEEK,
- (struct sockaddr *)&sockAddr, &sockAddrLen);
-
- if (length < 0) {
- int err = convertError(errno);
- log_socket_close(handle, err);
- throwSocketException(env, err);
- return 0;
- }
-
- if (socketAddressToInetAddress(env, &sockAddr, sender, &port) < 0) {
- throwIOExceptionStr(env, "Address conversion failed");
- return -1;
- }
- add_recv_stats(handle, length);
- return port;
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_receiveDatagramDirectImpl(JNIEnv* env, jclass clazz,
- jobject fd, jobject packet, jint address, jint offset, jint length,
- jint receiveTimeout, jboolean peek) {
- // LOGD("ENTER receiveDatagramDirectImpl");
-
- int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
- if (0 > result) {
- return (jint) 0;
- }
-
- int handle = jniGetFDFromFileDescriptor(env, fd);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return 0;
- }
-
- struct sockaddr_in sockAddr;
- socklen_t sockAddrLen = sizeof(sockAddr);
-
- int mode = peek ? MSG_PEEK : 0;
-
- int actualLength = recvfrom(handle, (char*)(address + offset), length, mode,
- (struct sockaddr *)&sockAddr, &sockAddrLen);
-
- if (actualLength < 0) {
- int err = convertError(errno);
- log_socket_close(handle, err);
- throwSocketException(env, err);
- return 0;
- }
-
- if (packet != NULL) {
- /*
- int port = ntohs(sockAddr.sin_port);
- jbyteArray addr = env->NewByteArray(sizeof(struct in_addr));
- if ((structInToJavaAddress(env, &sockAddr.sin_addr, addr)) < 0) {
- jniThrowException(env, "java/net/SocketException",
- "Could not set address of packet.");
- return 0;
- }
- jobject sender = env->CallStaticObjectMethod(
- gCachedFields.iaddr_class, gCachedFields.iaddr_getbyaddress,
- addr);
- env->SetObjectField(packet, gCachedFields.dpack_address, sender);
- env->SetIntField(packet, gCachedFields.dpack_port, port);
- */
- env->SetIntField(packet, gCachedFields.dpack_length, actualLength);
- }
- add_recv_stats(handle, actualLength);
- return actualLength;
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_receiveDatagramImpl(JNIEnv* env, jclass clazz,
- jobject fd, jobject packet, jbyteArray data, jint offset, jint length,
- jint receiveTimeout, jboolean peek) {
- // LOGD("ENTER receiveDatagramImpl");
-
- int localLength = (length < 65536) ? length : 65536;
- jbyte *bytes = (jbyte*) malloc(localLength);
- if (bytes == NULL) {
- jniThrowException(env, "java/lang/OutOfMemoryError",
- "couldn't allocate enough memory for receiveDatagram");
- return 0;
- }
-
- int actualLength = Java_org_sipdroid_net_impl_OSNetworkSystem_receiveDatagramDirectImpl(env, clazz, fd,
- packet, (jint)bytes, offset, localLength, receiveTimeout, peek);
-
- if (actualLength > 0) {
- env->SetByteArrayRegion(data, offset, actualLength, bytes);
- }
- free(bytes);
-
- return actualLength;
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_recvConnectedDatagramDirectImpl(JNIEnv* env,
- jclass clazz, jobject fd, jobject packet, jint address, jint offset,
- jint length, jint receiveTimeout, jboolean peek) {
- // LOGD("ENTER receiveConnectedDatagramDirectImpl");
-
- int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
-
- if (0 > result) {
- return 0;
- }
-
- int handle = jniGetFDFromFileDescriptor(env, fd);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return 0;
- }
-
- int mode = peek ? MSG_PEEK : 0;
-
- int actualLength = recvfrom(handle,
- (char*)(address + offset), length, mode, NULL, NULL);
-
- if (actualLength < 0) {
- jniThrowException(env, "java/net/PortUnreachableException", "");
- return 0;
- }
-
- if ( packet != NULL) {
- env->SetIntField(packet, gCachedFields.dpack_length, actualLength);
- }
- add_recv_stats(handle, actualLength);
- return actualLength;
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_recvConnectedDatagramImpl(JNIEnv* env, jclass clazz,
- jobject fd, jobject packet, jbyteArray data, jint offset, jint length,
- jint receiveTimeout, jboolean peek) {
- // LOGD("ENTER receiveConnectedDatagramImpl");
-
- int localLength = (length < 65536) ? length : 65536;
- jbyte *bytes = (jbyte*) malloc(localLength);
- if (bytes == NULL) {
- jniThrowException(env, "java/lang/OutOfMemoryError",
- "couldn't allocate enough memory for recvConnectedDatagram");
- return 0;
- }
-
- int actualLength = Java_org_sipdroid_net_impl_OSNetworkSystem_recvConnectedDatagramDirectImpl(env,
- clazz, fd, packet, (jint)bytes, offset, localLength,
- receiveTimeout, peek);
-
- if (actualLength > 0) {
- env->SetByteArrayRegion(data, offset, actualLength, bytes);
- }
- free(bytes);
-
- return actualLength;
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_sendDatagramDirectImpl(JNIEnv* env, jclass clazz,
- jobject fd, jint address, jint offset, jint length, jint port,
- jboolean bindToDevice, jint trafficClass, jobject inetAddress) {
- // LOGD("ENTER sendDatagramDirectImpl");
-
- int result = 0;
-
- int handle = jniGetFDFromFileDescriptor(env, fd);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return 0;
- }
-
- struct sockaddr_in receiver;
-
- if (inetAddressToSocketAddress(env, inetAddress, port, &receiver) < 0) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return 0;
- }
-
- result = sendto(handle, (char*)(address + offset), length, SOCKET_NOFLAGS,
- (struct sockaddr*)&receiver, sizeof(receiver));
-
- if (result < 0) {
- int err = convertError(errno);
- if ((SOCKERR_CONNRESET == err)
- || (SOCKERR_CONNECTION_REFUSED == err)) {
- return 0;
- } else {
- log_socket_close(handle, err);
- throwSocketException(env, err);
- return 0;
- }
- }
- add_send_stats(handle, result);
- return result;
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_sendDatagramImpl(JNIEnv* env, jclass clazz,
- jobject fd, jbyteArray data, jint offset, jint length, jint port,
- jboolean bindToDevice, jint trafficClass, jobject inetAddress) {
- // LOGD("ENTER sendDatagramImpl");
-
- jbyte *bytes = env->GetByteArrayElements(data, NULL);
- int actualLength = Java_org_sipdroid_net_impl_OSNetworkSystem_sendDatagramDirectImpl(env, clazz, fd,
- (jint)bytes, offset, length, port, bindToDevice, trafficClass,
- inetAddress);
- env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
-
- return actualLength;
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_sendConnectedDatagramDirectImpl(JNIEnv* env,
- jclass clazz, jobject fd, jint address, jint offset, jint length,
- jboolean bindToDevice) {
- // LOGD("ENTER sendConnectedDatagramDirectImpl");
-
- int handle = jniGetFDFromFileDescriptor(env, fd);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return 0;
- }
-
- int result = send(handle, (char*)(address + offset), length, 0);
-
- if (result < 0) {
- int err = convertError(errno);
- if ((SOCKERR_CONNRESET == err) || (SOCKERR_CONNECTION_REFUSED == err)) {
- return 0;
- } else {
- log_socket_close(handle, err);
- throwSocketException(env, err);
- return 0;
- }
- }
- add_send_stats(handle, length);
- return result;
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_sendConnectedDatagramImpl(JNIEnv* env, jclass clazz,
- jobject fd, jbyteArray data, jint offset, jint length,
- jboolean bindToDevice) {
- // LOGD("ENTER sendConnectedDatagramImpl");
-
- jbyte *bytes = env->GetByteArrayElements(data, NULL);
- int actualLength = Java_org_sipdroid_net_impl_OSNetworkSystem_sendConnectedDatagramDirectImpl(env,
- clazz, fd, (jint)bytes, offset, length, bindToDevice);
- env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
-
- return actualLength;
- }
-
- extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_createServerStreamSocketImpl(JNIEnv* env,
- jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) {
- // LOGD("ENTER createServerStreamSocketImpl");
-
- if (fileDescriptor == NULL) {
- throwNullPointerException(env);
- return;
- }
-
- int handle = socket(PF_INET, SOCK_STREAM, 0);
-
- if (handle < 0) {
- int err = convertError(errno);
- throwSocketException(env, err);
- return;
- }
-
- jniSetFileDescriptorOfFD(env, fileDescriptor, handle);
-
- int value = 1;
-
- setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
- }
-
- extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_createMulticastSocketImpl(JNIEnv* env,
- jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) {
- // LOGD("ENTER createMulticastSocketImpl");
-
- int handle = socket(PF_INET, SOCK_DGRAM, 0);
-
- if (handle < 0) {
- int err = convertError(errno);
- throwSocketException(env, err);
- return;
- }
-
- jniSetFileDescriptorOfFD(env, fileDescriptor, handle);
-
- 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
- */
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_receiveStreamImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jbyteArray data, jint offset, jint count,
- jint timeout) {
- // LOGD("ENTER receiveStreamImpl");
-
- int result;
- int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return 0;
- }
-
- // Cap read length to available buf size
- int spaceAvailable = env->GetArrayLength(data) - offset;
- int localCount = count < spaceAvailable? count : spaceAvailable;
-
- jboolean isCopy;
- jbyte *body = env->GetByteArrayElements(data, &isCopy);
-
- // set timeout
- struct timeval tv;
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000;
- setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv,
- sizeof(struct timeval));
-
- do {
- result = recv(handle, body + offset, localCount, SOCKET_NOFLAGS);
- } while (result < 0 && errno == EINTR);
-
- env->ReleaseByteArrayElements(data, body, 0);
-
- /*
- * If no bytes are read, return -1 to signal 'endOfFile'
- * to the Java input stream
- */
- if (0 < result) {
- add_recv_stats(handle, result);
- return result;
- } else if (0 == result) {
- return -1;
- } else {
- // If EAGAIN or EWOULDBLOCK, read timed out
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
- jniThrowException(env, "java/net/SocketTimeoutException",
- netLookupErrorString(SOCKERR_TIMEOUT));
- } else {
- int err = convertError(errno);
- log_socket_close(handle, err);
- throwSocketException(env, err);
- }
- return 0;
- }
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_sendStreamImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jbyteArray data, jint offset, jint count) {
- // LOGD("ENTER sendStreamImpl");
-
- int handle = 0;
- int result = 0, sent = 0;
-
- jboolean isCopy;
- jbyte *message = env->GetByteArrayElements(data, &isCopy);
-
- // Cap write length to available buf size
- int spaceAvailable = env->GetArrayLength(data) - offset;
- if (count > spaceAvailable) count = spaceAvailable;
-
- while (sent < count) {
-
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
- if (handle == 0 || handle == -1) {
- throwSocketException(env,
- sent == 0 ? SOCKERR_BADSOCKET : SOCKERR_INTERRUPTED);
- env->ReleaseByteArrayElements(data, message, 0);
- return 0;
- }
-
- // LOGD("before select %d", count);
- selectWait(handle, SEND_RETRY_TIME, SELECT_WRITE_TYPE);
- result = send(handle, (jbyte *)message + offset + sent,
- (int) count - sent, SOCKET_NOFLAGS);
-
- if (result < 0) {
- result = errno;
- if (result == EAGAIN ||result == EWOULDBLOCK) {
- // LOGD("write blocked %d", sent);
- continue;
- }
- env->ReleaseByteArrayElements(data, message, 0);
- int err = convertError(result);
- log_socket_close(handle, err);
- throwSocketException(env, err);
- return 0;
- }
- sent += result;
- }
-
- env->ReleaseByteArrayElements(data, message, 0);
- add_send_stats(handle, sent);
- return sent;
- }
-
- extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_shutdownInputImpl(JNIEnv* env, jobject obj,
- jobject fileDescriptor) {
- // LOGD("ENTER shutdownInputImpl");
-
- int ret;
- int handle;
-
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return;
- }
-
- ret = shutdown(handle, SHUT_RD);
-
- if (ret < 0) {
- int err = convertError(errno);
- log_socket_close(handle, err);
- throwSocketException(env, err);
- return;
- }
- }
-
- extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_shutdownOutputImpl(JNIEnv* env, jobject obj,
- jobject fileDescriptor) {
- // LOGD("ENTER shutdownOutputImpl");
-
- int ret;
- int handle;
-
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (handle == 0 || handle == -1) {
- return;
- }
-
- ret = shutdown(handle, SHUT_WR);
-
- if (ret < 0) {
- int err = convertError(errno);
- log_socket_close(handle, err);
- throwSocketException(env, err);
- return;
- }
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_sendDatagramImpl2(JNIEnv* env, jclass clazz,
- jobject fd, jbyteArray data, jint offset, jint length, jint port,
- jobject inetAddress) {
- // LOGD("ENTER sendDatagramImpl2");
-
- jbyte *message;
- jbyte nhostAddrBytes[4];
- unsigned short nPort;
- int result = 0, sent = 0;
- int handle = 0;
- struct sockaddr_in sockaddrP;
-
- if (inetAddress != NULL) {
-
- result = inetAddressToSocketAddress(env, inetAddress, port,
- (struct sockaddr_in *) &sockaddrP);
-
- if (result < 0) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return 0;
- }
-
- handle = jniGetFDFromFileDescriptor(env, fd);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return 0;
- }
- }
-
- message = (jbyte*) malloc(length * sizeof(jbyte));
- if (message == NULL) {
- jniThrowException(env, "java/lang/OutOfMemoryError",
- "couldn't allocate enough memory for readSocket");
- return 0;
- }
-
- env->GetByteArrayRegion(data, offset, length, message);
-
- while (sent < length) {
- handle = jniGetFDFromFileDescriptor(env, fd);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env,
- sent == 0 ? SOCKERR_BADSOCKET : SOCKERR_INTERRUPTED);
- free(message);
- return 0;
- }
-
- result = sendto(handle, (char *) (message + sent),
- (int) (length - sent), SOCKET_NOFLAGS,
- (struct sockaddr *) &sockaddrP, sizeof(sockaddrP));
-
- if (result < 0) {
- int err = convertError(errno);
- log_socket_close(handle, err);
- throwSocketException(env, err);
- free(message);
- return 0;
- }
-
- sent += result;
- }
-
- free(message);
- add_send_stats(handle, sent);
- return sent;
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_selectImpl(JNIEnv* env, jclass clazz,
- jobjectArray readFDArray, jobjectArray writeFDArray, jint countReadC,
- jint countWriteC, jintArray outFlags, jlong timeout) {
- // LOGD("ENTER selectImpl");
-
- struct timeval timeP;
- int result = 0;
- int size = 0;
- jobject gotFD;
- fd_set *fdset_read,*fdset_write;
- int handle;
- jboolean isCopy ;
- jint *flagArray;
- int val;
- unsigned int time_sec = (unsigned int)timeout/1000;
- unsigned int time_msec = (unsigned int)(timeout%1000);
-
- fdset_read = (fd_set *)malloc(sizeof(fd_set));
- fdset_write = (fd_set *)malloc(sizeof(fd_set));
-
- FD_ZERO(fdset_read);
- FD_ZERO(fdset_write);
-
- for (val = 0; val<countReadC; val++) {
-
- gotFD = env->GetObjectArrayElement(readFDArray,val);
-
- handle = jniGetFDFromFileDescriptor(env, gotFD);
-
- FD_SET(handle, fdset_read);
-
- if (0 > (size - handle)) {
- size = handle;
- }
- }
-
- for (val = 0; val<countWriteC; val++) {
-
- gotFD = env->GetObjectArrayElement(writeFDArray,val);
-
- handle = jniGetFDFromFileDescriptor(env, gotFD);
-
- FD_SET(handle, fdset_write);
-
- if (0 > (size - handle)) {
- size = handle;
- }
- }
-
- /* the size is the max_fd + 1 */
- size =size + 1;
-
- if (0 > size) {
- result = SOCKERR_FDSET_SIZEBAD;
- } else {
- /* only set when timeout >= 0 (non-block)*/
- if (0 <= timeout) {
-
- timeP.tv_sec = time_sec;
- timeP.tv_usec = time_msec*1000;
-
- result = sockSelect(size, fdset_read, fdset_write, NULL, &timeP);
-
- } else {
- result = sockSelect(size, fdset_read, fdset_write, NULL, NULL);
- }
- }
-
- if (0 < result) {
- /*output the result to a int array*/
- flagArray = env->GetIntArrayElements(outFlags, &isCopy);
-
- for (val=0; val<countReadC; val++) {
- gotFD = env->GetObjectArrayElement(readFDArray,val);
-
- handle = jniGetFDFromFileDescriptor(env, gotFD);
-
- if (FD_ISSET(handle,fdset_read)) {
- flagArray[val] = SOCKET_OP_READ;
- } else {
- flagArray[val] = SOCKET_OP_NONE;
- }
- }
-
- for (val=0; val<countWriteC; val++) {
-
- gotFD = env->GetObjectArrayElement(writeFDArray,val);
-
- handle = jniGetFDFromFileDescriptor(env, gotFD);
-
- if (FD_ISSET(handle,fdset_write)) {
- flagArray[val+countReadC] = SOCKET_OP_WRITE;
- } else {
- flagArray[val+countReadC] = SOCKET_OP_NONE;
- }
- }
-
- env->ReleaseIntArrayElements(outFlags, flagArray, 0);
- }
-
- free(fdset_write);
- free(fdset_read);
-
- /* return both correct and error result, let java handle the exception*/
- return result;
- }
-
- extern "C" jobject Java_org_sipdroid_net_impl_OSNetworkSystem_getSocketLocalAddressImpl(JNIEnv* env,
- jclass clazz, jobject fileDescriptor, jboolean preferIPv6Addresses) {
- // LOGD("ENTER getSocketLocalAddressImpl");
-
- struct sockaddr_in addr;
- socklen_t addrLen = sizeof(addr);
-
- memset(&addr, 0, addrLen);
-
- int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- int result;
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_UNKNOWNSOCKET);
- return NULL;
- }
-
- result = getsockname(handle, (struct sockaddr *)&addr, &addrLen);
-
- // Spec says ignore all errors
-
- return structInToInetAddress(env, &(addr.sin_addr));
-
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_getSocketLocalPortImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jboolean preferIPv6Addresses) {
- // LOGD("ENTER getSocketLocalPortImpl");
-
- struct sockaddr_in addr;
- socklen_t addrLen = sizeof(addr);
-
- int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
- int result;
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_UNKNOWNSOCKET);
- return 0;
- }
-
- result = getsockname(handle, (struct sockaddr *)&addr, &addrLen);
-
- if (0 != result) {
- // The java spec does not indicate any exceptions on this call
- return 0;
- } else {
- return ntohs(addr.sin_port);
- }
- }
-
- extern "C" jobject Java_org_sipdroid_net_impl_OSNetworkSystem_getSocketOptionImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jint anOption) {
- // LOGD("ENTER getSocketOptionImpl");
-
- int handle;
- int intValue = 0;
- socklen_t intSize = sizeof(int);
- unsigned char byteValue = 0;
- socklen_t byteSize = sizeof(unsigned char);
- int result;
- struct sockaddr_in sockVal;
- socklen_t sockSize = sizeof(sockVal);
-
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return NULL;
- }
-
- switch ((int) anOption & 0xffff) {
- case JAVASOCKOPT_SO_LINGER: {
- struct linger lingr;
- socklen_t size = sizeof(struct linger);
- result = getsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr, &size);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return NULL;
- }
- if (!lingr.l_onoff) {
- intValue = -1;
- } else {
- intValue = lingr.l_linger;
- }
- return newJavaLangInteger(env, intValue);
- }
- case JAVASOCKOPT_TCP_NODELAY: {
- if ((anOption >> 16) & BROKEN_TCP_NODELAY) {
- return NULL;
- }
- result = getsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intValue, &intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return NULL;
- }
- return newJavaLangBoolean(env, intValue);
- }
- case JAVASOCKOPT_MCAST_TTL: {
- if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
- return newJavaLangByte(env, 0);
- }
- result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_TTL, &byteValue, &byteSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return NULL;
- }
- return newJavaLangByte(env, (jbyte)(byteValue & 0xFF));
- }
- case JAVASOCKOPT_MCAST_INTERFACE: {
- if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
- return NULL;
- }
- result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, &sockVal, &sockSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return NULL;
- }
- return structInToInetAddress(env, &(sockVal.sin_addr));
- }
- case JAVASOCKOPT_SO_SNDBUF: {
- result = getsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intValue, &intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return NULL;
- }
- return newJavaLangInteger(env, intValue);
- }
- case JAVASOCKOPT_SO_RCVBUF: {
- result = getsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intValue, &intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return NULL;
- }
- return newJavaLangInteger(env, intValue);
- }
- case JAVASOCKOPT_SO_BROADCAST: {
- result = getsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intValue, &intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return NULL;
- }
- return newJavaLangBoolean(env, intValue);
- }
- case JAVASOCKOPT_SO_REUSEADDR: {
- result = getsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intValue, &intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return NULL;
- }
- return newJavaLangBoolean(env, intValue);
- }
- case JAVASOCKOPT_SO_KEEPALIVE: {
- result = getsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intValue, &intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return NULL;
- }
- return newJavaLangBoolean(env, intValue);
- }
- case JAVASOCKOPT_SO_OOBINLINE: {
- result = getsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intValue, &intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return NULL;
- }
- return newJavaLangBoolean(env, intValue);
- }
- case JAVASOCKOPT_IP_MULTICAST_LOOP: {
- result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_LOOP, &intValue, &intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return NULL;
- }
- return newJavaLangBoolean(env, intValue);
- }
- case JAVASOCKOPT_IP_TOS: {
- result = getsockopt(handle, IPPROTO_IP, IP_TOS, &intValue, &intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return NULL;
- }
- return newJavaLangInteger(env, intValue);
- }
- case JAVASOCKOPT_SO_RCVTIMEOUT: {
- struct timeval timeout;
- socklen_t size = sizeof(timeout);
- result = getsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout, &size);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return NULL;
- }
- return newJavaLangInteger(env, timeout.tv_sec * 1000 + timeout.tv_usec/1000);
- }
- default: {
- throwSocketException(env, SOCKERR_OPTUNSUPP);
- return NULL;
- }
- }
-
- }
-
- extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_setSocketOptionImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jint anOption, jobject optVal) {
- // LOGD("ENTER setSocketOptionImpl");
-
- int handle, result;
- int intVal, intSize = sizeof(int);
- unsigned char byteVal, byteSize = sizeof(unsigned char);
- struct sockaddr_in sockVal;
- int sockSize = sizeof(sockVal);
-
- if (env->IsInstanceOf(optVal, gCachedFields.integer_class)) {
- intVal = (int) env->GetIntField(optVal, gCachedFields.integer_class_value);
- } else if (env->IsInstanceOf(optVal, gCachedFields.boolean_class)) {
- intVal = (int) env->GetBooleanField(optVal, gCachedFields.boolean_class_value);
- } else if (env->IsInstanceOf(optVal, gCachedFields.byte_class)) {
- byteVal = (int) env->GetByteField(optVal, gCachedFields.byte_class_value);
- } else if (env->IsInstanceOf(optVal, gCachedFields.iaddr_class)) {
- if (inetAddressToSocketAddress(env, optVal, 0, &sockVal) < 0) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return;
- }
- } else if (env->IsInstanceOf(optVal, gCachedFields.genericipmreq_class)) {
- // we'll use optVal directly
- } else {
- throwSocketException(env, SOCKERR_OPTUNSUPP);
- return;
- }
-
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return;
- }
-
- switch ((int) anOption & 0xffff) {
- case JAVASOCKOPT_SO_LINGER: {
- struct linger lingr;
- lingr.l_onoff = intVal > 0 ? 1 : 0;
- lingr.l_linger = intVal;
- result = setsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr,
- sizeof(struct linger));
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_TCP_NODELAY: {
- if ((anOption >> 16) & BROKEN_TCP_NODELAY) {
- return;
- }
- result = setsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intVal, intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_MCAST_TTL: {
- if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
- return;
- }
- result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_TTL, &byteVal, byteSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_MCAST_ADD_MEMBERSHIP: {
- mcastAddDropMembership(env, handle, optVal,
- (anOption >> 16) & BROKEN_MULTICAST_IF, IP_ADD_MEMBERSHIP);
- return;
- }
-
- case JAVASOCKOPT_MCAST_DROP_MEMBERSHIP: {
- mcastAddDropMembership(env, handle, optVal,
- (anOption >> 16) & BROKEN_MULTICAST_IF, IP_DROP_MEMBERSHIP);
- return;
- }
-
- case JAVASOCKOPT_MCAST_INTERFACE: {
- if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
- return;
- }
- result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, &sockVal, sockSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_SO_SNDBUF: {
- result = setsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intVal, intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_SO_RCVBUF: {
- result = setsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intVal, intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_SO_BROADCAST: {
- result = setsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intVal, intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_SO_REUSEADDR: {
- result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return;
- }
- break;
- }
- case JAVASOCKOPT_SO_KEEPALIVE: {
- result = setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intVal, intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_SO_OOBINLINE: {
- result = setsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intVal, intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_IP_MULTICAST_LOOP: {
- result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_LOOP, &intVal, intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_IP_TOS: {
- result = setsockopt(handle, IPPROTO_IP, IP_TOS, &intVal, intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_REUSEADDR_AND_REUSEPORT: {
- // SO_REUSEPORT doesn't need to get set on this System
- result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_SO_RCVTIMEOUT: {
- struct timeval timeout;
- timeout.tv_sec = intVal / 1000;
- timeout.tv_usec = (intVal % 1000) * 1000;
- result = setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout,
- sizeof(struct timeval));
- if (0 != result) {
- throwSocketException(env, convertError(errno));
- return;
- }
- break;
- }
-
- default: {
- throwSocketException(env, SOCKERR_OPTUNSUPP);
- }
- }
- }
-
- extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_getSocketFlagsImpl(JNIEnv* env, jclass clazz) {
- // LOGD("ENTER getSocketFlagsImpl");
-
- // Not implemented by harmony
- return 0;
- }
-
- extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_socketCloseImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor) {
- // LOGD("ENTER socketCloseImpl");
-
- int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (handle == 0 || handle == -1) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- return;
- }
-
- log_socket_close(handle, SOCKET_CLOSE_LOCAL);
-
- jniSetFileDescriptorOfFD(env, fileDescriptor, -1);
-
- close(handle);
- }
-
- extern "C" jobject Java_org_sipdroid_net_impl_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;
- }
-
- extern "C" jobject Java_org_sipdroid_net_impl_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;
- }
- }
- }
-
- extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_setInetAddressImpl(JNIEnv* env, jobject obj,
- jobject sender, jbyteArray address) {
- // LOGD("ENTER setInetAddressImpl");
-
- env->SetObjectField(sender, gCachedFields.iaddr_ipaddress, address);
- }
-
- /*
- extern "C" jobject Java_org_sipdroid_net_impl_OSNetworkSystem_inheritedChannelImpl(JNIEnv* env, jobject obj) {
- // LOGD("ENTER inheritedChannelImpl");
-
- int socket = 0;
- int opt;
- socklen_t length = sizeof(opt);
- int socket_type;
- struct sockaddr_in local_addr;
- struct sockaddr_in remote_addr;
- jclass channel_class, socketaddr_class, serverSocket_class, socketImpl_class;
- jobject channel_object = NULL, socketaddr_object, serverSocket_object;
- jobject fd_object, addr_object, localAddr_object, socketImpl_object;
- jfieldID port_field, socketaddr_field, bound_field, fd_field;
- jfieldID serverSocket_field, socketImpl_field, addr_field, localAddr_field;
- jmethodID channel_new;
- jbyteArray addr_array;
- struct sockaddr_in *sock;
- jbyte * address;
- jbyte * localAddr;
- jboolean jtrue = JNI_TRUE;
-
- if (0 != getsockopt(socket, SOL_SOCKET, SO_TYPE, &opt, &length)) {
- return NULL;
- }
- if (SOCK_STREAM !=opt && SOCK_DGRAM !=opt) {
- return NULL;
- }
- socket_type = opt;
-
- length = sizeof(struct sockaddr);
- if (0 != getsockname(socket, (struct sockaddr *)&local_addr, &length)) {
- return NULL;
- } else {
- if (AF_INET != local_addr.sin_family || length != sizeof(struct sockaddr)) {
- return NULL;
- }
- localAddr = (jbyte*) malloc(sizeof(jbyte)*4);
- if (NULL == localAddr) {
- return NULL;
- }
- memcpy (localAddr, &(local_addr.sin_addr.s_addr), 4);
- }
- if (0 != getpeername(socket, (struct sockaddr *)&remote_addr, &length)) {
- remote_addr.sin_port = 0;
- remote_addr.sin_addr.s_addr = 0;
- address = (jbyte*) malloc(sizeof(jbyte)*4);
- bzero(address, sizeof(jbyte)*4);
- } else {
- if (AF_INET != remote_addr.sin_family
- || length != sizeof(struct sockaddr)) {
- return NULL;
- }
- address = (jbyte*) malloc(sizeof(jbyte)*4);
- memcpy (address, &(remote_addr.sin_addr.s_addr), 4);
- }
-
- // analysis end, begin pack to java
- if (SOCK_STREAM == opt) {
- if (remote_addr.sin_port!=0) {
- //socket
- channel_class = env->FindClass(
- "org/apache/harmony/nio/internal/SocketChannelImpl");
- if (NULL == channel_class) {
- goto clean;
- }
-
- channel_new = env->GetMethodID(channel_class, "<init>", "()V");
- if (NULL == channel_new) {
- goto clean;
- }
- channel_object = env->NewObject(channel_class, channel_new);
- if (NULL == channel_object) {
- goto clean;
- }
- // new and set FileDescript
-
- fd_field = env->GetFieldID(channel_class, "fd",
- "java/io/FielDescriptor");
- fd_object = env->GetObjectField(channel_object, fd_field);
- if (NULL == fd_object) {
- goto clean;
- }
-
- jniSetFileDescriptorOfFD(env, fd_object, socket);
-
- // local port
- port_field = env->GetFieldID(channel_class, "localPort", "I");
- env->SetIntField(channel_object, port_field,
- ntohs(local_addr.sin_port));
-
- // new and set remote addr
- addr_object = env->NewObject(gCachedFields.iaddr_class,
- gCachedFields.iaddr_class_init);
- if (NULL == addr_object) {
- goto clean;
- }
- socketaddr_class = env->FindClass("java/net/InetSocketAddress");
- socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
- "Ljava/net/InetSocketAddress;");
- socketaddr_object = env->GetObjectField(channel_object,
- socketaddr_field);
- 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 = env->GetFieldID(channel_class, "connectAddress",
- "Ljava/net/InetSocketAddress;");
- socketaddr_object = env->GetObjectField(channel_object,
- socketaddr_field);
-
- localAddr_field = env->GetFieldID(channel_class, "localAddress",
- "Ljava/net/InetAddress;");
- localAddr_object = env->NewObject(gCachedFields.iaddr_class,
- gCachedFields.iaddr_class_init);
- jfieldID socketaddr_field = env->GetFieldID(channel_class,
- "connectAddress", "Ljava/net/InetSocketAddress;");
- jobject socketaddr_object = env->GetObjectField(channel_object,
- socketaddr_field);
- env->SetObjectField(socketaddr_object, localAddr_field,
- localAddr_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
- port_field = env->GetFieldID(socketaddr_class, "port", "I");
- env->SetIntField(socketaddr_object, port_field,
- ntohs(remote_addr.sin_port));
-
- // set bound
- if (0 != local_addr.sin_port) {
- bound_field = env->GetFieldID(channel_class, "isBound", "Z");
- env->SetBooleanField(channel_object, bound_field, jtrue);
- }
-
- } else {
- //serverSocket
- channel_class = env->FindClass(
- "org/apache/harmony/nio/internal/ServerSocketChannelImpl");
- if (NULL == channel_class) {
- goto clean;
- }
-
- channel_new = env->GetMethodID(channel_class, "<init>", "()V");
- if (NULL == channel_new) {
- goto clean;
- }
- channel_object = env->NewObject(channel_class, channel_new);
- if (NULL == channel_object) {
- goto clean;
- }
-
- serverSocket_field = env->GetFieldID(channel_class, "socket",
- "Ljava/net/ServerSocket;");
- serverSocket_class = env->FindClass("Ljava/net/ServerSocket;");
- serverSocket_object = env->GetObjectField(channel_object,
- serverSocket_field);
- // set bound
- if (0 != local_addr.sin_port) {
- bound_field = env->GetFieldID(channel_class, "isBound", "Z");
- env->SetBooleanField(channel_object, bound_field, jtrue);
- bound_field = env->GetFieldID(serverSocket_class, "isBound", "Z");
- env->SetBooleanField(serverSocket_object, bound_field, jtrue);
- }
- // localAddr
- socketImpl_class = env->FindClass("java/net/SocketImpl");
- socketImpl_field = env->GetFieldID(channel_class, "impl",
- "Ljava/net/SocketImpl;");
- socketImpl_object = env->GetObjectField(channel_object,
- socketImpl_field);
- if (NULL == socketImpl_object) {
- goto clean;
- }
-
- localAddr_field = env->GetFieldID(channel_class, "localAddress",
- "Ljava/net/InetAddress;");
- localAddr_object = env->NewObject(gCachedFields.iaddr_class,
- gCachedFields.iaddr_class_init);
- if (NULL == localAddr_object) {
- goto clean;
- }
- env->SetObjectField(socketImpl_object, localAddr_field,
- localAddr_object);
- 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
- port_field = env->GetFieldID(socketImpl_class, "localport", "I");
- env->SetIntField(socketImpl_object, port_field,
- ntohs(local_addr.sin_port));
- }
- } else {
- //Datagram Socket
- // new DatagramChannel
- channel_class = env->FindClass(
- "org/apache/harmony/nio/internal/DatagramChannelImpl");
- if (NULL == channel_class) {
- goto clean;
- }
-
- channel_new = env->GetMethodID(channel_class, "<init>", "()V");
- if (NULL == channel_new) {
- goto clean;
- }
- channel_object = env->NewObject(channel_class, channel_new);
- if (NULL == channel_object) {
- goto clean;
- }
-
- // new and set FileDescript
- fd_field = env->GetFieldID(channel_class, "fd", "java/io/FileDescriptor");
- fd_object = env->GetObjectField(channel_object, fd_field);
- if (NULL == fd_object) {
- goto clean;
- }
-
- jniSetFileDescriptorOfFD(env, fd_object, socket);
-
- port_field = env->GetFieldID(channel_class, "localPort", "I");
- env->SetIntField(channel_object, port_field, ntohs(local_addr.sin_port));
-
- // new and set remote addr
- addr_object = env->NewObject(gCachedFields.iaddr_class,
- gCachedFields.iaddr_class_init);
- if (NULL == addr_object) {
- goto clean;
- }
- socketaddr_class = env->FindClass("java/net/InetSocketAddress");
- socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
- "Ljava/net/InetSocketAddress;");
- socketaddr_object = env->GetObjectField(channel_object, socketaddr_field);
- 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) {
- bound_field = env->GetFieldID(channel_class, "isBound", "Z");
- env->SetBooleanField(channel_object, bound_field, jtrue);
- }
- }
- clean:
- free(address);
- free(localAddr);
- return channel_object;
- }
- */