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 #include <netinet/in6.h>
28 #include <netinet/tcp.h>
32 #include <sys/ioctl.h>
35 #include <cutils/properties.h>
36 #include <cutils/adb_networking.h>
37 #include <utils/LogSocket.h>
38 #include "AndroidSystemNatives.h"
42 * Error codes for socket operations
44 * @internal SOCKERR* range from -200 to -299 avoid overlap
46 #define SOCKERR_BADSOCKET -200 /* generic error */
47 #define SOCKERR_NOTINITIALIZED -201 /* socket library uninitialized */
48 #define SOCKERR_BADAF -202 /* bad address family */
49 #define SOCKERR_BADPROTO -203 /* bad protocol */
50 #define SOCKERR_BADTYPE -204 /* bad type */
51 #define SOCKERR_SYSTEMBUSY -205 /* system busy handling requests */
52 #define SOCKERR_SYSTEMFULL -206 /* too many sockets */
53 #define SOCKERR_NOTCONNECTED -207 /* socket is not connected */
54 #define SOCKERR_INTERRUPTED -208 /* the call was cancelled */
55 #define SOCKERR_TIMEOUT -209 /* the operation timed out */
56 #define SOCKERR_CONNRESET -210 /* the connection was reset */
57 #define SOCKERR_WOULDBLOCK -211 /* the socket is marked as nonblocking operation would block */
58 #define SOCKERR_ADDRNOTAVAIL -212 /* address not available */
59 #define SOCKERR_ADDRINUSE -213 /* address already in use */
60 #define SOCKERR_NOTBOUND -214 /* the socket is not bound */
61 #define SOCKERR_UNKNOWNSOCKET -215 /* resolution of fileDescriptor to socket failed */
62 #define SOCKERR_INVALIDTIMEOUT -216 /* the specified timeout is invalid */
63 #define SOCKERR_FDSETFULL -217 /* Unable to create an FDSET */
64 #define SOCKERR_TIMEVALFULL -218 /* Unable to create a TIMEVAL */
65 #define SOCKERR_REMSOCKSHUTDOWN -219 /* The remote socket has shutdown gracefully */
66 #define SOCKERR_NOTLISTENING -220 /* listen() was not invoked prior to accept() */
67 #define SOCKERR_NOTSTREAMSOCK -221 /* The socket does not support connection-oriented service */
68 #define SOCKERR_ALREADYBOUND -222 /* The socket is already bound to an address */
69 #define SOCKERR_NBWITHLINGER -223 /* The socket is marked non-blocking & SO_LINGER is non-zero */
70 #define SOCKERR_ISCONNECTED -224 /* The socket is already connected */
71 #define SOCKERR_NOBUFFERS -225 /* No buffer space is available */
72 #define SOCKERR_HOSTNOTFOUND -226 /* Authoritative Answer Host not found */
73 #define SOCKERR_NODATA -227 /* Valid name, no data record of requested type */
74 #define SOCKERR_BOUNDORCONN -228 /* The socket has not been bound or is already connected */
75 #define SOCKERR_OPNOTSUPP -229 /* The socket does not support the operation */
76 #define SOCKERR_OPTUNSUPP -230 /* The socket option is not supported */
77 #define SOCKERR_OPTARGSINVALID -231 /* The socket option arguments are invalid */
78 #define SOCKERR_SOCKLEVELINVALID -232 /* The socket level is invalid */
79 #define SOCKERR_TIMEOUTFAILURE -233
80 #define SOCKERR_SOCKADDRALLOCFAIL -234 /* Unable to allocate the sockaddr structure */
81 #define SOCKERR_FDSET_SIZEBAD -235 /* The calculated maximum size of the file descriptor set is bad */
82 #define SOCKERR_UNKNOWNFLAG -236 /* The flag is unknown */
83 #define SOCKERR_MSGSIZE -237 /* The datagram was too big to fit the specified buffer & was truncated. */
84 #define SOCKERR_NORECOVERY -238 /* The operation failed with no recovery possible */
85 #define SOCKERR_ARGSINVALID -239 /* The arguments are invalid */
86 #define SOCKERR_BADDESC -240 /* The socket argument is not a valid file descriptor */
87 #define SOCKERR_NOTSOCK -241 /* The socket argument is not a socket */
88 #define SOCKERR_HOSTENTALLOCFAIL -242 /* Unable to allocate the hostent structure */
89 #define SOCKERR_TIMEVALALLOCFAIL -243 /* Unable to allocate the timeval structure */
90 #define SOCKERR_LINGERALLOCFAIL -244 /* Unable to allocate the linger structure */
91 #define SOCKERR_IPMREQALLOCFAIL -245 /* Unable to allocate the ipmreq structure */
92 #define SOCKERR_FDSETALLOCFAIL -246 /* Unable to allocate the fdset structure */
93 #define SOCKERR_OPFAILED -247 /* Operation failed */
94 #define SOCKERR_VALUE_NULL -248 /* The value indexed was NULL */
95 #define SOCKERR_CONNECTION_REFUSED -249 /* connection was refused */
96 #define SOCKERR_ENETUNREACH -250 /* network is not reachable */
97 #define SOCKERR_EACCES -251 /* permissions do not allow action on socket */
98 #define SOCKERR_EHOSTUNREACH -252 /* no route to host */
99 #define SOCKERR_EPIPE -253 /* broken pipe */
101 #define JAVASOCKOPT_TCP_NODELAY 1
102 #define JAVASOCKOPT_IP_TOS 3
103 #define JAVASOCKOPT_SO_REUSEADDR 4
104 #define JAVASOCKOPT_SO_KEEPALIVE 8
105 #define JAVASOCKOPT_MCAST_TIME_TO_LIVE 10 /* Currently unused */
106 #define JAVASOCKOPT_SO_BINDADDR 15
107 #define JAVASOCKOPT_MCAST_INTERFACE 16
108 #define JAVASOCKOPT_MCAST_TTL 17
109 #define JAVASOCKOPT_IP_MULTICAST_LOOP 18
110 #define JAVASOCKOPT_MCAST_ADD_MEMBERSHIP 19
111 #define JAVASOCKOPT_MCAST_DROP_MEMBERSHIP 20
112 #define JAVASOCKOPT_IP_MULTICAST_IF2 31
113 #define JAVASOCKOPT_SO_BROADCAST 32
114 #define JAVASOCKOPT_SO_LINGER 128
115 #define JAVASOCKOPT_REUSEADDR_AND_REUSEPORT 10001
116 #define JAVASOCKOPT_SO_SNDBUF 4097
117 #define JAVASOCKOPT_SO_RCVBUF 4098
118 #define JAVASOCKOPT_SO_RCVTIMEOUT 4102
119 #define JAVASOCKOPT_SO_OOBINLINE 4099
121 /* constants for calling multi-call functions */
122 #define SOCKET_STEP_START 10
123 #define SOCKET_STEP_CHECK 20
124 #define SOCKET_STEP_DONE 30
126 #define BROKEN_MULTICAST_IF 1
127 #define BROKEN_MULTICAST_TTL 2
128 #define BROKEN_TCP_NODELAY 4
130 #define SOCKET_CONNECT_STEP_START 0
131 #define SOCKET_CONNECT_STEP_CHECK 1
133 #define SOCKET_OP_NONE 0
134 #define SOCKET_OP_READ 1
135 #define SOCKET_OP_WRITE 2
136 #define SOCKET_READ_WRITE 3
138 #define SOCKET_MSG_PEEK 1
139 #define SOCKET_MSG_OOB 2
141 #define SOCKET_NOFLAGS 0
144 #define BUFFERSIZE 2048
146 // wait for 500000 usec = 0.5 second
147 #define SEND_RETRY_TIME 500000
149 // Local constants for getOrSetSocketOption
150 #define SOCKOPT_GET 1
151 #define SOCKOPT_SET 2
153 struct CachedFields {
154 jfieldID fd_descriptor;
156 jmethodID iaddr_class_init;
157 jmethodID iaddr_getbyaddress;
158 jfieldID iaddr_ipaddress;
159 jclass genericipmreq_class;
160 jclass integer_class;
161 jmethodID integer_class_init;
162 jfieldID integer_class_value;
163 jclass boolean_class;
164 jmethodID boolean_class_init;
165 jfieldID boolean_class_value;
167 jmethodID byte_class_init;
168 jfieldID byte_class_value;
170 jmethodID string_class_init;
171 jfieldID socketimpl_address;
172 jfieldID socketimpl_port;
174 jfieldID dpack_address;
176 jfieldID dpack_length;
179 static int useAdbNetworking = 0;
181 /* needed for connecting with timeout */
182 typedef struct selectFDSet {
190 static const char * netLookupErrorString(int anErrorNum);
193 * Throws an SocketException with the message affiliated with the errorCode.
195 static void throwSocketException(JNIEnv *env, int errorCode) {
196 jniThrowException(env, "java/net/SocketException",
197 netLookupErrorString(errorCode));
201 * Throws an IOException with the given message.
203 static void throwIOExceptionStr(JNIEnv *env, const char *message) {
204 jniThrowException(env, "java/io/IOException", message);
208 * Throws a NullPointerException.
210 static void throwNullPointerException(JNIEnv *env) {
211 jniThrowException(env, "java/lang/NullPointerException", NULL);
215 * Converts a 4-byte array to a native address structure. Throws a
216 * NullPointerException or an IOException in case of error. This is
217 * signaled by a return value of -1. The normal return value is 0.
219 static int javaAddressToStructIn(
220 JNIEnv *env, jbyteArray java_address, struct in_addr *address) {
222 memset(address, 0, sizeof(address));
224 if (java_address == NULL) {
228 if (env->GetArrayLength(java_address) != sizeof(address->s_addr)) {
232 jbyte * java_address_bytes
233 = env->GetByteArrayElements(java_address, NULL);
235 memcpy(&(address->s_addr),
237 sizeof(address->s_addr));
239 env->ReleaseByteArrayElements(java_address, java_address_bytes, JNI_ABORT);
245 * Converts a native address structure to a Java byte array. Throws a
246 * NullPointerException or an IOException in case of error. This is
247 * signaled by a return value of -1. The normal return value is 0.
249 * @param address the sockaddr_storage structure to convert
251 * @exception SocketException the address family is unknown, or out of memory
254 static jbyteArray socketAddressToAddressBytes(JNIEnv *env,
255 struct sockaddr_storage *address) {
258 size_t addressLength;
259 if (address->ss_family == AF_INET) {
260 struct sockaddr_in *sin = (struct sockaddr_in *) address;
261 rawAddress = &sin->sin_addr.s_addr;
263 } else if (address->ss_family == AF_INET6) {
264 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address;
265 rawAddress = &sin6->sin6_addr.s6_addr;
268 throwSocketException(env, SOCKERR_BADAF);
272 jbyteArray byteArray = env->NewByteArray(addressLength);
273 if (byteArray == NULL) {
274 throwSocketException(env, SOCKERR_NOBUFFERS);
277 env->SetByteArrayRegion(byteArray, 0, addressLength, (jbyte *) rawAddress);
283 * Wrapper function for log_socket_connect, which is currently disabled.
284 * TODO: either unbreak log_socket_connect and fix it to take strings or IP
285 * addresses or remove it. After that, remove this function.
287 * @param fd the socket file descriptor to enable logging on
288 * @param address pointer to the socket address the socket is connecting to
290 static void logSocketConnect(int fd, struct sockaddr_storage *address) {
291 // Since connection logging is disabled for now, don't implement IPv6
292 // support for it just yet.
293 if (address->ss_family == AF_INET) {
294 struct sockaddr_in *sin = (struct sockaddr_in *) address;
295 log_socket_connect(fd, ntohl(sin->sin_addr.s_addr),
296 ntohs(sin->sin_port));
301 * Returns the port number in a sockaddr_storage structure.
303 * @param address the sockaddr_storage structure to get the port from
305 * @return the port number, or -1 if the address family is unknown.
307 static int getSocketAddressPort(struct sockaddr_storage *address) {
308 switch (address->ss_family) {
310 return ntohs(((struct sockaddr_in *) address)->sin_port);
312 return ntohs(((struct sockaddr_in6 *) address)->sin6_port);
319 * Converts a native address structure to an InetAddress object.
320 * Throws a NullPointerException or an IOException in case of
321 * error. This is signaled by a return value of -1. The normal
324 * @param sockaddress the sockaddr_storage structure to convert
326 * @return a jobject representing an InetAddress
328 static jobject socketAddressToInetAddress(JNIEnv *env,
329 struct sockaddr_storage *sockaddress) {
331 jbyteArray byteArray = socketAddressToAddressBytes(env, sockaddress);
332 if (byteArray == NULL) // Exception has already been thrown.
335 return env->CallStaticObjectMethod(gCachedFields.iaddr_class,
336 gCachedFields.iaddr_getbyaddress, byteArray);
340 * Converts an InetAddress object and port number to a native address structure.
341 * Throws a NullPointerException or a SocketException in case of
342 * error. This is signaled by a return value of -1. The normal
345 * @param inetaddress the InetAddress object to convert
346 * @param port the port number
347 * @param sockaddress the sockaddr_storage structure to write to
349 * @return 0 on success, -1 on failure
351 * @exception SocketError if the address family is unknown
353 static int inetAddressToSocketAddress(JNIEnv *env,
354 jobject inetaddress, int port, struct sockaddr_storage *sockaddress) {
356 // Get the byte array that stores the IP address bytes in the InetAddress.
357 jbyteArray addressByteArray;
358 addressByteArray = (jbyteArray)env->GetObjectField(inetaddress,
359 gCachedFields.iaddr_ipaddress);
360 if (addressByteArray == NULL) {
361 throwNullPointerException(env);
365 // Get the raw IP address bytes.
366 jbyte *addressBytes = env->GetByteArrayElements(addressByteArray, NULL);
367 if (addressBytes == NULL) {
368 throwNullPointerException(env);
372 // Convert the IP address bytes to the proper IP address type.
373 size_t addressLength = env->GetArrayLength(addressByteArray);
375 if (addressLength == 4) {
377 struct sockaddr_in *sin = (struct sockaddr_in *) sockaddress;
378 memset(sin, 0, sizeof(struct sockaddr_in));
379 sin->sin_family = AF_INET;
380 sin->sin_port = htons(port);
381 memcpy(&sin->sin_addr.s_addr, addressBytes, 4);
382 } else if (addressLength == 16) {
384 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sockaddress;
385 memset(sin6, 0, sizeof(struct sockaddr_in6));
386 sin6->sin6_family = AF_INET6;
387 sin6->sin6_port = htons(port);
388 memcpy(&sin6->sin6_addr.s6_addr, addressBytes, 16);
390 // Unknown address family.
391 throwSocketException(env, SOCKERR_BADAF);
394 env->ReleaseByteArrayElements(addressByteArray, addressBytes, 0);
399 * Answer a new java.lang.Boolean object.
401 * @param env pointer to the JNI library
402 * @param anInt the Boolean constructor argument
404 * @return the new Boolean
407 jobject newJavaLangBoolean(JNIEnv * env, jint anInt) {
409 jmethodID tempMethod;
411 tempClass = gCachedFields.boolean_class;
412 tempMethod = gCachedFields.boolean_class_init;
413 return env->NewObject(tempClass, tempMethod, (jboolean) (anInt != 0));
417 * Answer a new java.lang.Byte object.
419 * @param env pointer to the JNI library
420 * @param anInt the Byte constructor argument
422 * @return the new Byte
425 jobject newJavaLangByte(JNIEnv * env, jbyte val) {
427 jmethodID tempMethod;
429 tempClass = gCachedFields.byte_class;
430 tempMethod = gCachedFields.byte_class_init;
431 return env->NewObject(tempClass, tempMethod, val);
435 * Answer a new java.lang.Integer object.
437 * @param env pointer to the JNI library
438 * @param anInt the Integer constructor argument
440 * @return the new Integer
443 jobject newJavaLangInteger(JNIEnv * env, jint anInt) {
445 jmethodID tempMethod;
447 tempClass = gCachedFields.integer_class;
448 tempMethod = gCachedFields.integer_class_init;
449 return env->NewObject(tempClass, tempMethod, anInt);
453 * Answer a new java.lang.String object.
455 * @param env pointer to the JNI library
456 * @param anInt the byte[] constructor argument
458 * @return the new String
461 jobject newJavaLangString(JNIEnv * env, jbyteArray bytes) {
463 jmethodID tempMethod;
465 tempClass = gCachedFields.string_class;
466 tempMethod = gCachedFields.string_class_init;
467 return env->NewObject(tempClass, tempMethod, (jbyteArray) bytes);
471 * Query OS for timestamp.
472 * Retrieve the current value of system clock and convert to milliseconds.
474 * @param[in] portLibrary The port library.
476 * @return 0 on failure, time value in milliseconds on success.
477 * @deprecated Use @ref time_hires_clock and @ref time_hires_delta
479 * technically, this should return I_64 since both timeval.tv_sec and
480 * timeval.tv_usec are long
483 static int time_msec_clock() {
487 gettimeofday(&tp, &tzp);
488 return (tp.tv_sec * 1000) + (tp.tv_usec / 1000);
492 * Check if the passed sockaddr_storage struct contains a localhost address
494 * @param address address pointer to the address to check
496 * @return 0 if the passed address isn't a localhost address
498 static int isLocalHost(struct sockaddr_storage *address) {
499 if (address->ss_family == AF_INET) {
500 struct sockaddr_in *sin = (struct sockaddr_in *) address;
501 return (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK));
502 } else if (address->ss_family == AF_INET6) {
503 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address;
504 return IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr);
511 * Decide whether to use ADB networking for the given socket address.
513 * @param address pointer to sockaddr_storage structure to check
515 * @return true if ADB networking should be used, false otherwise.
517 static bool useAdbNetworkingForAddress(struct sockaddr_storage *address) {
518 return useAdbNetworking && !isLocalHost(address) &&
519 address->ss_family == AF_INET;
523 * Convert a sockaddr_storage structure to a string for logging purposes.
525 * @param address pointer to sockaddr_storage structure to print
527 * @return a string with the textual representation of the address.
529 * @note Returns a statically allocated buffer, so is not thread-safe.
531 static char *socketAddressToString(struct sockaddr_storage *address) {
532 static char invalidString[] = "<invalid>";
533 static char ipString[INET6_ADDRSTRLEN + sizeof("[]:65535")];
535 char tmp[INET6_ADDRSTRLEN];
537 // TODO: getnameinfo seems to want its length parameter to be exactly
538 // sizeof(sockaddr_in) for an IPv4 address and sizeof (sockaddr_in6) for an
539 // IPv6 address. Fix getnameinfo so it accepts sizeof(sockaddr_storage), and
540 // then remove this hack.
541 int size = (address->ss_family == AF_INET) ?
542 sizeof(sockaddr_in) : sizeof(sockaddr_in6);
543 int result = getnameinfo((struct sockaddr *)address,
544 size, tmp, sizeof(tmp), NULL, 0,
548 return invalidString;
550 if (address->ss_family == AF_INET6) {
551 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address;
552 port = ntohs(sin6->sin6_port);
553 sprintf(ipString, "[%s]:%d", tmp, port);
555 } else if (address->ss_family == AF_INET) {
556 struct sockaddr_in *sin = (struct sockaddr_in *) address;
557 port = ntohs(sin->sin_port);
558 sprintf(ipString, "%s:%d", tmp, port);
561 return invalidString;
566 * Answer the errorString corresponding to the errorNumber, if available.
567 * This function will answer a default error string, if the errorNumber is not
570 * This function will have to be reworked to handle internationalization
571 * properly, removing the explicit strings.
573 * @param anErrorNum the error code to resolve to a human readable string
575 * @return a human readable error string
578 static const char * netLookupErrorString(int anErrorNum) {
579 switch (anErrorNum) {
580 case SOCKERR_BADSOCKET:
582 case SOCKERR_NOTINITIALIZED:
583 return "Socket library uninitialized";
585 return "Bad address family";
586 case SOCKERR_BADPROTO:
587 return "Bad protocol";
588 case SOCKERR_BADTYPE:
590 case SOCKERR_SYSTEMBUSY:
591 return "System busy handling requests";
592 case SOCKERR_SYSTEMFULL:
593 return "Too many sockets allocated";
594 case SOCKERR_NOTCONNECTED:
595 return "Socket is not connected";
596 case SOCKERR_INTERRUPTED:
597 return "The system call was cancelled";
598 case SOCKERR_TIMEOUT:
599 return "The operation timed out";
600 case SOCKERR_CONNRESET:
601 return "The connection was reset";
602 case SOCKERR_WOULDBLOCK:
603 return "The nonblocking operation would block";
604 case SOCKERR_ADDRNOTAVAIL:
605 return "The address is not available";
606 case SOCKERR_ADDRINUSE:
607 return "The address is already in use";
608 case SOCKERR_NOTBOUND:
609 return "The socket is not bound";
610 case SOCKERR_UNKNOWNSOCKET:
611 return "Resolution of the FileDescriptor to socket failed";
612 case SOCKERR_INVALIDTIMEOUT:
613 return "The specified timeout is invalid";
614 case SOCKERR_FDSETFULL:
615 return "Unable to create an FDSET";
616 case SOCKERR_TIMEVALFULL:
617 return "Unable to create a TIMEVAL";
618 case SOCKERR_REMSOCKSHUTDOWN:
619 return "The remote socket has shutdown gracefully";
620 case SOCKERR_NOTLISTENING:
621 return "Listen() was not invoked prior to accept()";
622 case SOCKERR_NOTSTREAMSOCK:
623 return "The socket does not support connection-oriented service";
624 case SOCKERR_ALREADYBOUND:
625 return "The socket is already bound to an address";
626 case SOCKERR_NBWITHLINGER:
627 return "The socket is marked non-blocking & SO_LINGER is non-zero";
628 case SOCKERR_ISCONNECTED:
629 return "The socket is already connected";
630 case SOCKERR_NOBUFFERS:
631 return "No buffer space is available";
632 case SOCKERR_HOSTNOTFOUND:
633 return "Authoritative Answer Host not found";
635 return "Valid name, no data record of requested type";
636 case SOCKERR_BOUNDORCONN:
637 return "The socket has not been bound or is already connected";
638 case SOCKERR_OPNOTSUPP:
639 return "The socket does not support the operation";
640 case SOCKERR_OPTUNSUPP:
641 return "The socket option is not supported";
642 case SOCKERR_OPTARGSINVALID:
643 return "The socket option arguments are invalid";
644 case SOCKERR_SOCKLEVELINVALID:
645 return "The socket level is invalid";
646 case SOCKERR_TIMEOUTFAILURE:
647 return "The timeout operation failed";
648 case SOCKERR_SOCKADDRALLOCFAIL:
649 return "Failed to allocate address structure";
650 case SOCKERR_FDSET_SIZEBAD:
651 return "The calculated maximum size of the file descriptor set is bad";
652 case SOCKERR_UNKNOWNFLAG:
653 return "The flag is unknown";
654 case SOCKERR_MSGSIZE:
655 return "The datagram was too big to fit the specified buffer, so truncated";
656 case SOCKERR_NORECOVERY:
657 return "The operation failed with no recovery possible";
658 case SOCKERR_ARGSINVALID:
659 return "The arguments are invalid";
660 case SOCKERR_BADDESC:
661 return "The socket argument is not a valid file descriptor";
662 case SOCKERR_NOTSOCK:
663 return "The socket argument is not a socket";
664 case SOCKERR_HOSTENTALLOCFAIL:
665 return "Unable to allocate the hostent structure";
666 case SOCKERR_TIMEVALALLOCFAIL:
667 return "Unable to allocate the timeval structure";
668 case SOCKERR_LINGERALLOCFAIL:
669 return "Unable to allocate the linger structure";
670 case SOCKERR_IPMREQALLOCFAIL:
671 return "Unable to allocate the ipmreq structure";
672 case SOCKERR_FDSETALLOCFAIL:
673 return "Unable to allocate the fdset structure";
674 case SOCKERR_OPFAILED:
675 return "Operation failed";
676 case SOCKERR_CONNECTION_REFUSED:
677 return "Connection refused";
678 case SOCKERR_ENETUNREACH:
679 return "Network unreachable";
680 case SOCKERR_EHOSTUNREACH:
681 return "No route to host";
683 return "Broken pipe";
685 return "Permission denied (maybe missing INTERNET permission)";
688 LOGE("unknown socket error %d", anErrorNum);
689 return "unknown error";
693 static int convertError(int errorCode) {
696 return SOCKERR_BADDESC;
698 return SOCKERR_NOBUFFERS;
700 return SOCKERR_OPNOTSUPP;
702 return SOCKERR_OPTUNSUPP;
704 return SOCKERR_SOCKLEVELINVALID;
706 return SOCKERR_NOTSOCK;
708 return SOCKERR_INTERRUPTED;
710 return SOCKERR_NOTCONNECTED;
712 return SOCKERR_BADAF;
713 /* note: CONNRESET not included because it has the same
714 * value as ECONNRESET and they both map to SOCKERR_CONNRESET */
716 return SOCKERR_CONNRESET;
718 return SOCKERR_WOULDBLOCK;
719 case EPROTONOSUPPORT:
720 return SOCKERR_BADPROTO;
722 return SOCKERR_ARGSINVALID;
724 return SOCKERR_TIMEOUT;
726 return SOCKERR_CONNECTION_REFUSED;
728 return SOCKERR_ENETUNREACH;
730 return SOCKERR_EACCES;
732 return SOCKERR_EPIPE;
734 return SOCKERR_EHOSTUNREACH;
736 return SOCKERR_ADDRINUSE;
738 return SOCKERR_ADDRNOTAVAIL;
740 return SOCKERR_MSGSIZE;
742 LOGE("unclassified errno %d (%s)", errorCode, strerror(errorCode));
743 return SOCKERR_OPFAILED;
747 static int sockSelect(int nfds, fd_set *readfds, fd_set *writefds,
748 fd_set *exceptfds, struct timeval *timeout) {
750 int result = select(nfds, readfds, writefds, exceptfds, timeout);
753 if (errno == EINTR) {
754 result = SOCKERR_INTERRUPTED;
756 result = SOCKERR_OPFAILED;
758 } else if (result == 0) {
759 result = SOCKERR_TIMEOUT;
764 #define SELECT_READ_TYPE 0
765 #define SELECT_WRITE_TYPE 1
767 static int selectWait(int handle, int uSecTime, int type) {
769 struct timeval time, *timePtr;
771 int size = handle + 1;
774 FD_SET(handle, &fdset);
777 /* Use a timeout if uSecTime >= 0 */
778 memset(&time, 0, sizeof(time));
779 time.tv_usec = uSecTime;
782 /* Infinite timeout if uSecTime < 0 */
786 if (type == SELECT_READ_TYPE) {
787 result = sockSelect(size, &fdset, NULL, NULL, timePtr);
789 result = sockSelect(size, NULL, &fdset, NULL, timePtr);
794 static int pollSelectWait(JNIEnv *env, jobject fileDescriptor, int timeout, int type) {
795 /* now try reading the socket for the timespan timeout.
796 * if timeout is 0 try forever until the soclets gets ready or until an
799 int pollTimeoutUSec = 100000, pollMsec = 100;
801 int timeLeft = timeout;
802 int hasTimeout = timeout > 0 ? 1 : 0;
807 finishTime = time_msec_clock() + timeout;
812 while (poll) { /* begin polling loop */
815 * Fetch the handle every time in case the socket is closed.
817 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
819 if (handle == 0 || handle == -1) {
820 throwSocketException(env, SOCKERR_INTERRUPTED);
826 if (timeLeft - 10 < pollMsec) {
827 pollTimeoutUSec = timeLeft <= 0 ? 0 : (timeLeft * 1000);
830 result = selectWait(handle, pollTimeoutUSec, type);
833 * because we are polling at a time smaller than timeout
834 * (presumably) lets treat an interrupt and timeout the same - go
835 * see if we're done timewise, and then just try again if not.
837 if (SOCKERR_TIMEOUT == result ||
838 SOCKERR_INTERRUPTED == result) {
840 timeLeft = finishTime - time_msec_clock();
844 * Always throw the "timeout" message because that is
845 * effectively what has happened, even if we happen to
846 * have been interrupted.
848 jniThrowException(env, "java/net/SocketTimeoutException",
849 netLookupErrorString(SOCKERR_TIMEOUT));
851 continue; // try again
854 } else if (0 > result) {
855 log_socket_close(handle, result);
856 throwSocketException(env, result);
860 } else { /* polling with no timeout (why would you do this?)*/
862 result = selectWait(handle, pollTimeoutUSec, type);
865 * if interrupted (or a timeout) just retry
867 if (SOCKERR_TIMEOUT == result ||
868 SOCKERR_INTERRUPTED == result) {
870 continue; // try again
871 } else if (0 > result) {
872 log_socket_close(handle, result);
873 throwSocketException(env, result);
877 } /* end polling loop */
883 * Obtain the socket address family from an existing socket.
885 * @param socket the filedescriptor of the socket to examine
887 * @return an integer, the address family of the socket
889 static int getSocketAddressFamily(int socket) {
890 struct sockaddr_storage ss;
891 socklen_t namelen = sizeof(ss);
892 int ret = getsockname(socket, (struct sockaddr*) &ss, &namelen);
901 * A helper method, to set the connect context to a Long object.
903 * @param env pointer to the JNI library
904 * @param longclass Java Long Object
906 void setConnectContext(JNIEnv *env,jobject longclass,jbyte * context) {
907 jclass descriptorCLS;
908 jfieldID descriptorFID;
909 descriptorCLS = env->FindClass("java/lang/Long");
910 descriptorFID = env->GetFieldID(descriptorCLS, "value", "J");
911 env->SetLongField(longclass, descriptorFID, (jlong)((jint)context));
915 * A helper method, to get the connect context.
917 * @param env pointer to the JNI library
918 * @param longclass Java Long Object
920 jbyte *getConnectContext(JNIEnv *env, jobject longclass) {
921 jclass descriptorCLS;
922 jfieldID descriptorFID;
923 descriptorCLS = env->FindClass("java/lang/Long");
924 descriptorFID = env->GetFieldID(descriptorCLS, "value", "J");
925 return (jbyte*) ((jint)env->GetLongField(longclass, descriptorFID));
928 // typical ip checksum
929 unsigned short ip_checksum(unsigned short* buffer, int size) {
930 register unsigned short * buf = buffer;
931 register int bufleft = size;
932 register unsigned long sum = 0;
934 while (bufleft > 1) {
935 sum = sum + (*buf++);
936 bufleft = bufleft - sizeof(unsigned short );
939 sum = sum + (*(unsigned char*)buf);
941 sum = (sum >> 16) + (sum & 0xffff);
944 return (unsigned short )(~sum);
948 * Establish a connection to a peer with a timeout. This function is called
949 * repeatedly in order to carry out the connect and to allow other tasks to
950 * proceed on certain platforms. The caller must first call with
951 * step = SOCKET_STEP_START, if the result is SOCKERR_NOTCONNECTED it will then
952 * call it with step = CHECK until either another error or 0 is returned to
953 * indicate the connect is complete. Each time the function should sleep for no
954 * more than timeout milliseconds. If the connect succeeds or an error occurs,
955 * the caller must always end the process by calling the function with
956 * step = SOCKET_STEP_DONE
958 * @param[in] portLibrary The port library.
959 * @param[in] sock pointer to the unconnected local socket.
960 * @param[in] addr pointer to the sockaddr, specifying remote host/port.
961 * @param[in] timeout the timeout in milliseconds. If timeout is negative,
962 * perform a block operation.
963 * @param[in,out] pointer to context pointer. Filled in on first call and then
964 * to be passed into each subsequent call.
966 * @return 0, if no errors occurred, otherwise the (negative) error code.
968 static int sockConnectWithTimeout(int handle, struct sockaddr_storage addr,
969 unsigned int timeout, unsigned int step, jbyte *ctxt) {
971 struct timeval passedTimeout;
973 socklen_t errorValLen = sizeof(int);
974 struct selectFDSet *context = NULL;
976 if (SOCKET_STEP_START == step) {
978 context = (struct selectFDSet *) ctxt;
980 context->sock = handle;
981 context->nfds = handle + 1;
983 if (useAdbNetworkingForAddress(&addr)) {
985 // LOGD("+connect to address 0x%08x (via adb)",
986 // addr.sin_addr.s_addr);
987 rc = adb_networking_connect_fd(handle, (struct sockaddr_in *) &addr);
988 // LOGD("-connect ret %d errno %d (via adb)", rc, errno);
991 logSocketConnect(handle, &addr);
993 /* set the socket to non-blocking */
994 int block = JNI_TRUE;
995 rc = ioctl(handle, FIONBIO, &block);
997 return convertError(rc);
1000 // LOGD("+connect to address 0x%08x (via normal) on handle %d",
1001 // addr.sin_addr.s_addr, handle);
1003 rc = connect(handle, (struct sockaddr *) &addr,
1004 sizeof(struct sockaddr));
1005 } while (rc < 0 && errno == EINTR);
1006 // LOGD("-connect to address 0x%08x (via normal) returned %d",
1007 // addr.sin_addr.s_addr, (int) rc);
1015 return SOCKERR_ALREADYBOUND;
1018 return SOCKERR_NOTCONNECTED;
1020 return convertError(rc);
1024 /* we connected right off the bat so just return */
1027 } else if (SOCKET_STEP_CHECK == step) {
1028 /* now check if we have connected yet */
1030 context = (struct selectFDSet *) ctxt;
1033 * set the timeout value to be used. Because on some unix platforms we
1034 * don't get notified when a socket is closed we only sleep for 100ms
1037 passedTimeout.tv_sec = 0;
1038 if (timeout > 100) {
1039 passedTimeout.tv_usec = 100 * 1000;
1040 } else if ((int)timeout >= 0) {
1041 passedTimeout.tv_usec = timeout * 1000;
1044 /* initialize the FD sets for the select */
1045 FD_ZERO(&(context->exceptionSet));
1046 FD_ZERO(&(context->writeSet));
1047 FD_ZERO(&(context->readSet));
1048 FD_SET(context->sock, &(context->writeSet));
1049 FD_SET(context->sock, &(context->readSet));
1050 FD_SET(context->sock, &(context->exceptionSet));
1052 rc = select(context->nfds,
1053 &(context->readSet),
1054 &(context->writeSet),
1055 &(context->exceptionSet),
1056 (int)timeout >= 0 ? &passedTimeout : NULL);
1058 /* if there is at least one descriptor ready to be checked */
1060 /* if the descriptor is in the write set we connected or failed */
1061 if (FD_ISSET(context->sock, &(context->writeSet))) {
1063 if (!FD_ISSET(context->sock, &(context->readSet))) {
1064 /* ok we have connected ok */
1067 /* ok we have more work to do to figure it out */
1068 if (getsockopt(context->sock, SOL_SOCKET, SO_ERROR,
1069 &errorVal, &errorValLen) >= 0) {
1070 return errorVal ? convertError(errorVal) : 0;
1072 return convertError(errno);
1077 /* if the descriptor is in the exception set the connect failed */
1078 if (FD_ISSET(context->sock, &(context->exceptionSet))) {
1079 if (getsockopt(context->sock, SOL_SOCKET, SO_ERROR, &errorVal,
1080 &errorValLen) >= 0) {
1081 return errorVal ? convertError(errorVal) : 0;
1084 return convertError(rc);
1087 } else if (rc < 0) {
1088 /* something went wrong with the select call */
1091 /* if it was EINTR we can just try again. Return not connected */
1093 return SOCKERR_NOTCONNECTED;
1096 /* some other error occured so look it up and return */
1097 return convertError(rc);
1101 * if we get here the timeout expired or the connect had not yet
1102 * completed just indicate that the connect is not yet complete
1104 return SOCKERR_NOTCONNECTED;
1105 } else if (SOCKET_STEP_DONE == step) {
1106 /* we are done the connect or an error occured so clean up */
1108 int block = JNI_FALSE;
1109 ioctl(handle, FIONBIO, &block);
1113 return SOCKERR_ARGSINVALID;
1118 * Helper method to get or set socket options
1120 * @param action SOCKOPT_GET to get an option, SOCKOPT_SET to set it
1121 * @param socket the file descriptor of the socket to use
1122 * @param ipv4Option the option value to use for an IPv4 socket
1123 * @param ipv6Option the option value to use for an IPv6 socket
1124 * @param optionValue the value of the socket option to get or set
1125 * @param optionLength the length of the socket option to get or set
1127 * @return the value of the socket call, or -1 on failure inside this function
1129 * @note on internal failure, the errno variable will be set appropriately
1131 static int getOrSetSocketOption(int action, int socket, int ipv4Option,
1132 int ipv6Option, void *optionValue, socklen_t *optionLength) {
1135 int family = getSocketAddressFamily(socket);
1138 option = ipv4Option;
1139 protocol = IPPROTO_IP;
1142 option = ipv6Option;
1143 protocol = IPPROTO_IPV6;
1146 errno = EAFNOSUPPORT;
1149 if (action == SOCKOPT_GET) {
1150 return getsockopt(socket, protocol, option, &optionValue, optionLength);
1151 } else if (action == SOCKOPT_SET) {
1152 return setsockopt(socket, protocol, option, &optionValue,
1161 * Find the interface index that was set for this socket by the IP_MULTICAST_IF
1162 * or IPV6_MULTICAST_IF socket option.
1164 * @param socket the socket to examine
1166 * @return the interface index, or -1 on failure
1168 * @note on internal failure, the errno variable will be set appropriately
1170 static int interfaceIndexFromMulticastSocket(int socket) {
1171 int family = getSocketAddressFamily(socket);
1172 socklen_t requestLength;
1175 if (family == AF_INET) {
1176 // IP_MULTICAST_IF returns a pointer to a struct ip_mreqn.
1177 struct ip_mreqn tempRequest;
1178 requestLength = sizeof(tempRequest);
1179 result = getsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, &tempRequest,
1181 interfaceIndex = tempRequest.imr_ifindex;
1182 } else if (family == AF_INET6) {
1183 // IPV6_MULTICAST_IF returns a pointer to an integer.
1184 requestLength = sizeof(interfaceIndex);
1185 result = getsockopt(socket, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1186 &interfaceIndex, &requestLength);
1188 errno = EAFNOSUPPORT;
1193 return interfaceIndex;
1200 * Join/Leave the nominated multicast group on the specified socket.
1201 * Implemented by setting the multicast 'add membership'/'drop membership'
1202 * option at the HY_IPPROTO_IP level on the socket.
1204 * Implementation note for multicast sockets in general:
1206 * - This code is untested, because at the time of this writing multicast can't
1207 * be properly tested on Android due to GSM routing restrictions. So it might
1208 * or might not work.
1210 * - The REUSEPORT socket option that Harmony employs is not supported on Linux
1211 * and thus also not supported on Android. It's is not needed for multicast
1212 * to work anyway (REUSEADDR should suffice).
1214 * @param env pointer to the JNI library.
1215 * @param socketP pointer to the hysocket to join/leave on.
1216 * @param optVal pointer to the InetAddress, the multicast group to join/drop.
1218 * @exception SocketException if an error occurs during the call
1220 static void mcastAddDropMembership (JNIEnv * env, int handle, jobject optVal,
1221 int ignoreIF, int setSockOptVal) {
1222 struct sockaddr_storage sockaddrP;
1224 // By default, let the system decide which interface to use.
1225 int interfaceIndex = 0;
1228 * Check whether we are getting an InetAddress or an Generic IPMreq. For now
1229 * we support both so that we will not break the tests. If an InetAddress
1230 * is passed in, only support IPv4 as obtaining an interface from an
1231 * InetAddress is complex and should be done by the Java caller.
1233 if (env->IsInstanceOf (optVal, gCachedFields.iaddr_class)) {
1235 * optVal is an InetAddress. Construct a multicast request structure
1236 * from this address. Support IPv4 only.
1238 struct ip_mreqn multicastRequest;
1239 socklen_t length = sizeof(multicastRequest);
1240 memset(&multicastRequest, 0, length);
1242 // If ignoreIF is false, determine the index of the interface to use.
1244 interfaceIndex = interfaceIndexFromMulticastSocket(handle);
1245 multicastRequest.imr_ifindex = interfaceIndex;
1246 if (interfaceIndex == -1) {
1247 throwSocketException(env, convertError(errno));
1252 // Convert the inetAddress to an IPv4 address structure.
1253 result = inetAddressToSocketAddress(env, optVal, 0, &sockaddrP);
1254 if (result < 0) // Exception has already been thrown.
1256 if (sockaddrP.ss_family != AF_INET) {
1257 throwSocketException(env, SOCKERR_BADAF);
1260 struct sockaddr_in *sin = (struct sockaddr_in *) &sockaddrP;
1261 multicastRequest.imr_multiaddr = sin->sin_addr;
1263 result = setsockopt(handle, IPPROTO_IP, setSockOptVal,
1264 &multicastRequest, length);
1266 throwSocketException (env, convertError(errno));
1271 * optVal is a GenericIPMreq object. Extract the relevant fields from
1272 * it and construct a multicast request structure from these. Support
1273 * both IPv4 and IPv6.
1276 jfieldID multiaddrID;
1277 jfieldID interfaceIdxID;
1280 // Get the multicast address to join or leave.
1281 cls = env->GetObjectClass(optVal);
1282 multiaddrID = env->GetFieldID(cls, "multiaddr", "Ljava/net/InetAddress;");
1283 multiaddr = env->GetObjectField(optVal, multiaddrID);
1285 // Get the interface index to use.
1287 interfaceIdxID = env->GetFieldID(cls, "interfaceIdx", "I");
1288 interfaceIndex = env->GetIntField(optVal, interfaceIdxID);
1291 result = inetAddressToSocketAddress(env, multiaddr, 0, &sockaddrP);
1292 if (result < 0) // Exception has already been thrown.
1295 struct ip_mreqn ipv4Request;
1296 struct ipv6_mreq ipv6Request;
1297 void *multicastRequest;
1298 socklen_t requestLength;
1300 int family = getSocketAddressFamily(handle);
1303 requestLength = sizeof(ipv4Request);
1304 memset(&ipv4Request, 0, requestLength);
1305 ipv4Request.imr_multiaddr =
1306 ((struct sockaddr_in *) &sockaddrP)->sin_addr;
1307 ipv4Request.imr_ifindex = interfaceIndex;
1308 multicastRequest = &ipv4Request;
1312 requestLength = sizeof(ipv6Request);
1313 memset(&ipv6Request, 0, requestLength);
1314 ipv6Request.ipv6mr_multiaddr =
1315 ((struct sockaddr_in6 *) &sockaddrP)->sin6_addr;
1316 ipv6Request.ipv6mr_ifindex = interfaceIndex;
1317 multicastRequest = &ipv6Request;
1318 level = IPPROTO_IPV6;
1321 throwSocketException (env, SOCKERR_BADAF);
1325 /* join/drop the multicast address */
1326 result = setsockopt(handle, level, setSockOptVal, multicastRequest,
1329 throwSocketException (env, convertError(errno));
1335 static void osNetworkSystem_oneTimeInitializationImpl(JNIEnv* env, jobject obj,
1336 jboolean jcl_supports_ipv6) {
1337 // LOGD("ENTER oneTimeInitializationImpl of OSNetworkSystem");
1339 char useAdbNetworkingProperty[PROPERTY_VALUE_MAX];
1340 char adbConnectedProperty[PROPERTY_VALUE_MAX];
1342 property_get("android.net.use-adb-networking", useAdbNetworkingProperty, "");
1343 property_get("adb.connected", adbConnectedProperty, "");
1345 if (strlen((char *)useAdbNetworkingProperty) > 0
1346 && strlen((char *)adbConnectedProperty) > 0) {
1347 useAdbNetworking = 1;
1350 memset(&gCachedFields, 0, sizeof(gCachedFields));
1352 // initializing InetAddress
1354 jclass iaddrclass = env->FindClass("java/net/InetAddress");
1356 if (iaddrclass == NULL) {
1357 jniThrowException(env, "java/lang/ClassNotFoundException",
1358 "java.net.InetAddress");
1362 gCachedFields.iaddr_class = (jclass) env->NewGlobalRef(iaddrclass);
1364 jmethodID iaddrclassinit = env->GetMethodID(iaddrclass, "<init>", "()V");
1366 if (iaddrclassinit == NULL) {
1367 jniThrowException(env, "java/lang/NoSuchMethodError", "InetAddress.<init>()");
1371 gCachedFields.iaddr_class_init = iaddrclassinit;
1373 jmethodID iaddrgetbyaddress = env->GetStaticMethodID(iaddrclass,
1374 "getByAddress", "([B)Ljava/net/InetAddress;");
1376 if (iaddrgetbyaddress == NULL) {
1377 jniThrowException(env, "java/lang/NoSuchMethodError",
1378 "InetAddress.getByAddress(byte[] val)");
1382 gCachedFields.iaddr_getbyaddress = iaddrgetbyaddress;
1384 jfieldID iaddripaddress = env->GetFieldID(iaddrclass, "ipaddress", "[B");
1386 if (iaddripaddress == NULL) {
1387 jniThrowException(env, "java/lang/NoSuchFieldError",
1388 "Can't find field InetAddress.ipaddress");
1392 gCachedFields.iaddr_ipaddress = iaddripaddress;
1394 // get the GenericIPMreq class
1396 jclass genericipmreqclass = env->FindClass("org/apache/harmony/luni/net/GenericIPMreq");
1398 if (genericipmreqclass == NULL) {
1399 jniThrowException(env, "java/lang/ClassNotFoundException",
1400 "org.apache.harmony.luni.net.GenericIPMreq");
1404 gCachedFields.genericipmreq_class = (jclass) env->NewGlobalRef(genericipmreqclass);
1406 // initializing Integer
1408 jclass integerclass = env->FindClass("java/lang/Integer");
1410 if (integerclass == NULL) {
1411 jniThrowException(env, "java/lang/ClassNotFoundException",
1412 "java.lang.Integer");
1416 jmethodID integerclassinit = env->GetMethodID(integerclass, "<init>", "(I)V");
1418 if (integerclassinit == NULL) {
1419 jniThrowException(env, "java/lang/NoSuchMethodError",
1420 "Integer.<init>(int val)");
1424 jfieldID integerclassvalue = env->GetFieldID(integerclass, "value", "I");
1426 if (integerclassvalue == NULL) {
1427 jniThrowException(env, "java/lang/NoSuchMethodError", "Integer.value");
1431 gCachedFields.integer_class = (jclass) env->NewGlobalRef(integerclass);
1432 gCachedFields.integer_class_init = integerclassinit;
1433 gCachedFields.integer_class_value = integerclassvalue;
1435 // initializing Boolean
1437 jclass booleanclass = env->FindClass("java/lang/Boolean");
1439 if (booleanclass == NULL) {
1440 jniThrowException(env, "java/lang/ClassNotFoundException",
1441 "java.lang.Boolean");
1445 jmethodID booleanclassinit = env->GetMethodID(booleanclass, "<init>", "(Z)V");
1447 if (booleanclassinit == NULL) {
1448 jniThrowException(env, "java/lang/NoSuchMethodError",
1449 "Boolean.<init>(boolean val)");
1453 jfieldID booleanclassvalue = env->GetFieldID(booleanclass, "value", "Z");
1455 if (booleanclassvalue == NULL) {
1456 jniThrowException(env, "java/lang/NoSuchMethodError", "Boolean.value");
1460 gCachedFields.boolean_class = (jclass) env->NewGlobalRef(booleanclass);
1461 gCachedFields.boolean_class_init = booleanclassinit;
1462 gCachedFields.boolean_class_value = booleanclassvalue;
1464 // initializing Byte
1466 jclass byteclass = env->FindClass("java/lang/Byte");
1468 if (byteclass == NULL) {
1469 jniThrowException(env, "java/lang/ClassNotFoundException",
1474 jmethodID byteclassinit = env->GetMethodID(byteclass, "<init>", "(B)V");
1476 if (byteclassinit == NULL) {
1477 jniThrowException(env, "java/lang/NoSuchMethodError",
1478 "Byte.<init>(byte val)");
1482 jfieldID byteclassvalue = env->GetFieldID(byteclass, "value", "B");
1484 if (byteclassvalue == NULL) {
1485 jniThrowException(env, "java/lang/NoSuchMethodError", "Byte.value");
1489 gCachedFields.byte_class = (jclass) env->NewGlobalRef(byteclass);
1490 gCachedFields.byte_class_init = byteclassinit;
1491 gCachedFields.byte_class_value = byteclassvalue;
1493 // initializing String
1495 jclass stringclass = env->FindClass("java/lang/String");
1497 if (stringclass == NULL) {
1498 jniThrowException(env, "java/lang/ClassNotFoundException",
1499 "java.lang.String");
1503 jmethodID stringclassinit = env->GetMethodID(stringclass, "<init>", "([B)V");
1505 if (stringclassinit == NULL) {
1506 jniThrowException(env, "java/lang/NoSuchMethodError",
1507 "String.<init>(byte[] val)");
1511 gCachedFields.string_class = (jclass) env->NewGlobalRef(stringclass);
1512 gCachedFields.string_class_init = stringclassinit;
1514 // initializing ScoketImpl
1516 jclass socketimplclass = env->FindClass("java/net/SocketImpl");
1518 if (socketimplclass == NULL) {
1519 jniThrowException(env, "java/lang/ClassNotFoundException",
1520 "java.net.SocketImpl");
1524 jfieldID socketimplport = env->GetFieldID(socketimplclass, "port", "I");
1526 if (socketimplport == NULL) {
1527 jniThrowException(env, "java/lang/NoSuchFieldError", "SocketImpl.port");
1531 jfieldID socketimpladdress = env->GetFieldID(socketimplclass, "address",
1532 "Ljava/net/InetAddress;");
1534 if (socketimpladdress == NULL) {
1535 jniThrowException(env, "java/lang/NoSuchFieldError",
1536 "SocketImpl.address");
1540 gCachedFields.socketimpl_address = socketimpladdress;
1541 gCachedFields.socketimpl_port = socketimplport;
1543 gCachedFields.dpack_class = env->FindClass("java/net/DatagramPacket");
1544 if (gCachedFields.dpack_class == NULL) {
1545 jniThrowException(env, "java/lang/ClassNotFoundException",
1546 "java.net.DatagramPacket");
1550 gCachedFields.dpack_address = env->GetFieldID(gCachedFields.dpack_class,
1551 "address", "Ljava/net/InetAddress;");
1552 if (gCachedFields.dpack_address == NULL) {
1553 jniThrowException(env, "java/lang/NoSuchFieldError",
1554 "DatagramPacket.address");
1558 gCachedFields.dpack_port = env->GetFieldID(gCachedFields.dpack_class,
1560 if (gCachedFields.dpack_port == NULL) {
1561 jniThrowException(env, "java/lang/NoSuchFieldError",
1562 "DatagramPacket.port");
1566 gCachedFields.dpack_length = env->GetFieldID(gCachedFields.dpack_class,
1568 if (gCachedFields.dpack_length == NULL) {
1569 jniThrowException(env, "java/lang/NoSuchFieldError",
1570 "DatagramPacket.length");
1577 * Helper function to create a socket of the specified type and bind it to a
1578 * Java file descriptor.
1580 * @param fileDescriptor the file descriptor to bind the socket to
1581 * @param type the socket type to create, e.g., SOCK_STREAM
1583 * @return the socket file descriptor, or -1 on failure
1586 static int createSocketFileDescriptor(JNIEnv* env, jobject fileDescriptor,
1588 if (fileDescriptor == NULL) {
1589 throwNullPointerException(env);
1595 sock = socket(PF_INET6, type, 0);
1596 if (sock < 0 && errno == EAFNOSUPPORT) {
1597 sock = socket(PF_INET, type, 0);
1600 int err = convertError(errno);
1601 throwSocketException(env, err);
1603 jniSetFileDescriptorOfFD(env, fileDescriptor, sock);
1608 static void osNetworkSystem_createSocketImpl(JNIEnv* env, jclass clazz,
1609 jobject fileDescriptor, jboolean preferIPv4Stack) {
1610 // LOGD("ENTER createSocketImpl");
1611 createSocketFileDescriptor(env, fileDescriptor, SOCK_STREAM);
1614 static void osNetworkSystem_createDatagramSocketImpl(JNIEnv* env, jclass clazz,
1615 jobject fileDescriptor, jboolean preferIPv4Stack) {
1616 // LOGD("ENTER createDatagramSocketImpl");
1617 createSocketFileDescriptor(env, fileDescriptor, SOCK_DGRAM);
1620 static jint osNetworkSystem_readSocketDirectImpl(JNIEnv* env, jclass clazz,
1621 jobject fileDescriptor, jint address, jint offset, jint count,
1623 // LOGD("ENTER readSocketDirectImpl");
1626 jbyte *message = (jbyte *)address + offset;
1627 int result, ret, localCount;
1629 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1631 if (handle == 0 || handle == -1) {
1632 throwSocketException(env, SOCKERR_BADSOCKET);
1636 result = selectWait(handle, timeout, SELECT_READ_TYPE);
1642 localCount = (count < 65536) ? count : 65536;
1645 ret = recv(handle, (jbyte *) message, localCount, SOCKET_NOFLAGS);
1646 } while (ret < 0 && errno == EINTR);
1650 } else if (ret == -1) {
1651 int err = convertError(errno);
1652 log_socket_close(handle, err);
1653 throwSocketException(env, err);
1656 add_recv_stats(handle, ret);
1660 static jint osNetworkSystem_readSocketImpl(JNIEnv* env, jclass clazz,
1661 jobject fileDescriptor, jbyteArray data, jint offset, jint count,
1663 // LOGD("ENTER readSocketImpl");
1666 int result, localCount;
1668 jbyte internalBuffer[BUFFERSIZE];
1670 localCount = (count < 65536) ? count : 65536;
1672 if (localCount > BUFFERSIZE) {
1673 message = (jbyte*)malloc(localCount * sizeof(jbyte));
1674 if (message == NULL) {
1675 jniThrowException(env, "java/lang/OutOfMemoryError",
1676 "couldn't allocate enough memory for readSocket");
1680 message = (jbyte *)internalBuffer;
1683 result = osNetworkSystem_readSocketDirectImpl(env, clazz, fileDescriptor,
1684 (jint) message, 0, localCount, timeout);
1687 env->SetByteArrayRegion(data, offset, result, (jbyte *)message);
1690 if (((jbyte *)message) != internalBuffer) {
1691 free(( jbyte *)message);
1697 static jint osNetworkSystem_writeSocketDirectImpl(JNIEnv* env, jclass clazz,
1698 jobject fileDescriptor, jint address, jint offset, jint count) {
1699 // LOGD("ENTER writeSocketDirectImpl");
1702 jbyte *message = (jbyte *)address + offset;
1703 int result = 0, sent = 0;
1709 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1711 if (handle == 0 || handle == -1) {
1712 throwSocketException(env, SOCKERR_BADSOCKET);
1716 result = send(handle, (jbyte *) message, (int) count, SOCKET_NOFLAGS);
1718 int err = convertError(errno);
1719 log_socket_close(handle, err);
1721 if (SOCKERR_WOULDBLOCK == err){
1722 jclass socketExClass,errorCodeExClass;
1723 jmethodID errorCodeExConstructor, socketExConstructor,socketExCauseMethod;
1724 jobject errorCodeEx, socketEx;
1725 const char* errorMessage = netLookupErrorString(err);
1726 jstring errorMessageString = env->NewStringUTF(errorMessage);
1728 errorCodeExClass = env->FindClass("org/apache/harmony/luni/util/ErrorCodeException");
1729 if (!errorCodeExClass){
1732 errorCodeExConstructor = env->GetMethodID(errorCodeExClass,"<init>","(I)V");
1733 if (!errorCodeExConstructor){
1736 errorCodeEx = env->NewObject(errorCodeExClass,errorCodeExConstructor,err);
1738 socketExClass = env->FindClass("java/net/SocketException");
1739 if (!socketExClass) {
1742 socketExConstructor = env->GetMethodID(socketExClass,"<init>","(Ljava/lang/String;)V");
1743 if (!socketExConstructor) {
1746 socketEx = env->NewObject(socketExClass, socketExConstructor, errorMessageString);
1747 socketExCauseMethod = env->GetMethodID(socketExClass,"initCause","(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
1748 env->CallObjectMethod(socketEx,socketExCauseMethod,errorCodeEx);
1749 env->Throw((jthrowable)socketEx);
1752 throwSocketException(env, err);
1756 add_send_stats(handle, result);
1760 static jint osNetworkSystem_writeSocketImpl(JNIEnv* env, jclass clazz,
1761 jobject fileDescriptor, jbyteArray data, jint offset, jint count) {
1762 // LOGD("ENTER writeSocketImpl");
1768 /* TODO: ARRAY PINNING */
1769 #define INTERNAL_SEND_BUFFER_MAX 512
1770 jbyte internalBuffer[INTERNAL_SEND_BUFFER_MAX];
1772 if (count > INTERNAL_SEND_BUFFER_MAX) {
1773 message = (jbyte*)malloc(count * sizeof( jbyte));
1774 if (message == NULL) {
1775 jniThrowException(env, "java/lang/OutOfMemoryError",
1776 "couldn't allocate enough memory for writeSocket");
1780 message = (jbyte *)internalBuffer;
1783 env->GetByteArrayRegion(data, offset, count, message);
1785 result = osNetworkSystem_writeSocketDirectImpl(env, clazz, fileDescriptor,
1786 (jint) message, 0, count);
1788 if (( jbyte *)message != internalBuffer) {
1789 free(( jbyte *)message);
1791 #undef INTERNAL_SEND_BUFFER_MAX
1795 static void osNetworkSystem_setNonBlockingImpl(JNIEnv* env, jclass clazz,
1796 jobject fileDescriptor, jboolean nonblocking) {
1797 // LOGD("ENTER setNonBlockingImpl");
1802 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1804 if (handle == 0 || handle == -1) {
1805 throwSocketException(env, SOCKERR_BADSOCKET);
1809 int block = nonblocking;
1811 result = ioctl(handle, FIONBIO, &block);
1814 throwSocketException(env, convertError(errno));
1818 static jint osNetworkSystem_connectSocketImpl(JNIEnv* env, jclass clazz,
1819 jobject fileDescriptor, jint trafficClass, jobject inetAddr, jint port);
1821 static jint osNetworkSystem_connectWithTimeoutSocketImpl(JNIEnv* env,
1822 jclass clazz, jobject fileDescriptor, jint timeout, jint trafficClass,
1823 jobject inetAddr, jint port, jint step, jbyteArray passContext) {
1824 // LOGD("ENTER connectWithTimeoutSocketImpl");
1828 struct sockaddr_storage address;
1829 jbyte *context = NULL;
1831 result = inetAddressToSocketAddress(env, inetAddr, port, &address);
1835 // Check if we're using adb networking and redirect in case it is used.
1836 if (useAdbNetworkingForAddress(&address)) {
1837 return osNetworkSystem_connectSocketImpl(env, clazz, fileDescriptor,
1838 trafficClass, inetAddr, port);
1841 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1842 if (handle == 0 || handle == -1) {
1843 throwSocketException(env, SOCKERR_BADDESC);
1847 context = (jbyte *)env->GetPrimitiveArrayCritical(passContext, NULL);
1850 case SOCKET_CONNECT_STEP_START:
1851 result = sockConnectWithTimeout(handle, address, 0,
1852 SOCKET_STEP_START, context);
1854 case SOCKET_CONNECT_STEP_CHECK:
1855 result = sockConnectWithTimeout(handle, address, timeout,
1856 SOCKET_STEP_CHECK, context);
1860 env->ReleasePrimitiveArrayCritical(passContext, context, JNI_ABORT);
1863 /* connected , so stop here */
1864 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, NULL);
1865 } else if (result != SOCKERR_NOTCONNECTED) {
1866 /* can not connect... */
1867 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, NULL);
1868 if (result == SOCKERR_EACCES) {
1869 jniThrowException(env, "java/lang/SecurityException",
1870 netLookupErrorString(result));
1872 jniThrowException(env, "java/net/ConnectException",
1873 netLookupErrorString(result));
1880 static void osNetworkSystem_connectStreamWithTimeoutSocketImpl(JNIEnv* env,
1881 jclass clazz, jobject fileDescriptor, jint remotePort, jint timeout,
1882 jint trafficClass, jobject inetAddr) {
1883 // LOGD("ENTER connectStreamWithTimeoutSocketImpl");
1887 struct sockaddr_storage address;
1888 jbyte *context = NULL;
1889 int remainingTimeout = timeout;
1890 int passedTimeout = 0;
1893 char hasTimeout = timeout > 0;
1895 /* if a timeout was specified calculate the finish time value */
1897 finishTime = time_msec_clock() + (int) timeout;
1900 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1901 if (handle == 0 || handle == -1) {
1902 throwSocketException(env, SOCKERR_BADDESC);
1906 result = inetAddressToSocketAddress(env, inetAddr, remotePort, &address);
1907 if (result < 0) // Exception has already been thrown.
1910 // Check if we're using adb networking and redirect in case it is used.
1911 if (useAdbNetworkingForAddress(&address)) {
1912 int retVal = osNetworkSystem_connectSocketImpl(env, clazz,
1913 fileDescriptor, trafficClass, inetAddr, remotePort);
1915 throwSocketException(env, SOCKERR_BADSOCKET);
1921 * we will be looping checking for when we are connected so allocate
1922 * the descriptor sets that we will use
1924 context =(jbyte *) malloc(sizeof(struct selectFDSet));
1925 if (NULL == context) {
1926 throwSocketException(env, SOCKERR_NOBUFFERS);
1930 result = sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_START, context);
1932 /* ok we connected right away so we are done */
1933 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, context);
1935 } else if (result != SOCKERR_NOTCONNECTED) {
1936 log_socket_close(handle, result);
1937 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE,
1939 /* we got an error other than NOTCONNECTED so we cannot continue */
1940 if (SOCKERR_EACCES == result) {
1941 jniThrowException(env, "java/lang/SecurityException",
1942 netLookupErrorString(result));
1944 throwSocketException(env, result);
1949 while (SOCKERR_NOTCONNECTED == result) {
1950 passedTimeout = remainingTimeout;
1953 * ok now try and connect. Depending on the platform this may sleep
1954 * for up to passedTimeout milliseconds
1956 result = sockConnectWithTimeout(handle, address, passedTimeout,
1957 SOCKET_STEP_CHECK, context);
1960 * now check if the socket is still connected.
1961 * Do it here as some platforms seem to think they
1962 * are connected if the socket is closed on them.
1964 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1965 if (handle == 0 || handle == -1) {
1966 sockConnectWithTimeout(handle, address, 0,
1967 SOCKET_STEP_DONE, context);
1968 throwSocketException(env, SOCKERR_BADSOCKET);
1973 * check if we are now connected,
1974 * if so we can finish the process and return
1977 sockConnectWithTimeout(handle, address, 0,
1978 SOCKET_STEP_DONE, context);
1983 * if the error is SOCKERR_NOTCONNECTED then we have not yet
1984 * connected and we may not be done yet
1986 if (SOCKERR_NOTCONNECTED == result) {
1987 /* check if the timeout has expired */
1989 remainingTimeout = finishTime - time_msec_clock();
1990 if (remainingTimeout <= 0) {
1991 log_socket_close(handle, result);
1992 sockConnectWithTimeout(handle, address, 0,
1993 SOCKET_STEP_DONE, context);
1994 jniThrowException(env,
1995 "java/net/SocketTimeoutException",
1996 netLookupErrorString(result));
2000 remainingTimeout = 100;
2003 log_socket_close(handle, result);
2004 sockConnectWithTimeout(handle, address, remainingTimeout,
2005 SOCKET_STEP_DONE, context);
2006 if ((SOCKERR_CONNRESET == result) ||
2007 (SOCKERR_CONNECTION_REFUSED == result) ||
2008 (SOCKERR_ADDRNOTAVAIL == result) ||
2009 (SOCKERR_ADDRINUSE == result) ||
2010 (SOCKERR_ENETUNREACH == result)) {
2011 jniThrowException(env, "java/net/ConnectException",
2012 netLookupErrorString(result));
2013 } else if (SOCKERR_EACCES == result) {
2014 jniThrowException(env, "java/lang/SecurityException",
2015 netLookupErrorString(result));
2017 throwSocketException(env, result);
2025 /* free the memory for the FD set */
2026 if (context != NULL) {
2031 static jint osNetworkSystem_connectSocketImpl(JNIEnv* env, jclass clazz,
2032 jobject fileDescriptor, jint trafficClass, jobject inetAddr, jint port) {
2033 //LOGD("ENTER direct-call connectSocketImpl\n");
2035 struct sockaddr_storage address;
2039 ret = inetAddressToSocketAddress(env, inetAddr, port, &address);
2043 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2044 if (handle == 0 || handle == -1) {
2045 throwSocketException(env, SOCKERR_BADDESC);
2049 if (useAdbNetworkingForAddress(&address)) {
2051 // LOGD("+connect to address 0x%08x port %d (via adb)",
2052 // address.sin_addr.s_addr, (int) port);
2053 ret = adb_networking_connect_fd(handle, (struct sockaddr_in *) &address);
2054 // LOGD("-connect ret %d errno %d (via adb)", ret, errno);
2058 // call this method with a timeout of zero
2059 osNetworkSystem_connectStreamWithTimeoutSocketImpl(env, clazz,
2060 fileDescriptor, port, 0, trafficClass, inetAddr);
2061 if (env->ExceptionOccurred() != 0) {
2070 jniThrowException(env, "java/net/ConnectException",
2071 netLookupErrorString(convertError(errno)));
2078 static void osNetworkSystem_socketBindImpl(JNIEnv* env, jclass clazz,
2079 jobject fileDescriptor, jint port, jobject inetAddress) {
2080 // LOGD("ENTER socketBindImpl");
2082 struct sockaddr_storage sockaddress;
2086 ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddress);
2090 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2091 if (handle == 0 || handle == -1) {
2092 throwSocketException(env, SOCKERR_BADDESC);
2097 ret = bind(handle, (const sockaddr*) &sockaddress, sizeof(sockaddress));
2098 } while (ret < 0 && errno == EINTR);
2100 jniThrowException(env, "java/net/BindException",
2101 netLookupErrorString(convertError(errno)));
2106 static void osNetworkSystem_listenStreamSocketImpl(JNIEnv* env, jclass clazz,
2107 jobject fileDescriptor, jint backlog) {
2108 // LOGD("ENTER listenStreamSocketImpl");
2113 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2115 if (handle == 0 || handle == -1) {
2116 throwSocketException(env, SOCKERR_BADSOCKET);
2120 ret = listen(handle, backlog);
2123 int err = convertError(errno);
2124 log_socket_close(handle, err);
2125 throwSocketException(env, err);
2130 static jint osNetworkSystem_availableStreamImpl(JNIEnv* env, jclass clazz,
2131 jobject fileDescriptor) {
2132 // LOGD("ENTER availableStreamImpl");
2135 char message[BUFFERSIZE];
2139 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2140 if (handle == 0 || handle == -1) {
2141 throwSocketException(env, SOCKERR_BADDESC);
2146 result = selectWait(handle, 1, SELECT_READ_TYPE);
2148 if (SOCKERR_TIMEOUT == result) {
2149 // The read operation timed out, so answer 0 bytes available
2151 } else if (SOCKERR_INTERRUPTED == result) {
2153 } else if (0 > result) {
2154 log_socket_close(handle, result);
2155 throwSocketException(env, result);
2158 } while (SOCKERR_INTERRUPTED == result);
2160 result = recv(handle, (jbyte *) message, BUFFERSIZE, MSG_PEEK);
2163 int err = convertError(errno);
2164 log_socket_close(handle, err);
2165 throwSocketException(env, err);
2168 add_recv_stats(handle, result);
2172 static void osNetworkSystem_acceptSocketImpl(JNIEnv* env, jclass clazz,
2173 jobject fdServer, jobject newSocket, jobject fdnewSocket, jint timeout) {
2174 // LOGD("ENTER acceptSocketImpl");
2176 struct sockaddr_storage sa;
2184 if (newSocket == NULL) {
2185 throwNullPointerException(env);
2189 result = pollSelectWait(env, fdServer, timeout, SELECT_READ_TYPE);
2194 handle = jniGetFDFromFileDescriptor(env, fdServer);
2195 if (handle == 0 || handle == -1) {
2196 throwSocketException(env, SOCKERR_BADDESC);
2201 addrlen = sizeof(sa);
2202 ret = accept(handle, (struct sockaddr *) &sa, &addrlen);
2203 } while (ret < 0 && errno == EINTR);
2206 int err = convertError(errno);
2207 log_socket_close(handle, err);
2208 throwSocketException(env, err);
2215 * For network sockets, put the peer address and port in instance variables.
2216 * We don't bother to do this for UNIX domain sockets, since most peers are
2219 if (sa.ss_family == AF_INET || sa.ss_family == AF_INET6) {
2220 jobject inetAddress = socketAddressToInetAddress(env, &sa);
2223 newSocket = NULL; // Exception has already been thrown.
2227 env->SetObjectField(newSocket,
2228 gCachedFields.socketimpl_address, inetAddress);
2230 int port = getSocketAddressPort(&sa);
2231 env->SetIntField(newSocket, gCachedFields.socketimpl_port, port);
2234 jniSetFileDescriptorOfFD(env, fdnewSocket, retFD);
2237 static jboolean osNetworkSystem_supportsUrgentDataImpl(JNIEnv* env,
2238 jclass clazz, jobject fileDescriptor) {
2239 // LOGD("ENTER supportsUrgentDataImpl");
2243 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2244 if (handle == 0 || handle == -1) {
2251 static void osNetworkSystem_sendUrgentDataImpl(JNIEnv* env, jclass clazz,
2252 jobject fileDescriptor, jbyte value) {
2253 // LOGD("ENTER sendUrgentDataImpl");
2258 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2259 if (handle == 0 || handle == -1) {
2260 throwSocketException(env, SOCKERR_BADSOCKET);
2264 result = send(handle, (jbyte *) &value, 1, MSG_OOB);
2266 int err = convertError(errno);
2267 log_socket_close(handle, err);
2268 throwSocketException(env, err);
2272 static void osNetworkSystem_connectDatagramImpl2(JNIEnv* env, jclass clazz,
2273 jobject fd, jint port, jint trafficClass, jobject inetAddress) {
2274 // LOGD("ENTER connectDatagramImpl2");
2276 int handle = jniGetFDFromFileDescriptor(env, fd);
2278 struct sockaddr_storage sockAddr;
2281 ret = inetAddressToSocketAddress(env, inetAddress, port, &sockAddr);
2282 if (ret < 0) // Exception has already been thrown.
2285 logSocketConnect(handle, &sockAddr);
2288 ret = connect(handle, (struct sockaddr *) &sockAddr, sizeof(sockAddr));
2289 } while (ret < 0 && errno == EINTR);
2291 int err = convertError(errno);
2292 log_socket_close(handle, err);
2293 throwSocketException(env, err);
2297 static void osNetworkSystem_disconnectDatagramImpl(JNIEnv* env, jclass clazz,
2299 // LOGD("ENTER disconnectDatagramImpl");
2301 int handle = jniGetFDFromFileDescriptor(env, fd);
2303 struct sockaddr_storage sockAddr;
2304 memset(&sockAddr, 0, sizeof(sockAddr));
2305 sockAddr.ss_family = AF_UNSPEC;
2309 result = connect(handle, (struct sockaddr *) &sockAddr,
2311 } while (result < 0 && errno == EINTR);
2313 int err = convertError(errno);
2314 log_socket_close(handle, err);
2315 throwSocketException(env, err);
2319 static jboolean osNetworkSystem_socketBindImpl2(JNIEnv* env, jclass clazz,
2320 jobject fileDescriptor, jint port, jboolean bindToDevice,
2321 jobject inetAddress) {
2322 // LOGD("ENTER socketBindImpl2");
2324 struct sockaddr_storage sockaddress;
2328 ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddress);
2329 if (ret < 0) // Exception has already been thrown.
2332 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2333 if (handle == 0 || handle == -1) {
2334 throwSocketException(env, SOCKERR_BADDESC);
2339 ret = bind(handle, (const sockaddr*) &sockaddress, sizeof(sockaddress));
2340 } while (ret < 0 && errno == EINTR);
2342 int err = convertError(errno);
2343 log_socket_close(handle, err);
2344 jniThrowException(env, "java/net/BindException", netLookupErrorString(err));
2351 static jint osNetworkSystem_peekDatagramImpl(JNIEnv* env, jclass clazz,
2352 jobject fd, jobject sender, jint receiveTimeout) {
2353 // LOGD("ENTER peekDatagramImpl");
2357 int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
2362 int handle = jniGetFDFromFileDescriptor(env, fd);
2363 if (handle == 0 || handle == -1) {
2364 throwSocketException(env, SOCKERR_BADDESC);
2368 struct sockaddr_storage sockAddr;
2369 socklen_t sockAddrLen = sizeof(sockAddr);
2372 length = recvfrom(handle, NULL, 0, MSG_PEEK,
2373 (struct sockaddr *)&sockAddr, &sockAddrLen);
2374 } while (length < 0 && errno == EINTR);
2376 int err = convertError(errno);
2377 log_socket_close(handle, err);
2378 throwSocketException(env, err);
2382 sender = socketAddressToInetAddress(env, &sockAddr);
2383 if (sender == NULL) // Exception has already been thrown.
2386 port = getSocketAddressPort(&sockAddr);
2387 add_recv_stats(handle, length);
2391 static jint osNetworkSystem_receiveDatagramDirectImpl(JNIEnv* env, jclass clazz,
2392 jobject fd, jobject packet, jint address, jint offset, jint length,
2393 jint receiveTimeout, jboolean peek) {
2394 // LOGD("ENTER receiveDatagramDirectImpl");
2396 int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
2401 int handle = jniGetFDFromFileDescriptor(env, fd);
2402 if (handle == 0 || handle == -1) {
2403 throwSocketException(env, SOCKERR_BADDESC);
2407 struct sockaddr_storage sockAddr;
2408 socklen_t sockAddrLen = sizeof(sockAddr);
2410 int mode = peek ? MSG_PEEK : 0;
2412 ssize_t actualLength;
2414 actualLength = recvfrom(handle, (char*)(address + offset), length, mode,
2415 (struct sockaddr *)&sockAddr, &sockAddrLen);
2416 } while (actualLength < 0 && errno == EINTR);
2417 if (actualLength < 0) {
2418 int err = convertError(errno);
2419 log_socket_close(handle, err);
2420 throwSocketException(env, err);
2424 if (packet != NULL) {
2425 jbyteArray addr = socketAddressToAddressBytes(env, &sockAddr);
2426 if (addr == NULL) // Exception has already been thrown.
2428 int port = getSocketAddressPort(&sockAddr);
2429 jobject sender = env->CallStaticObjectMethod(
2430 gCachedFields.iaddr_class, gCachedFields.iaddr_getbyaddress,
2432 env->SetObjectField(packet, gCachedFields.dpack_address, sender);
2433 env->SetIntField(packet, gCachedFields.dpack_port, port);
2434 env->SetIntField(packet, gCachedFields.dpack_length,
2435 (jint) actualLength);
2437 add_recv_stats(handle, actualLength);
2438 return (jint) actualLength;
2441 static jint osNetworkSystem_receiveDatagramImpl(JNIEnv* env, jclass clazz,
2442 jobject fd, jobject packet, jbyteArray data, jint offset, jint length,
2443 jint receiveTimeout, jboolean peek) {
2444 // LOGD("ENTER receiveDatagramImpl");
2446 int localLength = (length < 65536) ? length : 65536;
2447 jbyte *bytes = (jbyte*) malloc(localLength);
2448 if (bytes == NULL) {
2449 jniThrowException(env, "java/lang/OutOfMemoryError",
2450 "couldn't allocate enough memory for receiveDatagram");
2454 int actualLength = osNetworkSystem_receiveDatagramDirectImpl(env, clazz, fd,
2455 packet, (jint)bytes, 0, localLength, receiveTimeout, peek);
2457 if (actualLength > 0) {
2458 env->SetByteArrayRegion(data, offset, actualLength, bytes);
2462 return actualLength;
2465 static jint osNetworkSystem_recvConnectedDatagramDirectImpl(JNIEnv* env,
2466 jclass clazz, jobject fd, jobject packet, jint address, jint offset,
2467 jint length, jint receiveTimeout, jboolean peek) {
2468 // LOGD("ENTER receiveConnectedDatagramDirectImpl");
2470 int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
2476 int handle = jniGetFDFromFileDescriptor(env, fd);
2478 if (handle == 0 || handle == -1) {
2479 throwSocketException(env, SOCKERR_BADSOCKET);
2483 int mode = peek ? MSG_PEEK : 0;
2485 int actualLength = recvfrom(handle,
2486 (char*)(address + offset), length, mode, NULL, NULL);
2488 if (actualLength < 0) {
2489 jniThrowException(env, "java/net/PortUnreachableException", "");
2493 if ( packet != NULL) {
2494 env->SetIntField(packet, gCachedFields.dpack_length, actualLength);
2496 add_recv_stats(handle, actualLength);
2497 return actualLength;
2500 static jint osNetworkSystem_recvConnectedDatagramImpl(JNIEnv* env, jclass clazz,
2501 jobject fd, jobject packet, jbyteArray data, jint offset, jint length,
2502 jint receiveTimeout, jboolean peek) {
2503 // LOGD("ENTER receiveConnectedDatagramImpl");
2505 int localLength = (length < 65536) ? length : 65536;
2506 jbyte *bytes = (jbyte*) malloc(localLength);
2507 if (bytes == NULL) {
2508 jniThrowException(env, "java/lang/OutOfMemoryError",
2509 "couldn't allocate enough memory for recvConnectedDatagram");
2513 int actualLength = osNetworkSystem_recvConnectedDatagramDirectImpl(env,
2514 clazz, fd, packet, (jint)bytes, 0, localLength,
2515 receiveTimeout, peek);
2517 if (actualLength > 0) {
2518 env->SetByteArrayRegion(data, offset, actualLength, bytes);
2522 return actualLength;
2525 static jint osNetworkSystem_sendDatagramDirectImpl(JNIEnv* env, jclass clazz,
2526 jobject fd, jint address, jint offset, jint length, jint port,
2527 jboolean bindToDevice, jint trafficClass, jobject inetAddress) {
2528 // LOGD("ENTER sendDatagramDirectImpl");
2530 int handle = jniGetFDFromFileDescriptor(env, fd);
2532 if (handle == 0 || handle == -1) {
2533 throwSocketException(env, SOCKERR_BADSOCKET);
2537 struct sockaddr_storage receiver;
2538 if (inetAddressToSocketAddress(env, inetAddress, port, &receiver) < 0) {
2539 // Exception has already been thrown.
2545 result = sendto(handle, (char*)(address + offset), length,
2546 SOCKET_NOFLAGS, (struct sockaddr*)&receiver, sizeof(receiver));
2547 } while (result < 0 && errno == EINTR);
2549 int err = convertError(errno);
2550 if ((SOCKERR_CONNRESET == err)
2551 || (SOCKERR_CONNECTION_REFUSED == err)) {
2554 log_socket_close(handle, err);
2555 throwSocketException(env, err);
2559 add_send_stats(handle, result);
2560 return (jint) result;
2563 static jint osNetworkSystem_sendDatagramImpl(JNIEnv* env, jclass clazz,
2564 jobject fd, jbyteArray data, jint offset, jint length, jint port,
2565 jboolean bindToDevice, jint trafficClass, jobject inetAddress) {
2566 // LOGD("ENTER sendDatagramImpl");
2568 jbyte *bytes = env->GetByteArrayElements(data, NULL);
2569 int actualLength = osNetworkSystem_sendDatagramDirectImpl(env, clazz, fd,
2570 (jint)bytes, offset, length, port, bindToDevice, trafficClass,
2572 env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
2574 return actualLength;
2577 static jint osNetworkSystem_sendConnectedDatagramDirectImpl(JNIEnv* env,
2578 jclass clazz, jobject fd, jint address, jint offset, jint length,
2579 jboolean bindToDevice) {
2580 // LOGD("ENTER sendConnectedDatagramDirectImpl");
2582 int handle = jniGetFDFromFileDescriptor(env, fd);
2584 if (handle == 0 || handle == -1) {
2585 throwSocketException(env, SOCKERR_BADSOCKET);
2589 int result = send(handle, (char*)(address + offset), length, 0);
2592 int err = convertError(errno);
2593 if ((SOCKERR_CONNRESET == err) || (SOCKERR_CONNECTION_REFUSED == err)) {
2596 log_socket_close(handle, err);
2597 throwSocketException(env, err);
2601 add_send_stats(handle, length);
2605 static jint osNetworkSystem_sendConnectedDatagramImpl(JNIEnv* env, jclass clazz,
2606 jobject fd, jbyteArray data, jint offset, jint length,
2607 jboolean bindToDevice) {
2608 // LOGD("ENTER sendConnectedDatagramImpl");
2610 jbyte *bytes = env->GetByteArrayElements(data, NULL);
2611 int actualLength = osNetworkSystem_sendConnectedDatagramDirectImpl(env,
2612 clazz, fd, (jint)bytes, offset, length, bindToDevice);
2613 env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
2615 return actualLength;
2618 static void osNetworkSystem_createServerStreamSocketImpl(JNIEnv* env,
2619 jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) {
2620 // LOGD("ENTER createServerStreamSocketImpl");
2622 int handle = createSocketFileDescriptor(env, fileDescriptor, SOCK_STREAM);
2627 setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
2630 static void osNetworkSystem_createMulticastSocketImpl(JNIEnv* env,
2631 jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) {
2632 // LOGD("ENTER createMulticastSocketImpl");
2634 int handle = createSocketFileDescriptor(env, fileDescriptor, SOCK_DGRAM);
2639 // setsockopt(handle, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(jbyte));
2640 setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
2644 * @param timeout in milliseconds. If zero, block until data received
2646 static jint osNetworkSystem_receiveStreamImpl(JNIEnv* env, jclass clazz,
2647 jobject fileDescriptor, jbyteArray data, jint offset, jint count,
2649 // LOGD("ENTER receiveStreamImpl");
2652 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2654 if (handle == 0 || handle == -1) {
2655 throwSocketException(env, SOCKERR_BADSOCKET);
2659 // Cap read length to available buf size
2660 int spaceAvailable = env->GetArrayLength(data) - offset;
2661 int localCount = count < spaceAvailable? count : spaceAvailable;
2664 jbyte *body = env->GetByteArrayElements(data, &isCopy);
2668 tv.tv_sec = timeout / 1000;
2669 tv.tv_usec = (timeout % 1000) * 1000;
2670 setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv,
2671 sizeof(struct timeval));
2674 result = recv(handle, body + offset, localCount, SOCKET_NOFLAGS);
2675 } while (result < 0 && errno == EINTR);
2677 env->ReleaseByteArrayElements(data, body, 0);
2680 * If no bytes are read, return -1 to signal 'endOfFile'
2681 * to the Java input stream
2684 add_recv_stats(handle, result);
2686 } else if (0 == result) {
2689 // If EAGAIN or EWOULDBLOCK, read timed out
2690 if (errno == EAGAIN || errno == EWOULDBLOCK) {
2691 jniThrowException(env, "java/net/SocketTimeoutException",
2692 netLookupErrorString(SOCKERR_TIMEOUT));
2694 int err = convertError(errno);
2695 log_socket_close(handle, err);
2696 throwSocketException(env, err);
2702 static jint osNetworkSystem_sendStreamImpl(JNIEnv* env, jclass clazz,
2703 jobject fileDescriptor, jbyteArray data, jint offset, jint count) {
2704 // LOGD("ENTER sendStreamImpl");
2707 int result = 0, sent = 0;
2710 jbyte *message = env->GetByteArrayElements(data, &isCopy);
2712 // Cap write length to available buf size
2713 int spaceAvailable = env->GetArrayLength(data) - offset;
2714 if (count > spaceAvailable) count = spaceAvailable;
2716 while (sent < count) {
2718 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2719 if (handle == 0 || handle == -1) {
2720 throwSocketException(env,
2721 sent == 0 ? SOCKERR_BADSOCKET : SOCKERR_INTERRUPTED);
2722 env->ReleaseByteArrayElements(data, message, 0);
2726 // LOGD("before select %d", count);
2727 selectWait(handle, SEND_RETRY_TIME, SELECT_WRITE_TYPE);
2728 result = send(handle, (jbyte *)message + offset + sent,
2729 (int) count - sent, SOCKET_NOFLAGS);
2733 if (result == EAGAIN ||result == EWOULDBLOCK) {
2734 // LOGD("write blocked %d", sent);
2737 env->ReleaseByteArrayElements(data, message, 0);
2738 int err = convertError(result);
2739 log_socket_close(handle, err);
2740 throwSocketException(env, err);
2746 env->ReleaseByteArrayElements(data, message, 0);
2747 add_send_stats(handle, sent);
2751 static void osNetworkSystem_shutdownInputImpl(JNIEnv* env, jobject obj,
2752 jobject fileDescriptor) {
2753 // LOGD("ENTER shutdownInputImpl");
2758 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2760 if (handle == 0 || handle == -1) {
2761 throwSocketException(env, SOCKERR_BADSOCKET);
2765 ret = shutdown(handle, SHUT_RD);
2768 int err = convertError(errno);
2769 log_socket_close(handle, err);
2770 throwSocketException(env, err);
2775 static void osNetworkSystem_shutdownOutputImpl(JNIEnv* env, jobject obj,
2776 jobject fileDescriptor) {
2777 // LOGD("ENTER shutdownOutputImpl");
2782 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2784 if (handle == 0 || handle == -1) {
2788 ret = shutdown(handle, SHUT_WR);
2791 int err = convertError(errno);
2792 log_socket_close(handle, err);
2793 throwSocketException(env, err);
2798 static jint osNetworkSystem_sendDatagramImpl2(JNIEnv* env, jclass clazz,
2799 jobject fd, jbyteArray data, jint offset, jint length, jint port,
2800 jobject inetAddress) {
2801 // LOGD("ENTER sendDatagramImpl2");
2804 unsigned short nPort;
2805 int ret = 0, sent = 0;
2807 struct sockaddr_storage sockaddrP;
2809 if (inetAddress != NULL) {
2810 ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddrP);
2811 if (ret < 0) // Exception has already been thrown.
2814 handle = jniGetFDFromFileDescriptor(env, fd);
2815 if (handle == 0 || handle == -1) {
2816 throwSocketException(env, SOCKERR_BADDESC);
2821 message = (jbyte*) malloc(length * sizeof(jbyte));
2822 if (message == NULL) {
2823 jniThrowException(env, "java/lang/OutOfMemoryError",
2824 "couldn't allocate enough memory for readSocket");
2828 env->GetByteArrayRegion(data, offset, length, message);
2830 while (sent < length) {
2831 handle = jniGetFDFromFileDescriptor(env, fd);
2833 if (handle == 0 || handle == -1) {
2834 throwSocketException(env,
2835 sent == 0 ? SOCKERR_BADDESC : SOCKERR_INTERRUPTED);
2842 result = sendto(handle, (char *) (message + sent),
2843 (int) (length - sent), SOCKET_NOFLAGS,
2844 (struct sockaddr *) &sockaddrP, sizeof(sockaddrP));
2845 } while (result < 0 && errno == EINTR);
2847 int err = convertError(errno);
2848 log_socket_close(handle, err);
2849 throwSocketException(env, err);
2858 add_send_stats(handle, sent);
2862 static jint osNetworkSystem_selectImpl(JNIEnv* env, jclass clazz,
2863 jobjectArray readFDArray, jobjectArray writeFDArray, jint countReadC,
2864 jint countWriteC, jintArray outFlags, jlong timeout) {
2865 // LOGD("ENTER selectImpl");
2867 struct timeval timeP;
2871 fd_set *fdset_read,*fdset_write;
2876 unsigned int time_sec = (unsigned int)timeout/1000;
2877 unsigned int time_msec = (unsigned int)(timeout%1000);
2879 fdset_read = (fd_set *)malloc(sizeof(fd_set));
2880 fdset_write = (fd_set *)malloc(sizeof(fd_set));
2882 FD_ZERO(fdset_read);
2883 FD_ZERO(fdset_write);
2885 for (val = 0; val<countReadC; val++) {
2887 gotFD = env->GetObjectArrayElement(readFDArray,val);
2889 handle = jniGetFDFromFileDescriptor(env, gotFD);
2891 FD_SET(handle, fdset_read);
2893 if (0 > (size - handle)) {
2898 for (val = 0; val<countWriteC; val++) {
2900 gotFD = env->GetObjectArrayElement(writeFDArray,val);
2902 handle = jniGetFDFromFileDescriptor(env, gotFD);
2904 FD_SET(handle, fdset_write);
2906 if (0 > (size - handle)) {
2911 /* the size is the max_fd + 1 */
2915 result = SOCKERR_FDSET_SIZEBAD;
2917 /* only set when timeout >= 0 (non-block)*/
2920 timeP.tv_sec = time_sec;
2921 timeP.tv_usec = time_msec*1000;
2923 result = sockSelect(size, fdset_read, fdset_write, NULL, &timeP);
2926 result = sockSelect(size, fdset_read, fdset_write, NULL, NULL);
2931 /*output the result to a int array*/
2932 flagArray = env->GetIntArrayElements(outFlags, &isCopy);
2934 for (val=0; val<countReadC; val++) {
2935 gotFD = env->GetObjectArrayElement(readFDArray,val);
2937 handle = jniGetFDFromFileDescriptor(env, gotFD);
2939 if (FD_ISSET(handle,fdset_read)) {
2940 flagArray[val] = SOCKET_OP_READ;
2942 flagArray[val] = SOCKET_OP_NONE;
2946 for (val=0; val<countWriteC; val++) {
2948 gotFD = env->GetObjectArrayElement(writeFDArray,val);
2950 handle = jniGetFDFromFileDescriptor(env, gotFD);
2952 if (FD_ISSET(handle,fdset_write)) {
2953 flagArray[val+countReadC] = SOCKET_OP_WRITE;
2955 flagArray[val+countReadC] = SOCKET_OP_NONE;
2959 env->ReleaseIntArrayElements(outFlags, flagArray, 0);
2965 /* return both correct and error result, let java handle the exception*/
2969 static jobject osNetworkSystem_getSocketLocalAddressImpl(JNIEnv* env,
2970 jclass clazz, jobject fileDescriptor, jboolean preferIPv6Addresses) {
2971 // LOGD("ENTER getSocketLocalAddressImpl");
2973 struct sockaddr_storage addr;
2974 socklen_t addrLen = sizeof(addr);
2976 memset(&addr, 0, addrLen);
2979 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2980 if (handle == 0 || handle == -1) {
2981 throwSocketException(env, SOCKERR_UNKNOWNSOCKET);
2986 result = getsockname(handle, (struct sockaddr *)&addr, &addrLen);
2988 // Spec says ignore all errors
2989 return socketAddressToInetAddress(env, &addr);
2992 static jint osNetworkSystem_getSocketLocalPortImpl(JNIEnv* env, jclass clazz,
2993 jobject fileDescriptor, jboolean preferIPv6Addresses) {
2994 // LOGD("ENTER getSocketLocalPortImpl");
2996 struct sockaddr_storage addr;
2997 socklen_t addrLen = sizeof(addr);
2999 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
3002 if (handle == 0 || handle == -1) {
3003 throwSocketException(env, SOCKERR_UNKNOWNSOCKET);
3007 result = getsockname(handle, (struct sockaddr *)&addr, &addrLen);
3010 // The java spec does not indicate any exceptions on this call
3013 return getSocketAddressPort(&addr);
3017 static jobject osNetworkSystem_getSocketOptionImpl(JNIEnv* env, jclass clazz,
3018 jobject fileDescriptor, jint anOption) {
3019 // LOGD("ENTER getSocketOptionImpl");
3023 socklen_t intSize = sizeof(int);
3024 unsigned char byteValue = 0;
3025 socklen_t byteSize = sizeof(unsigned char);
3027 struct sockaddr_storage sockVal;
3028 socklen_t sockSize = sizeof(sockVal);
3030 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
3031 if (handle == 0 || handle == -1) {
3032 throwSocketException(env, SOCKERR_BADDESC);
3036 switch ((int) anOption & 0xffff) {
3037 case JAVASOCKOPT_SO_LINGER: {
3038 struct linger lingr;
3039 socklen_t size = sizeof(struct linger);
3040 result = getsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr, &size);
3042 throwSocketException(env, convertError(errno));
3045 if (!lingr.l_onoff) {
3048 intValue = lingr.l_linger;
3050 return newJavaLangInteger(env, intValue);
3052 case JAVASOCKOPT_TCP_NODELAY: {
3053 if ((anOption >> 16) & BROKEN_TCP_NODELAY) {
3056 result = getsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intValue, &intSize);
3058 throwSocketException(env, convertError(errno));
3061 return newJavaLangBoolean(env, intValue);
3063 case JAVASOCKOPT_MCAST_TTL: {
3064 if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
3065 return newJavaLangByte(env, 0);
3067 result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_MULTICAST_TTL,
3068 IPV6_MULTICAST_HOPS, &byteValue,
3071 throwSocketException(env, convertError(errno));
3074 return newJavaLangByte(env, (jbyte)(byteValue & 0xFF));
3076 case JAVASOCKOPT_MCAST_INTERFACE: {
3077 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3080 result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, &sockVal, &sockSize);
3082 throwSocketException(env, convertError(errno));
3085 // This option is IPv4-only.
3086 sockVal.ss_family = AF_INET;
3087 return socketAddressToInetAddress(env, &sockVal);
3089 case JAVASOCKOPT_IP_MULTICAST_IF2: {
3090 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3093 struct ip_mreqn multicastRequest;
3095 socklen_t optionLength;
3096 int addressFamily = getSocketAddressFamily(handle);
3097 switch (addressFamily) {
3099 optionLength = sizeof(multicastRequest);
3100 result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
3101 &multicastRequest, &optionLength);
3103 interfaceIndex = multicastRequest.imr_ifindex;
3106 optionLength = sizeof(interfaceIndex);
3107 result = getsockopt(handle, IPPROTO_IPV6, IPV6_MULTICAST_IF,
3108 &interfaceIndex, &optionLength);
3111 throwSocketException(env, SOCKERR_BADAF);
3116 throwSocketException(env, convertError(errno));
3120 return newJavaLangInteger(env, interfaceIndex);
3122 case JAVASOCKOPT_SO_SNDBUF: {
3123 result = getsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intValue, &intSize);
3125 throwSocketException(env, convertError(errno));
3128 return newJavaLangInteger(env, intValue);
3130 case JAVASOCKOPT_SO_RCVBUF: {
3131 result = getsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intValue, &intSize);
3133 throwSocketException(env, convertError(errno));
3136 return newJavaLangInteger(env, intValue);
3138 case JAVASOCKOPT_SO_BROADCAST: {
3139 result = getsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intValue, &intSize);
3141 throwSocketException(env, convertError(errno));
3144 return newJavaLangBoolean(env, intValue);
3146 case JAVASOCKOPT_SO_REUSEADDR: {
3147 result = getsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intValue, &intSize);
3149 throwSocketException(env, convertError(errno));
3152 return newJavaLangBoolean(env, intValue);
3154 case JAVASOCKOPT_SO_KEEPALIVE: {
3155 result = getsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intValue, &intSize);
3157 throwSocketException(env, convertError(errno));
3160 return newJavaLangBoolean(env, intValue);
3162 case JAVASOCKOPT_SO_OOBINLINE: {
3163 result = getsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intValue, &intSize);
3165 throwSocketException(env, convertError(errno));
3168 return newJavaLangBoolean(env, intValue);
3170 case JAVASOCKOPT_IP_MULTICAST_LOOP: {
3171 result = getOrSetSocketOption(SOCKOPT_GET, handle,
3173 IPV6_MULTICAST_LOOP, &intValue,
3176 throwSocketException(env, convertError(errno));
3179 return newJavaLangBoolean(env, intValue);
3181 case JAVASOCKOPT_IP_TOS: {
3182 result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_TOS,
3183 IPV6_TCLASS, &intValue, &intSize);
3185 throwSocketException(env, convertError(errno));
3188 return newJavaLangInteger(env, intValue);
3190 case JAVASOCKOPT_SO_RCVTIMEOUT: {
3191 struct timeval timeout;
3192 socklen_t size = sizeof(timeout);
3193 result = getsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout, &size);
3195 throwSocketException(env, convertError(errno));
3198 return newJavaLangInteger(env, timeout.tv_sec * 1000 + timeout.tv_usec/1000);
3201 throwSocketException(env, SOCKERR_OPTUNSUPP);
3208 static void osNetworkSystem_setSocketOptionImpl(JNIEnv* env, jclass clazz,
3209 jobject fileDescriptor, jint anOption, jobject optVal) {
3210 // LOGD("ENTER setSocketOptionImpl");
3213 int intVal, intSize = sizeof(int);
3214 unsigned char byteVal;
3215 socklen_t byteSize = sizeof(unsigned char);
3216 struct sockaddr_storage sockVal;
3217 int sockSize = sizeof(sockVal);
3219 if (env->IsInstanceOf(optVal, gCachedFields.integer_class)) {
3220 intVal = (int) env->GetIntField(optVal, gCachedFields.integer_class_value);
3221 } else if (env->IsInstanceOf(optVal, gCachedFields.boolean_class)) {
3222 intVal = (int) env->GetBooleanField(optVal, gCachedFields.boolean_class_value);
3223 } else if (env->IsInstanceOf(optVal, gCachedFields.byte_class)) {
3224 byteVal = (int) env->GetByteField(optVal, gCachedFields.byte_class_value);
3225 } else if (env->IsInstanceOf(optVal, gCachedFields.iaddr_class)) {
3226 if (inetAddressToSocketAddress(env, optVal, 0, &sockVal) < 0) {
3227 // Exception has already been thrown.
3230 } else if (env->IsInstanceOf(optVal, gCachedFields.genericipmreq_class)) {
3231 // we'll use optVal directly
3233 throwSocketException(env, SOCKERR_OPTUNSUPP);
3237 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
3238 if (handle == 0 || handle == -1) {
3239 throwSocketException(env, SOCKERR_BADDESC);
3243 switch ((int) anOption & 0xffff) {
3244 case JAVASOCKOPT_SO_LINGER: {
3245 struct linger lingr;
3246 lingr.l_onoff = intVal > 0 ? 1 : 0;
3247 lingr.l_linger = intVal;
3248 result = setsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr,
3249 sizeof(struct linger));
3251 throwSocketException(env, convertError(errno));
3257 case JAVASOCKOPT_TCP_NODELAY: {
3258 if ((anOption >> 16) & BROKEN_TCP_NODELAY) {
3261 result = setsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intVal, intSize);
3263 throwSocketException(env, convertError(errno));
3269 case JAVASOCKOPT_MCAST_TTL: {
3270 if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
3273 result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_MULTICAST_TTL,
3274 IPV6_MULTICAST_HOPS, &byteVal,
3277 throwSocketException(env, convertError(errno));
3283 case JAVASOCKOPT_MCAST_ADD_MEMBERSHIP: {
3284 mcastAddDropMembership(env, handle, optVal,
3285 (anOption >> 16) & BROKEN_MULTICAST_IF, IP_ADD_MEMBERSHIP);
3289 case JAVASOCKOPT_MCAST_DROP_MEMBERSHIP: {
3290 mcastAddDropMembership(env, handle, optVal,
3291 (anOption >> 16) & BROKEN_MULTICAST_IF, IP_DROP_MEMBERSHIP);
3295 case JAVASOCKOPT_MCAST_INTERFACE: {
3296 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3299 // This call is IPv4 only.
3300 if (getSocketAddressFamily(handle) != AF_INET) {
3301 throwSocketException(env, SOCKERR_BADAF);
3304 struct ip_mreqn mcast_req;
3305 memset(&mcast_req, 0, sizeof(mcast_req));
3306 struct sockaddr_in *sin = (struct sockaddr_in *) &sockVal;
3307 mcast_req.imr_address = sin->sin_addr;
3308 result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
3309 &mcast_req, sizeof(mcast_req));
3311 throwSocketException(env, convertError(errno));
3317 case JAVASOCKOPT_IP_MULTICAST_IF2: {
3318 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3321 int addressFamily = getSocketAddressFamily(handle);
3322 int interfaceIndex = intVal;
3324 socklen_t optionLength;
3325 struct ip_mreqn multicastRequest;
3326 switch (addressFamily) {
3328 // IP_MULTICAST_IF expects a pointer to a struct ip_mreqn.
3329 memset(&multicastRequest, 0, sizeof(multicastRequest));
3330 multicastRequest.imr_ifindex = interfaceIndex;
3331 optionValue = &multicastRequest;
3332 optionLength = sizeof(multicastRequest);
3335 // IPV6_MULTICAST_IF expects a pointer to an integer.
3336 optionValue = &interfaceIndex;
3337 optionLength = sizeof(interfaceIndex);
3340 throwSocketException(env, SOCKERR_BADAF);
3343 result = getOrSetSocketOption(SOCKOPT_SET, handle,
3344 IP_MULTICAST_IF, IPV6_MULTICAST_IF, optionValue,
3347 throwSocketException(env, convertError(errno));
3353 case JAVASOCKOPT_SO_SNDBUF: {
3354 result = setsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intVal, intSize);
3356 throwSocketException(env, convertError(errno));
3362 case JAVASOCKOPT_SO_RCVBUF: {
3363 result = setsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intVal, intSize);
3365 throwSocketException(env, convertError(errno));
3371 case JAVASOCKOPT_SO_BROADCAST: {
3372 result = setsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intVal, intSize);
3374 throwSocketException(env, convertError(errno));
3380 case JAVASOCKOPT_SO_REUSEADDR: {
3381 result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
3383 throwSocketException(env, convertError(errno));
3388 case JAVASOCKOPT_SO_KEEPALIVE: {
3389 result = setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intVal, intSize);
3391 throwSocketException(env, convertError(errno));
3397 case JAVASOCKOPT_SO_OOBINLINE: {
3398 result = setsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intVal, intSize);
3400 throwSocketException(env, convertError(errno));
3406 case JAVASOCKOPT_IP_MULTICAST_LOOP: {
3407 result = getOrSetSocketOption(SOCKOPT_SET, handle,
3409 IPV6_MULTICAST_LOOP, &intVal,
3412 throwSocketException(env, convertError(errno));
3418 case JAVASOCKOPT_IP_TOS: {
3419 result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_TOS,
3420 IPV6_TCLASS, &intVal, &intSize);
3422 throwSocketException(env, convertError(errno));
3428 case JAVASOCKOPT_REUSEADDR_AND_REUSEPORT: {
3429 // SO_REUSEPORT doesn't need to get set on this System
3430 result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
3432 throwSocketException(env, convertError(errno));
3438 case JAVASOCKOPT_SO_RCVTIMEOUT: {
3439 struct timeval timeout;
3440 timeout.tv_sec = intVal / 1000;
3441 timeout.tv_usec = (intVal % 1000) * 1000;
3442 result = setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout,
3443 sizeof(struct timeval));
3445 throwSocketException(env, convertError(errno));
3452 throwSocketException(env, SOCKERR_OPTUNSUPP);
3457 static jint osNetworkSystem_getSocketFlagsImpl(JNIEnv* env, jclass clazz) {
3458 // LOGD("ENTER getSocketFlagsImpl");
3460 // Not implemented by harmony
3464 static void osNetworkSystem_socketCloseImpl(JNIEnv* env, jclass clazz,
3465 jobject fileDescriptor) {
3466 // LOGD("ENTER socketCloseImpl");
3468 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
3470 if (handle == 0 || handle == -1) {
3471 throwSocketException(env, SOCKERR_BADSOCKET);
3475 log_socket_close(handle, SOCKET_CLOSE_LOCAL);
3477 jniSetFileDescriptorOfFD(env, fileDescriptor, -1);
3482 static jobject osNetworkSystem_getHostByAddrImpl(JNIEnv* env, jclass clazz,
3483 jbyteArray addrStr) {
3484 // LOGD("ENTER getHostByAddrImpl");
3486 if (addrStr == NULL) {
3487 throwNullPointerException(env);
3491 jstring address = (jstring)newJavaLangString(env, addrStr);
3493 const char* addr = env->GetStringUTFChars(address, NULL);
3495 struct hostent* ent = gethostbyaddr(addr, strlen(addr), AF_INET);
3497 if (ent != NULL && ent->h_name != NULL) {
3498 result = env->NewStringUTF(ent->h_name);
3503 env->ReleaseStringUTFChars(address, addr);
3508 static jobject osNetworkSystem_getHostByNameImpl(JNIEnv* env, jclass clazz,
3509 jstring nameStr, jboolean preferIPv6Addresses) {
3510 // LOGD("ENTER getHostByNameImpl");
3512 if (nameStr == NULL) {
3513 throwNullPointerException(env);
3517 const char* name = env->GetStringUTFChars(nameStr, NULL);
3519 if (useAdbNetworking) {
3526 // LOGD("ADB networking: +gethostbyname '%s'", name);
3528 err = adb_networking_gethostbyname(name, &(outaddr.a));
3530 env->ReleaseStringUTFChars(nameStr, name);
3532 LOGD("ADB networking: -gethostbyname err %d addr 0x%08x %u.%u.%u.%u",
3533 err, (unsigned int)outaddr.a.s_addr,
3534 outaddr.j[0],outaddr.j[1],
3535 outaddr.j[2],outaddr.j[3]);
3541 jbyteArray addr = env->NewByteArray(4);
3542 env->SetByteArrayRegion(addr, 0, 4, outaddr.j);
3547 // normal case...no adb networking
3548 struct hostent* ent = gethostbyname(name);
3550 env->ReleaseStringUTFChars(nameStr, name);
3552 if (ent != NULL && ent->h_length > 0) {
3553 jbyteArray addr = env->NewByteArray(4);
3555 memcpy(v, ent->h_addr, 4);
3556 env->SetByteArrayRegion(addr, 0, 4, v);
3564 static void osNetworkSystem_setInetAddressImpl(JNIEnv* env, jobject obj,
3565 jobject sender, jbyteArray address) {
3566 // LOGD("ENTER setInetAddressImpl");
3568 env->SetObjectField(sender, gCachedFields.iaddr_ipaddress, address);
3571 // TODO: rewrite this method in Java and make it support IPv6.
3572 static jobject osNetworkSystem_inheritedChannelImpl(JNIEnv* env, jobject obj) {
3573 // LOGD("ENTER inheritedChannelImpl");
3577 socklen_t length = sizeof(opt);
3579 struct sockaddr_in local_addr;
3580 struct sockaddr_in remote_addr;
3581 jclass channel_class, socketaddr_class, serverSocket_class, socketImpl_class;
3582 jobject channel_object = NULL, socketaddr_object, serverSocket_object;
3583 jobject fd_object, addr_object, localAddr_object, socketImpl_object;
3584 jfieldID port_field, socketaddr_field, bound_field, fd_field;
3585 jfieldID serverSocket_field, socketImpl_field, addr_field, localAddr_field;
3586 jmethodID channel_new;
3587 jbyteArray addr_array;
3588 struct sockaddr_in *sock;
3591 jboolean jtrue = JNI_TRUE;
3593 if (0 != getsockopt(socket, SOL_SOCKET, SO_TYPE, &opt, &length)) {
3596 if (SOCK_STREAM !=opt && SOCK_DGRAM !=opt) {
3601 length = sizeof(struct sockaddr);
3602 if (0 != getsockname(socket, (struct sockaddr *)&local_addr, &length)) {
3605 if (AF_INET != local_addr.sin_family || length != sizeof(struct sockaddr)) {
3608 localAddr = (jbyte*) malloc(sizeof(jbyte)*4);
3609 if (NULL == localAddr) {
3612 memcpy (localAddr, &(local_addr.sin_addr.s_addr), 4);
3614 if (0 != getpeername(socket, (struct sockaddr *)&remote_addr, &length)) {
3615 remote_addr.sin_port = 0;
3616 remote_addr.sin_addr.s_addr = 0;
3617 address = (jbyte*) malloc(sizeof(jbyte)*4);
3618 bzero(address, sizeof(jbyte)*4);
3620 if (AF_INET != remote_addr.sin_family
3621 || length != sizeof(struct sockaddr)) {
3624 address = (jbyte*) malloc(sizeof(jbyte)*4);
3625 memcpy (address, &(remote_addr.sin_addr.s_addr), 4);
3628 // analysis end, begin pack to java
3629 if (SOCK_STREAM == opt) {
3630 if (remote_addr.sin_port!=0) {
3632 channel_class = env->FindClass(
3633 "org/apache/harmony/nio/internal/SocketChannelImpl");
3634 if (NULL == channel_class) {
3638 channel_new = env->GetMethodID(channel_class, "<init>", "()V");
3639 if (NULL == channel_new) {
3642 channel_object = env->NewObject(channel_class, channel_new);
3643 if (NULL == channel_object) {
3646 // new and set FileDescript
3648 fd_field = env->GetFieldID(channel_class, "fd",
3649 "java/io/FielDescriptor");
3650 fd_object = env->GetObjectField(channel_object, fd_field);
3651 if (NULL == fd_object) {
3655 jniSetFileDescriptorOfFD(env, fd_object, socket);
3658 port_field = env->GetFieldID(channel_class, "localPort", "I");
3659 env->SetIntField(channel_object, port_field,
3660 ntohs(local_addr.sin_port));
3662 // new and set remote addr
3663 addr_object = env->NewObject(gCachedFields.iaddr_class,
3664 gCachedFields.iaddr_class_init);
3665 if (NULL == addr_object) {
3668 socketaddr_class = env->FindClass("java/net/InetSocketAddress");
3669 socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
3670 "Ljava/net/InetSocketAddress;");
3671 socketaddr_object = env->GetObjectField(channel_object,
3673 if (NULL == socketaddr_object) {
3676 addr_field = env->GetFieldID(socketaddr_class, "addr",
3677 "Ljava/net/InetAddress;");
3678 env->SetObjectField(socketaddr_object, addr_field, addr_object);
3679 addr_array = env->NewByteArray((jsize)4);
3680 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
3681 env->SetObjectField(addr_object, gCachedFields.iaddr_ipaddress,
3685 socketaddr_class = env->FindClass("java/net/InetSocketAddress");
3686 socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
3687 "Ljava/net/InetSocketAddress;");
3688 socketaddr_object = env->GetObjectField(channel_object,
3691 localAddr_field = env->GetFieldID(channel_class, "localAddress",
3692 "Ljava/net/InetAddress;");
3693 localAddr_object = env->NewObject(gCachedFields.iaddr_class,
3694 gCachedFields.iaddr_class_init);
3695 jfieldID socketaddr_field = env->GetFieldID(channel_class,
3696 "connectAddress", "Ljava/net/InetSocketAddress;");
3697 jobject socketaddr_object = env->GetObjectField(channel_object,
3699 env->SetObjectField(socketaddr_object, localAddr_field,
3701 if (NULL == localAddr_object) {
3704 addr_array = env->NewByteArray((jsize)4);
3705 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, localAddr);
3706 env->SetObjectField(localAddr_object, gCachedFields.iaddr_ipaddress,
3711 port_field = env->GetFieldID(socketaddr_class, "port", "I");
3712 env->SetIntField(socketaddr_object, port_field,
3713 ntohs(remote_addr.sin_port));
3716 if (0 != local_addr.sin_port) {
3717 bound_field = env->GetFieldID(channel_class, "isBound", "Z");
3718 env->SetBooleanField(channel_object, bound_field, jtrue);
3723 channel_class = env->FindClass(
3724 "org/apache/harmony/nio/internal/ServerSocketChannelImpl");
3725 if (NULL == channel_class) {
3729 channel_new = env->GetMethodID(channel_class, "<init>", "()V");
3730 if (NULL == channel_new) {
3733 channel_object = env->NewObject(channel_class, channel_new);
3734 if (NULL == channel_object) {
3738 serverSocket_field = env->GetFieldID(channel_class, "socket",
3739 "Ljava/net/ServerSocket;");
3740 serverSocket_class = env->FindClass("Ljava/net/ServerSocket;");
3741 serverSocket_object = env->GetObjectField(channel_object,
3742 serverSocket_field);
3744 if (0 != local_addr.sin_port) {
3745 bound_field = env->GetFieldID(channel_class, "isBound", "Z");
3746 env->SetBooleanField(channel_object, bound_field, jtrue);
3747 bound_field = env->GetFieldID(serverSocket_class, "isBound", "Z");
3748 env->SetBooleanField(serverSocket_object, bound_field, jtrue);
3751 socketImpl_class = env->FindClass("java/net/SocketImpl");
3752 socketImpl_field = env->GetFieldID(channel_class, "impl",
3753 "Ljava/net/SocketImpl;");
3754 socketImpl_object = env->GetObjectField(channel_object,
3756 if (NULL == socketImpl_object) {
3760 localAddr_field = env->GetFieldID(channel_class, "localAddress",
3761 "Ljava/net/InetAddress;");
3762 localAddr_object = env->NewObject(gCachedFields.iaddr_class,
3763 gCachedFields.iaddr_class_init);
3764 if (NULL == localAddr_object) {
3767 env->SetObjectField(socketImpl_object, localAddr_field,
3769 addr_array = env->NewByteArray((jsize)4);
3770 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, localAddr);
3771 env->SetObjectField(localAddr_object,
3772 gCachedFields.iaddr_ipaddress, addr_array);
3775 port_field = env->GetFieldID(socketImpl_class, "localport", "I");
3776 env->SetIntField(socketImpl_object, port_field,
3777 ntohs(local_addr.sin_port));
3781 // new DatagramChannel
3782 channel_class = env->FindClass(
3783 "org/apache/harmony/nio/internal/DatagramChannelImpl");
3784 if (NULL == channel_class) {
3788 channel_new = env->GetMethodID(channel_class, "<init>", "()V");
3789 if (NULL == channel_new) {
3792 channel_object = env->NewObject(channel_class, channel_new);
3793 if (NULL == channel_object) {
3797 // new and set FileDescript
3798 fd_field = env->GetFieldID(channel_class, "fd", "java/io/FileDescriptor");
3799 fd_object = env->GetObjectField(channel_object, fd_field);
3800 if (NULL == fd_object) {
3804 jniSetFileDescriptorOfFD(env, fd_object, socket);
3806 port_field = env->GetFieldID(channel_class, "localPort", "I");
3807 env->SetIntField(channel_object, port_field, ntohs(local_addr.sin_port));
3809 // new and set remote addr
3810 addr_object = env->NewObject(gCachedFields.iaddr_class,
3811 gCachedFields.iaddr_class_init);
3812 if (NULL == addr_object) {
3815 socketaddr_class = env->FindClass("java/net/InetSocketAddress");
3816 socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
3817 "Ljava/net/InetSocketAddress;");
3818 socketaddr_object = env->GetObjectField(channel_object, socketaddr_field);
3819 if (NULL == socketaddr_object) {
3822 addr_field = env->GetFieldID(socketaddr_class, "addr",
3823 "Ljava/net/InetAddress;");
3824 env->SetObjectField(socketaddr_object, addr_field, addr_object);
3825 addr_array = env->NewByteArray((jsize)4);
3826 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
3827 env->SetObjectField(addr_object, gCachedFields.iaddr_ipaddress, addr_array);
3830 if (0 != local_addr.sin_port) {
3831 bound_field = env->GetFieldID(channel_class, "isBound", "Z");
3832 env->SetBooleanField(channel_object, bound_field, jtrue);
3838 return channel_object;
3844 static JNINativeMethod gMethods[] = {
3845 /* name, signature, funcPtr */
3846 { "oneTimeInitializationImpl", "(Z)V", (void*) osNetworkSystem_oneTimeInitializationImpl },
3847 { "createSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createSocketImpl },
3848 { "createDatagramSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createDatagramSocketImpl },
3849 { "readSocketImpl", "(Ljava/io/FileDescriptor;[BIII)I", (void*) osNetworkSystem_readSocketImpl },
3850 { "readSocketDirectImpl", "(Ljava/io/FileDescriptor;IIII)I", (void*) osNetworkSystem_readSocketDirectImpl },
3851 { "writeSocketImpl", "(Ljava/io/FileDescriptor;[BII)I", (void*) osNetworkSystem_writeSocketImpl },
3852 { "writeSocketDirectImpl", "(Ljava/io/FileDescriptor;III)I", (void*) osNetworkSystem_writeSocketDirectImpl },
3853 { "setNonBlockingImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_setNonBlockingImpl },
3854 { "connectSocketImpl", "(Ljava/io/FileDescriptor;ILjava/net/InetAddress;I)I", (void*) osNetworkSystem_connectSocketImpl },
3855 { "connectWithTimeoutSocketImpl", "(Ljava/io/FileDescriptor;IILjava/net/InetAddress;II[B)I", (void*) osNetworkSystem_connectWithTimeoutSocketImpl },
3856 { "connectStreamWithTimeoutSocketImpl","(Ljava/io/FileDescriptor;IIILjava/net/InetAddress;)V", (void*) osNetworkSystem_connectStreamWithTimeoutSocketImpl },
3857 { "socketBindImpl", "(Ljava/io/FileDescriptor;ILjava/net/InetAddress;)V", (void*) osNetworkSystem_socketBindImpl },
3858 { "listenStreamSocketImpl", "(Ljava/io/FileDescriptor;I)V", (void*) osNetworkSystem_listenStreamSocketImpl },
3859 { "availableStreamImpl", "(Ljava/io/FileDescriptor;)I", (void*) osNetworkSystem_availableStreamImpl },
3860 { "acceptSocketImpl", "(Ljava/io/FileDescriptor;Ljava/net/SocketImpl;Ljava/io/FileDescriptor;I)V",(void*) osNetworkSystem_acceptSocketImpl },
3861 { "supportsUrgentDataImpl", "(Ljava/io/FileDescriptor;)Z", (void*) osNetworkSystem_supportsUrgentDataImpl },
3862 { "sendUrgentDataImpl", "(Ljava/io/FileDescriptor;B)V", (void*) osNetworkSystem_sendUrgentDataImpl },
3863 { "connectDatagramImpl2", "(Ljava/io/FileDescriptor;IILjava/net/InetAddress;)V", (void*) osNetworkSystem_connectDatagramImpl2 },
3864 { "disconnectDatagramImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_disconnectDatagramImpl },
3865 { "socketBindImpl2", "(Ljava/io/FileDescriptor;IZLjava/net/InetAddress;)Z", (void*) osNetworkSystem_socketBindImpl2 },
3866 { "peekDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)I", (void*) osNetworkSystem_peekDatagramImpl },
3867 { "receiveDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;[BIIIZ)I", (void*) osNetworkSystem_receiveDatagramImpl },
3868 { "receiveDatagramDirectImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;IIIIZ)I", (void*) osNetworkSystem_receiveDatagramDirectImpl },
3869 { "recvConnectedDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;[BIIIZ)I", (void*) osNetworkSystem_recvConnectedDatagramImpl },
3870 { "recvConnectedDatagramDirectImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;IIIIZ)I", (void*) osNetworkSystem_recvConnectedDatagramDirectImpl },
3871 { "sendDatagramImpl", "(Ljava/io/FileDescriptor;[BIIIZILjava/net/InetAddress;)I", (void*) osNetworkSystem_sendDatagramImpl },
3872 { "sendDatagramDirectImpl", "(Ljava/io/FileDescriptor;IIIIZILjava/net/InetAddress;)I", (void*) osNetworkSystem_sendDatagramDirectImpl },
3873 { "sendConnectedDatagramImpl", "(Ljava/io/FileDescriptor;[BIIZ)I", (void*) osNetworkSystem_sendConnectedDatagramImpl },
3874 { "sendConnectedDatagramDirectImpl", "(Ljava/io/FileDescriptor;IIIZ)I", (void*) osNetworkSystem_sendConnectedDatagramDirectImpl },
3875 { "createServerStreamSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createServerStreamSocketImpl },
3876 { "createMulticastSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createMulticastSocketImpl },
3877 { "receiveStreamImpl", "(Ljava/io/FileDescriptor;[BIII)I", (void*) osNetworkSystem_receiveStreamImpl },
3878 { "sendStreamImpl", "(Ljava/io/FileDescriptor;[BII)I", (void*) osNetworkSystem_sendStreamImpl },
3879 { "shutdownInputImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_shutdownInputImpl },
3880 { "shutdownOutputImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_shutdownOutputImpl },
3881 { "sendDatagramImpl2", "(Ljava/io/FileDescriptor;[BIIILjava/net/InetAddress;)I", (void*) osNetworkSystem_sendDatagramImpl2 },
3882 { "selectImpl", "([Ljava/io/FileDescriptor;[Ljava/io/FileDescriptor;II[IJ)I", (void*) osNetworkSystem_selectImpl },
3883 { "getSocketLocalAddressImpl", "(Ljava/io/FileDescriptor;Z)Ljava/net/InetAddress;", (void*) osNetworkSystem_getSocketLocalAddressImpl },
3884 { "getSocketLocalPortImpl", "(Ljava/io/FileDescriptor;Z)I", (void*) osNetworkSystem_getSocketLocalPortImpl },
3885 { "getSocketOptionImpl", "(Ljava/io/FileDescriptor;I)Ljava/lang/Object;", (void*) osNetworkSystem_getSocketOptionImpl },
3886 { "setSocketOptionImpl", "(Ljava/io/FileDescriptor;ILjava/lang/Object;)V", (void*) osNetworkSystem_setSocketOptionImpl },
3887 { "getSocketFlagsImpl", "()I", (void*) osNetworkSystem_getSocketFlagsImpl },
3888 { "socketCloseImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_socketCloseImpl },
3889 { "getHostByAddrImpl", "([B)Ljava/net/InetAddress;", (void*) osNetworkSystem_getHostByAddrImpl },
3890 { "getHostByNameImpl", "(Ljava/lang/String;Z)Ljava/net/InetAddress;", (void*) osNetworkSystem_getHostByNameImpl },
3891 { "setInetAddressImpl", "(Ljava/net/InetAddress;[B)V", (void*) osNetworkSystem_setInetAddressImpl },
3892 { "inheritedChannelImpl", "()Ljava/nio/channels/Channel;", (void*) osNetworkSystem_inheritedChannelImpl },
3895 int register_org_apache_harmony_luni_platform_OSNetworkSystem(JNIEnv* env) {
3896 return jniRegisterNativeMethods(env,
3897 "org/apache/harmony/luni/platform/OSNetworkSystem",