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_createStreamSocketImpl(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 jint osNetworkSystem_peekDatagramImpl(JNIEnv* env, jclass clazz,
2344 jobject fd, jobject sender, jint receiveTimeout) {
2345 // LOGD("ENTER peekDatagramImpl");
2349 int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
2354 int handle = jniGetFDFromFileDescriptor(env, fd);
2355 if (handle == 0 || handle == -1) {
2356 throwSocketException(env, SOCKERR_BADDESC);
2360 struct sockaddr_storage sockAddr;
2361 socklen_t sockAddrLen = sizeof(sockAddr);
2364 length = recvfrom(handle, NULL, 0, MSG_PEEK,
2365 (struct sockaddr *)&sockAddr, &sockAddrLen);
2366 } while (length < 0 && errno == EINTR);
2368 int err = convertError(errno);
2369 throwSocketException(env, err);
2373 sender = socketAddressToInetAddress(env, &sockAddr);
2374 if (sender == NULL) // Exception has already been thrown.
2377 port = getSocketAddressPort(&sockAddr);
2381 static jint osNetworkSystem_receiveDatagramDirectImpl(JNIEnv* env, jclass clazz,
2382 jobject fd, jobject packet, jint address, jint offset, jint length,
2383 jint receiveTimeout, jboolean peek) {
2384 // LOGD("ENTER receiveDatagramDirectImpl");
2386 int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
2391 int handle = jniGetFDFromFileDescriptor(env, fd);
2392 if (handle == 0 || handle == -1) {
2393 throwSocketException(env, SOCKERR_BADDESC);
2397 struct sockaddr_storage sockAddr;
2398 socklen_t sockAddrLen = sizeof(sockAddr);
2400 int mode = peek ? MSG_PEEK : 0;
2402 ssize_t actualLength;
2404 actualLength = recvfrom(handle, (char*)(address + offset), length, mode,
2405 (struct sockaddr *)&sockAddr, &sockAddrLen);
2406 } while (actualLength < 0 && errno == EINTR);
2407 if (actualLength < 0) {
2408 int err = convertError(errno);
2409 throwSocketException(env, err);
2413 if (packet != NULL) {
2414 jbyteArray addr = socketAddressToAddressBytes(env, &sockAddr);
2415 if (addr == NULL) // Exception has already been thrown.
2417 int port = getSocketAddressPort(&sockAddr);
2418 jobject sender = env->CallStaticObjectMethod(
2419 gCachedFields.iaddr_class, gCachedFields.iaddr_getbyaddress,
2421 env->SetObjectField(packet, gCachedFields.dpack_address, sender);
2422 env->SetIntField(packet, gCachedFields.dpack_port, port);
2423 env->SetIntField(packet, gCachedFields.dpack_length,
2424 (jint) actualLength);
2426 return (jint) actualLength;
2429 static jint osNetworkSystem_receiveDatagramImpl(JNIEnv* env, jclass clazz,
2430 jobject fd, jobject packet, jbyteArray data, jint offset, jint length,
2431 jint receiveTimeout, jboolean peek) {
2432 // LOGD("ENTER receiveDatagramImpl");
2434 int localLength = (length < 65536) ? length : 65536;
2435 jbyte *bytes = (jbyte*) malloc(localLength);
2436 if (bytes == NULL) {
2437 jniThrowException(env, "java/lang/OutOfMemoryError",
2438 "couldn't allocate enough memory for receiveDatagram");
2442 int actualLength = osNetworkSystem_receiveDatagramDirectImpl(env, clazz, fd,
2443 packet, (jint)bytes, 0, localLength, receiveTimeout, peek);
2445 if (actualLength > 0) {
2446 env->SetByteArrayRegion(data, offset, actualLength, bytes);
2450 return actualLength;
2453 static jint osNetworkSystem_recvConnectedDatagramDirectImpl(JNIEnv* env,
2454 jclass clazz, jobject fd, jobject packet, jint address, jint offset,
2455 jint length, jint receiveTimeout, jboolean peek) {
2456 // LOGD("ENTER receiveConnectedDatagramDirectImpl");
2458 int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
2464 int handle = jniGetFDFromFileDescriptor(env, fd);
2466 if (handle == 0 || handle == -1) {
2467 throwSocketException(env, SOCKERR_BADSOCKET);
2471 int mode = peek ? MSG_PEEK : 0;
2473 int actualLength = recvfrom(handle,
2474 (char*)(address + offset), length, mode, NULL, NULL);
2476 if (actualLength < 0) {
2477 jniThrowException(env, "java/net/PortUnreachableException", "");
2481 if ( packet != NULL) {
2482 env->SetIntField(packet, gCachedFields.dpack_length, actualLength);
2484 return actualLength;
2487 static jint osNetworkSystem_recvConnectedDatagramImpl(JNIEnv* env, jclass clazz,
2488 jobject fd, jobject packet, jbyteArray data, jint offset, jint length,
2489 jint receiveTimeout, jboolean peek) {
2490 // LOGD("ENTER receiveConnectedDatagramImpl");
2492 int localLength = (length < 65536) ? length : 65536;
2493 jbyte *bytes = (jbyte*) malloc(localLength);
2494 if (bytes == NULL) {
2495 jniThrowException(env, "java/lang/OutOfMemoryError",
2496 "couldn't allocate enough memory for recvConnectedDatagram");
2500 int actualLength = osNetworkSystem_recvConnectedDatagramDirectImpl(env,
2501 clazz, fd, packet, (jint)bytes, 0, localLength,
2502 receiveTimeout, peek);
2504 if (actualLength > 0) {
2505 env->SetByteArrayRegion(data, offset, actualLength, bytes);
2509 return actualLength;
2512 static jint osNetworkSystem_sendDatagramDirectImpl(JNIEnv* env, jclass clazz,
2513 jobject fd, jint address, jint offset, jint length, jint port,
2514 jboolean bindToDevice, jint trafficClass, jobject inetAddress) {
2515 // LOGD("ENTER sendDatagramDirectImpl");
2517 int handle = jniGetFDFromFileDescriptor(env, fd);
2519 if (handle == 0 || handle == -1) {
2520 throwSocketException(env, SOCKERR_BADSOCKET);
2524 struct sockaddr_storage receiver;
2525 if (inetAddressToSocketAddress(env, inetAddress, port, &receiver) < 0) {
2526 // Exception has already been thrown.
2532 result = sendto(handle, (char*)(address + offset), length,
2533 SOCKET_NOFLAGS, (struct sockaddr*)&receiver, sizeof(receiver));
2534 } while (result < 0 && errno == EINTR);
2536 int err = convertError(errno);
2537 if ((SOCKERR_CONNRESET == err)
2538 || (SOCKERR_CONNECTION_REFUSED == err)) {
2541 throwSocketException(env, err);
2545 return (jint) result;
2548 static jint osNetworkSystem_sendDatagramImpl(JNIEnv* env, jclass clazz,
2549 jobject fd, jbyteArray data, jint offset, jint length, jint port,
2550 jboolean bindToDevice, jint trafficClass, jobject inetAddress) {
2551 // LOGD("ENTER sendDatagramImpl");
2553 jbyte *bytes = env->GetByteArrayElements(data, NULL);
2554 int actualLength = osNetworkSystem_sendDatagramDirectImpl(env, clazz, fd,
2555 (jint)bytes, offset, length, port, bindToDevice, trafficClass,
2557 env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
2559 return actualLength;
2562 static jint osNetworkSystem_sendConnectedDatagramDirectImpl(JNIEnv* env,
2563 jclass clazz, jobject fd, jint address, jint offset, jint length,
2564 jboolean bindToDevice) {
2565 // LOGD("ENTER sendConnectedDatagramDirectImpl");
2567 int handle = jniGetFDFromFileDescriptor(env, fd);
2569 if (handle == 0 || handle == -1) {
2570 throwSocketException(env, SOCKERR_BADSOCKET);
2574 int result = send(handle, (char*)(address + offset), length, 0);
2577 int err = convertError(errno);
2578 if ((SOCKERR_CONNRESET == err) || (SOCKERR_CONNECTION_REFUSED == err)) {
2581 throwSocketException(env, err);
2588 static jint osNetworkSystem_sendConnectedDatagramImpl(JNIEnv* env, jclass clazz,
2589 jobject fd, jbyteArray data, jint offset, jint length,
2590 jboolean bindToDevice) {
2591 // LOGD("ENTER sendConnectedDatagramImpl");
2593 jbyte *bytes = env->GetByteArrayElements(data, NULL);
2594 int actualLength = osNetworkSystem_sendConnectedDatagramDirectImpl(env,
2595 clazz, fd, (jint)bytes, offset, length, bindToDevice);
2596 env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
2598 return actualLength;
2601 static void osNetworkSystem_createServerStreamSocketImpl(JNIEnv* env,
2602 jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) {
2603 // LOGD("ENTER createServerStreamSocketImpl");
2605 int handle = createSocketFileDescriptor(env, fileDescriptor, SOCK_STREAM);
2610 setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
2614 * @param timeout in milliseconds. If zero, block until data received
2616 static jint osNetworkSystem_receiveStreamImpl(JNIEnv* env, jclass clazz,
2617 jobject fileDescriptor, jbyteArray data, jint offset, jint count,
2619 // LOGD("ENTER receiveStreamImpl");
2622 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2624 if (handle == 0 || handle == -1) {
2625 throwSocketException(env, SOCKERR_BADSOCKET);
2629 // Cap read length to available buf size
2630 int spaceAvailable = env->GetArrayLength(data) - offset;
2631 int localCount = count < spaceAvailable? count : spaceAvailable;
2634 jbyte *body = env->GetByteArrayElements(data, &isCopy);
2638 tv.tv_sec = timeout / 1000;
2639 tv.tv_usec = (timeout % 1000) * 1000;
2640 setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv,
2641 sizeof(struct timeval));
2644 result = recv(handle, body + offset, localCount, SOCKET_NOFLAGS);
2645 } while (result < 0 && errno == EINTR);
2647 env->ReleaseByteArrayElements(data, body, 0);
2650 * If no bytes are read, return -1 to signal 'endOfFile'
2651 * to the Java input stream
2655 } else if (0 == result) {
2658 // If EAGAIN or EWOULDBLOCK, read timed out
2659 if (errno == EAGAIN || errno == EWOULDBLOCK) {
2660 jniThrowException(env, "java/net/SocketTimeoutException",
2661 netLookupErrorString(SOCKERR_TIMEOUT));
2663 int err = convertError(errno);
2664 throwSocketException(env, err);
2670 static jint osNetworkSystem_sendStreamImpl(JNIEnv* env, jclass clazz,
2671 jobject fileDescriptor, jbyteArray data, jint offset, jint count) {
2672 // LOGD("ENTER sendStreamImpl");
2675 int result = 0, sent = 0;
2678 jbyte *message = env->GetByteArrayElements(data, &isCopy);
2680 // Cap write length to available buf size
2681 int spaceAvailable = env->GetArrayLength(data) - offset;
2682 if (count > spaceAvailable) count = spaceAvailable;
2684 while (sent < count) {
2686 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2687 if (handle == 0 || handle == -1) {
2688 throwSocketException(env,
2689 sent == 0 ? SOCKERR_BADSOCKET : SOCKERR_INTERRUPTED);
2690 env->ReleaseByteArrayElements(data, message, 0);
2694 // LOGD("before select %d", count);
2695 selectWait(handle, SEND_RETRY_TIME, SELECT_WRITE_TYPE);
2696 result = send(handle, (jbyte *)message + offset + sent,
2697 (int) count - sent, SOCKET_NOFLAGS);
2701 if (result == EAGAIN ||result == EWOULDBLOCK) {
2702 // LOGD("write blocked %d", sent);
2705 env->ReleaseByteArrayElements(data, message, 0);
2706 int err = convertError(result);
2707 throwSocketException(env, err);
2713 env->ReleaseByteArrayElements(data, message, 0);
2717 static void osNetworkSystem_shutdownInputImpl(JNIEnv* env, jobject obj,
2718 jobject fileDescriptor) {
2719 // LOGD("ENTER shutdownInputImpl");
2724 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2726 if (handle == 0 || handle == -1) {
2727 throwSocketException(env, SOCKERR_BADSOCKET);
2731 ret = shutdown(handle, SHUT_RD);
2734 int err = convertError(errno);
2735 throwSocketException(env, err);
2740 static void osNetworkSystem_shutdownOutputImpl(JNIEnv* env, jobject obj,
2741 jobject fileDescriptor) {
2742 // LOGD("ENTER shutdownOutputImpl");
2747 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2749 if (handle == 0 || handle == -1) {
2753 ret = shutdown(handle, SHUT_WR);
2756 int err = convertError(errno);
2757 throwSocketException(env, err);
2762 static jint osNetworkSystem_sendDatagramImpl2(JNIEnv* env, jclass clazz,
2763 jobject fd, jbyteArray data, jint offset, jint length, jint port,
2764 jobject inetAddress) {
2765 // LOGD("ENTER sendDatagramImpl2");
2768 unsigned short nPort;
2769 int ret = 0, sent = 0;
2771 struct sockaddr_storage sockaddrP;
2773 if (inetAddress != NULL) {
2774 ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddrP);
2775 if (ret < 0) // Exception has already been thrown.
2778 handle = jniGetFDFromFileDescriptor(env, fd);
2779 if (handle == 0 || handle == -1) {
2780 throwSocketException(env, SOCKERR_BADDESC);
2785 message = (jbyte*) malloc(length * sizeof(jbyte));
2786 if (message == NULL) {
2787 jniThrowException(env, "java/lang/OutOfMemoryError",
2788 "couldn't allocate enough memory for readSocket");
2792 env->GetByteArrayRegion(data, offset, length, message);
2794 while (sent < length) {
2795 handle = jniGetFDFromFileDescriptor(env, fd);
2797 if (handle == 0 || handle == -1) {
2798 throwSocketException(env,
2799 sent == 0 ? SOCKERR_BADDESC : SOCKERR_INTERRUPTED);
2806 result = sendto(handle, (char *) (message + sent),
2807 (int) (length - sent), SOCKET_NOFLAGS,
2808 (struct sockaddr *) &sockaddrP, sizeof(sockaddrP));
2809 } while (result < 0 && errno == EINTR);
2811 int err = convertError(errno);
2812 throwSocketException(env, err);
2824 static jint osNetworkSystem_selectImpl(JNIEnv* env, jclass clazz,
2825 jobjectArray readFDArray, jobjectArray writeFDArray, jint countReadC,
2826 jint countWriteC, jintArray outFlags, jlong timeout) {
2827 // LOGD("ENTER selectImpl");
2829 struct timeval timeP;
2833 fd_set *fdset_read,*fdset_write;
2838 unsigned int time_sec = (unsigned int)timeout/1000;
2839 unsigned int time_msec = (unsigned int)(timeout%1000);
2841 fdset_read = (fd_set *)malloc(sizeof(fd_set));
2842 fdset_write = (fd_set *)malloc(sizeof(fd_set));
2844 FD_ZERO(fdset_read);
2845 FD_ZERO(fdset_write);
2847 for (val = 0; val<countReadC; val++) {
2849 gotFD = env->GetObjectArrayElement(readFDArray,val);
2851 handle = jniGetFDFromFileDescriptor(env, gotFD);
2853 FD_SET(handle, fdset_read);
2855 if (0 > (size - handle)) {
2860 for (val = 0; val<countWriteC; val++) {
2862 gotFD = env->GetObjectArrayElement(writeFDArray,val);
2864 handle = jniGetFDFromFileDescriptor(env, gotFD);
2866 FD_SET(handle, fdset_write);
2868 if (0 > (size - handle)) {
2873 /* the size is the max_fd + 1 */
2877 result = SOCKERR_FDSET_SIZEBAD;
2879 /* only set when timeout >= 0 (non-block)*/
2882 timeP.tv_sec = time_sec;
2883 timeP.tv_usec = time_msec*1000;
2885 result = sockSelect(size, fdset_read, fdset_write, NULL, &timeP);
2888 result = sockSelect(size, fdset_read, fdset_write, NULL, NULL);
2893 /*output the result to a int array*/
2894 flagArray = env->GetIntArrayElements(outFlags, &isCopy);
2896 for (val=0; val<countReadC; val++) {
2897 gotFD = env->GetObjectArrayElement(readFDArray,val);
2899 handle = jniGetFDFromFileDescriptor(env, gotFD);
2901 if (FD_ISSET(handle,fdset_read)) {
2902 flagArray[val] = SOCKET_OP_READ;
2904 flagArray[val] = SOCKET_OP_NONE;
2908 for (val=0; val<countWriteC; val++) {
2910 gotFD = env->GetObjectArrayElement(writeFDArray,val);
2912 handle = jniGetFDFromFileDescriptor(env, gotFD);
2914 if (FD_ISSET(handle,fdset_write)) {
2915 flagArray[val+countReadC] = SOCKET_OP_WRITE;
2917 flagArray[val+countReadC] = SOCKET_OP_NONE;
2921 env->ReleaseIntArrayElements(outFlags, flagArray, 0);
2927 /* return both correct and error result, let java handle the exception*/
2931 static jobject osNetworkSystem_getSocketLocalAddressImpl(JNIEnv* env,
2932 jclass clazz, jobject fileDescriptor, jboolean preferIPv6Addresses) {
2933 // LOGD("ENTER getSocketLocalAddressImpl");
2935 struct sockaddr_storage addr;
2936 socklen_t addrLen = sizeof(addr);
2938 memset(&addr, 0, addrLen);
2941 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2942 if (handle == 0 || handle == -1) {
2943 throwSocketException(env, SOCKERR_UNKNOWNSOCKET);
2948 result = getsockname(handle, (struct sockaddr *)&addr, &addrLen);
2950 // Spec says ignore all errors
2951 return socketAddressToInetAddress(env, &addr);
2954 static jint osNetworkSystem_getSocketLocalPortImpl(JNIEnv* env, jclass clazz,
2955 jobject fileDescriptor, jboolean preferIPv6Addresses) {
2956 // LOGD("ENTER getSocketLocalPortImpl");
2958 struct sockaddr_storage addr;
2959 socklen_t addrLen = sizeof(addr);
2961 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2964 if (handle == 0 || handle == -1) {
2965 throwSocketException(env, SOCKERR_UNKNOWNSOCKET);
2969 result = getsockname(handle, (struct sockaddr *)&addr, &addrLen);
2972 // The java spec does not indicate any exceptions on this call
2975 return getSocketAddressPort(&addr);
2979 static jobject osNetworkSystem_getSocketOptionImpl(JNIEnv* env, jclass clazz,
2980 jobject fileDescriptor, jint anOption) {
2981 // LOGD("ENTER getSocketOptionImpl");
2985 socklen_t intSize = sizeof(int);
2986 unsigned char byteValue = 0;
2987 socklen_t byteSize = sizeof(unsigned char);
2989 struct sockaddr_storage sockVal;
2990 socklen_t sockSize = sizeof(sockVal);
2992 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2993 if (handle == 0 || handle == -1) {
2994 throwSocketException(env, SOCKERR_BADDESC);
2998 switch ((int) anOption & 0xffff) {
2999 case JAVASOCKOPT_SO_LINGER: {
3000 struct linger lingr;
3001 socklen_t size = sizeof(struct linger);
3002 result = getsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr, &size);
3004 throwSocketException(env, convertError(errno));
3007 if (!lingr.l_onoff) {
3010 intValue = lingr.l_linger;
3012 return newJavaLangInteger(env, intValue);
3014 case JAVASOCKOPT_TCP_NODELAY: {
3015 if ((anOption >> 16) & BROKEN_TCP_NODELAY) {
3018 result = getsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intValue, &intSize);
3020 throwSocketException(env, convertError(errno));
3023 return newJavaLangBoolean(env, intValue);
3025 case JAVASOCKOPT_MCAST_TTL: {
3026 if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
3027 return newJavaLangByte(env, 0);
3029 result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_MULTICAST_TTL,
3030 IPV6_MULTICAST_HOPS, &byteValue,
3033 throwSocketException(env, convertError(errno));
3036 return newJavaLangByte(env, (jbyte)(byteValue & 0xFF));
3038 case JAVASOCKOPT_MCAST_INTERFACE: {
3039 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3042 result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, &sockVal, &sockSize);
3044 throwSocketException(env, convertError(errno));
3047 // This option is IPv4-only.
3048 sockVal.ss_family = AF_INET;
3049 return socketAddressToInetAddress(env, &sockVal);
3051 case JAVASOCKOPT_IP_MULTICAST_IF2: {
3052 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3055 struct ip_mreqn multicastRequest;
3057 socklen_t optionLength;
3058 int addressFamily = getSocketAddressFamily(handle);
3059 switch (addressFamily) {
3061 optionLength = sizeof(multicastRequest);
3062 result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
3063 &multicastRequest, &optionLength);
3065 interfaceIndex = multicastRequest.imr_ifindex;
3068 optionLength = sizeof(interfaceIndex);
3069 result = getsockopt(handle, IPPROTO_IPV6, IPV6_MULTICAST_IF,
3070 &interfaceIndex, &optionLength);
3073 throwSocketException(env, SOCKERR_BADAF);
3078 throwSocketException(env, convertError(errno));
3082 return newJavaLangInteger(env, interfaceIndex);
3084 case JAVASOCKOPT_SO_SNDBUF: {
3085 result = getsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intValue, &intSize);
3087 throwSocketException(env, convertError(errno));
3090 return newJavaLangInteger(env, intValue);
3092 case JAVASOCKOPT_SO_RCVBUF: {
3093 result = getsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intValue, &intSize);
3095 throwSocketException(env, convertError(errno));
3098 return newJavaLangInteger(env, intValue);
3100 case JAVASOCKOPT_SO_BROADCAST: {
3101 result = getsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intValue, &intSize);
3103 throwSocketException(env, convertError(errno));
3106 return newJavaLangBoolean(env, intValue);
3108 case JAVASOCKOPT_SO_REUSEADDR: {
3109 result = getsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intValue, &intSize);
3111 throwSocketException(env, convertError(errno));
3114 return newJavaLangBoolean(env, intValue);
3116 case JAVASOCKOPT_SO_KEEPALIVE: {
3117 result = getsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intValue, &intSize);
3119 throwSocketException(env, convertError(errno));
3122 return newJavaLangBoolean(env, intValue);
3124 case JAVASOCKOPT_SO_OOBINLINE: {
3125 result = getsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intValue, &intSize);
3127 throwSocketException(env, convertError(errno));
3130 return newJavaLangBoolean(env, intValue);
3132 case JAVASOCKOPT_IP_MULTICAST_LOOP: {
3133 result = getOrSetSocketOption(SOCKOPT_GET, handle,
3135 IPV6_MULTICAST_LOOP, &intValue,
3138 throwSocketException(env, convertError(errno));
3141 return newJavaLangBoolean(env, intValue);
3143 case JAVASOCKOPT_IP_TOS: {
3144 result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_TOS,
3145 IPV6_TCLASS, &intValue, &intSize);
3147 throwSocketException(env, convertError(errno));
3150 return newJavaLangInteger(env, intValue);
3152 case JAVASOCKOPT_SO_RCVTIMEOUT: {
3153 struct timeval timeout;
3154 socklen_t size = sizeof(timeout);
3155 result = getsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout, &size);
3157 throwSocketException(env, convertError(errno));
3160 return newJavaLangInteger(env, timeout.tv_sec * 1000 + timeout.tv_usec/1000);
3163 throwSocketException(env, SOCKERR_OPTUNSUPP);
3170 static void osNetworkSystem_setSocketOptionImpl(JNIEnv* env, jclass clazz,
3171 jobject fileDescriptor, jint anOption, jobject optVal) {
3172 // LOGD("ENTER setSocketOptionImpl");
3176 socklen_t intSize = sizeof(int);
3177 unsigned char byteVal;
3178 socklen_t byteSize = sizeof(unsigned char);
3179 struct sockaddr_storage sockVal;
3180 int sockSize = sizeof(sockVal);
3182 if (env->IsInstanceOf(optVal, gCachedFields.integer_class)) {
3183 intVal = (int) env->GetIntField(optVal, gCachedFields.integer_class_value);
3184 } else if (env->IsInstanceOf(optVal, gCachedFields.boolean_class)) {
3185 intVal = (int) env->GetBooleanField(optVal, gCachedFields.boolean_class_value);
3186 } else if (env->IsInstanceOf(optVal, gCachedFields.byte_class)) {
3187 byteVal = (int) env->GetByteField(optVal, gCachedFields.byte_class_value);
3188 } else if (env->IsInstanceOf(optVal, gCachedFields.iaddr_class)) {
3189 if (inetAddressToSocketAddress(env, optVal, 0, &sockVal) < 0) {
3190 // Exception has already been thrown.
3193 } else if (env->IsInstanceOf(optVal, gCachedFields.genericipmreq_class)) {
3194 // we'll use optVal directly
3196 throwSocketException(env, SOCKERR_OPTUNSUPP);
3200 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
3201 if (handle == 0 || handle == -1) {
3202 throwSocketException(env, SOCKERR_BADDESC);
3206 switch ((int) anOption & 0xffff) {
3207 case JAVASOCKOPT_SO_LINGER: {
3208 struct linger lingr;
3209 lingr.l_onoff = intVal > 0 ? 1 : 0;
3210 lingr.l_linger = intVal;
3211 result = setsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr,
3212 sizeof(struct linger));
3214 throwSocketException(env, convertError(errno));
3220 case JAVASOCKOPT_TCP_NODELAY: {
3221 if ((anOption >> 16) & BROKEN_TCP_NODELAY) {
3224 result = setsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intVal, intSize);
3226 throwSocketException(env, convertError(errno));
3232 case JAVASOCKOPT_MCAST_TTL: {
3233 if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
3236 result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_MULTICAST_TTL,
3237 IPV6_MULTICAST_HOPS, &byteVal,
3240 throwSocketException(env, convertError(errno));
3246 case JAVASOCKOPT_MCAST_ADD_MEMBERSHIP: {
3247 mcastAddDropMembership(env, handle, optVal,
3248 (anOption >> 16) & BROKEN_MULTICAST_IF, IP_ADD_MEMBERSHIP);
3252 case JAVASOCKOPT_MCAST_DROP_MEMBERSHIP: {
3253 mcastAddDropMembership(env, handle, optVal,
3254 (anOption >> 16) & BROKEN_MULTICAST_IF, IP_DROP_MEMBERSHIP);
3258 case JAVASOCKOPT_MCAST_INTERFACE: {
3259 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3262 // This call is IPv4 only.
3263 if (getSocketAddressFamily(handle) != AF_INET) {
3264 throwSocketException(env, SOCKERR_BADAF);
3267 struct ip_mreqn mcast_req;
3268 memset(&mcast_req, 0, sizeof(mcast_req));
3269 struct sockaddr_in *sin = (struct sockaddr_in *) &sockVal;
3270 mcast_req.imr_address = sin->sin_addr;
3271 result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
3272 &mcast_req, sizeof(mcast_req));
3274 throwSocketException(env, convertError(errno));
3280 case JAVASOCKOPT_IP_MULTICAST_IF2: {
3281 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3284 int addressFamily = getSocketAddressFamily(handle);
3285 int interfaceIndex = intVal;
3287 socklen_t optionLength;
3288 struct ip_mreqn multicastRequest;
3289 switch (addressFamily) {
3291 // IP_MULTICAST_IF expects a pointer to a struct ip_mreqn.
3292 memset(&multicastRequest, 0, sizeof(multicastRequest));
3293 multicastRequest.imr_ifindex = interfaceIndex;
3294 optionValue = &multicastRequest;
3295 optionLength = sizeof(multicastRequest);
3298 // IPV6_MULTICAST_IF expects a pointer to an integer.
3299 optionValue = &interfaceIndex;
3300 optionLength = sizeof(interfaceIndex);
3303 throwSocketException(env, SOCKERR_BADAF);
3306 result = getOrSetSocketOption(SOCKOPT_SET, handle,
3307 IP_MULTICAST_IF, IPV6_MULTICAST_IF, optionValue,
3310 throwSocketException(env, convertError(errno));
3316 case JAVASOCKOPT_SO_SNDBUF: {
3317 result = setsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intVal, intSize);
3319 throwSocketException(env, convertError(errno));
3325 case JAVASOCKOPT_SO_RCVBUF: {
3326 result = setsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intVal, intSize);
3328 throwSocketException(env, convertError(errno));
3334 case JAVASOCKOPT_SO_BROADCAST: {
3335 result = setsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intVal, intSize);
3337 throwSocketException(env, convertError(errno));
3343 case JAVASOCKOPT_SO_REUSEADDR: {
3344 result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
3346 throwSocketException(env, convertError(errno));
3351 case JAVASOCKOPT_SO_KEEPALIVE: {
3352 result = setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intVal, intSize);
3354 throwSocketException(env, convertError(errno));
3360 case JAVASOCKOPT_SO_OOBINLINE: {
3361 result = setsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intVal, intSize);
3363 throwSocketException(env, convertError(errno));
3369 case JAVASOCKOPT_IP_MULTICAST_LOOP: {
3370 result = getOrSetSocketOption(SOCKOPT_SET, handle,
3372 IPV6_MULTICAST_LOOP, &intVal,
3375 throwSocketException(env, convertError(errno));
3381 case JAVASOCKOPT_IP_TOS: {
3382 result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_TOS,
3383 IPV6_TCLASS, &intVal, &intSize);
3385 throwSocketException(env, convertError(errno));
3391 case JAVASOCKOPT_REUSEADDR_AND_REUSEPORT: {
3392 // SO_REUSEPORT doesn't need to get set on this System
3393 result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
3395 throwSocketException(env, convertError(errno));
3401 case JAVASOCKOPT_SO_RCVTIMEOUT: {
3402 struct timeval timeout;
3403 timeout.tv_sec = intVal / 1000;
3404 timeout.tv_usec = (intVal % 1000) * 1000;
3405 result = setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout,
3406 sizeof(struct timeval));
3408 throwSocketException(env, convertError(errno));
3415 throwSocketException(env, SOCKERR_OPTUNSUPP);
3420 static jint osNetworkSystem_getSocketFlagsImpl(JNIEnv* env, jclass clazz) {
3421 // LOGD("ENTER getSocketFlagsImpl");
3423 // Not implemented by harmony
3427 static void osNetworkSystem_socketCloseImpl(JNIEnv* env, jclass clazz,
3428 jobject fileDescriptor) {
3429 // LOGD("ENTER socketCloseImpl");
3431 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
3433 if (handle == 0 || handle == -1) {
3434 throwSocketException(env, SOCKERR_BADSOCKET);
3438 jniSetFileDescriptorOfFD(env, fileDescriptor, -1);
3443 static jobject osNetworkSystem_getHostByAddrImpl(JNIEnv* env, jclass clazz,
3444 jbyteArray addrStr) {
3445 // LOGD("ENTER getHostByAddrImpl");
3447 if (addrStr == NULL) {
3448 throwNullPointerException(env);
3452 jstring address = (jstring)newJavaLangString(env, addrStr);
3454 const char* addr = env->GetStringUTFChars(address, NULL);
3456 struct hostent* ent = gethostbyaddr(addr, strlen(addr), AF_INET);
3458 if (ent != NULL && ent->h_name != NULL) {
3459 result = env->NewStringUTF(ent->h_name);
3464 env->ReleaseStringUTFChars(address, addr);
3469 static jobject osNetworkSystem_getHostByNameImpl(JNIEnv* env, jclass clazz,
3470 jstring nameStr, jboolean preferIPv6Addresses) {
3471 // LOGD("ENTER getHostByNameImpl");
3473 if (nameStr == NULL) {
3474 throwNullPointerException(env);
3478 const char* name = env->GetStringUTFChars(nameStr, NULL);
3480 if (useAdbNetworking) {
3487 // LOGD("ADB networking: +gethostbyname '%s'", name);
3489 err = adb_networking_gethostbyname(name, &(outaddr.a));
3491 env->ReleaseStringUTFChars(nameStr, name);
3493 LOGD("ADB networking: -gethostbyname err %d addr 0x%08x %u.%u.%u.%u",
3494 err, (unsigned int)outaddr.a.s_addr,
3495 outaddr.j[0],outaddr.j[1],
3496 outaddr.j[2],outaddr.j[3]);
3502 jbyteArray addr = env->NewByteArray(4);
3503 env->SetByteArrayRegion(addr, 0, 4, outaddr.j);
3508 // normal case...no adb networking
3509 struct hostent* ent = gethostbyname(name);
3511 env->ReleaseStringUTFChars(nameStr, name);
3513 if (ent != NULL && ent->h_length > 0) {
3514 jbyteArray addr = env->NewByteArray(4);
3516 memcpy(v, ent->h_addr, 4);
3517 env->SetByteArrayRegion(addr, 0, 4, v);
3525 static void osNetworkSystem_setInetAddressImpl(JNIEnv* env, jobject obj,
3526 jobject sender, jbyteArray address) {
3527 // LOGD("ENTER setInetAddressImpl");
3529 env->SetObjectField(sender, gCachedFields.iaddr_ipaddress, address);
3532 // TODO: rewrite this method in Java and make it support IPv6.
3533 static jobject osNetworkSystem_inheritedChannelImpl(JNIEnv* env, jobject obj) {
3534 // LOGD("ENTER inheritedChannelImpl");
3538 socklen_t length = sizeof(opt);
3540 struct sockaddr_in local_addr;
3541 struct sockaddr_in remote_addr;
3542 jclass channel_class, socketaddr_class, serverSocket_class, socketImpl_class;
3543 jobject channel_object = NULL, socketaddr_object, serverSocket_object;
3544 jobject fd_object, addr_object, localAddr_object, socketImpl_object;
3545 jfieldID port_field, socketaddr_field, bound_field, fd_field;
3546 jfieldID serverSocket_field, socketImpl_field, addr_field, localAddr_field;
3547 jmethodID channel_new;
3548 jbyteArray addr_array;
3549 struct sockaddr_in *sock;
3552 jboolean jtrue = JNI_TRUE;
3554 if (0 != getsockopt(socket, SOL_SOCKET, SO_TYPE, &opt, &length)) {
3557 if (SOCK_STREAM !=opt && SOCK_DGRAM !=opt) {
3562 length = sizeof(struct sockaddr);
3563 if (0 != getsockname(socket, (struct sockaddr *)&local_addr, &length)) {
3566 if (AF_INET != local_addr.sin_family || length != sizeof(struct sockaddr)) {
3569 localAddr = (jbyte*) malloc(sizeof(jbyte)*4);
3570 if (NULL == localAddr) {
3573 memcpy (localAddr, &(local_addr.sin_addr.s_addr), 4);
3575 if (0 != getpeername(socket, (struct sockaddr *)&remote_addr, &length)) {
3576 remote_addr.sin_port = 0;
3577 remote_addr.sin_addr.s_addr = 0;
3578 address = (jbyte*) malloc(sizeof(jbyte)*4);
3579 bzero(address, sizeof(jbyte)*4);
3581 if (AF_INET != remote_addr.sin_family
3582 || length != sizeof(struct sockaddr)) {
3585 address = (jbyte*) malloc(sizeof(jbyte)*4);
3586 memcpy (address, &(remote_addr.sin_addr.s_addr), 4);
3589 // analysis end, begin pack to java
3590 if (SOCK_STREAM == opt) {
3591 if (remote_addr.sin_port!=0) {
3593 channel_class = env->FindClass(
3594 "org/apache/harmony/nio/internal/SocketChannelImpl");
3595 if (NULL == channel_class) {
3599 channel_new = env->GetMethodID(channel_class, "<init>", "()V");
3600 if (NULL == channel_new) {
3603 channel_object = env->NewObject(channel_class, channel_new);
3604 if (NULL == channel_object) {
3607 // new and set FileDescript
3609 fd_field = env->GetFieldID(channel_class, "fd",
3610 "java/io/FielDescriptor");
3611 fd_object = env->GetObjectField(channel_object, fd_field);
3612 if (NULL == fd_object) {
3616 jniSetFileDescriptorOfFD(env, fd_object, socket);
3619 port_field = env->GetFieldID(channel_class, "localPort", "I");
3620 env->SetIntField(channel_object, port_field,
3621 ntohs(local_addr.sin_port));
3623 // new and set remote addr
3624 addr_object = env->NewObject(gCachedFields.iaddr_class,
3625 gCachedFields.iaddr_class_init);
3626 if (NULL == addr_object) {
3629 socketaddr_class = env->FindClass("java/net/InetSocketAddress");
3630 socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
3631 "Ljava/net/InetSocketAddress;");
3632 socketaddr_object = env->GetObjectField(channel_object,
3634 if (NULL == socketaddr_object) {
3637 addr_field = env->GetFieldID(socketaddr_class, "addr",
3638 "Ljava/net/InetAddress;");
3639 env->SetObjectField(socketaddr_object, addr_field, addr_object);
3640 addr_array = env->NewByteArray((jsize)4);
3641 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
3642 env->SetObjectField(addr_object, gCachedFields.iaddr_ipaddress,
3646 socketaddr_class = env->FindClass("java/net/InetSocketAddress");
3647 socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
3648 "Ljava/net/InetSocketAddress;");
3649 socketaddr_object = env->GetObjectField(channel_object,
3652 localAddr_field = env->GetFieldID(channel_class, "localAddress",
3653 "Ljava/net/InetAddress;");
3654 localAddr_object = env->NewObject(gCachedFields.iaddr_class,
3655 gCachedFields.iaddr_class_init);
3656 jfieldID socketaddr_field = env->GetFieldID(channel_class,
3657 "connectAddress", "Ljava/net/InetSocketAddress;");
3658 jobject socketaddr_object = env->GetObjectField(channel_object,
3660 env->SetObjectField(socketaddr_object, localAddr_field,
3662 if (NULL == localAddr_object) {
3665 addr_array = env->NewByteArray((jsize)4);
3666 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, localAddr);
3667 env->SetObjectField(localAddr_object, gCachedFields.iaddr_ipaddress,
3672 port_field = env->GetFieldID(socketaddr_class, "port", "I");
3673 env->SetIntField(socketaddr_object, port_field,
3674 ntohs(remote_addr.sin_port));
3677 if (0 != local_addr.sin_port) {
3678 bound_field = env->GetFieldID(channel_class, "isBound", "Z");
3679 env->SetBooleanField(channel_object, bound_field, jtrue);
3684 channel_class = env->FindClass(
3685 "org/apache/harmony/nio/internal/ServerSocketChannelImpl");
3686 if (NULL == channel_class) {
3690 channel_new = env->GetMethodID(channel_class, "<init>", "()V");
3691 if (NULL == channel_new) {
3694 channel_object = env->NewObject(channel_class, channel_new);
3695 if (NULL == channel_object) {
3699 serverSocket_field = env->GetFieldID(channel_class, "socket",
3700 "Ljava/net/ServerSocket;");
3701 serverSocket_class = env->FindClass("Ljava/net/ServerSocket;");
3702 serverSocket_object = env->GetObjectField(channel_object,
3703 serverSocket_field);
3705 if (0 != local_addr.sin_port) {
3706 bound_field = env->GetFieldID(channel_class, "isBound", "Z");
3707 env->SetBooleanField(channel_object, bound_field, jtrue);
3708 bound_field = env->GetFieldID(serverSocket_class, "isBound", "Z");
3709 env->SetBooleanField(serverSocket_object, bound_field, jtrue);
3712 socketImpl_class = env->FindClass("java/net/SocketImpl");
3713 socketImpl_field = env->GetFieldID(channel_class, "impl",
3714 "Ljava/net/SocketImpl;");
3715 socketImpl_object = env->GetObjectField(channel_object,
3717 if (NULL == socketImpl_object) {
3721 localAddr_field = env->GetFieldID(channel_class, "localAddress",
3722 "Ljava/net/InetAddress;");
3723 localAddr_object = env->NewObject(gCachedFields.iaddr_class,
3724 gCachedFields.iaddr_class_init);
3725 if (NULL == localAddr_object) {
3728 env->SetObjectField(socketImpl_object, localAddr_field,
3730 addr_array = env->NewByteArray((jsize)4);
3731 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, localAddr);
3732 env->SetObjectField(localAddr_object,
3733 gCachedFields.iaddr_ipaddress, addr_array);
3736 port_field = env->GetFieldID(socketImpl_class, "localport", "I");
3737 env->SetIntField(socketImpl_object, port_field,
3738 ntohs(local_addr.sin_port));
3742 // new DatagramChannel
3743 channel_class = env->FindClass(
3744 "org/apache/harmony/nio/internal/DatagramChannelImpl");
3745 if (NULL == channel_class) {
3749 channel_new = env->GetMethodID(channel_class, "<init>", "()V");
3750 if (NULL == channel_new) {
3753 channel_object = env->NewObject(channel_class, channel_new);
3754 if (NULL == channel_object) {
3758 // new and set FileDescript
3759 fd_field = env->GetFieldID(channel_class, "fd", "java/io/FileDescriptor");
3760 fd_object = env->GetObjectField(channel_object, fd_field);
3761 if (NULL == fd_object) {
3765 jniSetFileDescriptorOfFD(env, fd_object, socket);
3767 port_field = env->GetFieldID(channel_class, "localPort", "I");
3768 env->SetIntField(channel_object, port_field, ntohs(local_addr.sin_port));
3770 // new and set remote addr
3771 addr_object = env->NewObject(gCachedFields.iaddr_class,
3772 gCachedFields.iaddr_class_init);
3773 if (NULL == addr_object) {
3776 socketaddr_class = env->FindClass("java/net/InetSocketAddress");
3777 socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
3778 "Ljava/net/InetSocketAddress;");
3779 socketaddr_object = env->GetObjectField(channel_object, socketaddr_field);
3780 if (NULL == socketaddr_object) {
3783 addr_field = env->GetFieldID(socketaddr_class, "addr",
3784 "Ljava/net/InetAddress;");
3785 env->SetObjectField(socketaddr_object, addr_field, addr_object);
3786 addr_array = env->NewByteArray((jsize)4);
3787 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
3788 env->SetObjectField(addr_object, gCachedFields.iaddr_ipaddress, addr_array);
3791 if (0 != local_addr.sin_port) {
3792 bound_field = env->GetFieldID(channel_class, "isBound", "Z");
3793 env->SetBooleanField(channel_object, bound_field, jtrue);
3799 return channel_object;
3805 static JNINativeMethod gMethods[] = {
3806 /* name, signature, funcPtr */
3807 { "oneTimeInitializationImpl", "(Z)V", (void*) osNetworkSystem_oneTimeInitializationImpl },
3808 { "createStreamSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createStreamSocketImpl },
3809 { "createDatagramSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createDatagramSocketImpl },
3810 { "readSocketImpl", "(Ljava/io/FileDescriptor;[BIII)I", (void*) osNetworkSystem_readSocketImpl },
3811 { "readSocketDirectImpl", "(Ljava/io/FileDescriptor;IIII)I", (void*) osNetworkSystem_readSocketDirectImpl },
3812 { "writeSocketImpl", "(Ljava/io/FileDescriptor;[BII)I", (void*) osNetworkSystem_writeSocketImpl },
3813 { "writeSocketDirectImpl", "(Ljava/io/FileDescriptor;III)I", (void*) osNetworkSystem_writeSocketDirectImpl },
3814 { "setNonBlockingImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_setNonBlockingImpl },
3815 { "connectSocketImpl", "(Ljava/io/FileDescriptor;ILjava/net/InetAddress;I)I", (void*) osNetworkSystem_connectSocketImpl },
3816 { "connectWithTimeoutSocketImpl", "(Ljava/io/FileDescriptor;IILjava/net/InetAddress;II[B)I", (void*) osNetworkSystem_connectWithTimeoutSocketImpl },
3817 { "connectStreamWithTimeoutSocketImpl","(Ljava/io/FileDescriptor;IIILjava/net/InetAddress;)V", (void*) osNetworkSystem_connectStreamWithTimeoutSocketImpl },
3818 { "socketBindImpl", "(Ljava/io/FileDescriptor;ILjava/net/InetAddress;)V", (void*) osNetworkSystem_socketBindImpl },
3819 { "listenStreamSocketImpl", "(Ljava/io/FileDescriptor;I)V", (void*) osNetworkSystem_listenStreamSocketImpl },
3820 { "availableStreamImpl", "(Ljava/io/FileDescriptor;)I", (void*) osNetworkSystem_availableStreamImpl },
3821 { "acceptSocketImpl", "(Ljava/io/FileDescriptor;Ljava/net/SocketImpl;Ljava/io/FileDescriptor;I)V",(void*) osNetworkSystem_acceptSocketImpl },
3822 { "supportsUrgentDataImpl", "(Ljava/io/FileDescriptor;)Z", (void*) osNetworkSystem_supportsUrgentDataImpl },
3823 { "sendUrgentDataImpl", "(Ljava/io/FileDescriptor;B)V", (void*) osNetworkSystem_sendUrgentDataImpl },
3824 { "connectDatagramImpl2", "(Ljava/io/FileDescriptor;IILjava/net/InetAddress;)V", (void*) osNetworkSystem_connectDatagramImpl2 },
3825 { "disconnectDatagramImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_disconnectDatagramImpl },
3826 { "peekDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)I", (void*) osNetworkSystem_peekDatagramImpl },
3827 { "receiveDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;[BIIIZ)I", (void*) osNetworkSystem_receiveDatagramImpl },
3828 { "receiveDatagramDirectImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;IIIIZ)I", (void*) osNetworkSystem_receiveDatagramDirectImpl },
3829 { "recvConnectedDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;[BIIIZ)I", (void*) osNetworkSystem_recvConnectedDatagramImpl },
3830 { "recvConnectedDatagramDirectImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;IIIIZ)I", (void*) osNetworkSystem_recvConnectedDatagramDirectImpl },
3831 { "sendDatagramImpl", "(Ljava/io/FileDescriptor;[BIIIZILjava/net/InetAddress;)I", (void*) osNetworkSystem_sendDatagramImpl },
3832 { "sendDatagramDirectImpl", "(Ljava/io/FileDescriptor;IIIIZILjava/net/InetAddress;)I", (void*) osNetworkSystem_sendDatagramDirectImpl },
3833 { "sendConnectedDatagramImpl", "(Ljava/io/FileDescriptor;[BIIZ)I", (void*) osNetworkSystem_sendConnectedDatagramImpl },
3834 { "sendConnectedDatagramDirectImpl", "(Ljava/io/FileDescriptor;IIIZ)I", (void*) osNetworkSystem_sendConnectedDatagramDirectImpl },
3835 { "createServerStreamSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createServerStreamSocketImpl },
3836 { "receiveStreamImpl", "(Ljava/io/FileDescriptor;[BIII)I", (void*) osNetworkSystem_receiveStreamImpl },
3837 { "sendStreamImpl", "(Ljava/io/FileDescriptor;[BII)I", (void*) osNetworkSystem_sendStreamImpl },
3838 { "shutdownInputImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_shutdownInputImpl },
3839 { "shutdownOutputImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_shutdownOutputImpl },
3840 { "sendDatagramImpl2", "(Ljava/io/FileDescriptor;[BIIILjava/net/InetAddress;)I", (void*) osNetworkSystem_sendDatagramImpl2 },
3841 { "selectImpl", "([Ljava/io/FileDescriptor;[Ljava/io/FileDescriptor;II[IJ)I", (void*) osNetworkSystem_selectImpl },
3842 { "getSocketLocalAddressImpl", "(Ljava/io/FileDescriptor;Z)Ljava/net/InetAddress;", (void*) osNetworkSystem_getSocketLocalAddressImpl },
3843 { "getSocketLocalPortImpl", "(Ljava/io/FileDescriptor;Z)I", (void*) osNetworkSystem_getSocketLocalPortImpl },
3844 { "getSocketOptionImpl", "(Ljava/io/FileDescriptor;I)Ljava/lang/Object;", (void*) osNetworkSystem_getSocketOptionImpl },
3845 { "setSocketOptionImpl", "(Ljava/io/FileDescriptor;ILjava/lang/Object;)V", (void*) osNetworkSystem_setSocketOptionImpl },
3846 { "getSocketFlagsImpl", "()I", (void*) osNetworkSystem_getSocketFlagsImpl },
3847 { "socketCloseImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_socketCloseImpl },
3848 { "getHostByAddrImpl", "([B)Ljava/net/InetAddress;", (void*) osNetworkSystem_getHostByAddrImpl },
3849 { "getHostByNameImpl", "(Ljava/lang/String;Z)Ljava/net/InetAddress;", (void*) osNetworkSystem_getHostByNameImpl },
3850 { "setInetAddressImpl", "(Ljava/net/InetAddress;[B)V", (void*) osNetworkSystem_setInetAddressImpl },
3851 { "inheritedChannelImpl", "()Ljava/nio/channels/Channel;", (void*) osNetworkSystem_inheritedChannelImpl },
3854 int register_org_apache_harmony_luni_platform_OSNetworkSystem(JNIEnv* env) {
3855 return jniRegisterNativeMethods(env,
3856 "org/apache/harmony/luni/platform/OSNetworkSystem",