2 * Copyright (C) 2007 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #define LOG_TAG "OSNetworkSystem"
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 // Temporary hack to fix the sim build until bionic is updated.
28 #ifdef HAVE_ANDROID_OS
29 #include <netinet/in6.h>
31 #define ipv6mr_ifindex ipv6mr_interface
33 #include <netinet/tcp.h>
37 #include <sys/ioctl.h>
40 #include <cutils/properties.h>
41 #include <cutils/adb_networking.h>
42 #include "AndroidSystemNatives.h"
44 // Temporary hack to build on systems that don't have up-to-date libc headers.
46 #define IPV6_TCLASS 67
51 * Error codes for socket operations
53 * @internal SOCKERR* range from -200 to -299 avoid overlap
55 #define SOCKERR_BADSOCKET -200 /* generic error */
56 #define SOCKERR_NOTINITIALIZED -201 /* socket library uninitialized */
57 #define SOCKERR_BADAF -202 /* bad address family */
58 #define SOCKERR_BADPROTO -203 /* bad protocol */
59 #define SOCKERR_BADTYPE -204 /* bad type */
60 #define SOCKERR_SYSTEMBUSY -205 /* system busy handling requests */
61 #define SOCKERR_SYSTEMFULL -206 /* too many sockets */
62 #define SOCKERR_NOTCONNECTED -207 /* socket is not connected */
63 #define SOCKERR_INTERRUPTED -208 /* the call was cancelled */
64 #define SOCKERR_TIMEOUT -209 /* the operation timed out */
65 #define SOCKERR_CONNRESET -210 /* the connection was reset */
66 #define SOCKERR_WOULDBLOCK -211 /* the socket is marked as nonblocking operation would block */
67 #define SOCKERR_ADDRNOTAVAIL -212 /* address not available */
68 #define SOCKERR_ADDRINUSE -213 /* address already in use */
69 #define SOCKERR_NOTBOUND -214 /* the socket is not bound */
70 #define SOCKERR_UNKNOWNSOCKET -215 /* resolution of fileDescriptor to socket failed */
71 #define SOCKERR_INVALIDTIMEOUT -216 /* the specified timeout is invalid */
72 #define SOCKERR_FDSETFULL -217 /* Unable to create an FDSET */
73 #define SOCKERR_TIMEVALFULL -218 /* Unable to create a TIMEVAL */
74 #define SOCKERR_REMSOCKSHUTDOWN -219 /* The remote socket has shutdown gracefully */
75 #define SOCKERR_NOTLISTENING -220 /* listen() was not invoked prior to accept() */
76 #define SOCKERR_NOTSTREAMSOCK -221 /* The socket does not support connection-oriented service */
77 #define SOCKERR_ALREADYBOUND -222 /* The socket is already bound to an address */
78 #define SOCKERR_NBWITHLINGER -223 /* The socket is marked non-blocking & SO_LINGER is non-zero */
79 #define SOCKERR_ISCONNECTED -224 /* The socket is already connected */
80 #define SOCKERR_NOBUFFERS -225 /* No buffer space is available */
81 #define SOCKERR_HOSTNOTFOUND -226 /* Authoritative Answer Host not found */
82 #define SOCKERR_NODATA -227 /* Valid name, no data record of requested type */
83 #define SOCKERR_BOUNDORCONN -228 /* The socket has not been bound or is already connected */
84 #define SOCKERR_OPNOTSUPP -229 /* The socket does not support the operation */
85 #define SOCKERR_OPTUNSUPP -230 /* The socket option is not supported */
86 #define SOCKERR_OPTARGSINVALID -231 /* The socket option arguments are invalid */
87 #define SOCKERR_SOCKLEVELINVALID -232 /* The socket level is invalid */
88 #define SOCKERR_TIMEOUTFAILURE -233
89 #define SOCKERR_SOCKADDRALLOCFAIL -234 /* Unable to allocate the sockaddr structure */
90 #define SOCKERR_FDSET_SIZEBAD -235 /* The calculated maximum size of the file descriptor set is bad */
91 #define SOCKERR_UNKNOWNFLAG -236 /* The flag is unknown */
92 #define SOCKERR_MSGSIZE -237 /* The datagram was too big to fit the specified buffer & was truncated. */
93 #define SOCKERR_NORECOVERY -238 /* The operation failed with no recovery possible */
94 #define SOCKERR_ARGSINVALID -239 /* The arguments are invalid */
95 #define SOCKERR_BADDESC -240 /* The socket argument is not a valid file descriptor */
96 #define SOCKERR_NOTSOCK -241 /* The socket argument is not a socket */
97 #define SOCKERR_HOSTENTALLOCFAIL -242 /* Unable to allocate the hostent structure */
98 #define SOCKERR_TIMEVALALLOCFAIL -243 /* Unable to allocate the timeval structure */
99 #define SOCKERR_LINGERALLOCFAIL -244 /* Unable to allocate the linger structure */
100 #define SOCKERR_IPMREQALLOCFAIL -245 /* Unable to allocate the ipmreq structure */
101 #define SOCKERR_FDSETALLOCFAIL -246 /* Unable to allocate the fdset structure */
102 #define SOCKERR_OPFAILED -247 /* Operation failed */
103 #define SOCKERR_VALUE_NULL -248 /* The value indexed was NULL */
104 #define SOCKERR_CONNECTION_REFUSED -249 /* connection was refused */
105 #define SOCKERR_ENETUNREACH -250 /* network is not reachable */
106 #define SOCKERR_EACCES -251 /* permissions do not allow action on socket */
107 #define SOCKERR_EHOSTUNREACH -252 /* no route to host */
108 #define SOCKERR_EPIPE -253 /* broken pipe */
110 #define JAVASOCKOPT_TCP_NODELAY 1
111 #define JAVASOCKOPT_IP_TOS 3
112 #define JAVASOCKOPT_SO_REUSEADDR 4
113 #define JAVASOCKOPT_SO_KEEPALIVE 8
114 #define JAVASOCKOPT_MCAST_TIME_TO_LIVE 10 /* Currently unused */
115 #define JAVASOCKOPT_SO_BINDADDR 15
116 #define JAVASOCKOPT_MCAST_INTERFACE 16
117 #define JAVASOCKOPT_MCAST_TTL 17
118 #define JAVASOCKOPT_IP_MULTICAST_LOOP 18
119 #define JAVASOCKOPT_MCAST_ADD_MEMBERSHIP 19
120 #define JAVASOCKOPT_MCAST_DROP_MEMBERSHIP 20
121 #define JAVASOCKOPT_IP_MULTICAST_IF2 31
122 #define JAVASOCKOPT_SO_BROADCAST 32
123 #define JAVASOCKOPT_SO_LINGER 128
124 #define JAVASOCKOPT_REUSEADDR_AND_REUSEPORT 10001
125 #define JAVASOCKOPT_SO_SNDBUF 4097
126 #define JAVASOCKOPT_SO_RCVBUF 4098
127 #define JAVASOCKOPT_SO_RCVTIMEOUT 4102
128 #define JAVASOCKOPT_SO_OOBINLINE 4099
130 /* constants for calling multi-call functions */
131 #define SOCKET_STEP_START 10
132 #define SOCKET_STEP_CHECK 20
133 #define SOCKET_STEP_DONE 30
135 #define BROKEN_MULTICAST_IF 1
136 #define BROKEN_MULTICAST_TTL 2
137 #define BROKEN_TCP_NODELAY 4
139 #define SOCKET_CONNECT_STEP_START 0
140 #define SOCKET_CONNECT_STEP_CHECK 1
142 #define SOCKET_OP_NONE 0
143 #define SOCKET_OP_READ 1
144 #define SOCKET_OP_WRITE 2
145 #define SOCKET_READ_WRITE 3
147 #define SOCKET_MSG_PEEK 1
148 #define SOCKET_MSG_OOB 2
150 #define SOCKET_NOFLAGS 0
153 #define BUFFERSIZE 2048
155 // wait for 500000 usec = 0.5 second
156 #define SEND_RETRY_TIME 500000
158 // Local constants for getOrSetSocketOption
159 #define SOCKOPT_GET 1
160 #define SOCKOPT_SET 2
162 struct CachedFields {
163 jfieldID fd_descriptor;
165 jmethodID iaddr_class_init;
166 jmethodID iaddr_getbyaddress;
167 jfieldID iaddr_ipaddress;
168 jclass genericipmreq_class;
169 jclass integer_class;
170 jmethodID integer_class_init;
171 jfieldID integer_class_value;
172 jclass boolean_class;
173 jmethodID boolean_class_init;
174 jfieldID boolean_class_value;
176 jmethodID byte_class_init;
177 jfieldID byte_class_value;
179 jmethodID string_class_init;
180 jfieldID socketimpl_address;
181 jfieldID socketimpl_port;
183 jfieldID dpack_address;
185 jfieldID dpack_length;
188 static int useAdbNetworking = 0;
190 /* needed for connecting with timeout */
191 typedef struct selectFDSet {
199 static const char * netLookupErrorString(int anErrorNum);
202 * Throws an SocketException with the message affiliated with the errorCode.
204 static void throwSocketException(JNIEnv *env, int errorCode) {
205 jniThrowException(env, "java/net/SocketException",
206 netLookupErrorString(errorCode));
210 * Throws an IOException with the given message.
212 static void throwIOExceptionStr(JNIEnv *env, const char *message) {
213 jniThrowException(env, "java/io/IOException", message);
217 * Throws a NullPointerException.
219 static void throwNullPointerException(JNIEnv *env) {
220 jniThrowException(env, "java/lang/NullPointerException", NULL);
224 * Converts a 4-byte array to a native address structure. Throws a
225 * NullPointerException or an IOException in case of error. This is
226 * signaled by a return value of -1. The normal return value is 0.
228 static int javaAddressToStructIn(
229 JNIEnv *env, jbyteArray java_address, struct in_addr *address) {
231 memset(address, 0, sizeof(address));
233 if (java_address == NULL) {
237 if (env->GetArrayLength(java_address) != sizeof(address->s_addr)) {
241 jbyte * java_address_bytes
242 = env->GetByteArrayElements(java_address, NULL);
244 memcpy(&(address->s_addr),
246 sizeof(address->s_addr));
248 env->ReleaseByteArrayElements(java_address, java_address_bytes, JNI_ABORT);
254 * Converts a native address structure to a Java byte array. Throws a
255 * NullPointerException or an IOException in case of error. This is
256 * signaled by a return value of -1. The normal return value is 0.
258 * @param address the sockaddr_storage structure to convert
260 * @exception SocketException the address family is unknown, or out of memory
263 static jbyteArray socketAddressToAddressBytes(JNIEnv *env,
264 struct sockaddr_storage *address) {
267 size_t addressLength;
268 if (address->ss_family == AF_INET) {
269 struct sockaddr_in *sin = (struct sockaddr_in *) address;
270 rawAddress = &sin->sin_addr.s_addr;
272 } else if (address->ss_family == AF_INET6) {
273 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address;
274 rawAddress = &sin6->sin6_addr.s6_addr;
277 throwSocketException(env, SOCKERR_BADAF);
281 jbyteArray byteArray = env->NewByteArray(addressLength);
282 if (byteArray == NULL) {
283 throwSocketException(env, SOCKERR_NOBUFFERS);
286 env->SetByteArrayRegion(byteArray, 0, addressLength, (jbyte *) rawAddress);
292 * Returns the port number in a sockaddr_storage structure.
294 * @param address the sockaddr_storage structure to get the port from
296 * @return the port number, or -1 if the address family is unknown.
298 static int getSocketAddressPort(struct sockaddr_storage *address) {
299 switch (address->ss_family) {
301 return ntohs(((struct sockaddr_in *) address)->sin_port);
303 return ntohs(((struct sockaddr_in6 *) address)->sin6_port);
310 * Converts a native address structure to an InetAddress object.
311 * Throws a NullPointerException or an IOException in case of
312 * error. This is signaled by a return value of -1. The normal
315 * @param sockaddress the sockaddr_storage structure to convert
317 * @return a jobject representing an InetAddress
319 static jobject socketAddressToInetAddress(JNIEnv *env,
320 struct sockaddr_storage *sockaddress) {
322 jbyteArray byteArray = socketAddressToAddressBytes(env, sockaddress);
323 if (byteArray == NULL) // Exception has already been thrown.
326 return env->CallStaticObjectMethod(gCachedFields.iaddr_class,
327 gCachedFields.iaddr_getbyaddress, byteArray);
331 * Converts an InetAddress object and port number to a native address structure.
332 * Throws a NullPointerException or a SocketException in case of
333 * error. This is signaled by a return value of -1. The normal
336 * @param inetaddress the InetAddress object to convert
337 * @param port the port number
338 * @param sockaddress the sockaddr_storage structure to write to
340 * @return 0 on success, -1 on failure
342 * @exception SocketError if the address family is unknown
344 static int inetAddressToSocketAddress(JNIEnv *env,
345 jobject inetaddress, int port, struct sockaddr_storage *sockaddress) {
347 // Get the byte array that stores the IP address bytes in the InetAddress.
348 jbyteArray addressByteArray;
349 addressByteArray = (jbyteArray)env->GetObjectField(inetaddress,
350 gCachedFields.iaddr_ipaddress);
351 if (addressByteArray == NULL) {
352 throwNullPointerException(env);
356 // Get the raw IP address bytes.
357 jbyte *addressBytes = env->GetByteArrayElements(addressByteArray, NULL);
358 if (addressBytes == NULL) {
359 throwNullPointerException(env);
363 // Convert the IP address bytes to the proper IP address type.
364 size_t addressLength = env->GetArrayLength(addressByteArray);
366 if (addressLength == 4) {
368 struct sockaddr_in *sin = (struct sockaddr_in *) sockaddress;
369 memset(sin, 0, sizeof(struct sockaddr_in));
370 sin->sin_family = AF_INET;
371 sin->sin_port = htons(port);
372 memcpy(&sin->sin_addr.s_addr, addressBytes, 4);
373 } else if (addressLength == 16) {
375 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sockaddress;
376 memset(sin6, 0, sizeof(struct sockaddr_in6));
377 sin6->sin6_family = AF_INET6;
378 sin6->sin6_port = htons(port);
379 memcpy(&sin6->sin6_addr.s6_addr, addressBytes, 16);
381 // Unknown address family.
382 throwSocketException(env, SOCKERR_BADAF);
385 env->ReleaseByteArrayElements(addressByteArray, addressBytes, 0);
390 * Answer a new java.lang.Boolean object.
392 * @param env pointer to the JNI library
393 * @param anInt the Boolean constructor argument
395 * @return the new Boolean
398 jobject newJavaLangBoolean(JNIEnv * env, jint anInt) {
400 jmethodID tempMethod;
402 tempClass = gCachedFields.boolean_class;
403 tempMethod = gCachedFields.boolean_class_init;
404 return env->NewObject(tempClass, tempMethod, (jboolean) (anInt != 0));
408 * Answer a new java.lang.Byte object.
410 * @param env pointer to the JNI library
411 * @param anInt the Byte constructor argument
413 * @return the new Byte
416 jobject newJavaLangByte(JNIEnv * env, jbyte val) {
418 jmethodID tempMethod;
420 tempClass = gCachedFields.byte_class;
421 tempMethod = gCachedFields.byte_class_init;
422 return env->NewObject(tempClass, tempMethod, val);
426 * Answer a new java.lang.Integer object.
428 * @param env pointer to the JNI library
429 * @param anInt the Integer constructor argument
431 * @return the new Integer
434 jobject newJavaLangInteger(JNIEnv * env, jint anInt) {
436 jmethodID tempMethod;
438 tempClass = gCachedFields.integer_class;
439 tempMethod = gCachedFields.integer_class_init;
440 return env->NewObject(tempClass, tempMethod, anInt);
444 * Answer a new java.lang.String object.
446 * @param env pointer to the JNI library
447 * @param anInt the byte[] constructor argument
449 * @return the new String
452 jobject newJavaLangString(JNIEnv * env, jbyteArray bytes) {
454 jmethodID tempMethod;
456 tempClass = gCachedFields.string_class;
457 tempMethod = gCachedFields.string_class_init;
458 return env->NewObject(tempClass, tempMethod, (jbyteArray) bytes);
462 * Query OS for timestamp.
463 * Retrieve the current value of system clock and convert to milliseconds.
465 * @param[in] portLibrary The port library.
467 * @return 0 on failure, time value in milliseconds on success.
468 * @deprecated Use @ref time_hires_clock and @ref time_hires_delta
470 * technically, this should return I_64 since both timeval.tv_sec and
471 * timeval.tv_usec are long
474 static int time_msec_clock() {
478 gettimeofday(&tp, &tzp);
479 return (tp.tv_sec * 1000) + (tp.tv_usec / 1000);
483 * Check if the passed sockaddr_storage struct contains a localhost address
485 * @param address address pointer to the address to check
487 * @return 0 if the passed address isn't a localhost address
489 static int isLocalHost(struct sockaddr_storage *address) {
490 if (address->ss_family == AF_INET) {
491 struct sockaddr_in *sin = (struct sockaddr_in *) address;
492 return (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK));
493 } else if (address->ss_family == AF_INET6) {
494 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address;
495 return IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr);
502 * Decide whether to use ADB networking for the given socket address.
504 * @param address pointer to sockaddr_storage structure to check
506 * @return true if ADB networking should be used, false otherwise.
508 static bool useAdbNetworkingForAddress(struct sockaddr_storage *address) {
509 return useAdbNetworking && !isLocalHost(address) &&
510 address->ss_family == AF_INET;
514 * Convert a sockaddr_storage structure to a string for logging purposes.
516 * @param address pointer to sockaddr_storage structure to print
518 * @return a string with the textual representation of the address.
520 * @note Returns a statically allocated buffer, so is not thread-safe.
522 static char *socketAddressToString(struct sockaddr_storage *address) {
523 static char invalidString[] = "<invalid>";
524 static char ipString[INET6_ADDRSTRLEN + sizeof("[]:65535")];
526 char tmp[INET6_ADDRSTRLEN];
528 // TODO: getnameinfo seems to want its length parameter to be exactly
529 // sizeof(sockaddr_in) for an IPv4 address and sizeof (sockaddr_in6) for an
530 // IPv6 address. Fix getnameinfo so it accepts sizeof(sockaddr_storage), and
531 // then remove this hack.
532 int size = (address->ss_family == AF_INET) ?
533 sizeof(sockaddr_in) : sizeof(sockaddr_in6);
534 int result = getnameinfo((struct sockaddr *)address,
535 size, tmp, sizeof(tmp), NULL, 0,
539 return invalidString;
541 if (address->ss_family == AF_INET6) {
542 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address;
543 port = ntohs(sin6->sin6_port);
544 sprintf(ipString, "[%s]:%d", tmp, port);
546 } else if (address->ss_family == AF_INET) {
547 struct sockaddr_in *sin = (struct sockaddr_in *) address;
548 port = ntohs(sin->sin_port);
549 sprintf(ipString, "%s:%d", tmp, port);
552 return invalidString;
557 * Answer the errorString corresponding to the errorNumber, if available.
558 * This function will answer a default error string, if the errorNumber is not
561 * This function will have to be reworked to handle internationalization
562 * properly, removing the explicit strings.
564 * @param anErrorNum the error code to resolve to a human readable string
566 * @return a human readable error string
569 static const char * netLookupErrorString(int anErrorNum) {
570 switch (anErrorNum) {
571 case SOCKERR_BADSOCKET:
573 case SOCKERR_NOTINITIALIZED:
574 return "Socket library uninitialized";
576 return "Bad address family";
577 case SOCKERR_BADPROTO:
578 return "Bad protocol";
579 case SOCKERR_BADTYPE:
581 case SOCKERR_SYSTEMBUSY:
582 return "System busy handling requests";
583 case SOCKERR_SYSTEMFULL:
584 return "Too many sockets allocated";
585 case SOCKERR_NOTCONNECTED:
586 return "Socket is not connected";
587 case SOCKERR_INTERRUPTED:
588 return "The system call was cancelled";
589 case SOCKERR_TIMEOUT:
590 return "The operation timed out";
591 case SOCKERR_CONNRESET:
592 return "The connection was reset";
593 case SOCKERR_WOULDBLOCK:
594 return "The nonblocking operation would block";
595 case SOCKERR_ADDRNOTAVAIL:
596 return "The address is not available";
597 case SOCKERR_ADDRINUSE:
598 return "The address is already in use";
599 case SOCKERR_NOTBOUND:
600 return "The socket is not bound";
601 case SOCKERR_UNKNOWNSOCKET:
602 return "Resolution of the FileDescriptor to socket failed";
603 case SOCKERR_INVALIDTIMEOUT:
604 return "The specified timeout is invalid";
605 case SOCKERR_FDSETFULL:
606 return "Unable to create an FDSET";
607 case SOCKERR_TIMEVALFULL:
608 return "Unable to create a TIMEVAL";
609 case SOCKERR_REMSOCKSHUTDOWN:
610 return "The remote socket has shutdown gracefully";
611 case SOCKERR_NOTLISTENING:
612 return "Listen() was not invoked prior to accept()";
613 case SOCKERR_NOTSTREAMSOCK:
614 return "The socket does not support connection-oriented service";
615 case SOCKERR_ALREADYBOUND:
616 return "The socket is already bound to an address";
617 case SOCKERR_NBWITHLINGER:
618 return "The socket is marked non-blocking & SO_LINGER is non-zero";
619 case SOCKERR_ISCONNECTED:
620 return "The socket is already connected";
621 case SOCKERR_NOBUFFERS:
622 return "No buffer space is available";
623 case SOCKERR_HOSTNOTFOUND:
624 return "Authoritative Answer Host not found";
626 return "Valid name, no data record of requested type";
627 case SOCKERR_BOUNDORCONN:
628 return "The socket has not been bound or is already connected";
629 case SOCKERR_OPNOTSUPP:
630 return "The socket does not support the operation";
631 case SOCKERR_OPTUNSUPP:
632 return "The socket option is not supported";
633 case SOCKERR_OPTARGSINVALID:
634 return "The socket option arguments are invalid";
635 case SOCKERR_SOCKLEVELINVALID:
636 return "The socket level is invalid";
637 case SOCKERR_TIMEOUTFAILURE:
638 return "The timeout operation failed";
639 case SOCKERR_SOCKADDRALLOCFAIL:
640 return "Failed to allocate address structure";
641 case SOCKERR_FDSET_SIZEBAD:
642 return "The calculated maximum size of the file descriptor set is bad";
643 case SOCKERR_UNKNOWNFLAG:
644 return "The flag is unknown";
645 case SOCKERR_MSGSIZE:
646 return "The datagram was too big to fit the specified buffer, so truncated";
647 case SOCKERR_NORECOVERY:
648 return "The operation failed with no recovery possible";
649 case SOCKERR_ARGSINVALID:
650 return "The arguments are invalid";
651 case SOCKERR_BADDESC:
652 return "The socket argument is not a valid file descriptor";
653 case SOCKERR_NOTSOCK:
654 return "The socket argument is not a socket";
655 case SOCKERR_HOSTENTALLOCFAIL:
656 return "Unable to allocate the hostent structure";
657 case SOCKERR_TIMEVALALLOCFAIL:
658 return "Unable to allocate the timeval structure";
659 case SOCKERR_LINGERALLOCFAIL:
660 return "Unable to allocate the linger structure";
661 case SOCKERR_IPMREQALLOCFAIL:
662 return "Unable to allocate the ipmreq structure";
663 case SOCKERR_FDSETALLOCFAIL:
664 return "Unable to allocate the fdset structure";
665 case SOCKERR_OPFAILED:
666 return "Operation failed";
667 case SOCKERR_CONNECTION_REFUSED:
668 return "Connection refused";
669 case SOCKERR_ENETUNREACH:
670 return "Network unreachable";
671 case SOCKERR_EHOSTUNREACH:
672 return "No route to host";
674 return "Broken pipe";
676 return "Permission denied (maybe missing INTERNET permission)";
679 LOGE("unknown socket error %d", anErrorNum);
680 return "unknown error";
684 static int convertError(int errorCode) {
687 return SOCKERR_BADDESC;
689 return SOCKERR_NOBUFFERS;
691 return SOCKERR_OPNOTSUPP;
693 return SOCKERR_OPTUNSUPP;
695 return SOCKERR_SOCKLEVELINVALID;
697 return SOCKERR_NOTSOCK;
699 return SOCKERR_INTERRUPTED;
701 return SOCKERR_NOTCONNECTED;
703 return SOCKERR_BADAF;
704 /* note: CONNRESET not included because it has the same
705 * value as ECONNRESET and they both map to SOCKERR_CONNRESET */
707 return SOCKERR_CONNRESET;
709 return SOCKERR_WOULDBLOCK;
710 case EPROTONOSUPPORT:
711 return SOCKERR_BADPROTO;
713 return SOCKERR_ARGSINVALID;
715 return SOCKERR_TIMEOUT;
717 return SOCKERR_CONNECTION_REFUSED;
719 return SOCKERR_ENETUNREACH;
721 return SOCKERR_EACCES;
723 return SOCKERR_EPIPE;
725 return SOCKERR_EHOSTUNREACH;
727 return SOCKERR_ADDRINUSE;
729 return SOCKERR_ADDRNOTAVAIL;
731 return SOCKERR_MSGSIZE;
733 LOGE("unclassified errno %d (%s)", errorCode, strerror(errorCode));
734 return SOCKERR_OPFAILED;
738 static int sockSelect(int nfds, fd_set *readfds, fd_set *writefds,
739 fd_set *exceptfds, struct timeval *timeout) {
741 int result = select(nfds, readfds, writefds, exceptfds, timeout);
744 if (errno == EINTR) {
745 result = SOCKERR_INTERRUPTED;
747 result = SOCKERR_OPFAILED;
749 } else if (result == 0) {
750 result = SOCKERR_TIMEOUT;
755 #define SELECT_READ_TYPE 0
756 #define SELECT_WRITE_TYPE 1
758 static int selectWait(int handle, int uSecTime, int type) {
760 struct timeval time, *timePtr;
762 int size = handle + 1;
765 FD_SET(handle, &fdset);
768 /* Use a timeout if uSecTime >= 0 */
769 memset(&time, 0, sizeof(time));
770 time.tv_usec = uSecTime;
773 /* Infinite timeout if uSecTime < 0 */
777 if (type == SELECT_READ_TYPE) {
778 result = sockSelect(size, &fdset, NULL, NULL, timePtr);
780 result = sockSelect(size, NULL, &fdset, NULL, timePtr);
785 static int pollSelectWait(JNIEnv *env, jobject fileDescriptor, int timeout, int type) {
786 /* now try reading the socket for the timespan timeout.
787 * if timeout is 0 try forever until the soclets gets ready or until an
790 int pollTimeoutUSec = 100000, pollMsec = 100;
792 int timeLeft = timeout;
793 int hasTimeout = timeout > 0 ? 1 : 0;
798 finishTime = time_msec_clock() + timeout;
803 while (poll) { /* begin polling loop */
806 * Fetch the handle every time in case the socket is closed.
808 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
810 if (handle == 0 || handle == -1) {
811 throwSocketException(env, SOCKERR_INTERRUPTED);
817 if (timeLeft - 10 < pollMsec) {
818 pollTimeoutUSec = timeLeft <= 0 ? 0 : (timeLeft * 1000);
821 result = selectWait(handle, pollTimeoutUSec, type);
824 * because we are polling at a time smaller than timeout
825 * (presumably) lets treat an interrupt and timeout the same - go
826 * see if we're done timewise, and then just try again if not.
828 if (SOCKERR_TIMEOUT == result ||
829 SOCKERR_INTERRUPTED == result) {
831 timeLeft = finishTime - time_msec_clock();
835 * Always throw the "timeout" message because that is
836 * effectively what has happened, even if we happen to
837 * have been interrupted.
839 jniThrowException(env, "java/net/SocketTimeoutException",
840 netLookupErrorString(SOCKERR_TIMEOUT));
842 continue; // try again
845 } else if (0 > result) {
846 throwSocketException(env, result);
850 } else { /* polling with no timeout (why would you do this?)*/
852 result = selectWait(handle, pollTimeoutUSec, type);
855 * if interrupted (or a timeout) just retry
857 if (SOCKERR_TIMEOUT == result ||
858 SOCKERR_INTERRUPTED == result) {
860 continue; // try again
861 } else if (0 > result) {
862 throwSocketException(env, result);
866 } /* end polling loop */
872 * Obtain the socket address family from an existing socket.
874 * @param socket the filedescriptor of the socket to examine
876 * @return an integer, the address family of the socket
878 static int getSocketAddressFamily(int socket) {
879 struct sockaddr_storage ss;
880 socklen_t namelen = sizeof(ss);
881 int ret = getsockname(socket, (struct sockaddr*) &ss, &namelen);
890 * A helper method, to set the connect context to a Long object.
892 * @param env pointer to the JNI library
893 * @param longclass Java Long Object
895 void setConnectContext(JNIEnv *env,jobject longclass,jbyte * context) {
896 jclass descriptorCLS;
897 jfieldID descriptorFID;
898 descriptorCLS = env->FindClass("java/lang/Long");
899 descriptorFID = env->GetFieldID(descriptorCLS, "value", "J");
900 env->SetLongField(longclass, descriptorFID, (jlong)((jint)context));
904 * A helper method, to get the connect context.
906 * @param env pointer to the JNI library
907 * @param longclass Java Long Object
909 jbyte *getConnectContext(JNIEnv *env, jobject longclass) {
910 jclass descriptorCLS;
911 jfieldID descriptorFID;
912 descriptorCLS = env->FindClass("java/lang/Long");
913 descriptorFID = env->GetFieldID(descriptorCLS, "value", "J");
914 return (jbyte*) ((jint)env->GetLongField(longclass, descriptorFID));
917 // typical ip checksum
918 unsigned short ip_checksum(unsigned short* buffer, int size) {
919 register unsigned short * buf = buffer;
920 register int bufleft = size;
921 register unsigned long sum = 0;
923 while (bufleft > 1) {
924 sum = sum + (*buf++);
925 bufleft = bufleft - sizeof(unsigned short );
928 sum = sum + (*(unsigned char*)buf);
930 sum = (sum >> 16) + (sum & 0xffff);
933 return (unsigned short )(~sum);
937 * Converts an IPv4 address to an IPv4-mapped IPv6 address. Performs no error
940 * @param address the address to convert. Must contain an IPv4 address.
941 * @param outputAddress the converted address. Will contain an IPv6 address.
942 * @param mapUnspecified if true, convert 0.0.0.0 to ::ffff:0:0; if false, to ::
944 static void ipv4ToMappedAddress(struct sockaddr_storage *address,
945 struct sockaddr_storage *outputAddress, bool mapUnspecified) {
946 memset(outputAddress, 0, sizeof(struct sockaddr_storage));
947 const struct sockaddr_in *sin = ((struct sockaddr_in *) address);
948 struct sockaddr_in6 *sin6 = ((struct sockaddr_in6 *) outputAddress);
949 sin6->sin6_family = AF_INET6;
950 sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
951 if (sin->sin_addr.s_addr != 0 || mapUnspecified) {
952 sin6->sin6_addr.s6_addr32[2] = htonl(0xffff);
954 sin6->sin6_port = sin->sin_port;
958 * Wrapper for connect() that converts IPv4 addresses to IPv4-mapped IPv6
959 * addresses if necessary.
961 * @param socket the filedescriptor of the socket to connect
962 * @param socketAddress the address to connect to
964 static int doConnect(int socket, struct sockaddr_storage *socketAddress) {
965 struct sockaddr_storage mappedAddress;
966 struct sockaddr_storage *realAddress;
967 if (socketAddress->ss_family == AF_INET &&
968 getSocketAddressFamily(socket) == AF_INET6) {
969 ipv4ToMappedAddress(socketAddress, &mappedAddress, true);
970 realAddress = &mappedAddress;
972 realAddress = socketAddress;
976 ret = connect(socket, (struct sockaddr *) realAddress,
977 sizeof(struct sockaddr_storage));
978 } while (ret < 0 && errno == EINTR);
983 * Wrapper for bind() that converts IPv4 addresses to IPv4-mapped IPv6
984 * addresses if necessary.
986 * @param socket the filedescriptor of the socket to connect
987 * @param socketAddress the address to connect to
989 static int doBind(int socket, struct sockaddr_storage *socketAddress) {
990 struct sockaddr_storage mappedAddress;
991 struct sockaddr_storage *realAddress;
992 if (socketAddress->ss_family == AF_INET &&
993 getSocketAddressFamily(socket) == AF_INET6) {
994 ipv4ToMappedAddress(socketAddress, &mappedAddress, false);
995 realAddress = &mappedAddress;
997 realAddress = socketAddress;
1001 ret = bind(socket, (struct sockaddr *) realAddress,
1002 sizeof(struct sockaddr_storage));
1003 } while (ret < 0 && errno == EINTR);
1008 * Establish a connection to a peer with a timeout. This function is called
1009 * repeatedly in order to carry out the connect and to allow other tasks to
1010 * proceed on certain platforms. The caller must first call with
1011 * step = SOCKET_STEP_START, if the result is SOCKERR_NOTCONNECTED it will then
1012 * call it with step = CHECK until either another error or 0 is returned to
1013 * indicate the connect is complete. Each time the function should sleep for no
1014 * more than timeout milliseconds. If the connect succeeds or an error occurs,
1015 * the caller must always end the process by calling the function with
1016 * step = SOCKET_STEP_DONE
1018 * @param[in] portLibrary The port library.
1019 * @param[in] sock pointer to the unconnected local socket.
1020 * @param[in] addr pointer to the sockaddr, specifying remote host/port.
1021 * @param[in] timeout the timeout in milliseconds. If timeout is negative,
1022 * perform a block operation.
1023 * @param[in,out] pointer to context pointer. Filled in on first call and then
1024 * to be passed into each subsequent call.
1026 * @return 0, if no errors occurred, otherwise the (negative) error code.
1028 static int sockConnectWithTimeout(int handle, struct sockaddr_storage addr,
1029 unsigned int timeout, unsigned int step, jbyte *ctxt) {
1031 struct timeval passedTimeout;
1033 socklen_t errorValLen = sizeof(int);
1034 struct selectFDSet *context = NULL;
1036 if (SOCKET_STEP_START == step) {
1038 context = (struct selectFDSet *) ctxt;
1040 context->sock = handle;
1041 context->nfds = handle + 1;
1043 if (useAdbNetworkingForAddress(&addr)) {
1045 // LOGD("+connect to address 0x%08x (via adb)",
1046 // addr.sin_addr.s_addr);
1047 rc = adb_networking_connect_fd(handle, (struct sockaddr_in *) &addr);
1048 // LOGD("-connect ret %d errno %d (via adb)", rc, errno);
1051 /* set the socket to non-blocking */
1052 int block = JNI_TRUE;
1053 rc = ioctl(handle, FIONBIO, &block);
1055 return convertError(rc);
1058 // LOGD("+connect to address 0x%08x (via normal) on handle %d",
1059 // addr.sin_addr.s_addr, handle);
1060 doConnect(handle, &addr);
1061 // LOGD("-connect to address 0x%08x (via normal) returned %d",
1062 // addr.sin_addr.s_addr, (int) rc);
1070 return SOCKERR_ALREADYBOUND;
1073 return SOCKERR_NOTCONNECTED;
1075 return convertError(rc);
1079 /* we connected right off the bat so just return */
1082 } else if (SOCKET_STEP_CHECK == step) {
1083 /* now check if we have connected yet */
1085 context = (struct selectFDSet *) ctxt;
1088 * set the timeout value to be used. Because on some unix platforms we
1089 * don't get notified when a socket is closed we only sleep for 100ms
1092 passedTimeout.tv_sec = 0;
1093 if (timeout > 100) {
1094 passedTimeout.tv_usec = 100 * 1000;
1095 } else if ((int)timeout >= 0) {
1096 passedTimeout.tv_usec = timeout * 1000;
1099 /* initialize the FD sets for the select */
1100 FD_ZERO(&(context->exceptionSet));
1101 FD_ZERO(&(context->writeSet));
1102 FD_ZERO(&(context->readSet));
1103 FD_SET(context->sock, &(context->writeSet));
1104 FD_SET(context->sock, &(context->readSet));
1105 FD_SET(context->sock, &(context->exceptionSet));
1107 rc = select(context->nfds,
1108 &(context->readSet),
1109 &(context->writeSet),
1110 &(context->exceptionSet),
1111 (int)timeout >= 0 ? &passedTimeout : NULL);
1113 /* if there is at least one descriptor ready to be checked */
1115 /* if the descriptor is in the write set we connected or failed */
1116 if (FD_ISSET(context->sock, &(context->writeSet))) {
1118 if (!FD_ISSET(context->sock, &(context->readSet))) {
1119 /* ok we have connected ok */
1122 /* ok we have more work to do to figure it out */
1123 if (getsockopt(context->sock, SOL_SOCKET, SO_ERROR,
1124 &errorVal, &errorValLen) >= 0) {
1125 return errorVal ? convertError(errorVal) : 0;
1127 return convertError(errno);
1132 /* if the descriptor is in the exception set the connect failed */
1133 if (FD_ISSET(context->sock, &(context->exceptionSet))) {
1134 if (getsockopt(context->sock, SOL_SOCKET, SO_ERROR, &errorVal,
1135 &errorValLen) >= 0) {
1136 return errorVal ? convertError(errorVal) : 0;
1139 return convertError(rc);
1142 } else if (rc < 0) {
1143 /* something went wrong with the select call */
1146 /* if it was EINTR we can just try again. Return not connected */
1148 return SOCKERR_NOTCONNECTED;
1151 /* some other error occured so look it up and return */
1152 return convertError(rc);
1156 * if we get here the timeout expired or the connect had not yet
1157 * completed just indicate that the connect is not yet complete
1159 return SOCKERR_NOTCONNECTED;
1160 } else if (SOCKET_STEP_DONE == step) {
1161 /* we are done the connect or an error occured so clean up */
1163 int block = JNI_FALSE;
1164 ioctl(handle, FIONBIO, &block);
1168 return SOCKERR_ARGSINVALID;
1173 * Helper method to get or set socket options
1175 * @param action SOCKOPT_GET to get an option, SOCKOPT_SET to set it
1176 * @param socket the file descriptor of the socket to use
1177 * @param ipv4Option the option value to use for an IPv4 socket
1178 * @param ipv6Option the option value to use for an IPv6 socket
1179 * @param optionValue the value of the socket option to get or set
1180 * @param optionLength the length of the socket option to get or set
1182 * @return the value of the socket call, or -1 on failure inside this function
1184 * @note on internal failure, the errno variable will be set appropriately
1186 static int getOrSetSocketOption(int action, int socket, int ipv4Option,
1187 int ipv6Option, void *optionValue, socklen_t *optionLength) {
1190 int family = getSocketAddressFamily(socket);
1193 option = ipv4Option;
1194 protocol = IPPROTO_IP;
1197 option = ipv6Option;
1198 protocol = IPPROTO_IPV6;
1201 errno = EAFNOSUPPORT;
1204 if (action == SOCKOPT_GET) {
1205 return getsockopt(socket, protocol, option, &optionValue, optionLength);
1206 } else if (action == SOCKOPT_SET) {
1207 return setsockopt(socket, protocol, option, &optionValue,
1216 * Find the interface index that was set for this socket by the IP_MULTICAST_IF
1217 * or IPV6_MULTICAST_IF socket option.
1219 * @param socket the socket to examine
1221 * @return the interface index, or -1 on failure
1223 * @note on internal failure, the errno variable will be set appropriately
1225 static int interfaceIndexFromMulticastSocket(int socket) {
1226 int family = getSocketAddressFamily(socket);
1227 socklen_t requestLength;
1230 if (family == AF_INET) {
1231 // IP_MULTICAST_IF returns a pointer to a struct ip_mreqn.
1232 struct ip_mreqn tempRequest;
1233 requestLength = sizeof(tempRequest);
1234 result = getsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, &tempRequest,
1236 interfaceIndex = tempRequest.imr_ifindex;
1237 } else if (family == AF_INET6) {
1238 // IPV6_MULTICAST_IF returns a pointer to an integer.
1239 requestLength = sizeof(interfaceIndex);
1240 result = getsockopt(socket, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1241 &interfaceIndex, &requestLength);
1243 errno = EAFNOSUPPORT;
1248 return interfaceIndex;
1255 * Join/Leave the nominated multicast group on the specified socket.
1256 * Implemented by setting the multicast 'add membership'/'drop membership'
1257 * option at the HY_IPPROTO_IP level on the socket.
1259 * Implementation note for multicast sockets in general:
1261 * - This code is untested, because at the time of this writing multicast can't
1262 * be properly tested on Android due to GSM routing restrictions. So it might
1263 * or might not work.
1265 * - The REUSEPORT socket option that Harmony employs is not supported on Linux
1266 * and thus also not supported on Android. It's is not needed for multicast
1267 * to work anyway (REUSEADDR should suffice).
1269 * @param env pointer to the JNI library.
1270 * @param socketP pointer to the hysocket to join/leave on.
1271 * @param optVal pointer to the InetAddress, the multicast group to join/drop.
1273 * @exception SocketException if an error occurs during the call
1275 static void mcastAddDropMembership (JNIEnv * env, int handle, jobject optVal,
1276 int ignoreIF, int setSockOptVal) {
1277 struct sockaddr_storage sockaddrP;
1279 // By default, let the system decide which interface to use.
1280 int interfaceIndex = 0;
1283 * Check whether we are getting an InetAddress or an Generic IPMreq. For now
1284 * we support both so that we will not break the tests. If an InetAddress
1285 * is passed in, only support IPv4 as obtaining an interface from an
1286 * InetAddress is complex and should be done by the Java caller.
1288 if (env->IsInstanceOf (optVal, gCachedFields.iaddr_class)) {
1290 * optVal is an InetAddress. Construct a multicast request structure
1291 * from this address. Support IPv4 only.
1293 struct ip_mreqn multicastRequest;
1294 socklen_t length = sizeof(multicastRequest);
1295 memset(&multicastRequest, 0, length);
1297 // If ignoreIF is false, determine the index of the interface to use.
1299 interfaceIndex = interfaceIndexFromMulticastSocket(handle);
1300 multicastRequest.imr_ifindex = interfaceIndex;
1301 if (interfaceIndex == -1) {
1302 throwSocketException(env, convertError(errno));
1307 // Convert the inetAddress to an IPv4 address structure.
1308 result = inetAddressToSocketAddress(env, optVal, 0, &sockaddrP);
1309 if (result < 0) // Exception has already been thrown.
1311 if (sockaddrP.ss_family != AF_INET) {
1312 throwSocketException(env, SOCKERR_BADAF);
1315 struct sockaddr_in *sin = (struct sockaddr_in *) &sockaddrP;
1316 multicastRequest.imr_multiaddr = sin->sin_addr;
1318 result = setsockopt(handle, IPPROTO_IP, setSockOptVal,
1319 &multicastRequest, length);
1321 throwSocketException (env, convertError(errno));
1326 * optVal is a GenericIPMreq object. Extract the relevant fields from
1327 * it and construct a multicast request structure from these. Support
1328 * both IPv4 and IPv6.
1331 jfieldID multiaddrID;
1332 jfieldID interfaceIdxID;
1335 // Get the multicast address to join or leave.
1336 cls = env->GetObjectClass(optVal);
1337 multiaddrID = env->GetFieldID(cls, "multiaddr", "Ljava/net/InetAddress;");
1338 multiaddr = env->GetObjectField(optVal, multiaddrID);
1340 // Get the interface index to use.
1342 interfaceIdxID = env->GetFieldID(cls, "interfaceIdx", "I");
1343 interfaceIndex = env->GetIntField(optVal, interfaceIdxID);
1346 result = inetAddressToSocketAddress(env, multiaddr, 0, &sockaddrP);
1347 if (result < 0) // Exception has already been thrown.
1350 struct ip_mreqn ipv4Request;
1351 struct ipv6_mreq ipv6Request;
1352 void *multicastRequest;
1353 socklen_t requestLength;
1355 int family = getSocketAddressFamily(handle);
1358 requestLength = sizeof(ipv4Request);
1359 memset(&ipv4Request, 0, requestLength);
1360 ipv4Request.imr_multiaddr =
1361 ((struct sockaddr_in *) &sockaddrP)->sin_addr;
1362 ipv4Request.imr_ifindex = interfaceIndex;
1363 multicastRequest = &ipv4Request;
1367 requestLength = sizeof(ipv6Request);
1368 memset(&ipv6Request, 0, requestLength);
1369 ipv6Request.ipv6mr_multiaddr =
1370 ((struct sockaddr_in6 *) &sockaddrP)->sin6_addr;
1371 ipv6Request.ipv6mr_ifindex = interfaceIndex;
1372 multicastRequest = &ipv6Request;
1373 level = IPPROTO_IPV6;
1376 throwSocketException (env, SOCKERR_BADAF);
1380 /* join/drop the multicast address */
1381 result = setsockopt(handle, level, setSockOptVal, multicastRequest,
1384 throwSocketException (env, convertError(errno));
1390 static void osNetworkSystem_oneTimeInitializationImpl(JNIEnv* env, jobject obj,
1391 jboolean jcl_supports_ipv6) {
1392 // LOGD("ENTER oneTimeInitializationImpl of OSNetworkSystem");
1394 char useAdbNetworkingProperty[PROPERTY_VALUE_MAX];
1395 char adbConnectedProperty[PROPERTY_VALUE_MAX];
1397 property_get("android.net.use-adb-networking", useAdbNetworkingProperty, "");
1398 property_get("adb.connected", adbConnectedProperty, "");
1400 if (strlen((char *)useAdbNetworkingProperty) > 0
1401 && strlen((char *)adbConnectedProperty) > 0) {
1402 useAdbNetworking = 1;
1405 memset(&gCachedFields, 0, sizeof(gCachedFields));
1407 // initializing InetAddress
1409 jclass iaddrclass = env->FindClass("java/net/InetAddress");
1411 if (iaddrclass == NULL) {
1412 jniThrowException(env, "java/lang/ClassNotFoundException",
1413 "java.net.InetAddress");
1417 gCachedFields.iaddr_class = (jclass) env->NewGlobalRef(iaddrclass);
1419 jmethodID iaddrclassinit = env->GetMethodID(iaddrclass, "<init>", "()V");
1421 if (iaddrclassinit == NULL) {
1422 jniThrowException(env, "java/lang/NoSuchMethodError", "InetAddress.<init>()");
1426 gCachedFields.iaddr_class_init = iaddrclassinit;
1428 jmethodID iaddrgetbyaddress = env->GetStaticMethodID(iaddrclass,
1429 "getByAddress", "([B)Ljava/net/InetAddress;");
1431 if (iaddrgetbyaddress == NULL) {
1432 jniThrowException(env, "java/lang/NoSuchMethodError",
1433 "InetAddress.getByAddress(byte[] val)");
1437 gCachedFields.iaddr_getbyaddress = iaddrgetbyaddress;
1439 jfieldID iaddripaddress = env->GetFieldID(iaddrclass, "ipaddress", "[B");
1441 if (iaddripaddress == NULL) {
1442 jniThrowException(env, "java/lang/NoSuchFieldError",
1443 "Can't find field InetAddress.ipaddress");
1447 gCachedFields.iaddr_ipaddress = iaddripaddress;
1449 // get the GenericIPMreq class
1451 jclass genericipmreqclass = env->FindClass("org/apache/harmony/luni/net/GenericIPMreq");
1453 if (genericipmreqclass == NULL) {
1454 jniThrowException(env, "java/lang/ClassNotFoundException",
1455 "org.apache.harmony.luni.net.GenericIPMreq");
1459 gCachedFields.genericipmreq_class = (jclass) env->NewGlobalRef(genericipmreqclass);
1461 // initializing Integer
1463 jclass integerclass = env->FindClass("java/lang/Integer");
1465 if (integerclass == NULL) {
1466 jniThrowException(env, "java/lang/ClassNotFoundException",
1467 "java.lang.Integer");
1471 jmethodID integerclassinit = env->GetMethodID(integerclass, "<init>", "(I)V");
1473 if (integerclassinit == NULL) {
1474 jniThrowException(env, "java/lang/NoSuchMethodError",
1475 "Integer.<init>(int val)");
1479 jfieldID integerclassvalue = env->GetFieldID(integerclass, "value", "I");
1481 if (integerclassvalue == NULL) {
1482 jniThrowException(env, "java/lang/NoSuchMethodError", "Integer.value");
1486 gCachedFields.integer_class = (jclass) env->NewGlobalRef(integerclass);
1487 gCachedFields.integer_class_init = integerclassinit;
1488 gCachedFields.integer_class_value = integerclassvalue;
1490 // initializing Boolean
1492 jclass booleanclass = env->FindClass("java/lang/Boolean");
1494 if (booleanclass == NULL) {
1495 jniThrowException(env, "java/lang/ClassNotFoundException",
1496 "java.lang.Boolean");
1500 jmethodID booleanclassinit = env->GetMethodID(booleanclass, "<init>", "(Z)V");
1502 if (booleanclassinit == NULL) {
1503 jniThrowException(env, "java/lang/NoSuchMethodError",
1504 "Boolean.<init>(boolean val)");
1508 jfieldID booleanclassvalue = env->GetFieldID(booleanclass, "value", "Z");
1510 if (booleanclassvalue == NULL) {
1511 jniThrowException(env, "java/lang/NoSuchMethodError", "Boolean.value");
1515 gCachedFields.boolean_class = (jclass) env->NewGlobalRef(booleanclass);
1516 gCachedFields.boolean_class_init = booleanclassinit;
1517 gCachedFields.boolean_class_value = booleanclassvalue;
1519 // initializing Byte
1521 jclass byteclass = env->FindClass("java/lang/Byte");
1523 if (byteclass == NULL) {
1524 jniThrowException(env, "java/lang/ClassNotFoundException",
1529 jmethodID byteclassinit = env->GetMethodID(byteclass, "<init>", "(B)V");
1531 if (byteclassinit == NULL) {
1532 jniThrowException(env, "java/lang/NoSuchMethodError",
1533 "Byte.<init>(byte val)");
1537 jfieldID byteclassvalue = env->GetFieldID(byteclass, "value", "B");
1539 if (byteclassvalue == NULL) {
1540 jniThrowException(env, "java/lang/NoSuchMethodError", "Byte.value");
1544 gCachedFields.byte_class = (jclass) env->NewGlobalRef(byteclass);
1545 gCachedFields.byte_class_init = byteclassinit;
1546 gCachedFields.byte_class_value = byteclassvalue;
1548 // initializing String
1550 jclass stringclass = env->FindClass("java/lang/String");
1552 if (stringclass == NULL) {
1553 jniThrowException(env, "java/lang/ClassNotFoundException",
1554 "java.lang.String");
1558 jmethodID stringclassinit = env->GetMethodID(stringclass, "<init>", "([B)V");
1560 if (stringclassinit == NULL) {
1561 jniThrowException(env, "java/lang/NoSuchMethodError",
1562 "String.<init>(byte[] val)");
1566 gCachedFields.string_class = (jclass) env->NewGlobalRef(stringclass);
1567 gCachedFields.string_class_init = stringclassinit;
1569 // initializing ScoketImpl
1571 jclass socketimplclass = env->FindClass("java/net/SocketImpl");
1573 if (socketimplclass == NULL) {
1574 jniThrowException(env, "java/lang/ClassNotFoundException",
1575 "java.net.SocketImpl");
1579 jfieldID socketimplport = env->GetFieldID(socketimplclass, "port", "I");
1581 if (socketimplport == NULL) {
1582 jniThrowException(env, "java/lang/NoSuchFieldError", "SocketImpl.port");
1586 jfieldID socketimpladdress = env->GetFieldID(socketimplclass, "address",
1587 "Ljava/net/InetAddress;");
1589 if (socketimpladdress == NULL) {
1590 jniThrowException(env, "java/lang/NoSuchFieldError",
1591 "SocketImpl.address");
1595 gCachedFields.socketimpl_address = socketimpladdress;
1596 gCachedFields.socketimpl_port = socketimplport;
1598 gCachedFields.dpack_class = env->FindClass("java/net/DatagramPacket");
1599 if (gCachedFields.dpack_class == NULL) {
1600 jniThrowException(env, "java/lang/ClassNotFoundException",
1601 "java.net.DatagramPacket");
1605 gCachedFields.dpack_address = env->GetFieldID(gCachedFields.dpack_class,
1606 "address", "Ljava/net/InetAddress;");
1607 if (gCachedFields.dpack_address == NULL) {
1608 jniThrowException(env, "java/lang/NoSuchFieldError",
1609 "DatagramPacket.address");
1613 gCachedFields.dpack_port = env->GetFieldID(gCachedFields.dpack_class,
1615 if (gCachedFields.dpack_port == NULL) {
1616 jniThrowException(env, "java/lang/NoSuchFieldError",
1617 "DatagramPacket.port");
1621 gCachedFields.dpack_length = env->GetFieldID(gCachedFields.dpack_class,
1623 if (gCachedFields.dpack_length == NULL) {
1624 jniThrowException(env, "java/lang/NoSuchFieldError",
1625 "DatagramPacket.length");
1632 * Helper function to create a socket of the specified type and bind it to a
1633 * Java file descriptor.
1635 * @param fileDescriptor the file descriptor to bind the socket to
1636 * @param type the socket type to create, e.g., SOCK_STREAM
1638 * @return the socket file descriptor, or -1 on failure
1641 static int createSocketFileDescriptor(JNIEnv* env, jobject fileDescriptor,
1643 if (fileDescriptor == NULL) {
1644 throwNullPointerException(env);
1650 sock = socket(PF_INET6, type, 0);
1651 if (sock < 0 && errno == EAFNOSUPPORT) {
1652 sock = socket(PF_INET, type, 0);
1655 int err = convertError(errno);
1656 throwSocketException(env, err);
1658 jniSetFileDescriptorOfFD(env, fileDescriptor, sock);
1663 static void osNetworkSystem_createSocketImpl(JNIEnv* env, jclass clazz,
1664 jobject fileDescriptor, jboolean preferIPv4Stack) {
1665 // LOGD("ENTER createSocketImpl");
1666 createSocketFileDescriptor(env, fileDescriptor, SOCK_STREAM);
1669 static void osNetworkSystem_createDatagramSocketImpl(JNIEnv* env, jclass clazz,
1670 jobject fileDescriptor, jboolean preferIPv4Stack) {
1671 // LOGD("ENTER createDatagramSocketImpl");
1672 createSocketFileDescriptor(env, fileDescriptor, SOCK_DGRAM);
1675 static jint osNetworkSystem_readSocketDirectImpl(JNIEnv* env, jclass clazz,
1676 jobject fileDescriptor, jint address, jint offset, jint count,
1678 // LOGD("ENTER readSocketDirectImpl");
1681 jbyte *message = (jbyte *)address + offset;
1682 int result, ret, localCount;
1684 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1686 if (handle == 0 || handle == -1) {
1687 throwSocketException(env, SOCKERR_BADSOCKET);
1691 result = selectWait(handle, timeout, SELECT_READ_TYPE);
1697 localCount = (count < 65536) ? count : 65536;
1700 ret = recv(handle, (jbyte *) message, localCount, SOCKET_NOFLAGS);
1701 } while (ret < 0 && errno == EINTR);
1705 } else if (ret == -1) {
1706 int err = convertError(errno);
1707 throwSocketException(env, err);
1713 static jint osNetworkSystem_readSocketImpl(JNIEnv* env, jclass clazz,
1714 jobject fileDescriptor, jbyteArray data, jint offset, jint count,
1716 // LOGD("ENTER readSocketImpl");
1719 int result, localCount;
1721 jbyte internalBuffer[BUFFERSIZE];
1723 localCount = (count < 65536) ? count : 65536;
1725 if (localCount > BUFFERSIZE) {
1726 message = (jbyte*)malloc(localCount * sizeof(jbyte));
1727 if (message == NULL) {
1728 jniThrowException(env, "java/lang/OutOfMemoryError",
1729 "couldn't allocate enough memory for readSocket");
1733 message = (jbyte *)internalBuffer;
1736 result = osNetworkSystem_readSocketDirectImpl(env, clazz, fileDescriptor,
1737 (jint) message, 0, localCount, timeout);
1740 env->SetByteArrayRegion(data, offset, result, (jbyte *)message);
1743 if (((jbyte *)message) != internalBuffer) {
1744 free(( jbyte *)message);
1750 static jint osNetworkSystem_writeSocketDirectImpl(JNIEnv* env, jclass clazz,
1751 jobject fileDescriptor, jint address, jint offset, jint count) {
1752 // LOGD("ENTER writeSocketDirectImpl");
1755 jbyte *message = (jbyte *)address + offset;
1756 int result = 0, sent = 0;
1762 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1764 if (handle == 0 || handle == -1) {
1765 throwSocketException(env, SOCKERR_BADSOCKET);
1769 result = send(handle, (jbyte *) message, (int) count, SOCKET_NOFLAGS);
1771 int err = convertError(errno);
1773 if (SOCKERR_WOULDBLOCK == err){
1774 jclass socketExClass,errorCodeExClass;
1775 jmethodID errorCodeExConstructor, socketExConstructor,socketExCauseMethod;
1776 jobject errorCodeEx, socketEx;
1777 const char* errorMessage = netLookupErrorString(err);
1778 jstring errorMessageString = env->NewStringUTF(errorMessage);
1780 errorCodeExClass = env->FindClass("org/apache/harmony/luni/util/ErrorCodeException");
1781 if (!errorCodeExClass){
1784 errorCodeExConstructor = env->GetMethodID(errorCodeExClass,"<init>","(I)V");
1785 if (!errorCodeExConstructor){
1788 errorCodeEx = env->NewObject(errorCodeExClass,errorCodeExConstructor,err);
1790 socketExClass = env->FindClass("java/net/SocketException");
1791 if (!socketExClass) {
1794 socketExConstructor = env->GetMethodID(socketExClass,"<init>","(Ljava/lang/String;)V");
1795 if (!socketExConstructor) {
1798 socketEx = env->NewObject(socketExClass, socketExConstructor, errorMessageString);
1799 socketExCauseMethod = env->GetMethodID(socketExClass,"initCause","(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
1800 env->CallObjectMethod(socketEx,socketExCauseMethod,errorCodeEx);
1801 env->Throw((jthrowable)socketEx);
1804 throwSocketException(env, err);
1811 static jint osNetworkSystem_writeSocketImpl(JNIEnv* env, jclass clazz,
1812 jobject fileDescriptor, jbyteArray data, jint offset, jint count) {
1813 // LOGD("ENTER writeSocketImpl");
1819 /* TODO: ARRAY PINNING */
1820 #define INTERNAL_SEND_BUFFER_MAX 512
1821 jbyte internalBuffer[INTERNAL_SEND_BUFFER_MAX];
1823 if (count > INTERNAL_SEND_BUFFER_MAX) {
1824 message = (jbyte*)malloc(count * sizeof( jbyte));
1825 if (message == NULL) {
1826 jniThrowException(env, "java/lang/OutOfMemoryError",
1827 "couldn't allocate enough memory for writeSocket");
1831 message = (jbyte *)internalBuffer;
1834 env->GetByteArrayRegion(data, offset, count, message);
1836 result = osNetworkSystem_writeSocketDirectImpl(env, clazz, fileDescriptor,
1837 (jint) message, 0, count);
1839 if (( jbyte *)message != internalBuffer) {
1840 free(( jbyte *)message);
1842 #undef INTERNAL_SEND_BUFFER_MAX
1846 static void osNetworkSystem_setNonBlockingImpl(JNIEnv* env, jclass clazz,
1847 jobject fileDescriptor, jboolean nonblocking) {
1848 // LOGD("ENTER setNonBlockingImpl");
1853 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1855 if (handle == 0 || handle == -1) {
1856 throwSocketException(env, SOCKERR_BADSOCKET);
1860 int block = nonblocking;
1862 result = ioctl(handle, FIONBIO, &block);
1865 throwSocketException(env, convertError(errno));
1869 static jint osNetworkSystem_connectSocketImpl(JNIEnv* env, jclass clazz,
1870 jobject fileDescriptor, jint trafficClass, jobject inetAddr, jint port);
1872 static jint osNetworkSystem_connectWithTimeoutSocketImpl(JNIEnv* env,
1873 jclass clazz, jobject fileDescriptor, jint timeout, jint trafficClass,
1874 jobject inetAddr, jint port, jint step, jbyteArray passContext) {
1875 // LOGD("ENTER connectWithTimeoutSocketImpl");
1879 struct sockaddr_storage address;
1880 jbyte *context = NULL;
1882 result = inetAddressToSocketAddress(env, inetAddr, port, &address);
1886 // Check if we're using adb networking and redirect in case it is used.
1887 if (useAdbNetworkingForAddress(&address)) {
1888 return osNetworkSystem_connectSocketImpl(env, clazz, fileDescriptor,
1889 trafficClass, inetAddr, port);
1892 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1893 if (handle == 0 || handle == -1) {
1894 throwSocketException(env, SOCKERR_BADDESC);
1898 context = (jbyte *)env->GetPrimitiveArrayCritical(passContext, NULL);
1901 case SOCKET_CONNECT_STEP_START:
1902 result = sockConnectWithTimeout(handle, address, 0,
1903 SOCKET_STEP_START, context);
1905 case SOCKET_CONNECT_STEP_CHECK:
1906 result = sockConnectWithTimeout(handle, address, timeout,
1907 SOCKET_STEP_CHECK, context);
1911 env->ReleasePrimitiveArrayCritical(passContext, context, JNI_ABORT);
1914 /* connected , so stop here */
1915 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, NULL);
1916 } else if (result != SOCKERR_NOTCONNECTED) {
1917 /* can not connect... */
1918 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, NULL);
1919 if (result == SOCKERR_EACCES) {
1920 jniThrowException(env, "java/lang/SecurityException",
1921 netLookupErrorString(result));
1923 jniThrowException(env, "java/net/ConnectException",
1924 netLookupErrorString(result));
1931 static void osNetworkSystem_connectStreamWithTimeoutSocketImpl(JNIEnv* env,
1932 jclass clazz, jobject fileDescriptor, jint remotePort, jint timeout,
1933 jint trafficClass, jobject inetAddr) {
1934 // LOGD("ENTER connectStreamWithTimeoutSocketImpl");
1938 struct sockaddr_storage address;
1939 jbyte *context = NULL;
1940 int remainingTimeout = timeout;
1941 int passedTimeout = 0;
1944 char hasTimeout = timeout > 0;
1946 /* if a timeout was specified calculate the finish time value */
1948 finishTime = time_msec_clock() + (int) timeout;
1951 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1952 if (handle == 0 || handle == -1) {
1953 throwSocketException(env, SOCKERR_BADDESC);
1957 result = inetAddressToSocketAddress(env, inetAddr, remotePort, &address);
1958 if (result < 0) // Exception has already been thrown.
1961 // Check if we're using adb networking and redirect in case it is used.
1962 if (useAdbNetworkingForAddress(&address)) {
1963 int retVal = osNetworkSystem_connectSocketImpl(env, clazz,
1964 fileDescriptor, trafficClass, inetAddr, remotePort);
1966 throwSocketException(env, SOCKERR_BADSOCKET);
1972 * we will be looping checking for when we are connected so allocate
1973 * the descriptor sets that we will use
1975 context =(jbyte *) malloc(sizeof(struct selectFDSet));
1976 if (NULL == context) {
1977 throwSocketException(env, SOCKERR_NOBUFFERS);
1981 result = sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_START, context);
1983 /* ok we connected right away so we are done */
1984 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, context);
1986 } else if (result != SOCKERR_NOTCONNECTED) {
1987 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE,
1989 /* we got an error other than NOTCONNECTED so we cannot continue */
1990 if (SOCKERR_EACCES == result) {
1991 jniThrowException(env, "java/lang/SecurityException",
1992 netLookupErrorString(result));
1994 throwSocketException(env, result);
1999 while (SOCKERR_NOTCONNECTED == result) {
2000 passedTimeout = remainingTimeout;
2003 * ok now try and connect. Depending on the platform this may sleep
2004 * for up to passedTimeout milliseconds
2006 result = sockConnectWithTimeout(handle, address, passedTimeout,
2007 SOCKET_STEP_CHECK, context);
2010 * now check if the socket is still connected.
2011 * Do it here as some platforms seem to think they
2012 * are connected if the socket is closed on them.
2014 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2015 if (handle == 0 || handle == -1) {
2016 sockConnectWithTimeout(handle, address, 0,
2017 SOCKET_STEP_DONE, context);
2018 throwSocketException(env, SOCKERR_BADSOCKET);
2023 * check if we are now connected,
2024 * if so we can finish the process and return
2027 sockConnectWithTimeout(handle, address, 0,
2028 SOCKET_STEP_DONE, context);
2033 * if the error is SOCKERR_NOTCONNECTED then we have not yet
2034 * connected and we may not be done yet
2036 if (SOCKERR_NOTCONNECTED == result) {
2037 /* check if the timeout has expired */
2039 remainingTimeout = finishTime - time_msec_clock();
2040 if (remainingTimeout <= 0) {
2041 sockConnectWithTimeout(handle, address, 0,
2042 SOCKET_STEP_DONE, context);
2043 jniThrowException(env,
2044 "java/net/SocketTimeoutException",
2045 netLookupErrorString(result));
2049 remainingTimeout = 100;
2052 sockConnectWithTimeout(handle, address, remainingTimeout,
2053 SOCKET_STEP_DONE, context);
2054 if ((SOCKERR_CONNRESET == result) ||
2055 (SOCKERR_CONNECTION_REFUSED == result) ||
2056 (SOCKERR_ADDRNOTAVAIL == result) ||
2057 (SOCKERR_ADDRINUSE == result) ||
2058 (SOCKERR_ENETUNREACH == result)) {
2059 jniThrowException(env, "java/net/ConnectException",
2060 netLookupErrorString(result));
2061 } else if (SOCKERR_EACCES == result) {
2062 jniThrowException(env, "java/lang/SecurityException",
2063 netLookupErrorString(result));
2065 throwSocketException(env, result);
2073 /* free the memory for the FD set */
2074 if (context != NULL) {
2079 static jint osNetworkSystem_connectSocketImpl(JNIEnv* env, jclass clazz,
2080 jobject fileDescriptor, jint trafficClass, jobject inetAddr, jint port) {
2081 //LOGD("ENTER direct-call connectSocketImpl\n");
2083 struct sockaddr_storage address;
2087 ret = inetAddressToSocketAddress(env, inetAddr, port, &address);
2091 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2092 if (handle == 0 || handle == -1) {
2093 throwSocketException(env, SOCKERR_BADDESC);
2097 if (useAdbNetworkingForAddress(&address)) {
2099 // LOGD("+connect to address 0x%08x port %d (via adb)",
2100 // address.sin_addr.s_addr, (int) port);
2101 ret = adb_networking_connect_fd(handle, (struct sockaddr_in *) &address);
2102 // LOGD("-connect ret %d errno %d (via adb)", ret, errno);
2106 // call this method with a timeout of zero
2107 osNetworkSystem_connectStreamWithTimeoutSocketImpl(env, clazz,
2108 fileDescriptor, port, 0, trafficClass, inetAddr);
2109 if (env->ExceptionOccurred() != 0) {
2118 jniThrowException(env, "java/net/ConnectException",
2119 netLookupErrorString(convertError(errno)));
2126 static void osNetworkSystem_socketBindImpl(JNIEnv* env, jclass clazz,
2127 jobject fileDescriptor, jint port, jobject inetAddress) {
2128 // LOGD("ENTER socketBindImpl");
2130 struct sockaddr_storage sockaddress;
2134 ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddress);
2138 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2139 if (handle == 0 || handle == -1) {
2140 throwSocketException(env, SOCKERR_BADDESC);
2144 ret = doBind(handle, &sockaddress);
2146 jniThrowException(env, "java/net/BindException",
2147 netLookupErrorString(convertError(errno)));
2152 static void osNetworkSystem_listenStreamSocketImpl(JNIEnv* env, jclass clazz,
2153 jobject fileDescriptor, jint backlog) {
2154 // LOGD("ENTER listenStreamSocketImpl");
2159 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2161 if (handle == 0 || handle == -1) {
2162 throwSocketException(env, SOCKERR_BADSOCKET);
2166 ret = listen(handle, backlog);
2169 int err = convertError(errno);
2170 throwSocketException(env, err);
2175 static jint osNetworkSystem_availableStreamImpl(JNIEnv* env, jclass clazz,
2176 jobject fileDescriptor) {
2177 // LOGD("ENTER availableStreamImpl");
2180 char message[BUFFERSIZE];
2184 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2185 if (handle == 0 || handle == -1) {
2186 throwSocketException(env, SOCKERR_BADDESC);
2191 result = selectWait(handle, 1, SELECT_READ_TYPE);
2193 if (SOCKERR_TIMEOUT == result) {
2194 // The read operation timed out, so answer 0 bytes available
2196 } else if (SOCKERR_INTERRUPTED == result) {
2198 } else if (0 > result) {
2199 throwSocketException(env, result);
2202 } while (SOCKERR_INTERRUPTED == result);
2204 result = recv(handle, (jbyte *) message, BUFFERSIZE, MSG_PEEK);
2207 int err = convertError(errno);
2208 throwSocketException(env, err);
2214 static void osNetworkSystem_acceptSocketImpl(JNIEnv* env, jclass clazz,
2215 jobject fdServer, jobject newSocket, jobject fdnewSocket, jint timeout) {
2216 // LOGD("ENTER acceptSocketImpl");
2218 struct sockaddr_storage sa;
2226 if (newSocket == NULL) {
2227 throwNullPointerException(env);
2231 result = pollSelectWait(env, fdServer, timeout, SELECT_READ_TYPE);
2236 handle = jniGetFDFromFileDescriptor(env, fdServer);
2237 if (handle == 0 || handle == -1) {
2238 throwSocketException(env, SOCKERR_BADDESC);
2243 addrlen = sizeof(sa);
2244 ret = accept(handle, (struct sockaddr *) &sa, &addrlen);
2245 } while (ret < 0 && errno == EINTR);
2248 int err = convertError(errno);
2249 throwSocketException(env, err);
2256 * For network sockets, put the peer address and port in instance variables.
2257 * We don't bother to do this for UNIX domain sockets, since most peers are
2260 if (sa.ss_family == AF_INET || sa.ss_family == AF_INET6) {
2261 jobject inetAddress = socketAddressToInetAddress(env, &sa);
2264 newSocket = NULL; // Exception has already been thrown.
2268 env->SetObjectField(newSocket,
2269 gCachedFields.socketimpl_address, inetAddress);
2271 int port = getSocketAddressPort(&sa);
2272 env->SetIntField(newSocket, gCachedFields.socketimpl_port, port);
2275 jniSetFileDescriptorOfFD(env, fdnewSocket, retFD);
2278 static jboolean osNetworkSystem_supportsUrgentDataImpl(JNIEnv* env,
2279 jclass clazz, jobject fileDescriptor) {
2280 // LOGD("ENTER supportsUrgentDataImpl");
2284 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2285 if (handle == 0 || handle == -1) {
2292 static void osNetworkSystem_sendUrgentDataImpl(JNIEnv* env, jclass clazz,
2293 jobject fileDescriptor, jbyte value) {
2294 // LOGD("ENTER sendUrgentDataImpl");
2299 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2300 if (handle == 0 || handle == -1) {
2301 throwSocketException(env, SOCKERR_BADSOCKET);
2305 result = send(handle, (jbyte *) &value, 1, MSG_OOB);
2307 int err = convertError(errno);
2308 throwSocketException(env, err);
2312 static void osNetworkSystem_connectDatagramImpl2(JNIEnv* env, jclass clazz,
2313 jobject fd, jint port, jint trafficClass, jobject inetAddress) {
2314 // LOGD("ENTER connectDatagramImpl2");
2316 int handle = jniGetFDFromFileDescriptor(env, fd);
2318 struct sockaddr_storage sockAddr;
2321 ret = inetAddressToSocketAddress(env, inetAddress, port, &sockAddr);
2322 if (ret < 0) // Exception has already been thrown.
2325 ret = doConnect(handle, &sockAddr);
2327 int err = convertError(errno);
2328 throwSocketException(env, err);
2332 static void osNetworkSystem_disconnectDatagramImpl(JNIEnv* env, jclass clazz,
2334 // LOGD("ENTER disconnectDatagramImpl");
2336 int handle = jniGetFDFromFileDescriptor(env, fd);
2338 struct sockaddr_storage sockAddr;
2339 memset(&sockAddr, 0, sizeof(sockAddr));
2340 sockAddr.ss_family = AF_UNSPEC;
2342 int result = doConnect(handle, &sockAddr);
2344 int err = convertError(errno);
2345 throwSocketException(env, err);
2349 static jboolean osNetworkSystem_socketBindImpl2(JNIEnv* env, jclass clazz,
2350 jobject fileDescriptor, jint port, jboolean bindToDevice,
2351 jobject inetAddress) {
2352 // LOGD("ENTER socketBindImpl2");
2354 struct sockaddr_storage sockaddress;
2358 ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddress);
2359 if (ret < 0) // Exception has already been thrown.
2362 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2363 if (handle == 0 || handle == -1) {
2364 throwSocketException(env, SOCKERR_BADDESC);
2368 ret = doBind(handle, &sockaddress);
2370 int err = convertError(errno);
2371 jniThrowException(env, "java/net/BindException", netLookupErrorString(err));
2378 static jint osNetworkSystem_peekDatagramImpl(JNIEnv* env, jclass clazz,
2379 jobject fd, jobject sender, jint receiveTimeout) {
2380 // LOGD("ENTER peekDatagramImpl");
2384 int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
2389 int handle = jniGetFDFromFileDescriptor(env, fd);
2390 if (handle == 0 || handle == -1) {
2391 throwSocketException(env, SOCKERR_BADDESC);
2395 struct sockaddr_storage sockAddr;
2396 socklen_t sockAddrLen = sizeof(sockAddr);
2399 length = recvfrom(handle, NULL, 0, MSG_PEEK,
2400 (struct sockaddr *)&sockAddr, &sockAddrLen);
2401 } while (length < 0 && errno == EINTR);
2403 int err = convertError(errno);
2404 throwSocketException(env, err);
2408 sender = socketAddressToInetAddress(env, &sockAddr);
2409 if (sender == NULL) // Exception has already been thrown.
2412 port = getSocketAddressPort(&sockAddr);
2416 static jint osNetworkSystem_receiveDatagramDirectImpl(JNIEnv* env, jclass clazz,
2417 jobject fd, jobject packet, jint address, jint offset, jint length,
2418 jint receiveTimeout, jboolean peek) {
2419 // LOGD("ENTER receiveDatagramDirectImpl");
2421 int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
2426 int handle = jniGetFDFromFileDescriptor(env, fd);
2427 if (handle == 0 || handle == -1) {
2428 throwSocketException(env, SOCKERR_BADDESC);
2432 struct sockaddr_storage sockAddr;
2433 socklen_t sockAddrLen = sizeof(sockAddr);
2435 int mode = peek ? MSG_PEEK : 0;
2437 ssize_t actualLength;
2439 actualLength = recvfrom(handle, (char*)(address + offset), length, mode,
2440 (struct sockaddr *)&sockAddr, &sockAddrLen);
2441 } while (actualLength < 0 && errno == EINTR);
2442 if (actualLength < 0) {
2443 int err = convertError(errno);
2444 throwSocketException(env, err);
2448 if (packet != NULL) {
2449 jbyteArray addr = socketAddressToAddressBytes(env, &sockAddr);
2450 if (addr == NULL) // Exception has already been thrown.
2452 int port = getSocketAddressPort(&sockAddr);
2453 jobject sender = env->CallStaticObjectMethod(
2454 gCachedFields.iaddr_class, gCachedFields.iaddr_getbyaddress,
2456 env->SetObjectField(packet, gCachedFields.dpack_address, sender);
2457 env->SetIntField(packet, gCachedFields.dpack_port, port);
2458 env->SetIntField(packet, gCachedFields.dpack_length,
2459 (jint) actualLength);
2461 return (jint) actualLength;
2464 static jint osNetworkSystem_receiveDatagramImpl(JNIEnv* env, jclass clazz,
2465 jobject fd, jobject packet, jbyteArray data, jint offset, jint length,
2466 jint receiveTimeout, jboolean peek) {
2467 // LOGD("ENTER receiveDatagramImpl");
2469 int localLength = (length < 65536) ? length : 65536;
2470 jbyte *bytes = (jbyte*) malloc(localLength);
2471 if (bytes == NULL) {
2472 jniThrowException(env, "java/lang/OutOfMemoryError",
2473 "couldn't allocate enough memory for receiveDatagram");
2477 int actualLength = osNetworkSystem_receiveDatagramDirectImpl(env, clazz, fd,
2478 packet, (jint)bytes, 0, localLength, receiveTimeout, peek);
2480 if (actualLength > 0) {
2481 env->SetByteArrayRegion(data, offset, actualLength, bytes);
2485 return actualLength;
2488 static jint osNetworkSystem_recvConnectedDatagramDirectImpl(JNIEnv* env,
2489 jclass clazz, jobject fd, jobject packet, jint address, jint offset,
2490 jint length, jint receiveTimeout, jboolean peek) {
2491 // LOGD("ENTER receiveConnectedDatagramDirectImpl");
2493 int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
2499 int handle = jniGetFDFromFileDescriptor(env, fd);
2501 if (handle == 0 || handle == -1) {
2502 throwSocketException(env, SOCKERR_BADSOCKET);
2506 int mode = peek ? MSG_PEEK : 0;
2508 int actualLength = recvfrom(handle,
2509 (char*)(address + offset), length, mode, NULL, NULL);
2511 if (actualLength < 0) {
2512 jniThrowException(env, "java/net/PortUnreachableException", "");
2516 if ( packet != NULL) {
2517 env->SetIntField(packet, gCachedFields.dpack_length, actualLength);
2519 return actualLength;
2522 static jint osNetworkSystem_recvConnectedDatagramImpl(JNIEnv* env, jclass clazz,
2523 jobject fd, jobject packet, jbyteArray data, jint offset, jint length,
2524 jint receiveTimeout, jboolean peek) {
2525 // LOGD("ENTER receiveConnectedDatagramImpl");
2527 int localLength = (length < 65536) ? length : 65536;
2528 jbyte *bytes = (jbyte*) malloc(localLength);
2529 if (bytes == NULL) {
2530 jniThrowException(env, "java/lang/OutOfMemoryError",
2531 "couldn't allocate enough memory for recvConnectedDatagram");
2535 int actualLength = osNetworkSystem_recvConnectedDatagramDirectImpl(env,
2536 clazz, fd, packet, (jint)bytes, 0, localLength,
2537 receiveTimeout, peek);
2539 if (actualLength > 0) {
2540 env->SetByteArrayRegion(data, offset, actualLength, bytes);
2544 return actualLength;
2547 static jint osNetworkSystem_sendDatagramDirectImpl(JNIEnv* env, jclass clazz,
2548 jobject fd, jint address, jint offset, jint length, jint port,
2549 jboolean bindToDevice, jint trafficClass, jobject inetAddress) {
2550 // LOGD("ENTER sendDatagramDirectImpl");
2552 int handle = jniGetFDFromFileDescriptor(env, fd);
2554 if (handle == 0 || handle == -1) {
2555 throwSocketException(env, SOCKERR_BADSOCKET);
2559 struct sockaddr_storage receiver;
2560 if (inetAddressToSocketAddress(env, inetAddress, port, &receiver) < 0) {
2561 // Exception has already been thrown.
2567 result = sendto(handle, (char*)(address + offset), length,
2568 SOCKET_NOFLAGS, (struct sockaddr*)&receiver, sizeof(receiver));
2569 } while (result < 0 && errno == EINTR);
2571 int err = convertError(errno);
2572 if ((SOCKERR_CONNRESET == err)
2573 || (SOCKERR_CONNECTION_REFUSED == err)) {
2576 throwSocketException(env, err);
2580 return (jint) result;
2583 static jint osNetworkSystem_sendDatagramImpl(JNIEnv* env, jclass clazz,
2584 jobject fd, jbyteArray data, jint offset, jint length, jint port,
2585 jboolean bindToDevice, jint trafficClass, jobject inetAddress) {
2586 // LOGD("ENTER sendDatagramImpl");
2588 jbyte *bytes = env->GetByteArrayElements(data, NULL);
2589 int actualLength = osNetworkSystem_sendDatagramDirectImpl(env, clazz, fd,
2590 (jint)bytes, offset, length, port, bindToDevice, trafficClass,
2592 env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
2594 return actualLength;
2597 static jint osNetworkSystem_sendConnectedDatagramDirectImpl(JNIEnv* env,
2598 jclass clazz, jobject fd, jint address, jint offset, jint length,
2599 jboolean bindToDevice) {
2600 // LOGD("ENTER sendConnectedDatagramDirectImpl");
2602 int handle = jniGetFDFromFileDescriptor(env, fd);
2604 if (handle == 0 || handle == -1) {
2605 throwSocketException(env, SOCKERR_BADSOCKET);
2609 int result = send(handle, (char*)(address + offset), length, 0);
2612 int err = convertError(errno);
2613 if ((SOCKERR_CONNRESET == err) || (SOCKERR_CONNECTION_REFUSED == err)) {
2616 throwSocketException(env, err);
2623 static jint osNetworkSystem_sendConnectedDatagramImpl(JNIEnv* env, jclass clazz,
2624 jobject fd, jbyteArray data, jint offset, jint length,
2625 jboolean bindToDevice) {
2626 // LOGD("ENTER sendConnectedDatagramImpl");
2628 jbyte *bytes = env->GetByteArrayElements(data, NULL);
2629 int actualLength = osNetworkSystem_sendConnectedDatagramDirectImpl(env,
2630 clazz, fd, (jint)bytes, offset, length, bindToDevice);
2631 env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
2633 return actualLength;
2636 static void osNetworkSystem_createServerStreamSocketImpl(JNIEnv* env,
2637 jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) {
2638 // LOGD("ENTER createServerStreamSocketImpl");
2640 int handle = createSocketFileDescriptor(env, fileDescriptor, SOCK_STREAM);
2645 setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
2648 static void osNetworkSystem_createMulticastSocketImpl(JNIEnv* env,
2649 jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) {
2650 // LOGD("ENTER createMulticastSocketImpl");
2652 int handle = createSocketFileDescriptor(env, fileDescriptor, SOCK_DGRAM);
2657 // setsockopt(handle, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(jbyte));
2658 setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
2662 * @param timeout in milliseconds. If zero, block until data received
2664 static jint osNetworkSystem_receiveStreamImpl(JNIEnv* env, jclass clazz,
2665 jobject fileDescriptor, jbyteArray data, jint offset, jint count,
2667 // LOGD("ENTER receiveStreamImpl");
2670 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2672 if (handle == 0 || handle == -1) {
2673 throwSocketException(env, SOCKERR_BADSOCKET);
2677 // Cap read length to available buf size
2678 int spaceAvailable = env->GetArrayLength(data) - offset;
2679 int localCount = count < spaceAvailable? count : spaceAvailable;
2682 jbyte *body = env->GetByteArrayElements(data, &isCopy);
2686 tv.tv_sec = timeout / 1000;
2687 tv.tv_usec = (timeout % 1000) * 1000;
2688 setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv,
2689 sizeof(struct timeval));
2692 result = recv(handle, body + offset, localCount, SOCKET_NOFLAGS);
2693 } while (result < 0 && errno == EINTR);
2695 env->ReleaseByteArrayElements(data, body, 0);
2698 * If no bytes are read, return -1 to signal 'endOfFile'
2699 * to the Java input stream
2703 } else if (0 == result) {
2706 // If EAGAIN or EWOULDBLOCK, read timed out
2707 if (errno == EAGAIN || errno == EWOULDBLOCK) {
2708 jniThrowException(env, "java/net/SocketTimeoutException",
2709 netLookupErrorString(SOCKERR_TIMEOUT));
2711 int err = convertError(errno);
2712 throwSocketException(env, err);
2718 static jint osNetworkSystem_sendStreamImpl(JNIEnv* env, jclass clazz,
2719 jobject fileDescriptor, jbyteArray data, jint offset, jint count) {
2720 // LOGD("ENTER sendStreamImpl");
2723 int result = 0, sent = 0;
2726 jbyte *message = env->GetByteArrayElements(data, &isCopy);
2728 // Cap write length to available buf size
2729 int spaceAvailable = env->GetArrayLength(data) - offset;
2730 if (count > spaceAvailable) count = spaceAvailable;
2732 while (sent < count) {
2734 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2735 if (handle == 0 || handle == -1) {
2736 throwSocketException(env,
2737 sent == 0 ? SOCKERR_BADSOCKET : SOCKERR_INTERRUPTED);
2738 env->ReleaseByteArrayElements(data, message, 0);
2742 // LOGD("before select %d", count);
2743 selectWait(handle, SEND_RETRY_TIME, SELECT_WRITE_TYPE);
2744 result = send(handle, (jbyte *)message + offset + sent,
2745 (int) count - sent, SOCKET_NOFLAGS);
2749 if (result == EAGAIN ||result == EWOULDBLOCK) {
2750 // LOGD("write blocked %d", sent);
2753 env->ReleaseByteArrayElements(data, message, 0);
2754 int err = convertError(result);
2755 throwSocketException(env, err);
2761 env->ReleaseByteArrayElements(data, message, 0);
2765 static void osNetworkSystem_shutdownInputImpl(JNIEnv* env, jobject obj,
2766 jobject fileDescriptor) {
2767 // LOGD("ENTER shutdownInputImpl");
2772 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2774 if (handle == 0 || handle == -1) {
2775 throwSocketException(env, SOCKERR_BADSOCKET);
2779 ret = shutdown(handle, SHUT_RD);
2782 int err = convertError(errno);
2783 throwSocketException(env, err);
2788 static void osNetworkSystem_shutdownOutputImpl(JNIEnv* env, jobject obj,
2789 jobject fileDescriptor) {
2790 // LOGD("ENTER shutdownOutputImpl");
2795 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2797 if (handle == 0 || handle == -1) {
2801 ret = shutdown(handle, SHUT_WR);
2804 int err = convertError(errno);
2805 throwSocketException(env, err);
2810 static jint osNetworkSystem_sendDatagramImpl2(JNIEnv* env, jclass clazz,
2811 jobject fd, jbyteArray data, jint offset, jint length, jint port,
2812 jobject inetAddress) {
2813 // LOGD("ENTER sendDatagramImpl2");
2816 unsigned short nPort;
2817 int ret = 0, sent = 0;
2819 struct sockaddr_storage sockaddrP;
2821 if (inetAddress != NULL) {
2822 ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddrP);
2823 if (ret < 0) // Exception has already been thrown.
2826 handle = jniGetFDFromFileDescriptor(env, fd);
2827 if (handle == 0 || handle == -1) {
2828 throwSocketException(env, SOCKERR_BADDESC);
2833 message = (jbyte*) malloc(length * sizeof(jbyte));
2834 if (message == NULL) {
2835 jniThrowException(env, "java/lang/OutOfMemoryError",
2836 "couldn't allocate enough memory for readSocket");
2840 env->GetByteArrayRegion(data, offset, length, message);
2842 while (sent < length) {
2843 handle = jniGetFDFromFileDescriptor(env, fd);
2845 if (handle == 0 || handle == -1) {
2846 throwSocketException(env,
2847 sent == 0 ? SOCKERR_BADDESC : SOCKERR_INTERRUPTED);
2854 result = sendto(handle, (char *) (message + sent),
2855 (int) (length - sent), SOCKET_NOFLAGS,
2856 (struct sockaddr *) &sockaddrP, sizeof(sockaddrP));
2857 } while (result < 0 && errno == EINTR);
2859 int err = convertError(errno);
2860 throwSocketException(env, err);
2872 static jint osNetworkSystem_selectImpl(JNIEnv* env, jclass clazz,
2873 jobjectArray readFDArray, jobjectArray writeFDArray, jint countReadC,
2874 jint countWriteC, jintArray outFlags, jlong timeout) {
2875 // LOGD("ENTER selectImpl");
2877 struct timeval timeP;
2881 fd_set *fdset_read,*fdset_write;
2886 unsigned int time_sec = (unsigned int)timeout/1000;
2887 unsigned int time_msec = (unsigned int)(timeout%1000);
2889 fdset_read = (fd_set *)malloc(sizeof(fd_set));
2890 fdset_write = (fd_set *)malloc(sizeof(fd_set));
2892 FD_ZERO(fdset_read);
2893 FD_ZERO(fdset_write);
2895 for (val = 0; val<countReadC; val++) {
2897 gotFD = env->GetObjectArrayElement(readFDArray,val);
2899 handle = jniGetFDFromFileDescriptor(env, gotFD);
2901 FD_SET(handle, fdset_read);
2903 if (0 > (size - handle)) {
2908 for (val = 0; val<countWriteC; val++) {
2910 gotFD = env->GetObjectArrayElement(writeFDArray,val);
2912 handle = jniGetFDFromFileDescriptor(env, gotFD);
2914 FD_SET(handle, fdset_write);
2916 if (0 > (size - handle)) {
2921 /* the size is the max_fd + 1 */
2925 result = SOCKERR_FDSET_SIZEBAD;
2927 /* only set when timeout >= 0 (non-block)*/
2930 timeP.tv_sec = time_sec;
2931 timeP.tv_usec = time_msec*1000;
2933 result = sockSelect(size, fdset_read, fdset_write, NULL, &timeP);
2936 result = sockSelect(size, fdset_read, fdset_write, NULL, NULL);
2941 /*output the result to a int array*/
2942 flagArray = env->GetIntArrayElements(outFlags, &isCopy);
2944 for (val=0; val<countReadC; val++) {
2945 gotFD = env->GetObjectArrayElement(readFDArray,val);
2947 handle = jniGetFDFromFileDescriptor(env, gotFD);
2949 if (FD_ISSET(handle,fdset_read)) {
2950 flagArray[val] = SOCKET_OP_READ;
2952 flagArray[val] = SOCKET_OP_NONE;
2956 for (val=0; val<countWriteC; val++) {
2958 gotFD = env->GetObjectArrayElement(writeFDArray,val);
2960 handle = jniGetFDFromFileDescriptor(env, gotFD);
2962 if (FD_ISSET(handle,fdset_write)) {
2963 flagArray[val+countReadC] = SOCKET_OP_WRITE;
2965 flagArray[val+countReadC] = SOCKET_OP_NONE;
2969 env->ReleaseIntArrayElements(outFlags, flagArray, 0);
2975 /* return both correct and error result, let java handle the exception*/
2979 static jobject osNetworkSystem_getSocketLocalAddressImpl(JNIEnv* env,
2980 jclass clazz, jobject fileDescriptor, jboolean preferIPv6Addresses) {
2981 // LOGD("ENTER getSocketLocalAddressImpl");
2983 struct sockaddr_storage addr;
2984 socklen_t addrLen = sizeof(addr);
2986 memset(&addr, 0, addrLen);
2989 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2990 if (handle == 0 || handle == -1) {
2991 throwSocketException(env, SOCKERR_UNKNOWNSOCKET);
2996 result = getsockname(handle, (struct sockaddr *)&addr, &addrLen);
2998 // Spec says ignore all errors
2999 return socketAddressToInetAddress(env, &addr);
3002 static jint osNetworkSystem_getSocketLocalPortImpl(JNIEnv* env, jclass clazz,
3003 jobject fileDescriptor, jboolean preferIPv6Addresses) {
3004 // LOGD("ENTER getSocketLocalPortImpl");
3006 struct sockaddr_storage addr;
3007 socklen_t addrLen = sizeof(addr);
3009 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
3012 if (handle == 0 || handle == -1) {
3013 throwSocketException(env, SOCKERR_UNKNOWNSOCKET);
3017 result = getsockname(handle, (struct sockaddr *)&addr, &addrLen);
3020 // The java spec does not indicate any exceptions on this call
3023 return getSocketAddressPort(&addr);
3027 static jobject osNetworkSystem_getSocketOptionImpl(JNIEnv* env, jclass clazz,
3028 jobject fileDescriptor, jint anOption) {
3029 // LOGD("ENTER getSocketOptionImpl");
3033 socklen_t intSize = sizeof(int);
3034 unsigned char byteValue = 0;
3035 socklen_t byteSize = sizeof(unsigned char);
3037 struct sockaddr_storage sockVal;
3038 socklen_t sockSize = sizeof(sockVal);
3040 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
3041 if (handle == 0 || handle == -1) {
3042 throwSocketException(env, SOCKERR_BADDESC);
3046 switch ((int) anOption & 0xffff) {
3047 case JAVASOCKOPT_SO_LINGER: {
3048 struct linger lingr;
3049 socklen_t size = sizeof(struct linger);
3050 result = getsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr, &size);
3052 throwSocketException(env, convertError(errno));
3055 if (!lingr.l_onoff) {
3058 intValue = lingr.l_linger;
3060 return newJavaLangInteger(env, intValue);
3062 case JAVASOCKOPT_TCP_NODELAY: {
3063 if ((anOption >> 16) & BROKEN_TCP_NODELAY) {
3066 result = getsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intValue, &intSize);
3068 throwSocketException(env, convertError(errno));
3071 return newJavaLangBoolean(env, intValue);
3073 case JAVASOCKOPT_MCAST_TTL: {
3074 if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
3075 return newJavaLangByte(env, 0);
3077 result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_MULTICAST_TTL,
3078 IPV6_MULTICAST_HOPS, &byteValue,
3081 throwSocketException(env, convertError(errno));
3084 return newJavaLangByte(env, (jbyte)(byteValue & 0xFF));
3086 case JAVASOCKOPT_MCAST_INTERFACE: {
3087 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3090 result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, &sockVal, &sockSize);
3092 throwSocketException(env, convertError(errno));
3095 // This option is IPv4-only.
3096 sockVal.ss_family = AF_INET;
3097 return socketAddressToInetAddress(env, &sockVal);
3099 case JAVASOCKOPT_IP_MULTICAST_IF2: {
3100 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3103 struct ip_mreqn multicastRequest;
3105 socklen_t optionLength;
3106 int addressFamily = getSocketAddressFamily(handle);
3107 switch (addressFamily) {
3109 optionLength = sizeof(multicastRequest);
3110 result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
3111 &multicastRequest, &optionLength);
3113 interfaceIndex = multicastRequest.imr_ifindex;
3116 optionLength = sizeof(interfaceIndex);
3117 result = getsockopt(handle, IPPROTO_IPV6, IPV6_MULTICAST_IF,
3118 &interfaceIndex, &optionLength);
3121 throwSocketException(env, SOCKERR_BADAF);
3126 throwSocketException(env, convertError(errno));
3130 return newJavaLangInteger(env, interfaceIndex);
3132 case JAVASOCKOPT_SO_SNDBUF: {
3133 result = getsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intValue, &intSize);
3135 throwSocketException(env, convertError(errno));
3138 return newJavaLangInteger(env, intValue);
3140 case JAVASOCKOPT_SO_RCVBUF: {
3141 result = getsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intValue, &intSize);
3143 throwSocketException(env, convertError(errno));
3146 return newJavaLangInteger(env, intValue);
3148 case JAVASOCKOPT_SO_BROADCAST: {
3149 result = getsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intValue, &intSize);
3151 throwSocketException(env, convertError(errno));
3154 return newJavaLangBoolean(env, intValue);
3156 case JAVASOCKOPT_SO_REUSEADDR: {
3157 result = getsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intValue, &intSize);
3159 throwSocketException(env, convertError(errno));
3162 return newJavaLangBoolean(env, intValue);
3164 case JAVASOCKOPT_SO_KEEPALIVE: {
3165 result = getsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intValue, &intSize);
3167 throwSocketException(env, convertError(errno));
3170 return newJavaLangBoolean(env, intValue);
3172 case JAVASOCKOPT_SO_OOBINLINE: {
3173 result = getsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intValue, &intSize);
3175 throwSocketException(env, convertError(errno));
3178 return newJavaLangBoolean(env, intValue);
3180 case JAVASOCKOPT_IP_MULTICAST_LOOP: {
3181 result = getOrSetSocketOption(SOCKOPT_GET, handle,
3183 IPV6_MULTICAST_LOOP, &intValue,
3186 throwSocketException(env, convertError(errno));
3189 return newJavaLangBoolean(env, intValue);
3191 case JAVASOCKOPT_IP_TOS: {
3192 result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_TOS,
3193 IPV6_TCLASS, &intValue, &intSize);
3195 throwSocketException(env, convertError(errno));
3198 return newJavaLangInteger(env, intValue);
3200 case JAVASOCKOPT_SO_RCVTIMEOUT: {
3201 struct timeval timeout;
3202 socklen_t size = sizeof(timeout);
3203 result = getsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout, &size);
3205 throwSocketException(env, convertError(errno));
3208 return newJavaLangInteger(env, timeout.tv_sec * 1000 + timeout.tv_usec/1000);
3211 throwSocketException(env, SOCKERR_OPTUNSUPP);
3218 static void osNetworkSystem_setSocketOptionImpl(JNIEnv* env, jclass clazz,
3219 jobject fileDescriptor, jint anOption, jobject optVal) {
3220 // LOGD("ENTER setSocketOptionImpl");
3224 socklen_t intSize = sizeof(int);
3225 unsigned char byteVal;
3226 socklen_t byteSize = sizeof(unsigned char);
3227 struct sockaddr_storage sockVal;
3228 int sockSize = sizeof(sockVal);
3230 if (env->IsInstanceOf(optVal, gCachedFields.integer_class)) {
3231 intVal = (int) env->GetIntField(optVal, gCachedFields.integer_class_value);
3232 } else if (env->IsInstanceOf(optVal, gCachedFields.boolean_class)) {
3233 intVal = (int) env->GetBooleanField(optVal, gCachedFields.boolean_class_value);
3234 } else if (env->IsInstanceOf(optVal, gCachedFields.byte_class)) {
3235 byteVal = (int) env->GetByteField(optVal, gCachedFields.byte_class_value);
3236 } else if (env->IsInstanceOf(optVal, gCachedFields.iaddr_class)) {
3237 if (inetAddressToSocketAddress(env, optVal, 0, &sockVal) < 0) {
3238 // Exception has already been thrown.
3241 } else if (env->IsInstanceOf(optVal, gCachedFields.genericipmreq_class)) {
3242 // we'll use optVal directly
3244 throwSocketException(env, SOCKERR_OPTUNSUPP);
3248 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
3249 if (handle == 0 || handle == -1) {
3250 throwSocketException(env, SOCKERR_BADDESC);
3254 switch ((int) anOption & 0xffff) {
3255 case JAVASOCKOPT_SO_LINGER: {
3256 struct linger lingr;
3257 lingr.l_onoff = intVal > 0 ? 1 : 0;
3258 lingr.l_linger = intVal;
3259 result = setsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr,
3260 sizeof(struct linger));
3262 throwSocketException(env, convertError(errno));
3268 case JAVASOCKOPT_TCP_NODELAY: {
3269 if ((anOption >> 16) & BROKEN_TCP_NODELAY) {
3272 result = setsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intVal, intSize);
3274 throwSocketException(env, convertError(errno));
3280 case JAVASOCKOPT_MCAST_TTL: {
3281 if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
3284 result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_MULTICAST_TTL,
3285 IPV6_MULTICAST_HOPS, &byteVal,
3288 throwSocketException(env, convertError(errno));
3294 case JAVASOCKOPT_MCAST_ADD_MEMBERSHIP: {
3295 mcastAddDropMembership(env, handle, optVal,
3296 (anOption >> 16) & BROKEN_MULTICAST_IF, IP_ADD_MEMBERSHIP);
3300 case JAVASOCKOPT_MCAST_DROP_MEMBERSHIP: {
3301 mcastAddDropMembership(env, handle, optVal,
3302 (anOption >> 16) & BROKEN_MULTICAST_IF, IP_DROP_MEMBERSHIP);
3306 case JAVASOCKOPT_MCAST_INTERFACE: {
3307 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3310 // This call is IPv4 only.
3311 if (getSocketAddressFamily(handle) != AF_INET) {
3312 throwSocketException(env, SOCKERR_BADAF);
3315 struct ip_mreqn mcast_req;
3316 memset(&mcast_req, 0, sizeof(mcast_req));
3317 struct sockaddr_in *sin = (struct sockaddr_in *) &sockVal;
3318 mcast_req.imr_address = sin->sin_addr;
3319 result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
3320 &mcast_req, sizeof(mcast_req));
3322 throwSocketException(env, convertError(errno));
3328 case JAVASOCKOPT_IP_MULTICAST_IF2: {
3329 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3332 int addressFamily = getSocketAddressFamily(handle);
3333 int interfaceIndex = intVal;
3335 socklen_t optionLength;
3336 struct ip_mreqn multicastRequest;
3337 switch (addressFamily) {
3339 // IP_MULTICAST_IF expects a pointer to a struct ip_mreqn.
3340 memset(&multicastRequest, 0, sizeof(multicastRequest));
3341 multicastRequest.imr_ifindex = interfaceIndex;
3342 optionValue = &multicastRequest;
3343 optionLength = sizeof(multicastRequest);
3346 // IPV6_MULTICAST_IF expects a pointer to an integer.
3347 optionValue = &interfaceIndex;
3348 optionLength = sizeof(interfaceIndex);
3351 throwSocketException(env, SOCKERR_BADAF);
3354 result = getOrSetSocketOption(SOCKOPT_SET, handle,
3355 IP_MULTICAST_IF, IPV6_MULTICAST_IF, optionValue,
3358 throwSocketException(env, convertError(errno));
3364 case JAVASOCKOPT_SO_SNDBUF: {
3365 result = setsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intVal, intSize);
3367 throwSocketException(env, convertError(errno));
3373 case JAVASOCKOPT_SO_RCVBUF: {
3374 result = setsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intVal, intSize);
3376 throwSocketException(env, convertError(errno));
3382 case JAVASOCKOPT_SO_BROADCAST: {
3383 result = setsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intVal, intSize);
3385 throwSocketException(env, convertError(errno));
3391 case JAVASOCKOPT_SO_REUSEADDR: {
3392 result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
3394 throwSocketException(env, convertError(errno));
3399 case JAVASOCKOPT_SO_KEEPALIVE: {
3400 result = setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intVal, intSize);
3402 throwSocketException(env, convertError(errno));
3408 case JAVASOCKOPT_SO_OOBINLINE: {
3409 result = setsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intVal, intSize);
3411 throwSocketException(env, convertError(errno));
3417 case JAVASOCKOPT_IP_MULTICAST_LOOP: {
3418 result = getOrSetSocketOption(SOCKOPT_SET, handle,
3420 IPV6_MULTICAST_LOOP, &intVal,
3423 throwSocketException(env, convertError(errno));
3429 case JAVASOCKOPT_IP_TOS: {
3430 result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_TOS,
3431 IPV6_TCLASS, &intVal, &intSize);
3433 throwSocketException(env, convertError(errno));
3439 case JAVASOCKOPT_REUSEADDR_AND_REUSEPORT: {
3440 // SO_REUSEPORT doesn't need to get set on this System
3441 result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
3443 throwSocketException(env, convertError(errno));
3449 case JAVASOCKOPT_SO_RCVTIMEOUT: {
3450 struct timeval timeout;
3451 timeout.tv_sec = intVal / 1000;
3452 timeout.tv_usec = (intVal % 1000) * 1000;
3453 result = setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout,
3454 sizeof(struct timeval));
3456 throwSocketException(env, convertError(errno));
3463 throwSocketException(env, SOCKERR_OPTUNSUPP);
3468 static jint osNetworkSystem_getSocketFlagsImpl(JNIEnv* env, jclass clazz) {
3469 // LOGD("ENTER getSocketFlagsImpl");
3471 // Not implemented by harmony
3475 static void osNetworkSystem_socketCloseImpl(JNIEnv* env, jclass clazz,
3476 jobject fileDescriptor) {
3477 // LOGD("ENTER socketCloseImpl");
3479 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
3481 if (handle == 0 || handle == -1) {
3482 throwSocketException(env, SOCKERR_BADSOCKET);
3486 jniSetFileDescriptorOfFD(env, fileDescriptor, -1);
3491 static jobject osNetworkSystem_getHostByAddrImpl(JNIEnv* env, jclass clazz,
3492 jbyteArray addrStr) {
3493 // LOGD("ENTER getHostByAddrImpl");
3495 if (addrStr == NULL) {
3496 throwNullPointerException(env);
3500 jstring address = (jstring)newJavaLangString(env, addrStr);
3502 const char* addr = env->GetStringUTFChars(address, NULL);
3504 struct hostent* ent = gethostbyaddr(addr, strlen(addr), AF_INET);
3506 if (ent != NULL && ent->h_name != NULL) {
3507 result = env->NewStringUTF(ent->h_name);
3512 env->ReleaseStringUTFChars(address, addr);
3517 static jobject osNetworkSystem_getHostByNameImpl(JNIEnv* env, jclass clazz,
3518 jstring nameStr, jboolean preferIPv6Addresses) {
3519 // LOGD("ENTER getHostByNameImpl");
3521 if (nameStr == NULL) {
3522 throwNullPointerException(env);
3526 const char* name = env->GetStringUTFChars(nameStr, NULL);
3528 if (useAdbNetworking) {
3535 // LOGD("ADB networking: +gethostbyname '%s'", name);
3537 err = adb_networking_gethostbyname(name, &(outaddr.a));
3539 env->ReleaseStringUTFChars(nameStr, name);
3541 LOGD("ADB networking: -gethostbyname err %d addr 0x%08x %u.%u.%u.%u",
3542 err, (unsigned int)outaddr.a.s_addr,
3543 outaddr.j[0],outaddr.j[1],
3544 outaddr.j[2],outaddr.j[3]);
3550 jbyteArray addr = env->NewByteArray(4);
3551 env->SetByteArrayRegion(addr, 0, 4, outaddr.j);
3556 // normal case...no adb networking
3557 struct hostent* ent = gethostbyname(name);
3559 env->ReleaseStringUTFChars(nameStr, name);
3561 if (ent != NULL && ent->h_length > 0) {
3562 jbyteArray addr = env->NewByteArray(4);
3564 memcpy(v, ent->h_addr, 4);
3565 env->SetByteArrayRegion(addr, 0, 4, v);
3573 static void osNetworkSystem_setInetAddressImpl(JNIEnv* env, jobject obj,
3574 jobject sender, jbyteArray address) {
3575 // LOGD("ENTER setInetAddressImpl");
3577 env->SetObjectField(sender, gCachedFields.iaddr_ipaddress, address);
3580 // TODO: rewrite this method in Java and make it support IPv6.
3581 static jobject osNetworkSystem_inheritedChannelImpl(JNIEnv* env, jobject obj) {
3582 // LOGD("ENTER inheritedChannelImpl");
3586 socklen_t length = sizeof(opt);
3588 struct sockaddr_in local_addr;
3589 struct sockaddr_in remote_addr;
3590 jclass channel_class, socketaddr_class, serverSocket_class, socketImpl_class;
3591 jobject channel_object = NULL, socketaddr_object, serverSocket_object;
3592 jobject fd_object, addr_object, localAddr_object, socketImpl_object;
3593 jfieldID port_field, socketaddr_field, bound_field, fd_field;
3594 jfieldID serverSocket_field, socketImpl_field, addr_field, localAddr_field;
3595 jmethodID channel_new;
3596 jbyteArray addr_array;
3597 struct sockaddr_in *sock;
3600 jboolean jtrue = JNI_TRUE;
3602 if (0 != getsockopt(socket, SOL_SOCKET, SO_TYPE, &opt, &length)) {
3605 if (SOCK_STREAM !=opt && SOCK_DGRAM !=opt) {
3610 length = sizeof(struct sockaddr);
3611 if (0 != getsockname(socket, (struct sockaddr *)&local_addr, &length)) {
3614 if (AF_INET != local_addr.sin_family || length != sizeof(struct sockaddr)) {
3617 localAddr = (jbyte*) malloc(sizeof(jbyte)*4);
3618 if (NULL == localAddr) {
3621 memcpy (localAddr, &(local_addr.sin_addr.s_addr), 4);
3623 if (0 != getpeername(socket, (struct sockaddr *)&remote_addr, &length)) {
3624 remote_addr.sin_port = 0;
3625 remote_addr.sin_addr.s_addr = 0;
3626 address = (jbyte*) malloc(sizeof(jbyte)*4);
3627 bzero(address, sizeof(jbyte)*4);
3629 if (AF_INET != remote_addr.sin_family
3630 || length != sizeof(struct sockaddr)) {
3633 address = (jbyte*) malloc(sizeof(jbyte)*4);
3634 memcpy (address, &(remote_addr.sin_addr.s_addr), 4);
3637 // analysis end, begin pack to java
3638 if (SOCK_STREAM == opt) {
3639 if (remote_addr.sin_port!=0) {
3641 channel_class = env->FindClass(
3642 "org/apache/harmony/nio/internal/SocketChannelImpl");
3643 if (NULL == channel_class) {
3647 channel_new = env->GetMethodID(channel_class, "<init>", "()V");
3648 if (NULL == channel_new) {
3651 channel_object = env->NewObject(channel_class, channel_new);
3652 if (NULL == channel_object) {
3655 // new and set FileDescript
3657 fd_field = env->GetFieldID(channel_class, "fd",
3658 "java/io/FielDescriptor");
3659 fd_object = env->GetObjectField(channel_object, fd_field);
3660 if (NULL == fd_object) {
3664 jniSetFileDescriptorOfFD(env, fd_object, socket);
3667 port_field = env->GetFieldID(channel_class, "localPort", "I");
3668 env->SetIntField(channel_object, port_field,
3669 ntohs(local_addr.sin_port));
3671 // new and set remote addr
3672 addr_object = env->NewObject(gCachedFields.iaddr_class,
3673 gCachedFields.iaddr_class_init);
3674 if (NULL == addr_object) {
3677 socketaddr_class = env->FindClass("java/net/InetSocketAddress");
3678 socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
3679 "Ljava/net/InetSocketAddress;");
3680 socketaddr_object = env->GetObjectField(channel_object,
3682 if (NULL == socketaddr_object) {
3685 addr_field = env->GetFieldID(socketaddr_class, "addr",
3686 "Ljava/net/InetAddress;");
3687 env->SetObjectField(socketaddr_object, addr_field, addr_object);
3688 addr_array = env->NewByteArray((jsize)4);
3689 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
3690 env->SetObjectField(addr_object, gCachedFields.iaddr_ipaddress,
3694 socketaddr_class = env->FindClass("java/net/InetSocketAddress");
3695 socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
3696 "Ljava/net/InetSocketAddress;");
3697 socketaddr_object = env->GetObjectField(channel_object,
3700 localAddr_field = env->GetFieldID(channel_class, "localAddress",
3701 "Ljava/net/InetAddress;");
3702 localAddr_object = env->NewObject(gCachedFields.iaddr_class,
3703 gCachedFields.iaddr_class_init);
3704 jfieldID socketaddr_field = env->GetFieldID(channel_class,
3705 "connectAddress", "Ljava/net/InetSocketAddress;");
3706 jobject socketaddr_object = env->GetObjectField(channel_object,
3708 env->SetObjectField(socketaddr_object, localAddr_field,
3710 if (NULL == localAddr_object) {
3713 addr_array = env->NewByteArray((jsize)4);
3714 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, localAddr);
3715 env->SetObjectField(localAddr_object, gCachedFields.iaddr_ipaddress,
3720 port_field = env->GetFieldID(socketaddr_class, "port", "I");
3721 env->SetIntField(socketaddr_object, port_field,
3722 ntohs(remote_addr.sin_port));
3725 if (0 != local_addr.sin_port) {
3726 bound_field = env->GetFieldID(channel_class, "isBound", "Z");
3727 env->SetBooleanField(channel_object, bound_field, jtrue);
3732 channel_class = env->FindClass(
3733 "org/apache/harmony/nio/internal/ServerSocketChannelImpl");
3734 if (NULL == channel_class) {
3738 channel_new = env->GetMethodID(channel_class, "<init>", "()V");
3739 if (NULL == channel_new) {
3742 channel_object = env->NewObject(channel_class, channel_new);
3743 if (NULL == channel_object) {
3747 serverSocket_field = env->GetFieldID(channel_class, "socket",
3748 "Ljava/net/ServerSocket;");
3749 serverSocket_class = env->FindClass("Ljava/net/ServerSocket;");
3750 serverSocket_object = env->GetObjectField(channel_object,
3751 serverSocket_field);
3753 if (0 != local_addr.sin_port) {
3754 bound_field = env->GetFieldID(channel_class, "isBound", "Z");
3755 env->SetBooleanField(channel_object, bound_field, jtrue);
3756 bound_field = env->GetFieldID(serverSocket_class, "isBound", "Z");
3757 env->SetBooleanField(serverSocket_object, bound_field, jtrue);
3760 socketImpl_class = env->FindClass("java/net/SocketImpl");
3761 socketImpl_field = env->GetFieldID(channel_class, "impl",
3762 "Ljava/net/SocketImpl;");
3763 socketImpl_object = env->GetObjectField(channel_object,
3765 if (NULL == socketImpl_object) {
3769 localAddr_field = env->GetFieldID(channel_class, "localAddress",
3770 "Ljava/net/InetAddress;");
3771 localAddr_object = env->NewObject(gCachedFields.iaddr_class,
3772 gCachedFields.iaddr_class_init);
3773 if (NULL == localAddr_object) {
3776 env->SetObjectField(socketImpl_object, localAddr_field,
3778 addr_array = env->NewByteArray((jsize)4);
3779 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, localAddr);
3780 env->SetObjectField(localAddr_object,
3781 gCachedFields.iaddr_ipaddress, addr_array);
3784 port_field = env->GetFieldID(socketImpl_class, "localport", "I");
3785 env->SetIntField(socketImpl_object, port_field,
3786 ntohs(local_addr.sin_port));
3790 // new DatagramChannel
3791 channel_class = env->FindClass(
3792 "org/apache/harmony/nio/internal/DatagramChannelImpl");
3793 if (NULL == channel_class) {
3797 channel_new = env->GetMethodID(channel_class, "<init>", "()V");
3798 if (NULL == channel_new) {
3801 channel_object = env->NewObject(channel_class, channel_new);
3802 if (NULL == channel_object) {
3806 // new and set FileDescript
3807 fd_field = env->GetFieldID(channel_class, "fd", "java/io/FileDescriptor");
3808 fd_object = env->GetObjectField(channel_object, fd_field);
3809 if (NULL == fd_object) {
3813 jniSetFileDescriptorOfFD(env, fd_object, socket);
3815 port_field = env->GetFieldID(channel_class, "localPort", "I");
3816 env->SetIntField(channel_object, port_field, ntohs(local_addr.sin_port));
3818 // new and set remote addr
3819 addr_object = env->NewObject(gCachedFields.iaddr_class,
3820 gCachedFields.iaddr_class_init);
3821 if (NULL == addr_object) {
3824 socketaddr_class = env->FindClass("java/net/InetSocketAddress");
3825 socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
3826 "Ljava/net/InetSocketAddress;");
3827 socketaddr_object = env->GetObjectField(channel_object, socketaddr_field);
3828 if (NULL == socketaddr_object) {
3831 addr_field = env->GetFieldID(socketaddr_class, "addr",
3832 "Ljava/net/InetAddress;");
3833 env->SetObjectField(socketaddr_object, addr_field, addr_object);
3834 addr_array = env->NewByteArray((jsize)4);
3835 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
3836 env->SetObjectField(addr_object, gCachedFields.iaddr_ipaddress, addr_array);
3839 if (0 != local_addr.sin_port) {
3840 bound_field = env->GetFieldID(channel_class, "isBound", "Z");
3841 env->SetBooleanField(channel_object, bound_field, jtrue);
3847 return channel_object;
3853 static JNINativeMethod gMethods[] = {
3854 /* name, signature, funcPtr */
3855 { "oneTimeInitializationImpl", "(Z)V", (void*) osNetworkSystem_oneTimeInitializationImpl },
3856 { "createSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createSocketImpl },
3857 { "createDatagramSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createDatagramSocketImpl },
3858 { "readSocketImpl", "(Ljava/io/FileDescriptor;[BIII)I", (void*) osNetworkSystem_readSocketImpl },
3859 { "readSocketDirectImpl", "(Ljava/io/FileDescriptor;IIII)I", (void*) osNetworkSystem_readSocketDirectImpl },
3860 { "writeSocketImpl", "(Ljava/io/FileDescriptor;[BII)I", (void*) osNetworkSystem_writeSocketImpl },
3861 { "writeSocketDirectImpl", "(Ljava/io/FileDescriptor;III)I", (void*) osNetworkSystem_writeSocketDirectImpl },
3862 { "setNonBlockingImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_setNonBlockingImpl },
3863 { "connectSocketImpl", "(Ljava/io/FileDescriptor;ILjava/net/InetAddress;I)I", (void*) osNetworkSystem_connectSocketImpl },
3864 { "connectWithTimeoutSocketImpl", "(Ljava/io/FileDescriptor;IILjava/net/InetAddress;II[B)I", (void*) osNetworkSystem_connectWithTimeoutSocketImpl },
3865 { "connectStreamWithTimeoutSocketImpl","(Ljava/io/FileDescriptor;IIILjava/net/InetAddress;)V", (void*) osNetworkSystem_connectStreamWithTimeoutSocketImpl },
3866 { "socketBindImpl", "(Ljava/io/FileDescriptor;ILjava/net/InetAddress;)V", (void*) osNetworkSystem_socketBindImpl },
3867 { "listenStreamSocketImpl", "(Ljava/io/FileDescriptor;I)V", (void*) osNetworkSystem_listenStreamSocketImpl },
3868 { "availableStreamImpl", "(Ljava/io/FileDescriptor;)I", (void*) osNetworkSystem_availableStreamImpl },
3869 { "acceptSocketImpl", "(Ljava/io/FileDescriptor;Ljava/net/SocketImpl;Ljava/io/FileDescriptor;I)V",(void*) osNetworkSystem_acceptSocketImpl },
3870 { "supportsUrgentDataImpl", "(Ljava/io/FileDescriptor;)Z", (void*) osNetworkSystem_supportsUrgentDataImpl },
3871 { "sendUrgentDataImpl", "(Ljava/io/FileDescriptor;B)V", (void*) osNetworkSystem_sendUrgentDataImpl },
3872 { "connectDatagramImpl2", "(Ljava/io/FileDescriptor;IILjava/net/InetAddress;)V", (void*) osNetworkSystem_connectDatagramImpl2 },
3873 { "disconnectDatagramImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_disconnectDatagramImpl },
3874 { "socketBindImpl2", "(Ljava/io/FileDescriptor;IZLjava/net/InetAddress;)Z", (void*) osNetworkSystem_socketBindImpl2 },
3875 { "peekDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)I", (void*) osNetworkSystem_peekDatagramImpl },
3876 { "receiveDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;[BIIIZ)I", (void*) osNetworkSystem_receiveDatagramImpl },
3877 { "receiveDatagramDirectImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;IIIIZ)I", (void*) osNetworkSystem_receiveDatagramDirectImpl },
3878 { "recvConnectedDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;[BIIIZ)I", (void*) osNetworkSystem_recvConnectedDatagramImpl },
3879 { "recvConnectedDatagramDirectImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;IIIIZ)I", (void*) osNetworkSystem_recvConnectedDatagramDirectImpl },
3880 { "sendDatagramImpl", "(Ljava/io/FileDescriptor;[BIIIZILjava/net/InetAddress;)I", (void*) osNetworkSystem_sendDatagramImpl },
3881 { "sendDatagramDirectImpl", "(Ljava/io/FileDescriptor;IIIIZILjava/net/InetAddress;)I", (void*) osNetworkSystem_sendDatagramDirectImpl },
3882 { "sendConnectedDatagramImpl", "(Ljava/io/FileDescriptor;[BIIZ)I", (void*) osNetworkSystem_sendConnectedDatagramImpl },
3883 { "sendConnectedDatagramDirectImpl", "(Ljava/io/FileDescriptor;IIIZ)I", (void*) osNetworkSystem_sendConnectedDatagramDirectImpl },
3884 { "createServerStreamSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createServerStreamSocketImpl },
3885 { "createMulticastSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createMulticastSocketImpl },
3886 { "receiveStreamImpl", "(Ljava/io/FileDescriptor;[BIII)I", (void*) osNetworkSystem_receiveStreamImpl },
3887 { "sendStreamImpl", "(Ljava/io/FileDescriptor;[BII)I", (void*) osNetworkSystem_sendStreamImpl },
3888 { "shutdownInputImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_shutdownInputImpl },
3889 { "shutdownOutputImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_shutdownOutputImpl },
3890 { "sendDatagramImpl2", "(Ljava/io/FileDescriptor;[BIIILjava/net/InetAddress;)I", (void*) osNetworkSystem_sendDatagramImpl2 },
3891 { "selectImpl", "([Ljava/io/FileDescriptor;[Ljava/io/FileDescriptor;II[IJ)I", (void*) osNetworkSystem_selectImpl },
3892 { "getSocketLocalAddressImpl", "(Ljava/io/FileDescriptor;Z)Ljava/net/InetAddress;", (void*) osNetworkSystem_getSocketLocalAddressImpl },
3893 { "getSocketLocalPortImpl", "(Ljava/io/FileDescriptor;Z)I", (void*) osNetworkSystem_getSocketLocalPortImpl },
3894 { "getSocketOptionImpl", "(Ljava/io/FileDescriptor;I)Ljava/lang/Object;", (void*) osNetworkSystem_getSocketOptionImpl },
3895 { "setSocketOptionImpl", "(Ljava/io/FileDescriptor;ILjava/lang/Object;)V", (void*) osNetworkSystem_setSocketOptionImpl },
3896 { "getSocketFlagsImpl", "()I", (void*) osNetworkSystem_getSocketFlagsImpl },
3897 { "socketCloseImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_socketCloseImpl },
3898 { "getHostByAddrImpl", "([B)Ljava/net/InetAddress;", (void*) osNetworkSystem_getHostByAddrImpl },
3899 { "getHostByNameImpl", "(Ljava/lang/String;Z)Ljava/net/InetAddress;", (void*) osNetworkSystem_getHostByNameImpl },
3900 { "setInetAddressImpl", "(Ljava/net/InetAddress;[B)V", (void*) osNetworkSystem_setInetAddressImpl },
3901 { "inheritedChannelImpl", "()Ljava/nio/channels/Channel;", (void*) osNetworkSystem_inheritedChannelImpl },
3904 int register_org_apache_harmony_luni_platform_OSNetworkSystem(JNIEnv* env) {
3905 return jniRegisterNativeMethods(env,
3906 "org/apache/harmony/luni/platform/OSNetworkSystem",