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/tcp.h>
31 #include <sys/ioctl.h>
34 #include <cutils/properties.h>
35 #include <cutils/adb_networking.h>
36 #include "AndroidSystemNatives.h"
38 // Temporary hack to build on systems that don't have up-to-date libc headers.
40 #define IPV6_TCLASS 67
45 * Error codes for socket operations
47 * @internal SOCKERR* range from -200 to -299 avoid overlap
49 #define SOCKERR_BADSOCKET -200 /* generic error */
50 #define SOCKERR_NOTINITIALIZED -201 /* socket library uninitialized */
51 #define SOCKERR_BADAF -202 /* bad address family */
52 #define SOCKERR_BADPROTO -203 /* bad protocol */
53 #define SOCKERR_BADTYPE -204 /* bad type */
54 #define SOCKERR_SYSTEMBUSY -205 /* system busy handling requests */
55 #define SOCKERR_SYSTEMFULL -206 /* too many sockets */
56 #define SOCKERR_NOTCONNECTED -207 /* socket is not connected */
57 #define SOCKERR_INTERRUPTED -208 /* the call was cancelled */
58 #define SOCKERR_TIMEOUT -209 /* the operation timed out */
59 #define SOCKERR_CONNRESET -210 /* the connection was reset */
60 #define SOCKERR_WOULDBLOCK -211 /* the socket is marked as nonblocking operation would block */
61 #define SOCKERR_ADDRNOTAVAIL -212 /* address not available */
62 #define SOCKERR_ADDRINUSE -213 /* address already in use */
63 #define SOCKERR_NOTBOUND -214 /* the socket is not bound */
64 #define SOCKERR_UNKNOWNSOCKET -215 /* resolution of fileDescriptor to socket failed */
65 #define SOCKERR_INVALIDTIMEOUT -216 /* the specified timeout is invalid */
66 #define SOCKERR_FDSETFULL -217 /* Unable to create an FDSET */
67 #define SOCKERR_TIMEVALFULL -218 /* Unable to create a TIMEVAL */
68 #define SOCKERR_REMSOCKSHUTDOWN -219 /* The remote socket has shutdown gracefully */
69 #define SOCKERR_NOTLISTENING -220 /* listen() was not invoked prior to accept() */
70 #define SOCKERR_NOTSTREAMSOCK -221 /* The socket does not support connection-oriented service */
71 #define SOCKERR_ALREADYBOUND -222 /* The socket is already bound to an address */
72 #define SOCKERR_NBWITHLINGER -223 /* The socket is marked non-blocking & SO_LINGER is non-zero */
73 #define SOCKERR_ISCONNECTED -224 /* The socket is already connected */
74 #define SOCKERR_NOBUFFERS -225 /* No buffer space is available */
75 #define SOCKERR_HOSTNOTFOUND -226 /* Authoritative Answer Host not found */
76 #define SOCKERR_NODATA -227 /* Valid name, no data record of requested type */
77 #define SOCKERR_BOUNDORCONN -228 /* The socket has not been bound or is already connected */
78 #define SOCKERR_OPNOTSUPP -229 /* The socket does not support the operation */
79 #define SOCKERR_OPTUNSUPP -230 /* The socket option is not supported */
80 #define SOCKERR_OPTARGSINVALID -231 /* The socket option arguments are invalid */
81 #define SOCKERR_SOCKLEVELINVALID -232 /* The socket level is invalid */
82 #define SOCKERR_TIMEOUTFAILURE -233
83 #define SOCKERR_SOCKADDRALLOCFAIL -234 /* Unable to allocate the sockaddr structure */
84 #define SOCKERR_FDSET_SIZEBAD -235 /* The calculated maximum size of the file descriptor set is bad */
85 #define SOCKERR_UNKNOWNFLAG -236 /* The flag is unknown */
86 #define SOCKERR_MSGSIZE -237 /* The datagram was too big to fit the specified buffer & was truncated. */
87 #define SOCKERR_NORECOVERY -238 /* The operation failed with no recovery possible */
88 #define SOCKERR_ARGSINVALID -239 /* The arguments are invalid */
89 #define SOCKERR_BADDESC -240 /* The socket argument is not a valid file descriptor */
90 #define SOCKERR_NOTSOCK -241 /* The socket argument is not a socket */
91 #define SOCKERR_HOSTENTALLOCFAIL -242 /* Unable to allocate the hostent structure */
92 #define SOCKERR_TIMEVALALLOCFAIL -243 /* Unable to allocate the timeval structure */
93 #define SOCKERR_LINGERALLOCFAIL -244 /* Unable to allocate the linger structure */
94 #define SOCKERR_IPMREQALLOCFAIL -245 /* Unable to allocate the ipmreq structure */
95 #define SOCKERR_FDSETALLOCFAIL -246 /* Unable to allocate the fdset structure */
96 #define SOCKERR_OPFAILED -247 /* Operation failed */
97 #define SOCKERR_VALUE_NULL -248 /* The value indexed was NULL */
98 #define SOCKERR_CONNECTION_REFUSED -249 /* connection was refused */
99 #define SOCKERR_ENETUNREACH -250 /* network is not reachable */
100 #define SOCKERR_EACCES -251 /* permissions do not allow action on socket */
101 #define SOCKERR_EHOSTUNREACH -252 /* no route to host */
102 #define SOCKERR_EPIPE -253 /* broken pipe */
104 #define JAVASOCKOPT_TCP_NODELAY 1
105 #define JAVASOCKOPT_IP_TOS 3
106 #define JAVASOCKOPT_SO_REUSEADDR 4
107 #define JAVASOCKOPT_SO_KEEPALIVE 8
108 #define JAVASOCKOPT_MCAST_TIME_TO_LIVE 10 /* Currently unused */
109 #define JAVASOCKOPT_SO_BINDADDR 15
110 #define JAVASOCKOPT_MCAST_INTERFACE 16
111 #define JAVASOCKOPT_MCAST_TTL 17
112 #define JAVASOCKOPT_IP_MULTICAST_LOOP 18
113 #define JAVASOCKOPT_MCAST_ADD_MEMBERSHIP 19
114 #define JAVASOCKOPT_MCAST_DROP_MEMBERSHIP 20
115 #define JAVASOCKOPT_IP_MULTICAST_IF2 31
116 #define JAVASOCKOPT_SO_BROADCAST 32
117 #define JAVASOCKOPT_SO_LINGER 128
118 #define JAVASOCKOPT_REUSEADDR_AND_REUSEPORT 10001
119 #define JAVASOCKOPT_SO_SNDBUF 4097
120 #define JAVASOCKOPT_SO_RCVBUF 4098
121 #define JAVASOCKOPT_SO_RCVTIMEOUT 4102
122 #define JAVASOCKOPT_SO_OOBINLINE 4099
124 /* constants for calling multi-call functions */
125 #define SOCKET_STEP_START 10
126 #define SOCKET_STEP_CHECK 20
127 #define SOCKET_STEP_DONE 30
129 #define BROKEN_MULTICAST_IF 1
130 #define BROKEN_MULTICAST_TTL 2
131 #define BROKEN_TCP_NODELAY 4
133 #define SOCKET_CONNECT_STEP_START 0
134 #define SOCKET_CONNECT_STEP_CHECK 1
136 #define SOCKET_OP_NONE 0
137 #define SOCKET_OP_READ 1
138 #define SOCKET_OP_WRITE 2
139 #define SOCKET_READ_WRITE 3
141 #define SOCKET_MSG_PEEK 1
142 #define SOCKET_MSG_OOB 2
144 #define SOCKET_NOFLAGS 0
147 #define BUFFERSIZE 2048
149 // wait for 500000 usec = 0.5 second
150 #define SEND_RETRY_TIME 500000
152 // Local constants for getOrSetSocketOption
153 #define SOCKOPT_GET 1
154 #define SOCKOPT_SET 2
156 struct CachedFields {
157 jfieldID fd_descriptor;
159 jmethodID iaddr_class_init;
160 jmethodID iaddr_getbyaddress;
161 jfieldID iaddr_ipaddress;
162 jclass genericipmreq_class;
163 jclass integer_class;
164 jmethodID integer_class_init;
165 jfieldID integer_class_value;
166 jclass boolean_class;
167 jmethodID boolean_class_init;
168 jfieldID boolean_class_value;
170 jmethodID byte_class_init;
171 jfieldID byte_class_value;
173 jmethodID string_class_init;
174 jfieldID socketimpl_address;
175 jfieldID socketimpl_port;
177 jfieldID dpack_address;
179 jfieldID dpack_length;
182 static int useAdbNetworking = 0;
184 /* needed for connecting with timeout */
185 typedef struct selectFDSet {
193 static const char * netLookupErrorString(int anErrorNum);
196 * Throws an SocketException with the message affiliated with the errorCode.
198 static void throwSocketException(JNIEnv *env, int errorCode) {
199 jniThrowException(env, "java/net/SocketException",
200 netLookupErrorString(errorCode));
204 * Throws an IOException with the given message.
206 static void throwIOExceptionStr(JNIEnv *env, const char *message) {
207 jniThrowException(env, "java/io/IOException", message);
211 * Throws a NullPointerException.
213 static void throwNullPointerException(JNIEnv *env) {
214 jniThrowException(env, "java/lang/NullPointerException", NULL);
218 * Converts a 4-byte array to a native address structure. Throws a
219 * NullPointerException or an IOException in case of error. This is
220 * signaled by a return value of -1. The normal return value is 0.
222 static int javaAddressToStructIn(
223 JNIEnv *env, jbyteArray java_address, struct in_addr *address) {
225 memset(address, 0, sizeof(address));
227 if (java_address == NULL) {
231 if (env->GetArrayLength(java_address) != sizeof(address->s_addr)) {
235 jbyte * java_address_bytes
236 = env->GetByteArrayElements(java_address, NULL);
238 memcpy(&(address->s_addr),
240 sizeof(address->s_addr));
242 env->ReleaseByteArrayElements(java_address, java_address_bytes, JNI_ABORT);
248 * Converts a native address structure to a Java byte array. Throws a
249 * NullPointerException or an IOException in case of error. This is
250 * signaled by a return value of -1. The normal return value is 0.
252 * @param address the sockaddr_storage structure to convert
254 * @exception SocketException the address family is unknown, or out of memory
257 static jbyteArray socketAddressToAddressBytes(JNIEnv *env,
258 struct sockaddr_storage *address) {
261 size_t addressLength;
262 if (address->ss_family == AF_INET) {
263 struct sockaddr_in *sin = (struct sockaddr_in *) address;
264 rawAddress = &sin->sin_addr.s_addr;
266 } else if (address->ss_family == AF_INET6) {
267 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address;
268 rawAddress = &sin6->sin6_addr.s6_addr;
271 throwSocketException(env, SOCKERR_BADAF);
275 jbyteArray byteArray = env->NewByteArray(addressLength);
276 if (byteArray == NULL) {
277 throwSocketException(env, SOCKERR_NOBUFFERS);
280 env->SetByteArrayRegion(byteArray, 0, addressLength, (jbyte *) rawAddress);
286 * Returns the port number in a sockaddr_storage structure.
288 * @param address the sockaddr_storage structure to get the port from
290 * @return the port number, or -1 if the address family is unknown.
292 static int getSocketAddressPort(struct sockaddr_storage *address) {
293 switch (address->ss_family) {
295 return ntohs(((struct sockaddr_in *) address)->sin_port);
297 return ntohs(((struct sockaddr_in6 *) address)->sin6_port);
304 * Converts a native address structure to an InetAddress object.
305 * Throws a NullPointerException or an IOException in case of
306 * error. This is signaled by a return value of -1. The normal
309 * @param sockaddress the sockaddr_storage structure to convert
311 * @return a jobject representing an InetAddress
313 static jobject socketAddressToInetAddress(JNIEnv *env,
314 struct sockaddr_storage *sockaddress) {
316 jbyteArray byteArray = socketAddressToAddressBytes(env, sockaddress);
317 if (byteArray == NULL) // Exception has already been thrown.
320 return env->CallStaticObjectMethod(gCachedFields.iaddr_class,
321 gCachedFields.iaddr_getbyaddress, byteArray);
325 * Converts an InetAddress object and port number to a native address structure.
326 * Throws a NullPointerException or a SocketException in case of
327 * error. This is signaled by a return value of -1. The normal
330 * @param inetaddress the InetAddress object to convert
331 * @param port the port number
332 * @param sockaddress the sockaddr_storage structure to write to
334 * @return 0 on success, -1 on failure
336 * @exception SocketError if the address family is unknown
338 static int inetAddressToSocketAddress(JNIEnv *env,
339 jobject inetaddress, int port, struct sockaddr_storage *sockaddress) {
341 // Get the byte array that stores the IP address bytes in the InetAddress.
342 jbyteArray addressByteArray;
343 addressByteArray = (jbyteArray)env->GetObjectField(inetaddress,
344 gCachedFields.iaddr_ipaddress);
345 if (addressByteArray == NULL) {
346 throwNullPointerException(env);
350 // Get the raw IP address bytes.
351 jbyte *addressBytes = env->GetByteArrayElements(addressByteArray, NULL);
352 if (addressBytes == NULL) {
353 throwNullPointerException(env);
357 // Convert the IP address bytes to the proper IP address type.
358 size_t addressLength = env->GetArrayLength(addressByteArray);
360 if (addressLength == 4) {
362 struct sockaddr_in *sin = (struct sockaddr_in *) sockaddress;
363 memset(sin, 0, sizeof(struct sockaddr_in));
364 sin->sin_family = AF_INET;
365 sin->sin_port = htons(port);
366 memcpy(&sin->sin_addr.s_addr, addressBytes, 4);
367 } else if (addressLength == 16) {
369 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sockaddress;
370 memset(sin6, 0, sizeof(struct sockaddr_in6));
371 sin6->sin6_family = AF_INET6;
372 sin6->sin6_port = htons(port);
373 memcpy(&sin6->sin6_addr.s6_addr, addressBytes, 16);
375 // Unknown address family.
376 throwSocketException(env, SOCKERR_BADAF);
379 env->ReleaseByteArrayElements(addressByteArray, addressBytes, 0);
384 * Answer a new java.lang.Boolean object.
386 * @param env pointer to the JNI library
387 * @param anInt the Boolean constructor argument
389 * @return the new Boolean
392 jobject newJavaLangBoolean(JNIEnv * env, jint anInt) {
394 jmethodID tempMethod;
396 tempClass = gCachedFields.boolean_class;
397 tempMethod = gCachedFields.boolean_class_init;
398 return env->NewObject(tempClass, tempMethod, (jboolean) (anInt != 0));
402 * Answer a new java.lang.Byte object.
404 * @param env pointer to the JNI library
405 * @param anInt the Byte constructor argument
407 * @return the new Byte
410 jobject newJavaLangByte(JNIEnv * env, jbyte val) {
412 jmethodID tempMethod;
414 tempClass = gCachedFields.byte_class;
415 tempMethod = gCachedFields.byte_class_init;
416 return env->NewObject(tempClass, tempMethod, val);
420 * Answer a new java.lang.Integer object.
422 * @param env pointer to the JNI library
423 * @param anInt the Integer constructor argument
425 * @return the new Integer
428 jobject newJavaLangInteger(JNIEnv * env, jint anInt) {
430 jmethodID tempMethod;
432 tempClass = gCachedFields.integer_class;
433 tempMethod = gCachedFields.integer_class_init;
434 return env->NewObject(tempClass, tempMethod, anInt);
438 * Answer a new java.lang.String object.
440 * @param env pointer to the JNI library
441 * @param anInt the byte[] constructor argument
443 * @return the new String
446 jobject newJavaLangString(JNIEnv * env, jbyteArray bytes) {
448 jmethodID tempMethod;
450 tempClass = gCachedFields.string_class;
451 tempMethod = gCachedFields.string_class_init;
452 return env->NewObject(tempClass, tempMethod, (jbyteArray) bytes);
456 * Query OS for timestamp.
457 * Retrieve the current value of system clock and convert to milliseconds.
459 * @param[in] portLibrary The port library.
461 * @return 0 on failure, time value in milliseconds on success.
462 * @deprecated Use @ref time_hires_clock and @ref time_hires_delta
464 * technically, this should return I_64 since both timeval.tv_sec and
465 * timeval.tv_usec are long
468 static int time_msec_clock() {
472 gettimeofday(&tp, &tzp);
473 return (tp.tv_sec * 1000) + (tp.tv_usec / 1000);
477 * Check if the passed sockaddr_storage struct contains a localhost address
479 * @param address address pointer to the address to check
481 * @return 0 if the passed address isn't a localhost address
483 static int isLocalHost(struct sockaddr_storage *address) {
484 if (address->ss_family == AF_INET) {
485 struct sockaddr_in *sin = (struct sockaddr_in *) address;
486 return (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK));
487 } else if (address->ss_family == AF_INET6) {
488 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address;
489 return IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr);
496 * Decide whether to use ADB networking for the given socket address.
498 * @param address pointer to sockaddr_storage structure to check
500 * @return true if ADB networking should be used, false otherwise.
502 static bool useAdbNetworkingForAddress(struct sockaddr_storage *address) {
503 return useAdbNetworking && !isLocalHost(address) &&
504 address->ss_family == AF_INET;
508 * Convert a sockaddr_storage structure to a string for logging purposes.
510 * @param address pointer to sockaddr_storage structure to print
512 * @return a string with the textual representation of the address.
514 * @note Returns a statically allocated buffer, so is not thread-safe.
516 static char *socketAddressToString(struct sockaddr_storage *address) {
517 static char invalidString[] = "<invalid>";
518 static char ipString[INET6_ADDRSTRLEN + sizeof("[]:65535")];
520 char tmp[INET6_ADDRSTRLEN];
522 // TODO: getnameinfo seems to want its length parameter to be exactly
523 // sizeof(sockaddr_in) for an IPv4 address and sizeof (sockaddr_in6) for an
524 // IPv6 address. Fix getnameinfo so it accepts sizeof(sockaddr_storage), and
525 // then remove this hack.
526 int size = (address->ss_family == AF_INET) ?
527 sizeof(sockaddr_in) : sizeof(sockaddr_in6);
528 int result = getnameinfo((struct sockaddr *)address,
529 size, tmp, sizeof(tmp), NULL, 0,
533 return invalidString;
535 if (address->ss_family == AF_INET6) {
536 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address;
537 port = ntohs(sin6->sin6_port);
538 sprintf(ipString, "[%s]:%d", tmp, port);
540 } else if (address->ss_family == AF_INET) {
541 struct sockaddr_in *sin = (struct sockaddr_in *) address;
542 port = ntohs(sin->sin_port);
543 sprintf(ipString, "%s:%d", tmp, port);
546 return invalidString;
551 * Answer the errorString corresponding to the errorNumber, if available.
552 * This function will answer a default error string, if the errorNumber is not
555 * This function will have to be reworked to handle internationalization
556 * properly, removing the explicit strings.
558 * @param anErrorNum the error code to resolve to a human readable string
560 * @return a human readable error string
563 static const char * netLookupErrorString(int anErrorNum) {
564 switch (anErrorNum) {
565 case SOCKERR_BADSOCKET:
567 case SOCKERR_NOTINITIALIZED:
568 return "Socket library uninitialized";
570 return "Bad address family";
571 case SOCKERR_BADPROTO:
572 return "Bad protocol";
573 case SOCKERR_BADTYPE:
575 case SOCKERR_SYSTEMBUSY:
576 return "System busy handling requests";
577 case SOCKERR_SYSTEMFULL:
578 return "Too many sockets allocated";
579 case SOCKERR_NOTCONNECTED:
580 return "Socket is not connected";
581 case SOCKERR_INTERRUPTED:
582 return "The system call was cancelled";
583 case SOCKERR_TIMEOUT:
584 return "The operation timed out";
585 case SOCKERR_CONNRESET:
586 return "The connection was reset";
587 case SOCKERR_WOULDBLOCK:
588 return "The nonblocking operation would block";
589 case SOCKERR_ADDRNOTAVAIL:
590 return "The address is not available";
591 case SOCKERR_ADDRINUSE:
592 return "The address is already in use";
593 case SOCKERR_NOTBOUND:
594 return "The socket is not bound";
595 case SOCKERR_UNKNOWNSOCKET:
596 return "Resolution of the FileDescriptor to socket failed";
597 case SOCKERR_INVALIDTIMEOUT:
598 return "The specified timeout is invalid";
599 case SOCKERR_FDSETFULL:
600 return "Unable to create an FDSET";
601 case SOCKERR_TIMEVALFULL:
602 return "Unable to create a TIMEVAL";
603 case SOCKERR_REMSOCKSHUTDOWN:
604 return "The remote socket has shutdown gracefully";
605 case SOCKERR_NOTLISTENING:
606 return "Listen() was not invoked prior to accept()";
607 case SOCKERR_NOTSTREAMSOCK:
608 return "The socket does not support connection-oriented service";
609 case SOCKERR_ALREADYBOUND:
610 return "The socket is already bound to an address";
611 case SOCKERR_NBWITHLINGER:
612 return "The socket is marked non-blocking & SO_LINGER is non-zero";
613 case SOCKERR_ISCONNECTED:
614 return "The socket is already connected";
615 case SOCKERR_NOBUFFERS:
616 return "No buffer space is available";
617 case SOCKERR_HOSTNOTFOUND:
618 return "Authoritative Answer Host not found";
620 return "Valid name, no data record of requested type";
621 case SOCKERR_BOUNDORCONN:
622 return "The socket has not been bound or is already connected";
623 case SOCKERR_OPNOTSUPP:
624 return "The socket does not support the operation";
625 case SOCKERR_OPTUNSUPP:
626 return "The socket option is not supported";
627 case SOCKERR_OPTARGSINVALID:
628 return "The socket option arguments are invalid";
629 case SOCKERR_SOCKLEVELINVALID:
630 return "The socket level is invalid";
631 case SOCKERR_TIMEOUTFAILURE:
632 return "The timeout operation failed";
633 case SOCKERR_SOCKADDRALLOCFAIL:
634 return "Failed to allocate address structure";
635 case SOCKERR_FDSET_SIZEBAD:
636 return "The calculated maximum size of the file descriptor set is bad";
637 case SOCKERR_UNKNOWNFLAG:
638 return "The flag is unknown";
639 case SOCKERR_MSGSIZE:
640 return "The datagram was too big to fit the specified buffer, so truncated";
641 case SOCKERR_NORECOVERY:
642 return "The operation failed with no recovery possible";
643 case SOCKERR_ARGSINVALID:
644 return "The arguments are invalid";
645 case SOCKERR_BADDESC:
646 return "The socket argument is not a valid file descriptor";
647 case SOCKERR_NOTSOCK:
648 return "The socket argument is not a socket";
649 case SOCKERR_HOSTENTALLOCFAIL:
650 return "Unable to allocate the hostent structure";
651 case SOCKERR_TIMEVALALLOCFAIL:
652 return "Unable to allocate the timeval structure";
653 case SOCKERR_LINGERALLOCFAIL:
654 return "Unable to allocate the linger structure";
655 case SOCKERR_IPMREQALLOCFAIL:
656 return "Unable to allocate the ipmreq structure";
657 case SOCKERR_FDSETALLOCFAIL:
658 return "Unable to allocate the fdset structure";
659 case SOCKERR_OPFAILED:
660 return "Operation failed";
661 case SOCKERR_CONNECTION_REFUSED:
662 return "Connection refused";
663 case SOCKERR_ENETUNREACH:
664 return "Network unreachable";
665 case SOCKERR_EHOSTUNREACH:
666 return "No route to host";
668 return "Broken pipe";
670 return "Permission denied (maybe missing INTERNET permission)";
673 LOGE("unknown socket error %d", anErrorNum);
674 return "unknown error";
678 static int convertError(int errorCode) {
681 return SOCKERR_BADDESC;
683 return SOCKERR_NOBUFFERS;
685 return SOCKERR_OPNOTSUPP;
687 return SOCKERR_OPTUNSUPP;
689 return SOCKERR_SOCKLEVELINVALID;
691 return SOCKERR_NOTSOCK;
693 return SOCKERR_INTERRUPTED;
695 return SOCKERR_NOTCONNECTED;
697 return SOCKERR_BADAF;
698 /* note: CONNRESET not included because it has the same
699 * value as ECONNRESET and they both map to SOCKERR_CONNRESET */
701 return SOCKERR_CONNRESET;
703 return SOCKERR_WOULDBLOCK;
704 case EPROTONOSUPPORT:
705 return SOCKERR_BADPROTO;
707 return SOCKERR_ARGSINVALID;
709 return SOCKERR_TIMEOUT;
711 return SOCKERR_CONNECTION_REFUSED;
713 return SOCKERR_ENETUNREACH;
715 return SOCKERR_EACCES;
717 return SOCKERR_EPIPE;
719 return SOCKERR_EHOSTUNREACH;
721 return SOCKERR_ADDRINUSE;
723 return SOCKERR_ADDRNOTAVAIL;
725 return SOCKERR_MSGSIZE;
727 LOGE("unclassified errno %d (%s)", errorCode, strerror(errorCode));
728 return SOCKERR_OPFAILED;
732 static int sockSelect(int nfds, fd_set *readfds, fd_set *writefds,
733 fd_set *exceptfds, struct timeval *timeout) {
735 int result = select(nfds, readfds, writefds, exceptfds, timeout);
738 if (errno == EINTR) {
739 result = SOCKERR_INTERRUPTED;
741 result = SOCKERR_OPFAILED;
743 } else if (result == 0) {
744 result = SOCKERR_TIMEOUT;
749 #define SELECT_READ_TYPE 0
750 #define SELECT_WRITE_TYPE 1
752 static int selectWait(int handle, int uSecTime, int type) {
754 struct timeval time, *timePtr;
756 int size = handle + 1;
759 FD_SET(handle, &fdset);
762 /* Use a timeout if uSecTime >= 0 */
763 memset(&time, 0, sizeof(time));
764 time.tv_usec = uSecTime;
767 /* Infinite timeout if uSecTime < 0 */
771 if (type == SELECT_READ_TYPE) {
772 result = sockSelect(size, &fdset, NULL, NULL, timePtr);
774 result = sockSelect(size, NULL, &fdset, NULL, timePtr);
779 static int pollSelectWait(JNIEnv *env, jobject fileDescriptor, int timeout, int type) {
780 /* now try reading the socket for the timespan timeout.
781 * if timeout is 0 try forever until the soclets gets ready or until an
784 int pollTimeoutUSec = 100000, pollMsec = 100;
786 int timeLeft = timeout;
787 int hasTimeout = timeout > 0 ? 1 : 0;
792 finishTime = time_msec_clock() + timeout;
797 while (poll) { /* begin polling loop */
800 * Fetch the handle every time in case the socket is closed.
802 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
804 if (handle == 0 || handle == -1) {
805 throwSocketException(env, SOCKERR_INTERRUPTED);
811 if (timeLeft - 10 < pollMsec) {
812 pollTimeoutUSec = timeLeft <= 0 ? 0 : (timeLeft * 1000);
815 result = selectWait(handle, pollTimeoutUSec, type);
818 * because we are polling at a time smaller than timeout
819 * (presumably) lets treat an interrupt and timeout the same - go
820 * see if we're done timewise, and then just try again if not.
822 if (SOCKERR_TIMEOUT == result ||
823 SOCKERR_INTERRUPTED == result) {
825 timeLeft = finishTime - time_msec_clock();
829 * Always throw the "timeout" message because that is
830 * effectively what has happened, even if we happen to
831 * have been interrupted.
833 jniThrowException(env, "java/net/SocketTimeoutException",
834 netLookupErrorString(SOCKERR_TIMEOUT));
836 continue; // try again
839 } else if (0 > result) {
840 throwSocketException(env, result);
844 } else { /* polling with no timeout (why would you do this?)*/
846 result = selectWait(handle, pollTimeoutUSec, type);
849 * if interrupted (or a timeout) just retry
851 if (SOCKERR_TIMEOUT == result ||
852 SOCKERR_INTERRUPTED == result) {
854 continue; // try again
855 } else if (0 > result) {
856 throwSocketException(env, result);
860 } /* end polling loop */
866 * Obtain the socket address family from an existing socket.
868 * @param socket the filedescriptor of the socket to examine
870 * @return an integer, the address family of the socket
872 static int getSocketAddressFamily(int socket) {
873 struct sockaddr_storage ss;
874 socklen_t namelen = sizeof(ss);
875 int ret = getsockname(socket, (struct sockaddr*) &ss, &namelen);
884 * A helper method, to set the connect context to a Long object.
886 * @param env pointer to the JNI library
887 * @param longclass Java Long Object
889 void setConnectContext(JNIEnv *env,jobject longclass,jbyte * context) {
890 jclass descriptorCLS;
891 jfieldID descriptorFID;
892 descriptorCLS = env->FindClass("java/lang/Long");
893 descriptorFID = env->GetFieldID(descriptorCLS, "value", "J");
894 env->SetLongField(longclass, descriptorFID, (jlong)((jint)context));
898 * A helper method, to get the connect context.
900 * @param env pointer to the JNI library
901 * @param longclass Java Long Object
903 jbyte *getConnectContext(JNIEnv *env, jobject longclass) {
904 jclass descriptorCLS;
905 jfieldID descriptorFID;
906 descriptorCLS = env->FindClass("java/lang/Long");
907 descriptorFID = env->GetFieldID(descriptorCLS, "value", "J");
908 return (jbyte*) ((jint)env->GetLongField(longclass, descriptorFID));
911 // typical ip checksum
912 unsigned short ip_checksum(unsigned short* buffer, int size) {
913 register unsigned short * buf = buffer;
914 register int bufleft = size;
915 register unsigned long sum = 0;
917 while (bufleft > 1) {
918 sum = sum + (*buf++);
919 bufleft = bufleft - sizeof(unsigned short );
922 sum = sum + (*(unsigned char*)buf);
924 sum = (sum >> 16) + (sum & 0xffff);
927 return (unsigned short )(~sum);
931 * Converts an IPv4 address to an IPv4-mapped IPv6 address. Performs no error
934 * @param address the address to convert. Must contain an IPv4 address.
935 * @param outputAddress the converted address. Will contain an IPv6 address.
936 * @param mapUnspecified if true, convert 0.0.0.0 to ::ffff:0:0; if false, to ::
938 static void ipv4ToMappedAddress(struct sockaddr_storage *address,
939 struct sockaddr_storage *outputAddress, bool mapUnspecified) {
940 memset(outputAddress, 0, sizeof(struct sockaddr_storage));
941 const struct sockaddr_in *sin = ((struct sockaddr_in *) address);
942 struct sockaddr_in6 *sin6 = ((struct sockaddr_in6 *) outputAddress);
943 sin6->sin6_family = AF_INET6;
944 sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
945 if (sin->sin_addr.s_addr != 0 || mapUnspecified) {
946 sin6->sin6_addr.s6_addr32[2] = htonl(0xffff);
948 sin6->sin6_port = sin->sin_port;
952 * Wrapper for connect() that converts IPv4 addresses to IPv4-mapped IPv6
953 * addresses if necessary.
955 * @param socket the filedescriptor of the socket to connect
956 * @param socketAddress the address to connect to
958 static int doConnect(int socket, struct sockaddr_storage *socketAddress) {
959 struct sockaddr_storage mappedAddress;
960 struct sockaddr_storage *realAddress;
961 if (socketAddress->ss_family == AF_INET &&
962 getSocketAddressFamily(socket) == AF_INET6) {
963 ipv4ToMappedAddress(socketAddress, &mappedAddress, true);
964 realAddress = &mappedAddress;
966 realAddress = socketAddress;
970 ret = connect(socket, (struct sockaddr *) realAddress,
971 sizeof(struct sockaddr_storage));
972 } while (ret < 0 && errno == EINTR);
977 * Wrapper for bind() that converts IPv4 addresses to IPv4-mapped IPv6
978 * addresses if necessary.
980 * @param socket the filedescriptor of the socket to connect
981 * @param socketAddress the address to connect to
983 static int doBind(int socket, struct sockaddr_storage *socketAddress) {
984 struct sockaddr_storage mappedAddress;
985 struct sockaddr_storage *realAddress;
986 if (socketAddress->ss_family == AF_INET &&
987 getSocketAddressFamily(socket) == AF_INET6) {
988 ipv4ToMappedAddress(socketAddress, &mappedAddress, false);
989 realAddress = &mappedAddress;
991 realAddress = socketAddress;
995 ret = bind(socket, (struct sockaddr *) realAddress,
996 sizeof(struct sockaddr_storage));
997 } while (ret < 0 && errno == EINTR);
1002 * Establish a connection to a peer with a timeout. This function is called
1003 * repeatedly in order to carry out the connect and to allow other tasks to
1004 * proceed on certain platforms. The caller must first call with
1005 * step = SOCKET_STEP_START, if the result is SOCKERR_NOTCONNECTED it will then
1006 * call it with step = CHECK until either another error or 0 is returned to
1007 * indicate the connect is complete. Each time the function should sleep for no
1008 * more than timeout milliseconds. If the connect succeeds or an error occurs,
1009 * the caller must always end the process by calling the function with
1010 * step = SOCKET_STEP_DONE
1012 * @param[in] portLibrary The port library.
1013 * @param[in] sock pointer to the unconnected local socket.
1014 * @param[in] addr pointer to the sockaddr, specifying remote host/port.
1015 * @param[in] timeout the timeout in milliseconds. If timeout is negative,
1016 * perform a block operation.
1017 * @param[in,out] pointer to context pointer. Filled in on first call and then
1018 * to be passed into each subsequent call.
1020 * @return 0, if no errors occurred, otherwise the (negative) error code.
1022 static int sockConnectWithTimeout(int handle, struct sockaddr_storage addr,
1023 unsigned int timeout, unsigned int step, jbyte *ctxt) {
1025 struct timeval passedTimeout;
1027 socklen_t errorValLen = sizeof(int);
1028 struct selectFDSet *context = NULL;
1030 if (SOCKET_STEP_START == step) {
1032 context = (struct selectFDSet *) ctxt;
1034 context->sock = handle;
1035 context->nfds = handle + 1;
1037 if (useAdbNetworkingForAddress(&addr)) {
1039 // LOGD("+connect to address 0x%08x (via adb)",
1040 // addr.sin_addr.s_addr);
1041 rc = adb_networking_connect_fd(handle, (struct sockaddr_in *) &addr);
1042 // LOGD("-connect ret %d errno %d (via adb)", rc, errno);
1045 /* set the socket to non-blocking */
1046 int block = JNI_TRUE;
1047 rc = ioctl(handle, FIONBIO, &block);
1049 return convertError(rc);
1052 // LOGD("+connect to address 0x%08x (via normal) on handle %d",
1053 // addr.sin_addr.s_addr, handle);
1054 rc = doConnect(handle, &addr);
1055 // LOGD("-connect to address 0x%08x (via normal) returned %d",
1056 // addr.sin_addr.s_addr, (int) rc);
1064 return SOCKERR_ALREADYBOUND;
1067 return SOCKERR_NOTCONNECTED;
1069 return convertError(rc);
1073 /* we connected right off the bat so just return */
1076 } else if (SOCKET_STEP_CHECK == step) {
1077 /* now check if we have connected yet */
1079 context = (struct selectFDSet *) ctxt;
1082 * set the timeout value to be used. Because on some unix platforms we
1083 * don't get notified when a socket is closed we only sleep for 100ms
1086 passedTimeout.tv_sec = 0;
1087 if (timeout > 100) {
1088 passedTimeout.tv_usec = 100 * 1000;
1089 } else if ((int)timeout >= 0) {
1090 passedTimeout.tv_usec = timeout * 1000;
1093 /* initialize the FD sets for the select */
1094 FD_ZERO(&(context->exceptionSet));
1095 FD_ZERO(&(context->writeSet));
1096 FD_ZERO(&(context->readSet));
1097 FD_SET(context->sock, &(context->writeSet));
1098 FD_SET(context->sock, &(context->readSet));
1099 FD_SET(context->sock, &(context->exceptionSet));
1101 rc = select(context->nfds,
1102 &(context->readSet),
1103 &(context->writeSet),
1104 &(context->exceptionSet),
1105 (int)timeout >= 0 ? &passedTimeout : NULL);
1107 /* if there is at least one descriptor ready to be checked */
1109 /* if the descriptor is in the write set we connected or failed */
1110 if (FD_ISSET(context->sock, &(context->writeSet))) {
1112 if (!FD_ISSET(context->sock, &(context->readSet))) {
1113 /* ok we have connected ok */
1116 /* ok we have more work to do to figure it out */
1117 if (getsockopt(context->sock, SOL_SOCKET, SO_ERROR,
1118 &errorVal, &errorValLen) >= 0) {
1119 return errorVal ? convertError(errorVal) : 0;
1121 return convertError(errno);
1126 /* if the descriptor is in the exception set the connect failed */
1127 if (FD_ISSET(context->sock, &(context->exceptionSet))) {
1128 if (getsockopt(context->sock, SOL_SOCKET, SO_ERROR, &errorVal,
1129 &errorValLen) >= 0) {
1130 return errorVal ? convertError(errorVal) : 0;
1133 return convertError(rc);
1136 } else if (rc < 0) {
1137 /* something went wrong with the select call */
1140 /* if it was EINTR we can just try again. Return not connected */
1142 return SOCKERR_NOTCONNECTED;
1145 /* some other error occured so look it up and return */
1146 return convertError(rc);
1150 * if we get here the timeout expired or the connect had not yet
1151 * completed just indicate that the connect is not yet complete
1153 return SOCKERR_NOTCONNECTED;
1154 } else if (SOCKET_STEP_DONE == step) {
1155 /* we are done the connect or an error occured so clean up */
1157 int block = JNI_FALSE;
1158 ioctl(handle, FIONBIO, &block);
1162 return SOCKERR_ARGSINVALID;
1167 * Helper method to get or set socket options
1169 * @param action SOCKOPT_GET to get an option, SOCKOPT_SET to set it
1170 * @param socket the file descriptor of the socket to use
1171 * @param ipv4Option the option value to use for an IPv4 socket
1172 * @param ipv6Option the option value to use for an IPv6 socket
1173 * @param optionValue the value of the socket option to get or set
1174 * @param optionLength the length of the socket option to get or set
1176 * @return the value of the socket call, or -1 on failure inside this function
1178 * @note on internal failure, the errno variable will be set appropriately
1180 static int getOrSetSocketOption(int action, int socket, int ipv4Option,
1181 int ipv6Option, void *optionValue, socklen_t *optionLength) {
1184 int family = getSocketAddressFamily(socket);
1187 option = ipv4Option;
1188 protocol = IPPROTO_IP;
1191 option = ipv6Option;
1192 protocol = IPPROTO_IPV6;
1195 errno = EAFNOSUPPORT;
1198 if (action == SOCKOPT_GET) {
1199 return getsockopt(socket, protocol, option, &optionValue, optionLength);
1200 } else if (action == SOCKOPT_SET) {
1201 return setsockopt(socket, protocol, option, &optionValue,
1210 * Find the interface index that was set for this socket by the IP_MULTICAST_IF
1211 * or IPV6_MULTICAST_IF socket option.
1213 * @param socket the socket to examine
1215 * @return the interface index, or -1 on failure
1217 * @note on internal failure, the errno variable will be set appropriately
1219 static int interfaceIndexFromMulticastSocket(int socket) {
1220 int family = getSocketAddressFamily(socket);
1221 socklen_t requestLength;
1224 if (family == AF_INET) {
1225 // IP_MULTICAST_IF returns a pointer to a struct ip_mreqn.
1226 struct ip_mreqn tempRequest;
1227 requestLength = sizeof(tempRequest);
1228 result = getsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, &tempRequest,
1230 interfaceIndex = tempRequest.imr_ifindex;
1231 } else if (family == AF_INET6) {
1232 // IPV6_MULTICAST_IF returns a pointer to an integer.
1233 requestLength = sizeof(interfaceIndex);
1234 result = getsockopt(socket, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1235 &interfaceIndex, &requestLength);
1237 errno = EAFNOSUPPORT;
1242 return interfaceIndex;
1249 * Join/Leave the nominated multicast group on the specified socket.
1250 * Implemented by setting the multicast 'add membership'/'drop membership'
1251 * option at the HY_IPPROTO_IP level on the socket.
1253 * Implementation note for multicast sockets in general:
1255 * - This code is untested, because at the time of this writing multicast can't
1256 * be properly tested on Android due to GSM routing restrictions. So it might
1257 * or might not work.
1259 * - The REUSEPORT socket option that Harmony employs is not supported on Linux
1260 * and thus also not supported on Android. It's is not needed for multicast
1261 * to work anyway (REUSEADDR should suffice).
1263 * @param env pointer to the JNI library.
1264 * @param socketP pointer to the hysocket to join/leave on.
1265 * @param optVal pointer to the InetAddress, the multicast group to join/drop.
1267 * @exception SocketException if an error occurs during the call
1269 static void mcastAddDropMembership (JNIEnv * env, int handle, jobject optVal,
1270 int ignoreIF, int setSockOptVal) {
1271 struct sockaddr_storage sockaddrP;
1273 // By default, let the system decide which interface to use.
1274 int interfaceIndex = 0;
1277 * Check whether we are getting an InetAddress or an Generic IPMreq. For now
1278 * we support both so that we will not break the tests. If an InetAddress
1279 * is passed in, only support IPv4 as obtaining an interface from an
1280 * InetAddress is complex and should be done by the Java caller.
1282 if (env->IsInstanceOf (optVal, gCachedFields.iaddr_class)) {
1284 * optVal is an InetAddress. Construct a multicast request structure
1285 * from this address. Support IPv4 only.
1287 struct ip_mreqn multicastRequest;
1288 socklen_t length = sizeof(multicastRequest);
1289 memset(&multicastRequest, 0, length);
1291 // If ignoreIF is false, determine the index of the interface to use.
1293 interfaceIndex = interfaceIndexFromMulticastSocket(handle);
1294 multicastRequest.imr_ifindex = interfaceIndex;
1295 if (interfaceIndex == -1) {
1296 throwSocketException(env, convertError(errno));
1301 // Convert the inetAddress to an IPv4 address structure.
1302 result = inetAddressToSocketAddress(env, optVal, 0, &sockaddrP);
1303 if (result < 0) // Exception has already been thrown.
1305 if (sockaddrP.ss_family != AF_INET) {
1306 throwSocketException(env, SOCKERR_BADAF);
1309 struct sockaddr_in *sin = (struct sockaddr_in *) &sockaddrP;
1310 multicastRequest.imr_multiaddr = sin->sin_addr;
1312 result = setsockopt(handle, IPPROTO_IP, setSockOptVal,
1313 &multicastRequest, length);
1315 throwSocketException (env, convertError(errno));
1320 * optVal is a GenericIPMreq object. Extract the relevant fields from
1321 * it and construct a multicast request structure from these. Support
1322 * both IPv4 and IPv6.
1325 jfieldID multiaddrID;
1326 jfieldID interfaceIdxID;
1329 // Get the multicast address to join or leave.
1330 cls = env->GetObjectClass(optVal);
1331 multiaddrID = env->GetFieldID(cls, "multiaddr", "Ljava/net/InetAddress;");
1332 multiaddr = env->GetObjectField(optVal, multiaddrID);
1334 // Get the interface index to use.
1336 interfaceIdxID = env->GetFieldID(cls, "interfaceIdx", "I");
1337 interfaceIndex = env->GetIntField(optVal, interfaceIdxID);
1340 result = inetAddressToSocketAddress(env, multiaddr, 0, &sockaddrP);
1341 if (result < 0) // Exception has already been thrown.
1344 struct ip_mreqn ipv4Request;
1345 struct ipv6_mreq ipv6Request;
1346 void *multicastRequest;
1347 socklen_t requestLength;
1349 int family = getSocketAddressFamily(handle);
1352 requestLength = sizeof(ipv4Request);
1353 memset(&ipv4Request, 0, requestLength);
1354 ipv4Request.imr_multiaddr =
1355 ((struct sockaddr_in *) &sockaddrP)->sin_addr;
1356 ipv4Request.imr_ifindex = interfaceIndex;
1357 multicastRequest = &ipv4Request;
1361 requestLength = sizeof(ipv6Request);
1362 memset(&ipv6Request, 0, requestLength);
1363 ipv6Request.ipv6mr_multiaddr =
1364 ((struct sockaddr_in6 *) &sockaddrP)->sin6_addr;
1365 ipv6Request.ipv6mr_interface = interfaceIndex;
1366 multicastRequest = &ipv6Request;
1367 level = IPPROTO_IPV6;
1370 throwSocketException (env, SOCKERR_BADAF);
1374 /* join/drop the multicast address */
1375 result = setsockopt(handle, level, setSockOptVal, multicastRequest,
1378 throwSocketException (env, convertError(errno));
1384 static void osNetworkSystem_oneTimeInitializationImpl(JNIEnv* env, jobject obj,
1385 jboolean jcl_supports_ipv6) {
1386 // LOGD("ENTER oneTimeInitializationImpl of OSNetworkSystem");
1388 char useAdbNetworkingProperty[PROPERTY_VALUE_MAX];
1389 char adbConnectedProperty[PROPERTY_VALUE_MAX];
1391 property_get("android.net.use-adb-networking", useAdbNetworkingProperty, "");
1392 property_get("adb.connected", adbConnectedProperty, "");
1394 if (strlen((char *)useAdbNetworkingProperty) > 0
1395 && strlen((char *)adbConnectedProperty) > 0) {
1396 useAdbNetworking = 1;
1399 memset(&gCachedFields, 0, sizeof(gCachedFields));
1401 // initializing InetAddress
1403 jclass iaddrclass = env->FindClass("java/net/InetAddress");
1405 if (iaddrclass == NULL) {
1406 jniThrowException(env, "java/lang/ClassNotFoundException",
1407 "java.net.InetAddress");
1411 gCachedFields.iaddr_class = (jclass) env->NewGlobalRef(iaddrclass);
1413 jmethodID iaddrclassinit = env->GetMethodID(iaddrclass, "<init>", "()V");
1415 if (iaddrclassinit == NULL) {
1416 jniThrowException(env, "java/lang/NoSuchMethodError", "InetAddress.<init>()");
1420 gCachedFields.iaddr_class_init = iaddrclassinit;
1422 jmethodID iaddrgetbyaddress = env->GetStaticMethodID(iaddrclass,
1423 "getByAddress", "([B)Ljava/net/InetAddress;");
1425 if (iaddrgetbyaddress == NULL) {
1426 jniThrowException(env, "java/lang/NoSuchMethodError",
1427 "InetAddress.getByAddress(byte[] val)");
1431 gCachedFields.iaddr_getbyaddress = iaddrgetbyaddress;
1433 jfieldID iaddripaddress = env->GetFieldID(iaddrclass, "ipaddress", "[B");
1435 if (iaddripaddress == NULL) {
1436 jniThrowException(env, "java/lang/NoSuchFieldError",
1437 "Can't find field InetAddress.ipaddress");
1441 gCachedFields.iaddr_ipaddress = iaddripaddress;
1443 // get the GenericIPMreq class
1445 jclass genericipmreqclass = env->FindClass("org/apache/harmony/luni/net/GenericIPMreq");
1447 if (genericipmreqclass == NULL) {
1448 jniThrowException(env, "java/lang/ClassNotFoundException",
1449 "org.apache.harmony.luni.net.GenericIPMreq");
1453 gCachedFields.genericipmreq_class = (jclass) env->NewGlobalRef(genericipmreqclass);
1455 // initializing Integer
1457 jclass integerclass = env->FindClass("java/lang/Integer");
1459 if (integerclass == NULL) {
1460 jniThrowException(env, "java/lang/ClassNotFoundException",
1461 "java.lang.Integer");
1465 jmethodID integerclassinit = env->GetMethodID(integerclass, "<init>", "(I)V");
1467 if (integerclassinit == NULL) {
1468 jniThrowException(env, "java/lang/NoSuchMethodError",
1469 "Integer.<init>(int val)");
1473 jfieldID integerclassvalue = env->GetFieldID(integerclass, "value", "I");
1475 if (integerclassvalue == NULL) {
1476 jniThrowException(env, "java/lang/NoSuchMethodError", "Integer.value");
1480 gCachedFields.integer_class = (jclass) env->NewGlobalRef(integerclass);
1481 gCachedFields.integer_class_init = integerclassinit;
1482 gCachedFields.integer_class_value = integerclassvalue;
1484 // initializing Boolean
1486 jclass booleanclass = env->FindClass("java/lang/Boolean");
1488 if (booleanclass == NULL) {
1489 jniThrowException(env, "java/lang/ClassNotFoundException",
1490 "java.lang.Boolean");
1494 jmethodID booleanclassinit = env->GetMethodID(booleanclass, "<init>", "(Z)V");
1496 if (booleanclassinit == NULL) {
1497 jniThrowException(env, "java/lang/NoSuchMethodError",
1498 "Boolean.<init>(boolean val)");
1502 jfieldID booleanclassvalue = env->GetFieldID(booleanclass, "value", "Z");
1504 if (booleanclassvalue == NULL) {
1505 jniThrowException(env, "java/lang/NoSuchMethodError", "Boolean.value");
1509 gCachedFields.boolean_class = (jclass) env->NewGlobalRef(booleanclass);
1510 gCachedFields.boolean_class_init = booleanclassinit;
1511 gCachedFields.boolean_class_value = booleanclassvalue;
1513 // initializing Byte
1515 jclass byteclass = env->FindClass("java/lang/Byte");
1517 if (byteclass == NULL) {
1518 jniThrowException(env, "java/lang/ClassNotFoundException",
1523 jmethodID byteclassinit = env->GetMethodID(byteclass, "<init>", "(B)V");
1525 if (byteclassinit == NULL) {
1526 jniThrowException(env, "java/lang/NoSuchMethodError",
1527 "Byte.<init>(byte val)");
1531 jfieldID byteclassvalue = env->GetFieldID(byteclass, "value", "B");
1533 if (byteclassvalue == NULL) {
1534 jniThrowException(env, "java/lang/NoSuchMethodError", "Byte.value");
1538 gCachedFields.byte_class = (jclass) env->NewGlobalRef(byteclass);
1539 gCachedFields.byte_class_init = byteclassinit;
1540 gCachedFields.byte_class_value = byteclassvalue;
1542 // initializing String
1544 jclass stringclass = env->FindClass("java/lang/String");
1546 if (stringclass == NULL) {
1547 jniThrowException(env, "java/lang/ClassNotFoundException",
1548 "java.lang.String");
1552 jmethodID stringclassinit = env->GetMethodID(stringclass, "<init>", "([B)V");
1554 if (stringclassinit == NULL) {
1555 jniThrowException(env, "java/lang/NoSuchMethodError",
1556 "String.<init>(byte[] val)");
1560 gCachedFields.string_class = (jclass) env->NewGlobalRef(stringclass);
1561 gCachedFields.string_class_init = stringclassinit;
1563 // initializing ScoketImpl
1565 jclass socketimplclass = env->FindClass("java/net/SocketImpl");
1567 if (socketimplclass == NULL) {
1568 jniThrowException(env, "java/lang/ClassNotFoundException",
1569 "java.net.SocketImpl");
1573 jfieldID socketimplport = env->GetFieldID(socketimplclass, "port", "I");
1575 if (socketimplport == NULL) {
1576 jniThrowException(env, "java/lang/NoSuchFieldError", "SocketImpl.port");
1580 jfieldID socketimpladdress = env->GetFieldID(socketimplclass, "address",
1581 "Ljava/net/InetAddress;");
1583 if (socketimpladdress == NULL) {
1584 jniThrowException(env, "java/lang/NoSuchFieldError",
1585 "SocketImpl.address");
1589 gCachedFields.socketimpl_address = socketimpladdress;
1590 gCachedFields.socketimpl_port = socketimplport;
1592 gCachedFields.dpack_class = env->FindClass("java/net/DatagramPacket");
1593 if (gCachedFields.dpack_class == NULL) {
1594 jniThrowException(env, "java/lang/ClassNotFoundException",
1595 "java.net.DatagramPacket");
1599 gCachedFields.dpack_address = env->GetFieldID(gCachedFields.dpack_class,
1600 "address", "Ljava/net/InetAddress;");
1601 if (gCachedFields.dpack_address == NULL) {
1602 jniThrowException(env, "java/lang/NoSuchFieldError",
1603 "DatagramPacket.address");
1607 gCachedFields.dpack_port = env->GetFieldID(gCachedFields.dpack_class,
1609 if (gCachedFields.dpack_port == NULL) {
1610 jniThrowException(env, "java/lang/NoSuchFieldError",
1611 "DatagramPacket.port");
1615 gCachedFields.dpack_length = env->GetFieldID(gCachedFields.dpack_class,
1617 if (gCachedFields.dpack_length == NULL) {
1618 jniThrowException(env, "java/lang/NoSuchFieldError",
1619 "DatagramPacket.length");
1626 * Helper function to create a socket of the specified type and bind it to a
1627 * Java file descriptor.
1629 * @param fileDescriptor the file descriptor to bind the socket to
1630 * @param type the socket type to create, e.g., SOCK_STREAM
1632 * @return the socket file descriptor, or -1 on failure
1635 static int createSocketFileDescriptor(JNIEnv* env, jobject fileDescriptor,
1637 if (fileDescriptor == NULL) {
1638 throwNullPointerException(env);
1644 sock = socket(PF_INET6, type, 0);
1645 if (sock < 0 && errno == EAFNOSUPPORT) {
1646 sock = socket(PF_INET, type, 0);
1649 int err = convertError(errno);
1650 throwSocketException(env, err);
1652 jniSetFileDescriptorOfFD(env, fileDescriptor, sock);
1657 static void osNetworkSystem_createSocketImpl(JNIEnv* env, jclass clazz,
1658 jobject fileDescriptor, jboolean preferIPv4Stack) {
1659 // LOGD("ENTER createSocketImpl");
1660 createSocketFileDescriptor(env, fileDescriptor, SOCK_STREAM);
1663 static void osNetworkSystem_createDatagramSocketImpl(JNIEnv* env, jclass clazz,
1664 jobject fileDescriptor, jboolean preferIPv4Stack) {
1665 // LOGD("ENTER createDatagramSocketImpl");
1666 createSocketFileDescriptor(env, fileDescriptor, SOCK_DGRAM);
1669 static jint osNetworkSystem_readSocketDirectImpl(JNIEnv* env, jclass clazz,
1670 jobject fileDescriptor, jint address, jint offset, jint count,
1672 // LOGD("ENTER readSocketDirectImpl");
1675 jbyte *message = (jbyte *)address + offset;
1676 int result, ret, localCount;
1678 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1680 if (handle == 0 || handle == -1) {
1681 throwSocketException(env, SOCKERR_BADSOCKET);
1685 result = selectWait(handle, timeout, SELECT_READ_TYPE);
1691 localCount = (count < 65536) ? count : 65536;
1694 ret = recv(handle, (jbyte *) message, localCount, SOCKET_NOFLAGS);
1695 } while (ret < 0 && errno == EINTR);
1699 } else if (ret == -1) {
1700 int err = convertError(errno);
1701 throwSocketException(env, err);
1707 static jint osNetworkSystem_readSocketImpl(JNIEnv* env, jclass clazz,
1708 jobject fileDescriptor, jbyteArray data, jint offset, jint count,
1710 // LOGD("ENTER readSocketImpl");
1713 int result, localCount;
1715 jbyte internalBuffer[BUFFERSIZE];
1717 localCount = (count < 65536) ? count : 65536;
1719 if (localCount > BUFFERSIZE) {
1720 message = (jbyte*)malloc(localCount * sizeof(jbyte));
1721 if (message == NULL) {
1722 jniThrowException(env, "java/lang/OutOfMemoryError",
1723 "couldn't allocate enough memory for readSocket");
1727 message = (jbyte *)internalBuffer;
1730 result = osNetworkSystem_readSocketDirectImpl(env, clazz, fileDescriptor,
1731 (jint) message, 0, localCount, timeout);
1734 env->SetByteArrayRegion(data, offset, result, (jbyte *)message);
1737 if (((jbyte *)message) != internalBuffer) {
1738 free(( jbyte *)message);
1744 static jint osNetworkSystem_writeSocketDirectImpl(JNIEnv* env, jclass clazz,
1745 jobject fileDescriptor, jint address, jint offset, jint count) {
1746 // LOGD("ENTER writeSocketDirectImpl");
1749 jbyte *message = (jbyte *)address + offset;
1750 int result = 0, sent = 0;
1756 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1758 if (handle == 0 || handle == -1) {
1759 throwSocketException(env, SOCKERR_BADSOCKET);
1763 result = send(handle, (jbyte *) message, (int) count, SOCKET_NOFLAGS);
1765 int err = convertError(errno);
1767 if (SOCKERR_WOULDBLOCK == err){
1768 jclass socketExClass,errorCodeExClass;
1769 jmethodID errorCodeExConstructor, socketExConstructor,socketExCauseMethod;
1770 jobject errorCodeEx, socketEx;
1771 const char* errorMessage = netLookupErrorString(err);
1772 jstring errorMessageString = env->NewStringUTF(errorMessage);
1774 errorCodeExClass = env->FindClass("org/apache/harmony/luni/util/ErrorCodeException");
1775 if (!errorCodeExClass){
1778 errorCodeExConstructor = env->GetMethodID(errorCodeExClass,"<init>","(I)V");
1779 if (!errorCodeExConstructor){
1782 errorCodeEx = env->NewObject(errorCodeExClass,errorCodeExConstructor,err);
1784 socketExClass = env->FindClass("java/net/SocketException");
1785 if (!socketExClass) {
1788 socketExConstructor = env->GetMethodID(socketExClass,"<init>","(Ljava/lang/String;)V");
1789 if (!socketExConstructor) {
1792 socketEx = env->NewObject(socketExClass, socketExConstructor, errorMessageString);
1793 socketExCauseMethod = env->GetMethodID(socketExClass,"initCause","(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
1794 env->CallObjectMethod(socketEx,socketExCauseMethod,errorCodeEx);
1795 env->Throw((jthrowable)socketEx);
1798 throwSocketException(env, err);
1805 static jint osNetworkSystem_writeSocketImpl(JNIEnv* env, jclass clazz,
1806 jobject fileDescriptor, jbyteArray data, jint offset, jint count) {
1807 // LOGD("ENTER writeSocketImpl");
1813 /* TODO: ARRAY PINNING */
1814 #define INTERNAL_SEND_BUFFER_MAX 512
1815 jbyte internalBuffer[INTERNAL_SEND_BUFFER_MAX];
1817 if (count > INTERNAL_SEND_BUFFER_MAX) {
1818 message = (jbyte*)malloc(count * sizeof( jbyte));
1819 if (message == NULL) {
1820 jniThrowException(env, "java/lang/OutOfMemoryError",
1821 "couldn't allocate enough memory for writeSocket");
1825 message = (jbyte *)internalBuffer;
1828 env->GetByteArrayRegion(data, offset, count, message);
1830 result = osNetworkSystem_writeSocketDirectImpl(env, clazz, fileDescriptor,
1831 (jint) message, 0, count);
1833 if (( jbyte *)message != internalBuffer) {
1834 free(( jbyte *)message);
1836 #undef INTERNAL_SEND_BUFFER_MAX
1840 static void osNetworkSystem_setNonBlockingImpl(JNIEnv* env, jclass clazz,
1841 jobject fileDescriptor, jboolean nonblocking) {
1842 // LOGD("ENTER setNonBlockingImpl");
1847 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1849 if (handle == 0 || handle == -1) {
1850 throwSocketException(env, SOCKERR_BADSOCKET);
1854 int block = nonblocking;
1856 result = ioctl(handle, FIONBIO, &block);
1859 throwSocketException(env, convertError(errno));
1863 static jint osNetworkSystem_connectSocketImpl(JNIEnv* env, jclass clazz,
1864 jobject fileDescriptor, jint trafficClass, jobject inetAddr, jint port);
1866 static jint osNetworkSystem_connectWithTimeoutSocketImpl(JNIEnv* env,
1867 jclass clazz, jobject fileDescriptor, jint timeout, jint trafficClass,
1868 jobject inetAddr, jint port, jint step, jbyteArray passContext) {
1869 // LOGD("ENTER connectWithTimeoutSocketImpl");
1873 struct sockaddr_storage address;
1874 jbyte *context = NULL;
1876 result = inetAddressToSocketAddress(env, inetAddr, port, &address);
1880 // Check if we're using adb networking and redirect in case it is used.
1881 if (useAdbNetworkingForAddress(&address)) {
1882 return osNetworkSystem_connectSocketImpl(env, clazz, fileDescriptor,
1883 trafficClass, inetAddr, port);
1886 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1887 if (handle == 0 || handle == -1) {
1888 throwSocketException(env, SOCKERR_BADDESC);
1892 context = (jbyte *)env->GetPrimitiveArrayCritical(passContext, NULL);
1895 case SOCKET_CONNECT_STEP_START:
1896 result = sockConnectWithTimeout(handle, address, 0,
1897 SOCKET_STEP_START, context);
1899 case SOCKET_CONNECT_STEP_CHECK:
1900 result = sockConnectWithTimeout(handle, address, timeout,
1901 SOCKET_STEP_CHECK, context);
1905 env->ReleasePrimitiveArrayCritical(passContext, context, JNI_ABORT);
1908 /* connected , so stop here */
1909 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, NULL);
1910 } else if (result != SOCKERR_NOTCONNECTED) {
1911 /* can not connect... */
1912 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, NULL);
1913 if (result == SOCKERR_EACCES) {
1914 jniThrowException(env, "java/lang/SecurityException",
1915 netLookupErrorString(result));
1917 jniThrowException(env, "java/net/ConnectException",
1918 netLookupErrorString(result));
1925 static void osNetworkSystem_connectStreamWithTimeoutSocketImpl(JNIEnv* env,
1926 jclass clazz, jobject fileDescriptor, jint remotePort, jint timeout,
1927 jint trafficClass, jobject inetAddr) {
1928 // LOGD("ENTER connectStreamWithTimeoutSocketImpl");
1932 struct sockaddr_storage address;
1933 jbyte *context = NULL;
1934 int remainingTimeout = timeout;
1935 int passedTimeout = 0;
1938 char hasTimeout = timeout > 0;
1940 /* if a timeout was specified calculate the finish time value */
1942 finishTime = time_msec_clock() + (int) timeout;
1945 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1946 if (handle == 0 || handle == -1) {
1947 throwSocketException(env, SOCKERR_BADDESC);
1951 result = inetAddressToSocketAddress(env, inetAddr, remotePort, &address);
1952 if (result < 0) // Exception has already been thrown.
1955 // Check if we're using adb networking and redirect in case it is used.
1956 if (useAdbNetworkingForAddress(&address)) {
1957 int retVal = osNetworkSystem_connectSocketImpl(env, clazz,
1958 fileDescriptor, trafficClass, inetAddr, remotePort);
1960 throwSocketException(env, SOCKERR_BADSOCKET);
1966 * we will be looping checking for when we are connected so allocate
1967 * the descriptor sets that we will use
1969 context =(jbyte *) malloc(sizeof(struct selectFDSet));
1970 if (NULL == context) {
1971 throwSocketException(env, SOCKERR_NOBUFFERS);
1975 result = sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_START, context);
1977 /* ok we connected right away so we are done */
1978 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, context);
1980 } else if (result != SOCKERR_NOTCONNECTED) {
1981 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE,
1983 /* we got an error other than NOTCONNECTED so we cannot continue */
1984 if (SOCKERR_EACCES == result) {
1985 jniThrowException(env, "java/lang/SecurityException",
1986 netLookupErrorString(result));
1988 throwSocketException(env, result);
1993 while (SOCKERR_NOTCONNECTED == result) {
1994 passedTimeout = remainingTimeout;
1997 * ok now try and connect. Depending on the platform this may sleep
1998 * for up to passedTimeout milliseconds
2000 result = sockConnectWithTimeout(handle, address, passedTimeout,
2001 SOCKET_STEP_CHECK, context);
2004 * now check if the socket is still connected.
2005 * Do it here as some platforms seem to think they
2006 * are connected if the socket is closed on them.
2008 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2009 if (handle == 0 || handle == -1) {
2010 sockConnectWithTimeout(handle, address, 0,
2011 SOCKET_STEP_DONE, context);
2012 throwSocketException(env, SOCKERR_BADSOCKET);
2017 * check if we are now connected,
2018 * if so we can finish the process and return
2021 sockConnectWithTimeout(handle, address, 0,
2022 SOCKET_STEP_DONE, context);
2027 * if the error is SOCKERR_NOTCONNECTED then we have not yet
2028 * connected and we may not be done yet
2030 if (SOCKERR_NOTCONNECTED == result) {
2031 /* check if the timeout has expired */
2033 remainingTimeout = finishTime - time_msec_clock();
2034 if (remainingTimeout <= 0) {
2035 sockConnectWithTimeout(handle, address, 0,
2036 SOCKET_STEP_DONE, context);
2037 jniThrowException(env,
2038 "java/net/SocketTimeoutException",
2039 netLookupErrorString(result));
2043 remainingTimeout = 100;
2046 sockConnectWithTimeout(handle, address, remainingTimeout,
2047 SOCKET_STEP_DONE, context);
2048 if ((SOCKERR_CONNRESET == result) ||
2049 (SOCKERR_CONNECTION_REFUSED == result) ||
2050 (SOCKERR_ADDRNOTAVAIL == result) ||
2051 (SOCKERR_ADDRINUSE == result) ||
2052 (SOCKERR_ENETUNREACH == result)) {
2053 jniThrowException(env, "java/net/ConnectException",
2054 netLookupErrorString(result));
2055 } else if (SOCKERR_EACCES == result) {
2056 jniThrowException(env, "java/lang/SecurityException",
2057 netLookupErrorString(result));
2059 throwSocketException(env, result);
2067 /* free the memory for the FD set */
2068 if (context != NULL) {
2073 static jint osNetworkSystem_connectSocketImpl(JNIEnv* env, jclass clazz,
2074 jobject fileDescriptor, jint trafficClass, jobject inetAddr, jint port) {
2075 //LOGD("ENTER direct-call connectSocketImpl\n");
2077 struct sockaddr_storage address;
2081 ret = inetAddressToSocketAddress(env, inetAddr, port, &address);
2085 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2086 if (handle == 0 || handle == -1) {
2087 throwSocketException(env, SOCKERR_BADDESC);
2091 if (useAdbNetworkingForAddress(&address)) {
2093 // LOGD("+connect to address 0x%08x port %d (via adb)",
2094 // address.sin_addr.s_addr, (int) port);
2095 ret = adb_networking_connect_fd(handle, (struct sockaddr_in *) &address);
2096 // LOGD("-connect ret %d errno %d (via adb)", ret, errno);
2100 // call this method with a timeout of zero
2101 osNetworkSystem_connectStreamWithTimeoutSocketImpl(env, clazz,
2102 fileDescriptor, port, 0, trafficClass, inetAddr);
2103 if (env->ExceptionOccurred() != 0) {
2112 jniThrowException(env, "java/net/ConnectException",
2113 netLookupErrorString(convertError(errno)));
2120 static void osNetworkSystem_socketBindImpl(JNIEnv* env, jclass clazz,
2121 jobject fileDescriptor, jint port, jobject inetAddress) {
2122 // LOGD("ENTER socketBindImpl");
2124 struct sockaddr_storage sockaddress;
2128 ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddress);
2132 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2133 if (handle == 0 || handle == -1) {
2134 throwSocketException(env, SOCKERR_BADDESC);
2138 ret = doBind(handle, &sockaddress);
2140 jniThrowException(env, "java/net/BindException",
2141 netLookupErrorString(convertError(errno)));
2146 static void osNetworkSystem_listenStreamSocketImpl(JNIEnv* env, jclass clazz,
2147 jobject fileDescriptor, jint backlog) {
2148 // LOGD("ENTER listenStreamSocketImpl");
2153 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2155 if (handle == 0 || handle == -1) {
2156 throwSocketException(env, SOCKERR_BADSOCKET);
2160 ret = listen(handle, backlog);
2163 int err = convertError(errno);
2164 throwSocketException(env, err);
2169 static jint osNetworkSystem_availableStreamImpl(JNIEnv* env, jclass clazz,
2170 jobject fileDescriptor) {
2171 // LOGD("ENTER availableStreamImpl");
2174 char message[BUFFERSIZE];
2178 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2179 if (handle == 0 || handle == -1) {
2180 throwSocketException(env, SOCKERR_BADDESC);
2185 result = selectWait(handle, 1, SELECT_READ_TYPE);
2187 if (SOCKERR_TIMEOUT == result) {
2188 // The read operation timed out, so answer 0 bytes available
2190 } else if (SOCKERR_INTERRUPTED == result) {
2192 } else if (0 > result) {
2193 throwSocketException(env, result);
2196 } while (SOCKERR_INTERRUPTED == result);
2198 result = recv(handle, (jbyte *) message, BUFFERSIZE, MSG_PEEK);
2201 int err = convertError(errno);
2202 throwSocketException(env, err);
2208 static void osNetworkSystem_acceptSocketImpl(JNIEnv* env, jclass clazz,
2209 jobject fdServer, jobject newSocket, jobject fdnewSocket, jint timeout) {
2210 // LOGD("ENTER acceptSocketImpl");
2212 struct sockaddr_storage sa;
2220 if (newSocket == NULL) {
2221 throwNullPointerException(env);
2225 result = pollSelectWait(env, fdServer, timeout, SELECT_READ_TYPE);
2230 handle = jniGetFDFromFileDescriptor(env, fdServer);
2231 if (handle == 0 || handle == -1) {
2232 throwSocketException(env, SOCKERR_BADDESC);
2237 addrlen = sizeof(sa);
2238 ret = accept(handle, (struct sockaddr *) &sa, &addrlen);
2239 } while (ret < 0 && errno == EINTR);
2242 int err = convertError(errno);
2243 throwSocketException(env, err);
2250 * For network sockets, put the peer address and port in instance variables.
2251 * We don't bother to do this for UNIX domain sockets, since most peers are
2254 if (sa.ss_family == AF_INET || sa.ss_family == AF_INET6) {
2255 jobject inetAddress = socketAddressToInetAddress(env, &sa);
2258 newSocket = NULL; // Exception has already been thrown.
2262 env->SetObjectField(newSocket,
2263 gCachedFields.socketimpl_address, inetAddress);
2265 int port = getSocketAddressPort(&sa);
2266 env->SetIntField(newSocket, gCachedFields.socketimpl_port, port);
2269 jniSetFileDescriptorOfFD(env, fdnewSocket, retFD);
2272 static jboolean osNetworkSystem_supportsUrgentDataImpl(JNIEnv* env,
2273 jclass clazz, jobject fileDescriptor) {
2274 // LOGD("ENTER supportsUrgentDataImpl");
2278 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2279 if (handle == 0 || handle == -1) {
2286 static void osNetworkSystem_sendUrgentDataImpl(JNIEnv* env, jclass clazz,
2287 jobject fileDescriptor, jbyte value) {
2288 // LOGD("ENTER sendUrgentDataImpl");
2293 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2294 if (handle == 0 || handle == -1) {
2295 throwSocketException(env, SOCKERR_BADSOCKET);
2299 result = send(handle, (jbyte *) &value, 1, MSG_OOB);
2301 int err = convertError(errno);
2302 throwSocketException(env, err);
2306 static void osNetworkSystem_connectDatagramImpl2(JNIEnv* env, jclass clazz,
2307 jobject fd, jint port, jint trafficClass, jobject inetAddress) {
2308 // LOGD("ENTER connectDatagramImpl2");
2310 int handle = jniGetFDFromFileDescriptor(env, fd);
2312 struct sockaddr_storage sockAddr;
2315 ret = inetAddressToSocketAddress(env, inetAddress, port, &sockAddr);
2316 if (ret < 0) // Exception has already been thrown.
2319 ret = doConnect(handle, &sockAddr);
2321 int err = convertError(errno);
2322 throwSocketException(env, err);
2326 static void osNetworkSystem_disconnectDatagramImpl(JNIEnv* env, jclass clazz,
2328 // LOGD("ENTER disconnectDatagramImpl");
2330 int handle = jniGetFDFromFileDescriptor(env, fd);
2332 struct sockaddr_storage sockAddr;
2333 memset(&sockAddr, 0, sizeof(sockAddr));
2334 sockAddr.ss_family = AF_UNSPEC;
2336 int result = doConnect(handle, &sockAddr);
2338 int err = convertError(errno);
2339 throwSocketException(env, err);
2343 static jboolean osNetworkSystem_socketBindImpl2(JNIEnv* env, jclass clazz,
2344 jobject fileDescriptor, jint port, jboolean bindToDevice,
2345 jobject inetAddress) {
2346 // LOGD("ENTER socketBindImpl2");
2348 struct sockaddr_storage sockaddress;
2352 ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddress);
2353 if (ret < 0) // Exception has already been thrown.
2356 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2357 if (handle == 0 || handle == -1) {
2358 throwSocketException(env, SOCKERR_BADDESC);
2362 ret = doBind(handle, &sockaddress);
2364 int err = convertError(errno);
2365 jniThrowException(env, "java/net/BindException", netLookupErrorString(err));
2372 static jint osNetworkSystem_peekDatagramImpl(JNIEnv* env, jclass clazz,
2373 jobject fd, jobject sender, jint receiveTimeout) {
2374 // LOGD("ENTER peekDatagramImpl");
2378 int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
2383 int handle = jniGetFDFromFileDescriptor(env, fd);
2384 if (handle == 0 || handle == -1) {
2385 throwSocketException(env, SOCKERR_BADDESC);
2389 struct sockaddr_storage sockAddr;
2390 socklen_t sockAddrLen = sizeof(sockAddr);
2393 length = recvfrom(handle, NULL, 0, MSG_PEEK,
2394 (struct sockaddr *)&sockAddr, &sockAddrLen);
2395 } while (length < 0 && errno == EINTR);
2397 int err = convertError(errno);
2398 throwSocketException(env, err);
2402 sender = socketAddressToInetAddress(env, &sockAddr);
2403 if (sender == NULL) // Exception has already been thrown.
2406 port = getSocketAddressPort(&sockAddr);
2410 static jint osNetworkSystem_receiveDatagramDirectImpl(JNIEnv* env, jclass clazz,
2411 jobject fd, jobject packet, jint address, jint offset, jint length,
2412 jint receiveTimeout, jboolean peek) {
2413 // LOGD("ENTER receiveDatagramDirectImpl");
2415 int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
2420 int handle = jniGetFDFromFileDescriptor(env, fd);
2421 if (handle == 0 || handle == -1) {
2422 throwSocketException(env, SOCKERR_BADDESC);
2426 struct sockaddr_storage sockAddr;
2427 socklen_t sockAddrLen = sizeof(sockAddr);
2429 int mode = peek ? MSG_PEEK : 0;
2431 ssize_t actualLength;
2433 actualLength = recvfrom(handle, (char*)(address + offset), length, mode,
2434 (struct sockaddr *)&sockAddr, &sockAddrLen);
2435 } while (actualLength < 0 && errno == EINTR);
2436 if (actualLength < 0) {
2437 int err = convertError(errno);
2438 throwSocketException(env, err);
2442 if (packet != NULL) {
2443 jbyteArray addr = socketAddressToAddressBytes(env, &sockAddr);
2444 if (addr == NULL) // Exception has already been thrown.
2446 int port = getSocketAddressPort(&sockAddr);
2447 jobject sender = env->CallStaticObjectMethod(
2448 gCachedFields.iaddr_class, gCachedFields.iaddr_getbyaddress,
2450 env->SetObjectField(packet, gCachedFields.dpack_address, sender);
2451 env->SetIntField(packet, gCachedFields.dpack_port, port);
2452 env->SetIntField(packet, gCachedFields.dpack_length,
2453 (jint) actualLength);
2455 return (jint) actualLength;
2458 static jint osNetworkSystem_receiveDatagramImpl(JNIEnv* env, jclass clazz,
2459 jobject fd, jobject packet, jbyteArray data, jint offset, jint length,
2460 jint receiveTimeout, jboolean peek) {
2461 // LOGD("ENTER receiveDatagramImpl");
2463 int localLength = (length < 65536) ? length : 65536;
2464 jbyte *bytes = (jbyte*) malloc(localLength);
2465 if (bytes == NULL) {
2466 jniThrowException(env, "java/lang/OutOfMemoryError",
2467 "couldn't allocate enough memory for receiveDatagram");
2471 int actualLength = osNetworkSystem_receiveDatagramDirectImpl(env, clazz, fd,
2472 packet, (jint)bytes, 0, localLength, receiveTimeout, peek);
2474 if (actualLength > 0) {
2475 env->SetByteArrayRegion(data, offset, actualLength, bytes);
2479 return actualLength;
2482 static jint osNetworkSystem_recvConnectedDatagramDirectImpl(JNIEnv* env,
2483 jclass clazz, jobject fd, jobject packet, jint address, jint offset,
2484 jint length, jint receiveTimeout, jboolean peek) {
2485 // LOGD("ENTER receiveConnectedDatagramDirectImpl");
2487 int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
2493 int handle = jniGetFDFromFileDescriptor(env, fd);
2495 if (handle == 0 || handle == -1) {
2496 throwSocketException(env, SOCKERR_BADSOCKET);
2500 int mode = peek ? MSG_PEEK : 0;
2502 int actualLength = recvfrom(handle,
2503 (char*)(address + offset), length, mode, NULL, NULL);
2505 if (actualLength < 0) {
2506 jniThrowException(env, "java/net/PortUnreachableException", "");
2510 if ( packet != NULL) {
2511 env->SetIntField(packet, gCachedFields.dpack_length, actualLength);
2513 return actualLength;
2516 static jint osNetworkSystem_recvConnectedDatagramImpl(JNIEnv* env, jclass clazz,
2517 jobject fd, jobject packet, jbyteArray data, jint offset, jint length,
2518 jint receiveTimeout, jboolean peek) {
2519 // LOGD("ENTER receiveConnectedDatagramImpl");
2521 int localLength = (length < 65536) ? length : 65536;
2522 jbyte *bytes = (jbyte*) malloc(localLength);
2523 if (bytes == NULL) {
2524 jniThrowException(env, "java/lang/OutOfMemoryError",
2525 "couldn't allocate enough memory for recvConnectedDatagram");
2529 int actualLength = osNetworkSystem_recvConnectedDatagramDirectImpl(env,
2530 clazz, fd, packet, (jint)bytes, 0, localLength,
2531 receiveTimeout, peek);
2533 if (actualLength > 0) {
2534 env->SetByteArrayRegion(data, offset, actualLength, bytes);
2538 return actualLength;
2541 static jint osNetworkSystem_sendDatagramDirectImpl(JNIEnv* env, jclass clazz,
2542 jobject fd, jint address, jint offset, jint length, jint port,
2543 jboolean bindToDevice, jint trafficClass, jobject inetAddress) {
2544 // LOGD("ENTER sendDatagramDirectImpl");
2546 int handle = jniGetFDFromFileDescriptor(env, fd);
2548 if (handle == 0 || handle == -1) {
2549 throwSocketException(env, SOCKERR_BADSOCKET);
2553 struct sockaddr_storage receiver;
2554 if (inetAddressToSocketAddress(env, inetAddress, port, &receiver) < 0) {
2555 // Exception has already been thrown.
2561 result = sendto(handle, (char*)(address + offset), length,
2562 SOCKET_NOFLAGS, (struct sockaddr*)&receiver, sizeof(receiver));
2563 } while (result < 0 && errno == EINTR);
2565 int err = convertError(errno);
2566 if ((SOCKERR_CONNRESET == err)
2567 || (SOCKERR_CONNECTION_REFUSED == err)) {
2570 throwSocketException(env, err);
2574 return (jint) result;
2577 static jint osNetworkSystem_sendDatagramImpl(JNIEnv* env, jclass clazz,
2578 jobject fd, jbyteArray data, jint offset, jint length, jint port,
2579 jboolean bindToDevice, jint trafficClass, jobject inetAddress) {
2580 // LOGD("ENTER sendDatagramImpl");
2582 jbyte *bytes = env->GetByteArrayElements(data, NULL);
2583 int actualLength = osNetworkSystem_sendDatagramDirectImpl(env, clazz, fd,
2584 (jint)bytes, offset, length, port, bindToDevice, trafficClass,
2586 env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
2588 return actualLength;
2591 static jint osNetworkSystem_sendConnectedDatagramDirectImpl(JNIEnv* env,
2592 jclass clazz, jobject fd, jint address, jint offset, jint length,
2593 jboolean bindToDevice) {
2594 // LOGD("ENTER sendConnectedDatagramDirectImpl");
2596 int handle = jniGetFDFromFileDescriptor(env, fd);
2598 if (handle == 0 || handle == -1) {
2599 throwSocketException(env, SOCKERR_BADSOCKET);
2603 int result = send(handle, (char*)(address + offset), length, 0);
2606 int err = convertError(errno);
2607 if ((SOCKERR_CONNRESET == err) || (SOCKERR_CONNECTION_REFUSED == err)) {
2610 throwSocketException(env, err);
2617 static jint osNetworkSystem_sendConnectedDatagramImpl(JNIEnv* env, jclass clazz,
2618 jobject fd, jbyteArray data, jint offset, jint length,
2619 jboolean bindToDevice) {
2620 // LOGD("ENTER sendConnectedDatagramImpl");
2622 jbyte *bytes = env->GetByteArrayElements(data, NULL);
2623 int actualLength = osNetworkSystem_sendConnectedDatagramDirectImpl(env,
2624 clazz, fd, (jint)bytes, offset, length, bindToDevice);
2625 env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
2627 return actualLength;
2630 static void osNetworkSystem_createServerStreamSocketImpl(JNIEnv* env,
2631 jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) {
2632 // LOGD("ENTER createServerStreamSocketImpl");
2634 int handle = createSocketFileDescriptor(env, fileDescriptor, SOCK_STREAM);
2639 setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
2642 static void osNetworkSystem_createMulticastSocketImpl(JNIEnv* env,
2643 jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) {
2644 // LOGD("ENTER createMulticastSocketImpl");
2646 int handle = createSocketFileDescriptor(env, fileDescriptor, SOCK_DGRAM);
2651 // setsockopt(handle, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(jbyte));
2652 setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
2656 * @param timeout in milliseconds. If zero, block until data received
2658 static jint osNetworkSystem_receiveStreamImpl(JNIEnv* env, jclass clazz,
2659 jobject fileDescriptor, jbyteArray data, jint offset, jint count,
2661 // LOGD("ENTER receiveStreamImpl");
2664 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2666 if (handle == 0 || handle == -1) {
2667 throwSocketException(env, SOCKERR_BADSOCKET);
2671 // Cap read length to available buf size
2672 int spaceAvailable = env->GetArrayLength(data) - offset;
2673 int localCount = count < spaceAvailable? count : spaceAvailable;
2676 jbyte *body = env->GetByteArrayElements(data, &isCopy);
2680 tv.tv_sec = timeout / 1000;
2681 tv.tv_usec = (timeout % 1000) * 1000;
2682 setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv,
2683 sizeof(struct timeval));
2686 result = recv(handle, body + offset, localCount, SOCKET_NOFLAGS);
2687 } while (result < 0 && errno == EINTR);
2689 env->ReleaseByteArrayElements(data, body, 0);
2692 * If no bytes are read, return -1 to signal 'endOfFile'
2693 * to the Java input stream
2697 } else if (0 == result) {
2700 // If EAGAIN or EWOULDBLOCK, read timed out
2701 if (errno == EAGAIN || errno == EWOULDBLOCK) {
2702 jniThrowException(env, "java/net/SocketTimeoutException",
2703 netLookupErrorString(SOCKERR_TIMEOUT));
2705 int err = convertError(errno);
2706 throwSocketException(env, err);
2712 static jint osNetworkSystem_sendStreamImpl(JNIEnv* env, jclass clazz,
2713 jobject fileDescriptor, jbyteArray data, jint offset, jint count) {
2714 // LOGD("ENTER sendStreamImpl");
2717 int result = 0, sent = 0;
2720 jbyte *message = env->GetByteArrayElements(data, &isCopy);
2722 // Cap write length to available buf size
2723 int spaceAvailable = env->GetArrayLength(data) - offset;
2724 if (count > spaceAvailable) count = spaceAvailable;
2726 while (sent < count) {
2728 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2729 if (handle == 0 || handle == -1) {
2730 throwSocketException(env,
2731 sent == 0 ? SOCKERR_BADSOCKET : SOCKERR_INTERRUPTED);
2732 env->ReleaseByteArrayElements(data, message, 0);
2736 // LOGD("before select %d", count);
2737 selectWait(handle, SEND_RETRY_TIME, SELECT_WRITE_TYPE);
2738 result = send(handle, (jbyte *)message + offset + sent,
2739 (int) count - sent, SOCKET_NOFLAGS);
2743 if (result == EAGAIN ||result == EWOULDBLOCK) {
2744 // LOGD("write blocked %d", sent);
2747 env->ReleaseByteArrayElements(data, message, 0);
2748 int err = convertError(result);
2749 throwSocketException(env, err);
2755 env->ReleaseByteArrayElements(data, message, 0);
2759 static void osNetworkSystem_shutdownInputImpl(JNIEnv* env, jobject obj,
2760 jobject fileDescriptor) {
2761 // LOGD("ENTER shutdownInputImpl");
2766 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2768 if (handle == 0 || handle == -1) {
2769 throwSocketException(env, SOCKERR_BADSOCKET);
2773 ret = shutdown(handle, SHUT_RD);
2776 int err = convertError(errno);
2777 throwSocketException(env, err);
2782 static void osNetworkSystem_shutdownOutputImpl(JNIEnv* env, jobject obj,
2783 jobject fileDescriptor) {
2784 // LOGD("ENTER shutdownOutputImpl");
2789 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2791 if (handle == 0 || handle == -1) {
2795 ret = shutdown(handle, SHUT_WR);
2798 int err = convertError(errno);
2799 throwSocketException(env, err);
2804 static jint osNetworkSystem_sendDatagramImpl2(JNIEnv* env, jclass clazz,
2805 jobject fd, jbyteArray data, jint offset, jint length, jint port,
2806 jobject inetAddress) {
2807 // LOGD("ENTER sendDatagramImpl2");
2810 unsigned short nPort;
2811 int ret = 0, sent = 0;
2813 struct sockaddr_storage sockaddrP;
2815 if (inetAddress != NULL) {
2816 ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddrP);
2817 if (ret < 0) // Exception has already been thrown.
2820 handle = jniGetFDFromFileDescriptor(env, fd);
2821 if (handle == 0 || handle == -1) {
2822 throwSocketException(env, SOCKERR_BADDESC);
2827 message = (jbyte*) malloc(length * sizeof(jbyte));
2828 if (message == NULL) {
2829 jniThrowException(env, "java/lang/OutOfMemoryError",
2830 "couldn't allocate enough memory for readSocket");
2834 env->GetByteArrayRegion(data, offset, length, message);
2836 while (sent < length) {
2837 handle = jniGetFDFromFileDescriptor(env, fd);
2839 if (handle == 0 || handle == -1) {
2840 throwSocketException(env,
2841 sent == 0 ? SOCKERR_BADDESC : SOCKERR_INTERRUPTED);
2848 result = sendto(handle, (char *) (message + sent),
2849 (int) (length - sent), SOCKET_NOFLAGS,
2850 (struct sockaddr *) &sockaddrP, sizeof(sockaddrP));
2851 } while (result < 0 && errno == EINTR);
2853 int err = convertError(errno);
2854 throwSocketException(env, err);
2866 static jint osNetworkSystem_selectImpl(JNIEnv* env, jclass clazz,
2867 jobjectArray readFDArray, jobjectArray writeFDArray, jint countReadC,
2868 jint countWriteC, jintArray outFlags, jlong timeout) {
2869 // LOGD("ENTER selectImpl");
2871 struct timeval timeP;
2875 fd_set *fdset_read,*fdset_write;
2880 unsigned int time_sec = (unsigned int)timeout/1000;
2881 unsigned int time_msec = (unsigned int)(timeout%1000);
2883 fdset_read = (fd_set *)malloc(sizeof(fd_set));
2884 fdset_write = (fd_set *)malloc(sizeof(fd_set));
2886 FD_ZERO(fdset_read);
2887 FD_ZERO(fdset_write);
2889 for (val = 0; val<countReadC; val++) {
2891 gotFD = env->GetObjectArrayElement(readFDArray,val);
2893 handle = jniGetFDFromFileDescriptor(env, gotFD);
2895 FD_SET(handle, fdset_read);
2897 if (0 > (size - handle)) {
2902 for (val = 0; val<countWriteC; val++) {
2904 gotFD = env->GetObjectArrayElement(writeFDArray,val);
2906 handle = jniGetFDFromFileDescriptor(env, gotFD);
2908 FD_SET(handle, fdset_write);
2910 if (0 > (size - handle)) {
2915 /* the size is the max_fd + 1 */
2919 result = SOCKERR_FDSET_SIZEBAD;
2921 /* only set when timeout >= 0 (non-block)*/
2924 timeP.tv_sec = time_sec;
2925 timeP.tv_usec = time_msec*1000;
2927 result = sockSelect(size, fdset_read, fdset_write, NULL, &timeP);
2930 result = sockSelect(size, fdset_read, fdset_write, NULL, NULL);
2935 /*output the result to a int array*/
2936 flagArray = env->GetIntArrayElements(outFlags, &isCopy);
2938 for (val=0; val<countReadC; val++) {
2939 gotFD = env->GetObjectArrayElement(readFDArray,val);
2941 handle = jniGetFDFromFileDescriptor(env, gotFD);
2943 if (FD_ISSET(handle,fdset_read)) {
2944 flagArray[val] = SOCKET_OP_READ;
2946 flagArray[val] = SOCKET_OP_NONE;
2950 for (val=0; val<countWriteC; val++) {
2952 gotFD = env->GetObjectArrayElement(writeFDArray,val);
2954 handle = jniGetFDFromFileDescriptor(env, gotFD);
2956 if (FD_ISSET(handle,fdset_write)) {
2957 flagArray[val+countReadC] = SOCKET_OP_WRITE;
2959 flagArray[val+countReadC] = SOCKET_OP_NONE;
2963 env->ReleaseIntArrayElements(outFlags, flagArray, 0);
2969 /* return both correct and error result, let java handle the exception*/
2973 static jobject osNetworkSystem_getSocketLocalAddressImpl(JNIEnv* env,
2974 jclass clazz, jobject fileDescriptor, jboolean preferIPv6Addresses) {
2975 // LOGD("ENTER getSocketLocalAddressImpl");
2977 struct sockaddr_storage addr;
2978 socklen_t addrLen = sizeof(addr);
2980 memset(&addr, 0, addrLen);
2983 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2984 if (handle == 0 || handle == -1) {
2985 throwSocketException(env, SOCKERR_UNKNOWNSOCKET);
2990 result = getsockname(handle, (struct sockaddr *)&addr, &addrLen);
2992 // Spec says ignore all errors
2993 return socketAddressToInetAddress(env, &addr);
2996 static jint osNetworkSystem_getSocketLocalPortImpl(JNIEnv* env, jclass clazz,
2997 jobject fileDescriptor, jboolean preferIPv6Addresses) {
2998 // LOGD("ENTER getSocketLocalPortImpl");
3000 struct sockaddr_storage addr;
3001 socklen_t addrLen = sizeof(addr);
3003 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
3006 if (handle == 0 || handle == -1) {
3007 throwSocketException(env, SOCKERR_UNKNOWNSOCKET);
3011 result = getsockname(handle, (struct sockaddr *)&addr, &addrLen);
3014 // The java spec does not indicate any exceptions on this call
3017 return getSocketAddressPort(&addr);
3021 static jobject osNetworkSystem_getSocketOptionImpl(JNIEnv* env, jclass clazz,
3022 jobject fileDescriptor, jint anOption) {
3023 // LOGD("ENTER getSocketOptionImpl");
3027 socklen_t intSize = sizeof(int);
3028 unsigned char byteValue = 0;
3029 socklen_t byteSize = sizeof(unsigned char);
3031 struct sockaddr_storage sockVal;
3032 socklen_t sockSize = sizeof(sockVal);
3034 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
3035 if (handle == 0 || handle == -1) {
3036 throwSocketException(env, SOCKERR_BADDESC);
3040 switch ((int) anOption & 0xffff) {
3041 case JAVASOCKOPT_SO_LINGER: {
3042 struct linger lingr;
3043 socklen_t size = sizeof(struct linger);
3044 result = getsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr, &size);
3046 throwSocketException(env, convertError(errno));
3049 if (!lingr.l_onoff) {
3052 intValue = lingr.l_linger;
3054 return newJavaLangInteger(env, intValue);
3056 case JAVASOCKOPT_TCP_NODELAY: {
3057 if ((anOption >> 16) & BROKEN_TCP_NODELAY) {
3060 result = getsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intValue, &intSize);
3062 throwSocketException(env, convertError(errno));
3065 return newJavaLangBoolean(env, intValue);
3067 case JAVASOCKOPT_MCAST_TTL: {
3068 if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
3069 return newJavaLangByte(env, 0);
3071 result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_MULTICAST_TTL,
3072 IPV6_MULTICAST_HOPS, &byteValue,
3075 throwSocketException(env, convertError(errno));
3078 return newJavaLangByte(env, (jbyte)(byteValue & 0xFF));
3080 case JAVASOCKOPT_MCAST_INTERFACE: {
3081 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3084 result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, &sockVal, &sockSize);
3086 throwSocketException(env, convertError(errno));
3089 // This option is IPv4-only.
3090 sockVal.ss_family = AF_INET;
3091 return socketAddressToInetAddress(env, &sockVal);
3093 case JAVASOCKOPT_IP_MULTICAST_IF2: {
3094 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3097 struct ip_mreqn multicastRequest;
3099 socklen_t optionLength;
3100 int addressFamily = getSocketAddressFamily(handle);
3101 switch (addressFamily) {
3103 optionLength = sizeof(multicastRequest);
3104 result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
3105 &multicastRequest, &optionLength);
3107 interfaceIndex = multicastRequest.imr_ifindex;
3110 optionLength = sizeof(interfaceIndex);
3111 result = getsockopt(handle, IPPROTO_IPV6, IPV6_MULTICAST_IF,
3112 &interfaceIndex, &optionLength);
3115 throwSocketException(env, SOCKERR_BADAF);
3120 throwSocketException(env, convertError(errno));
3124 return newJavaLangInteger(env, interfaceIndex);
3126 case JAVASOCKOPT_SO_SNDBUF: {
3127 result = getsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intValue, &intSize);
3129 throwSocketException(env, convertError(errno));
3132 return newJavaLangInteger(env, intValue);
3134 case JAVASOCKOPT_SO_RCVBUF: {
3135 result = getsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intValue, &intSize);
3137 throwSocketException(env, convertError(errno));
3140 return newJavaLangInteger(env, intValue);
3142 case JAVASOCKOPT_SO_BROADCAST: {
3143 result = getsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intValue, &intSize);
3145 throwSocketException(env, convertError(errno));
3148 return newJavaLangBoolean(env, intValue);
3150 case JAVASOCKOPT_SO_REUSEADDR: {
3151 result = getsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intValue, &intSize);
3153 throwSocketException(env, convertError(errno));
3156 return newJavaLangBoolean(env, intValue);
3158 case JAVASOCKOPT_SO_KEEPALIVE: {
3159 result = getsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intValue, &intSize);
3161 throwSocketException(env, convertError(errno));
3164 return newJavaLangBoolean(env, intValue);
3166 case JAVASOCKOPT_SO_OOBINLINE: {
3167 result = getsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intValue, &intSize);
3169 throwSocketException(env, convertError(errno));
3172 return newJavaLangBoolean(env, intValue);
3174 case JAVASOCKOPT_IP_MULTICAST_LOOP: {
3175 result = getOrSetSocketOption(SOCKOPT_GET, handle,
3177 IPV6_MULTICAST_LOOP, &intValue,
3180 throwSocketException(env, convertError(errno));
3183 return newJavaLangBoolean(env, intValue);
3185 case JAVASOCKOPT_IP_TOS: {
3186 result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_TOS,
3187 IPV6_TCLASS, &intValue, &intSize);
3189 throwSocketException(env, convertError(errno));
3192 return newJavaLangInteger(env, intValue);
3194 case JAVASOCKOPT_SO_RCVTIMEOUT: {
3195 struct timeval timeout;
3196 socklen_t size = sizeof(timeout);
3197 result = getsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout, &size);
3199 throwSocketException(env, convertError(errno));
3202 return newJavaLangInteger(env, timeout.tv_sec * 1000 + timeout.tv_usec/1000);
3205 throwSocketException(env, SOCKERR_OPTUNSUPP);
3212 static void osNetworkSystem_setSocketOptionImpl(JNIEnv* env, jclass clazz,
3213 jobject fileDescriptor, jint anOption, jobject optVal) {
3214 // LOGD("ENTER setSocketOptionImpl");
3218 socklen_t intSize = sizeof(int);
3219 unsigned char byteVal;
3220 socklen_t byteSize = sizeof(unsigned char);
3221 struct sockaddr_storage sockVal;
3222 int sockSize = sizeof(sockVal);
3224 if (env->IsInstanceOf(optVal, gCachedFields.integer_class)) {
3225 intVal = (int) env->GetIntField(optVal, gCachedFields.integer_class_value);
3226 } else if (env->IsInstanceOf(optVal, gCachedFields.boolean_class)) {
3227 intVal = (int) env->GetBooleanField(optVal, gCachedFields.boolean_class_value);
3228 } else if (env->IsInstanceOf(optVal, gCachedFields.byte_class)) {
3229 byteVal = (int) env->GetByteField(optVal, gCachedFields.byte_class_value);
3230 } else if (env->IsInstanceOf(optVal, gCachedFields.iaddr_class)) {
3231 if (inetAddressToSocketAddress(env, optVal, 0, &sockVal) < 0) {
3232 // Exception has already been thrown.
3235 } else if (env->IsInstanceOf(optVal, gCachedFields.genericipmreq_class)) {
3236 // we'll use optVal directly
3238 throwSocketException(env, SOCKERR_OPTUNSUPP);
3242 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
3243 if (handle == 0 || handle == -1) {
3244 throwSocketException(env, SOCKERR_BADDESC);
3248 switch ((int) anOption & 0xffff) {
3249 case JAVASOCKOPT_SO_LINGER: {
3250 struct linger lingr;
3251 lingr.l_onoff = intVal > 0 ? 1 : 0;
3252 lingr.l_linger = intVal;
3253 result = setsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr,
3254 sizeof(struct linger));
3256 throwSocketException(env, convertError(errno));
3262 case JAVASOCKOPT_TCP_NODELAY: {
3263 if ((anOption >> 16) & BROKEN_TCP_NODELAY) {
3266 result = setsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intVal, intSize);
3268 throwSocketException(env, convertError(errno));
3274 case JAVASOCKOPT_MCAST_TTL: {
3275 if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
3278 result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_MULTICAST_TTL,
3279 IPV6_MULTICAST_HOPS, &byteVal,
3282 throwSocketException(env, convertError(errno));
3288 case JAVASOCKOPT_MCAST_ADD_MEMBERSHIP: {
3289 mcastAddDropMembership(env, handle, optVal,
3290 (anOption >> 16) & BROKEN_MULTICAST_IF, IP_ADD_MEMBERSHIP);
3294 case JAVASOCKOPT_MCAST_DROP_MEMBERSHIP: {
3295 mcastAddDropMembership(env, handle, optVal,
3296 (anOption >> 16) & BROKEN_MULTICAST_IF, IP_DROP_MEMBERSHIP);
3300 case JAVASOCKOPT_MCAST_INTERFACE: {
3301 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3304 // This call is IPv4 only.
3305 if (getSocketAddressFamily(handle) != AF_INET) {
3306 throwSocketException(env, SOCKERR_BADAF);
3309 struct ip_mreqn mcast_req;
3310 memset(&mcast_req, 0, sizeof(mcast_req));
3311 struct sockaddr_in *sin = (struct sockaddr_in *) &sockVal;
3312 mcast_req.imr_address = sin->sin_addr;
3313 result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
3314 &mcast_req, sizeof(mcast_req));
3316 throwSocketException(env, convertError(errno));
3322 case JAVASOCKOPT_IP_MULTICAST_IF2: {
3323 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3326 int addressFamily = getSocketAddressFamily(handle);
3327 int interfaceIndex = intVal;
3329 socklen_t optionLength;
3330 struct ip_mreqn multicastRequest;
3331 switch (addressFamily) {
3333 // IP_MULTICAST_IF expects a pointer to a struct ip_mreqn.
3334 memset(&multicastRequest, 0, sizeof(multicastRequest));
3335 multicastRequest.imr_ifindex = interfaceIndex;
3336 optionValue = &multicastRequest;
3337 optionLength = sizeof(multicastRequest);
3340 // IPV6_MULTICAST_IF expects a pointer to an integer.
3341 optionValue = &interfaceIndex;
3342 optionLength = sizeof(interfaceIndex);
3345 throwSocketException(env, SOCKERR_BADAF);
3348 result = getOrSetSocketOption(SOCKOPT_SET, handle,
3349 IP_MULTICAST_IF, IPV6_MULTICAST_IF, optionValue,
3352 throwSocketException(env, convertError(errno));
3358 case JAVASOCKOPT_SO_SNDBUF: {
3359 result = setsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intVal, intSize);
3361 throwSocketException(env, convertError(errno));
3367 case JAVASOCKOPT_SO_RCVBUF: {
3368 result = setsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intVal, intSize);
3370 throwSocketException(env, convertError(errno));
3376 case JAVASOCKOPT_SO_BROADCAST: {
3377 result = setsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intVal, intSize);
3379 throwSocketException(env, convertError(errno));
3385 case JAVASOCKOPT_SO_REUSEADDR: {
3386 result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
3388 throwSocketException(env, convertError(errno));
3393 case JAVASOCKOPT_SO_KEEPALIVE: {
3394 result = setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intVal, intSize);
3396 throwSocketException(env, convertError(errno));
3402 case JAVASOCKOPT_SO_OOBINLINE: {
3403 result = setsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intVal, intSize);
3405 throwSocketException(env, convertError(errno));
3411 case JAVASOCKOPT_IP_MULTICAST_LOOP: {
3412 result = getOrSetSocketOption(SOCKOPT_SET, handle,
3414 IPV6_MULTICAST_LOOP, &intVal,
3417 throwSocketException(env, convertError(errno));
3423 case JAVASOCKOPT_IP_TOS: {
3424 result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_TOS,
3425 IPV6_TCLASS, &intVal, &intSize);
3427 throwSocketException(env, convertError(errno));
3433 case JAVASOCKOPT_REUSEADDR_AND_REUSEPORT: {
3434 // SO_REUSEPORT doesn't need to get set on this System
3435 result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
3437 throwSocketException(env, convertError(errno));
3443 case JAVASOCKOPT_SO_RCVTIMEOUT: {
3444 struct timeval timeout;
3445 timeout.tv_sec = intVal / 1000;
3446 timeout.tv_usec = (intVal % 1000) * 1000;
3447 result = setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout,
3448 sizeof(struct timeval));
3450 throwSocketException(env, convertError(errno));
3457 throwSocketException(env, SOCKERR_OPTUNSUPP);
3462 static jint osNetworkSystem_getSocketFlagsImpl(JNIEnv* env, jclass clazz) {
3463 // LOGD("ENTER getSocketFlagsImpl");
3465 // Not implemented by harmony
3469 static void osNetworkSystem_socketCloseImpl(JNIEnv* env, jclass clazz,
3470 jobject fileDescriptor) {
3471 // LOGD("ENTER socketCloseImpl");
3473 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
3475 if (handle == 0 || handle == -1) {
3476 throwSocketException(env, SOCKERR_BADSOCKET);
3480 jniSetFileDescriptorOfFD(env, fileDescriptor, -1);
3485 static jobject osNetworkSystem_getHostByAddrImpl(JNIEnv* env, jclass clazz,
3486 jbyteArray addrStr) {
3487 // LOGD("ENTER getHostByAddrImpl");
3489 if (addrStr == NULL) {
3490 throwNullPointerException(env);
3494 jstring address = (jstring)newJavaLangString(env, addrStr);
3496 const char* addr = env->GetStringUTFChars(address, NULL);
3498 struct hostent* ent = gethostbyaddr(addr, strlen(addr), AF_INET);
3500 if (ent != NULL && ent->h_name != NULL) {
3501 result = env->NewStringUTF(ent->h_name);
3506 env->ReleaseStringUTFChars(address, addr);
3511 static jobject osNetworkSystem_getHostByNameImpl(JNIEnv* env, jclass clazz,
3512 jstring nameStr, jboolean preferIPv6Addresses) {
3513 // LOGD("ENTER getHostByNameImpl");
3515 if (nameStr == NULL) {
3516 throwNullPointerException(env);
3520 const char* name = env->GetStringUTFChars(nameStr, NULL);
3522 if (useAdbNetworking) {
3529 // LOGD("ADB networking: +gethostbyname '%s'", name);
3531 err = adb_networking_gethostbyname(name, &(outaddr.a));
3533 env->ReleaseStringUTFChars(nameStr, name);
3535 LOGD("ADB networking: -gethostbyname err %d addr 0x%08x %u.%u.%u.%u",
3536 err, (unsigned int)outaddr.a.s_addr,
3537 outaddr.j[0],outaddr.j[1],
3538 outaddr.j[2],outaddr.j[3]);
3544 jbyteArray addr = env->NewByteArray(4);
3545 env->SetByteArrayRegion(addr, 0, 4, outaddr.j);
3550 // normal case...no adb networking
3551 struct hostent* ent = gethostbyname(name);
3553 env->ReleaseStringUTFChars(nameStr, name);
3555 if (ent != NULL && ent->h_length > 0) {
3556 jbyteArray addr = env->NewByteArray(4);
3558 memcpy(v, ent->h_addr, 4);
3559 env->SetByteArrayRegion(addr, 0, 4, v);
3567 static void osNetworkSystem_setInetAddressImpl(JNIEnv* env, jobject obj,
3568 jobject sender, jbyteArray address) {
3569 // LOGD("ENTER setInetAddressImpl");
3571 env->SetObjectField(sender, gCachedFields.iaddr_ipaddress, address);
3574 // TODO: rewrite this method in Java and make it support IPv6.
3575 static jobject osNetworkSystem_inheritedChannelImpl(JNIEnv* env, jobject obj) {
3576 // LOGD("ENTER inheritedChannelImpl");
3580 socklen_t length = sizeof(opt);
3582 struct sockaddr_in local_addr;
3583 struct sockaddr_in remote_addr;
3584 jclass channel_class, socketaddr_class, serverSocket_class, socketImpl_class;
3585 jobject channel_object = NULL, socketaddr_object, serverSocket_object;
3586 jobject fd_object, addr_object, localAddr_object, socketImpl_object;
3587 jfieldID port_field, socketaddr_field, bound_field, fd_field;
3588 jfieldID serverSocket_field, socketImpl_field, addr_field, localAddr_field;
3589 jmethodID channel_new;
3590 jbyteArray addr_array;
3591 struct sockaddr_in *sock;
3594 jboolean jtrue = JNI_TRUE;
3596 if (0 != getsockopt(socket, SOL_SOCKET, SO_TYPE, &opt, &length)) {
3599 if (SOCK_STREAM !=opt && SOCK_DGRAM !=opt) {
3604 length = sizeof(struct sockaddr);
3605 if (0 != getsockname(socket, (struct sockaddr *)&local_addr, &length)) {
3608 if (AF_INET != local_addr.sin_family || length != sizeof(struct sockaddr)) {
3611 localAddr = (jbyte*) malloc(sizeof(jbyte)*4);
3612 if (NULL == localAddr) {
3615 memcpy (localAddr, &(local_addr.sin_addr.s_addr), 4);
3617 if (0 != getpeername(socket, (struct sockaddr *)&remote_addr, &length)) {
3618 remote_addr.sin_port = 0;
3619 remote_addr.sin_addr.s_addr = 0;
3620 address = (jbyte*) malloc(sizeof(jbyte)*4);
3621 bzero(address, sizeof(jbyte)*4);
3623 if (AF_INET != remote_addr.sin_family
3624 || length != sizeof(struct sockaddr)) {
3627 address = (jbyte*) malloc(sizeof(jbyte)*4);
3628 memcpy (address, &(remote_addr.sin_addr.s_addr), 4);
3631 // analysis end, begin pack to java
3632 if (SOCK_STREAM == opt) {
3633 if (remote_addr.sin_port!=0) {
3635 channel_class = env->FindClass(
3636 "org/apache/harmony/nio/internal/SocketChannelImpl");
3637 if (NULL == channel_class) {
3641 channel_new = env->GetMethodID(channel_class, "<init>", "()V");
3642 if (NULL == channel_new) {
3645 channel_object = env->NewObject(channel_class, channel_new);
3646 if (NULL == channel_object) {
3649 // new and set FileDescript
3651 fd_field = env->GetFieldID(channel_class, "fd",
3652 "java/io/FielDescriptor");
3653 fd_object = env->GetObjectField(channel_object, fd_field);
3654 if (NULL == fd_object) {
3658 jniSetFileDescriptorOfFD(env, fd_object, socket);
3661 port_field = env->GetFieldID(channel_class, "localPort", "I");
3662 env->SetIntField(channel_object, port_field,
3663 ntohs(local_addr.sin_port));
3665 // new and set remote addr
3666 addr_object = env->NewObject(gCachedFields.iaddr_class,
3667 gCachedFields.iaddr_class_init);
3668 if (NULL == addr_object) {
3671 socketaddr_class = env->FindClass("java/net/InetSocketAddress");
3672 socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
3673 "Ljava/net/InetSocketAddress;");
3674 socketaddr_object = env->GetObjectField(channel_object,
3676 if (NULL == socketaddr_object) {
3679 addr_field = env->GetFieldID(socketaddr_class, "addr",
3680 "Ljava/net/InetAddress;");
3681 env->SetObjectField(socketaddr_object, addr_field, addr_object);
3682 addr_array = env->NewByteArray((jsize)4);
3683 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
3684 env->SetObjectField(addr_object, gCachedFields.iaddr_ipaddress,
3688 socketaddr_class = env->FindClass("java/net/InetSocketAddress");
3689 socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
3690 "Ljava/net/InetSocketAddress;");
3691 socketaddr_object = env->GetObjectField(channel_object,
3694 localAddr_field = env->GetFieldID(channel_class, "localAddress",
3695 "Ljava/net/InetAddress;");
3696 localAddr_object = env->NewObject(gCachedFields.iaddr_class,
3697 gCachedFields.iaddr_class_init);
3698 jfieldID socketaddr_field = env->GetFieldID(channel_class,
3699 "connectAddress", "Ljava/net/InetSocketAddress;");
3700 jobject socketaddr_object = env->GetObjectField(channel_object,
3702 env->SetObjectField(socketaddr_object, localAddr_field,
3704 if (NULL == localAddr_object) {
3707 addr_array = env->NewByteArray((jsize)4);
3708 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, localAddr);
3709 env->SetObjectField(localAddr_object, gCachedFields.iaddr_ipaddress,
3714 port_field = env->GetFieldID(socketaddr_class, "port", "I");
3715 env->SetIntField(socketaddr_object, port_field,
3716 ntohs(remote_addr.sin_port));
3719 if (0 != local_addr.sin_port) {
3720 bound_field = env->GetFieldID(channel_class, "isBound", "Z");
3721 env->SetBooleanField(channel_object, bound_field, jtrue);
3726 channel_class = env->FindClass(
3727 "org/apache/harmony/nio/internal/ServerSocketChannelImpl");
3728 if (NULL == channel_class) {
3732 channel_new = env->GetMethodID(channel_class, "<init>", "()V");
3733 if (NULL == channel_new) {
3736 channel_object = env->NewObject(channel_class, channel_new);
3737 if (NULL == channel_object) {
3741 serverSocket_field = env->GetFieldID(channel_class, "socket",
3742 "Ljava/net/ServerSocket;");
3743 serverSocket_class = env->FindClass("Ljava/net/ServerSocket;");
3744 serverSocket_object = env->GetObjectField(channel_object,
3745 serverSocket_field);
3747 if (0 != local_addr.sin_port) {
3748 bound_field = env->GetFieldID(channel_class, "isBound", "Z");
3749 env->SetBooleanField(channel_object, bound_field, jtrue);
3750 bound_field = env->GetFieldID(serverSocket_class, "isBound", "Z");
3751 env->SetBooleanField(serverSocket_object, bound_field, jtrue);
3754 socketImpl_class = env->FindClass("java/net/SocketImpl");
3755 socketImpl_field = env->GetFieldID(channel_class, "impl",
3756 "Ljava/net/SocketImpl;");
3757 socketImpl_object = env->GetObjectField(channel_object,
3759 if (NULL == socketImpl_object) {
3763 localAddr_field = env->GetFieldID(channel_class, "localAddress",
3764 "Ljava/net/InetAddress;");
3765 localAddr_object = env->NewObject(gCachedFields.iaddr_class,
3766 gCachedFields.iaddr_class_init);
3767 if (NULL == localAddr_object) {
3770 env->SetObjectField(socketImpl_object, localAddr_field,
3772 addr_array = env->NewByteArray((jsize)4);
3773 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, localAddr);
3774 env->SetObjectField(localAddr_object,
3775 gCachedFields.iaddr_ipaddress, addr_array);
3778 port_field = env->GetFieldID(socketImpl_class, "localport", "I");
3779 env->SetIntField(socketImpl_object, port_field,
3780 ntohs(local_addr.sin_port));
3784 // new DatagramChannel
3785 channel_class = env->FindClass(
3786 "org/apache/harmony/nio/internal/DatagramChannelImpl");
3787 if (NULL == channel_class) {
3791 channel_new = env->GetMethodID(channel_class, "<init>", "()V");
3792 if (NULL == channel_new) {
3795 channel_object = env->NewObject(channel_class, channel_new);
3796 if (NULL == channel_object) {
3800 // new and set FileDescript
3801 fd_field = env->GetFieldID(channel_class, "fd", "java/io/FileDescriptor");
3802 fd_object = env->GetObjectField(channel_object, fd_field);
3803 if (NULL == fd_object) {
3807 jniSetFileDescriptorOfFD(env, fd_object, socket);
3809 port_field = env->GetFieldID(channel_class, "localPort", "I");
3810 env->SetIntField(channel_object, port_field, ntohs(local_addr.sin_port));
3812 // new and set remote addr
3813 addr_object = env->NewObject(gCachedFields.iaddr_class,
3814 gCachedFields.iaddr_class_init);
3815 if (NULL == addr_object) {
3818 socketaddr_class = env->FindClass("java/net/InetSocketAddress");
3819 socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
3820 "Ljava/net/InetSocketAddress;");
3821 socketaddr_object = env->GetObjectField(channel_object, socketaddr_field);
3822 if (NULL == socketaddr_object) {
3825 addr_field = env->GetFieldID(socketaddr_class, "addr",
3826 "Ljava/net/InetAddress;");
3827 env->SetObjectField(socketaddr_object, addr_field, addr_object);
3828 addr_array = env->NewByteArray((jsize)4);
3829 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
3830 env->SetObjectField(addr_object, gCachedFields.iaddr_ipaddress, addr_array);
3833 if (0 != local_addr.sin_port) {
3834 bound_field = env->GetFieldID(channel_class, "isBound", "Z");
3835 env->SetBooleanField(channel_object, bound_field, jtrue);
3841 return channel_object;
3847 static JNINativeMethod gMethods[] = {
3848 /* name, signature, funcPtr */
3849 { "oneTimeInitializationImpl", "(Z)V", (void*) osNetworkSystem_oneTimeInitializationImpl },
3850 { "createSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createSocketImpl },
3851 { "createDatagramSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createDatagramSocketImpl },
3852 { "readSocketImpl", "(Ljava/io/FileDescriptor;[BIII)I", (void*) osNetworkSystem_readSocketImpl },
3853 { "readSocketDirectImpl", "(Ljava/io/FileDescriptor;IIII)I", (void*) osNetworkSystem_readSocketDirectImpl },
3854 { "writeSocketImpl", "(Ljava/io/FileDescriptor;[BII)I", (void*) osNetworkSystem_writeSocketImpl },
3855 { "writeSocketDirectImpl", "(Ljava/io/FileDescriptor;III)I", (void*) osNetworkSystem_writeSocketDirectImpl },
3856 { "setNonBlockingImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_setNonBlockingImpl },
3857 { "connectSocketImpl", "(Ljava/io/FileDescriptor;ILjava/net/InetAddress;I)I", (void*) osNetworkSystem_connectSocketImpl },
3858 { "connectWithTimeoutSocketImpl", "(Ljava/io/FileDescriptor;IILjava/net/InetAddress;II[B)I", (void*) osNetworkSystem_connectWithTimeoutSocketImpl },
3859 { "connectStreamWithTimeoutSocketImpl","(Ljava/io/FileDescriptor;IIILjava/net/InetAddress;)V", (void*) osNetworkSystem_connectStreamWithTimeoutSocketImpl },
3860 { "socketBindImpl", "(Ljava/io/FileDescriptor;ILjava/net/InetAddress;)V", (void*) osNetworkSystem_socketBindImpl },
3861 { "listenStreamSocketImpl", "(Ljava/io/FileDescriptor;I)V", (void*) osNetworkSystem_listenStreamSocketImpl },
3862 { "availableStreamImpl", "(Ljava/io/FileDescriptor;)I", (void*) osNetworkSystem_availableStreamImpl },
3863 { "acceptSocketImpl", "(Ljava/io/FileDescriptor;Ljava/net/SocketImpl;Ljava/io/FileDescriptor;I)V",(void*) osNetworkSystem_acceptSocketImpl },
3864 { "supportsUrgentDataImpl", "(Ljava/io/FileDescriptor;)Z", (void*) osNetworkSystem_supportsUrgentDataImpl },
3865 { "sendUrgentDataImpl", "(Ljava/io/FileDescriptor;B)V", (void*) osNetworkSystem_sendUrgentDataImpl },
3866 { "connectDatagramImpl2", "(Ljava/io/FileDescriptor;IILjava/net/InetAddress;)V", (void*) osNetworkSystem_connectDatagramImpl2 },
3867 { "disconnectDatagramImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_disconnectDatagramImpl },
3868 { "socketBindImpl2", "(Ljava/io/FileDescriptor;IZLjava/net/InetAddress;)Z", (void*) osNetworkSystem_socketBindImpl2 },
3869 { "peekDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)I", (void*) osNetworkSystem_peekDatagramImpl },
3870 { "receiveDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;[BIIIZ)I", (void*) osNetworkSystem_receiveDatagramImpl },
3871 { "receiveDatagramDirectImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;IIIIZ)I", (void*) osNetworkSystem_receiveDatagramDirectImpl },
3872 { "recvConnectedDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;[BIIIZ)I", (void*) osNetworkSystem_recvConnectedDatagramImpl },
3873 { "recvConnectedDatagramDirectImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;IIIIZ)I", (void*) osNetworkSystem_recvConnectedDatagramDirectImpl },
3874 { "sendDatagramImpl", "(Ljava/io/FileDescriptor;[BIIIZILjava/net/InetAddress;)I", (void*) osNetworkSystem_sendDatagramImpl },
3875 { "sendDatagramDirectImpl", "(Ljava/io/FileDescriptor;IIIIZILjava/net/InetAddress;)I", (void*) osNetworkSystem_sendDatagramDirectImpl },
3876 { "sendConnectedDatagramImpl", "(Ljava/io/FileDescriptor;[BIIZ)I", (void*) osNetworkSystem_sendConnectedDatagramImpl },
3877 { "sendConnectedDatagramDirectImpl", "(Ljava/io/FileDescriptor;IIIZ)I", (void*) osNetworkSystem_sendConnectedDatagramDirectImpl },
3878 { "createServerStreamSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createServerStreamSocketImpl },
3879 { "createMulticastSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createMulticastSocketImpl },
3880 { "receiveStreamImpl", "(Ljava/io/FileDescriptor;[BIII)I", (void*) osNetworkSystem_receiveStreamImpl },
3881 { "sendStreamImpl", "(Ljava/io/FileDescriptor;[BII)I", (void*) osNetworkSystem_sendStreamImpl },
3882 { "shutdownInputImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_shutdownInputImpl },
3883 { "shutdownOutputImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_shutdownOutputImpl },
3884 { "sendDatagramImpl2", "(Ljava/io/FileDescriptor;[BIIILjava/net/InetAddress;)I", (void*) osNetworkSystem_sendDatagramImpl2 },
3885 { "selectImpl", "([Ljava/io/FileDescriptor;[Ljava/io/FileDescriptor;II[IJ)I", (void*) osNetworkSystem_selectImpl },
3886 { "getSocketLocalAddressImpl", "(Ljava/io/FileDescriptor;Z)Ljava/net/InetAddress;", (void*) osNetworkSystem_getSocketLocalAddressImpl },
3887 { "getSocketLocalPortImpl", "(Ljava/io/FileDescriptor;Z)I", (void*) osNetworkSystem_getSocketLocalPortImpl },
3888 { "getSocketOptionImpl", "(Ljava/io/FileDescriptor;I)Ljava/lang/Object;", (void*) osNetworkSystem_getSocketOptionImpl },
3889 { "setSocketOptionImpl", "(Ljava/io/FileDescriptor;ILjava/lang/Object;)V", (void*) osNetworkSystem_setSocketOptionImpl },
3890 { "getSocketFlagsImpl", "()I", (void*) osNetworkSystem_getSocketFlagsImpl },
3891 { "socketCloseImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_socketCloseImpl },
3892 { "getHostByAddrImpl", "([B)Ljava/net/InetAddress;", (void*) osNetworkSystem_getHostByAddrImpl },
3893 { "getHostByNameImpl", "(Ljava/lang/String;Z)Ljava/net/InetAddress;", (void*) osNetworkSystem_getHostByNameImpl },
3894 { "setInetAddressImpl", "(Ljava/net/InetAddress;[B)V", (void*) osNetworkSystem_setInetAddressImpl },
3895 { "inheritedChannelImpl", "()Ljava/nio/channels/Channel;", (void*) osNetworkSystem_inheritedChannelImpl },
3898 int register_org_apache_harmony_luni_platform_OSNetworkSystem(JNIEnv* env) {
3899 return jniRegisterNativeMethods(env,
3900 "org/apache/harmony/luni/platform/OSNetworkSystem",