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_getbyaddress;
161 jmethodID i4addr_class_init;
162 jfieldID iaddr_ipaddress;
163 jclass genericipmreq_class;
164 jclass integer_class;
165 jmethodID integer_class_init;
166 jfieldID integer_class_value;
167 jclass boolean_class;
168 jmethodID boolean_class_init;
169 jfieldID boolean_class_value;
171 jmethodID byte_class_init;
172 jfieldID byte_class_value;
174 jmethodID string_class_init;
175 jfieldID socketimpl_address;
176 jfieldID socketimpl_port;
178 jfieldID dpack_address;
180 jfieldID dpack_length;
183 static int useAdbNetworking = 0;
185 /* needed for connecting with timeout */
186 typedef struct selectFDSet {
194 static const char * netLookupErrorString(int anErrorNum);
197 * Throws an SocketException with the message affiliated with the errorCode.
199 static void throwSocketException(JNIEnv *env, int errorCode) {
200 jniThrowException(env, "java/net/SocketException",
201 netLookupErrorString(errorCode));
205 * Throws an IOException with the given message.
207 static void throwIOExceptionStr(JNIEnv *env, const char *message) {
208 jniThrowException(env, "java/io/IOException", message);
212 * Throws a NullPointerException.
214 static void throwNullPointerException(JNIEnv *env) {
215 jniThrowException(env, "java/lang/NullPointerException", NULL);
219 * Converts a 4-byte array to a native address structure. Throws a
220 * NullPointerException or an IOException in case of error. This is
221 * signaled by a return value of -1. The normal return value is 0.
223 static int javaAddressToStructIn(
224 JNIEnv *env, jbyteArray java_address, struct in_addr *address) {
226 memset(address, 0, sizeof(address));
228 if (java_address == NULL) {
232 if (env->GetArrayLength(java_address) != sizeof(address->s_addr)) {
236 jbyte * java_address_bytes
237 = env->GetByteArrayElements(java_address, NULL);
239 memcpy(&(address->s_addr),
241 sizeof(address->s_addr));
243 env->ReleaseByteArrayElements(java_address, java_address_bytes, JNI_ABORT);
249 * Converts a native address structure to a Java byte array. Throws a
250 * NullPointerException or an IOException in case of error. This is
251 * signaled by a return value of -1. The normal return value is 0.
253 * @param address the sockaddr_storage structure to convert
255 * @exception SocketException the address family is unknown, or out of memory
258 static jbyteArray socketAddressToAddressBytes(JNIEnv *env,
259 struct sockaddr_storage *address) {
262 size_t addressLength;
263 if (address->ss_family == AF_INET) {
264 struct sockaddr_in *sin = (struct sockaddr_in *) address;
265 rawAddress = &sin->sin_addr.s_addr;
267 } else if (address->ss_family == AF_INET6) {
268 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address;
269 rawAddress = &sin6->sin6_addr.s6_addr;
272 throwSocketException(env, SOCKERR_BADAF);
276 jbyteArray byteArray = env->NewByteArray(addressLength);
277 if (byteArray == NULL) {
278 throwSocketException(env, SOCKERR_NOBUFFERS);
281 env->SetByteArrayRegion(byteArray, 0, addressLength, (jbyte *) rawAddress);
287 * Returns the port number in a sockaddr_storage structure.
289 * @param address the sockaddr_storage structure to get the port from
291 * @return the port number, or -1 if the address family is unknown.
293 static int getSocketAddressPort(struct sockaddr_storage *address) {
294 switch (address->ss_family) {
296 return ntohs(((struct sockaddr_in *) address)->sin_port);
298 return ntohs(((struct sockaddr_in6 *) address)->sin6_port);
305 * Converts a native address structure to an InetAddress object.
306 * Throws a NullPointerException or an IOException in case of
307 * error. This is signaled by a return value of -1. The normal
310 * @param sockaddress the sockaddr_storage structure to convert
312 * @return a jobject representing an InetAddress
314 static jobject socketAddressToInetAddress(JNIEnv *env,
315 struct sockaddr_storage *sockaddress) {
317 jbyteArray byteArray = socketAddressToAddressBytes(env, sockaddress);
318 if (byteArray == NULL) // Exception has already been thrown.
321 return env->CallStaticObjectMethod(gCachedFields.iaddr_class,
322 gCachedFields.iaddr_getbyaddress, byteArray);
326 * Converts an InetAddress object and port number to a native address structure.
327 * Throws a NullPointerException or a SocketException in case of
328 * error. This is signaled by a return value of -1. The normal
331 * @param inetaddress the InetAddress object to convert
332 * @param port the port number
333 * @param sockaddress the sockaddr_storage structure to write to
335 * @return 0 on success, -1 on failure
337 * @exception SocketError if the address family is unknown
339 static int inetAddressToSocketAddress(JNIEnv *env,
340 jobject inetaddress, int port, struct sockaddr_storage *sockaddress) {
342 // Get the byte array that stores the IP address bytes in the InetAddress.
343 jbyteArray addressByteArray;
344 addressByteArray = (jbyteArray)env->GetObjectField(inetaddress,
345 gCachedFields.iaddr_ipaddress);
346 if (addressByteArray == NULL) {
347 throwNullPointerException(env);
351 // Get the raw IP address bytes.
352 jbyte *addressBytes = env->GetByteArrayElements(addressByteArray, NULL);
353 if (addressBytes == NULL) {
354 throwNullPointerException(env);
358 // Convert the IP address bytes to the proper IP address type.
359 size_t addressLength = env->GetArrayLength(addressByteArray);
361 if (addressLength == 4) {
363 struct sockaddr_in *sin = (struct sockaddr_in *) sockaddress;
364 memset(sin, 0, sizeof(struct sockaddr_in));
365 sin->sin_family = AF_INET;
366 sin->sin_port = htons(port);
367 memcpy(&sin->sin_addr.s_addr, addressBytes, 4);
368 } else if (addressLength == 16) {
370 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sockaddress;
371 memset(sin6, 0, sizeof(struct sockaddr_in6));
372 sin6->sin6_family = AF_INET6;
373 sin6->sin6_port = htons(port);
374 memcpy(&sin6->sin6_addr.s6_addr, addressBytes, 16);
376 // Unknown address family.
377 throwSocketException(env, SOCKERR_BADAF);
380 env->ReleaseByteArrayElements(addressByteArray, addressBytes, 0);
385 * Answer a new java.lang.Boolean object.
387 * @param env pointer to the JNI library
388 * @param anInt the Boolean constructor argument
390 * @return the new Boolean
393 jobject newJavaLangBoolean(JNIEnv * env, jint anInt) {
395 jmethodID tempMethod;
397 tempClass = gCachedFields.boolean_class;
398 tempMethod = gCachedFields.boolean_class_init;
399 return env->NewObject(tempClass, tempMethod, (jboolean) (anInt != 0));
403 * Answer a new java.lang.Byte object.
405 * @param env pointer to the JNI library
406 * @param anInt the Byte constructor argument
408 * @return the new Byte
411 jobject newJavaLangByte(JNIEnv * env, jbyte val) {
413 jmethodID tempMethod;
415 tempClass = gCachedFields.byte_class;
416 tempMethod = gCachedFields.byte_class_init;
417 return env->NewObject(tempClass, tempMethod, val);
421 * Answer a new java.lang.Integer object.
423 * @param env pointer to the JNI library
424 * @param anInt the Integer constructor argument
426 * @return the new Integer
429 jobject newJavaLangInteger(JNIEnv * env, jint anInt) {
431 jmethodID tempMethod;
433 tempClass = gCachedFields.integer_class;
434 tempMethod = gCachedFields.integer_class_init;
435 return env->NewObject(tempClass, tempMethod, anInt);
439 * Answer a new java.lang.String object.
441 * @param env pointer to the JNI library
442 * @param anInt the byte[] constructor argument
444 * @return the new String
447 jobject newJavaLangString(JNIEnv * env, jbyteArray bytes) {
449 jmethodID tempMethod;
451 tempClass = gCachedFields.string_class;
452 tempMethod = gCachedFields.string_class_init;
453 return env->NewObject(tempClass, tempMethod, (jbyteArray) bytes);
457 * Query OS for timestamp.
458 * Retrieve the current value of system clock and convert to milliseconds.
460 * @param[in] portLibrary The port library.
462 * @return 0 on failure, time value in milliseconds on success.
463 * @deprecated Use @ref time_hires_clock and @ref time_hires_delta
465 * technically, this should return I_64 since both timeval.tv_sec and
466 * timeval.tv_usec are long
469 static int time_msec_clock() {
473 gettimeofday(&tp, &tzp);
474 return (tp.tv_sec * 1000) + (tp.tv_usec / 1000);
478 * Check if the passed sockaddr_storage struct contains a localhost address
480 * @param address address pointer to the address to check
482 * @return 0 if the passed address isn't a localhost address
484 static int isLocalHost(struct sockaddr_storage *address) {
485 if (address->ss_family == AF_INET) {
486 struct sockaddr_in *sin = (struct sockaddr_in *) address;
487 return (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK));
488 } else if (address->ss_family == AF_INET6) {
489 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address;
490 return IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr);
497 * Decide whether to use ADB networking for the given socket address.
499 * @param address pointer to sockaddr_storage structure to check
501 * @return true if ADB networking should be used, false otherwise.
503 static bool useAdbNetworkingForAddress(struct sockaddr_storage *address) {
504 return useAdbNetworking && !isLocalHost(address) &&
505 address->ss_family == AF_INET;
509 * Convert a sockaddr_storage structure to a string for logging purposes.
511 * @param address pointer to sockaddr_storage structure to print
513 * @return a string with the textual representation of the address.
515 * @note Returns a statically allocated buffer, so is not thread-safe.
517 static char *socketAddressToString(struct sockaddr_storage *address) {
518 static char invalidString[] = "<invalid>";
519 static char ipString[INET6_ADDRSTRLEN + sizeof("[]:65535")];
521 char tmp[INET6_ADDRSTRLEN];
523 // TODO: getnameinfo seems to want its length parameter to be exactly
524 // sizeof(sockaddr_in) for an IPv4 address and sizeof (sockaddr_in6) for an
525 // IPv6 address. Fix getnameinfo so it accepts sizeof(sockaddr_storage), and
526 // then remove this hack.
527 int size = (address->ss_family == AF_INET) ?
528 sizeof(sockaddr_in) : sizeof(sockaddr_in6);
529 int result = getnameinfo((struct sockaddr *)address,
530 size, tmp, sizeof(tmp), NULL, 0,
534 return invalidString;
536 if (address->ss_family == AF_INET6) {
537 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address;
538 port = ntohs(sin6->sin6_port);
539 sprintf(ipString, "[%s]:%d", tmp, port);
541 } else if (address->ss_family == AF_INET) {
542 struct sockaddr_in *sin = (struct sockaddr_in *) address;
543 port = ntohs(sin->sin_port);
544 sprintf(ipString, "%s:%d", tmp, port);
547 return invalidString;
552 * Answer the errorString corresponding to the errorNumber, if available.
553 * This function will answer a default error string, if the errorNumber is not
556 * This function will have to be reworked to handle internationalization
557 * properly, removing the explicit strings.
559 * @param anErrorNum the error code to resolve to a human readable string
561 * @return a human readable error string
564 static const char * netLookupErrorString(int anErrorNum) {
565 switch (anErrorNum) {
566 case SOCKERR_BADSOCKET:
568 case SOCKERR_NOTINITIALIZED:
569 return "Socket library uninitialized";
571 return "Bad address family";
572 case SOCKERR_BADPROTO:
573 return "Bad protocol";
574 case SOCKERR_BADTYPE:
576 case SOCKERR_SYSTEMBUSY:
577 return "System busy handling requests";
578 case SOCKERR_SYSTEMFULL:
579 return "Too many sockets allocated";
580 case SOCKERR_NOTCONNECTED:
581 return "Socket is not connected";
582 case SOCKERR_INTERRUPTED:
583 return "The system call was cancelled";
584 case SOCKERR_TIMEOUT:
585 return "The operation timed out";
586 case SOCKERR_CONNRESET:
587 return "The connection was reset";
588 case SOCKERR_WOULDBLOCK:
589 return "The nonblocking operation would block";
590 case SOCKERR_ADDRNOTAVAIL:
591 return "The address is not available";
592 case SOCKERR_ADDRINUSE:
593 return "The address is already in use";
594 case SOCKERR_NOTBOUND:
595 return "The socket is not bound";
596 case SOCKERR_UNKNOWNSOCKET:
597 return "Resolution of the FileDescriptor to socket failed";
598 case SOCKERR_INVALIDTIMEOUT:
599 return "The specified timeout is invalid";
600 case SOCKERR_FDSETFULL:
601 return "Unable to create an FDSET";
602 case SOCKERR_TIMEVALFULL:
603 return "Unable to create a TIMEVAL";
604 case SOCKERR_REMSOCKSHUTDOWN:
605 return "The remote socket has shutdown gracefully";
606 case SOCKERR_NOTLISTENING:
607 return "Listen() was not invoked prior to accept()";
608 case SOCKERR_NOTSTREAMSOCK:
609 return "The socket does not support connection-oriented service";
610 case SOCKERR_ALREADYBOUND:
611 return "The socket is already bound to an address";
612 case SOCKERR_NBWITHLINGER:
613 return "The socket is marked non-blocking & SO_LINGER is non-zero";
614 case SOCKERR_ISCONNECTED:
615 return "The socket is already connected";
616 case SOCKERR_NOBUFFERS:
617 return "No buffer space is available";
618 case SOCKERR_HOSTNOTFOUND:
619 return "Authoritative Answer Host not found";
621 return "Valid name, no data record of requested type";
622 case SOCKERR_BOUNDORCONN:
623 return "The socket has not been bound or is already connected";
624 case SOCKERR_OPNOTSUPP:
625 return "The socket does not support the operation";
626 case SOCKERR_OPTUNSUPP:
627 return "The socket option is not supported";
628 case SOCKERR_OPTARGSINVALID:
629 return "The socket option arguments are invalid";
630 case SOCKERR_SOCKLEVELINVALID:
631 return "The socket level is invalid";
632 case SOCKERR_TIMEOUTFAILURE:
633 return "The timeout operation failed";
634 case SOCKERR_SOCKADDRALLOCFAIL:
635 return "Failed to allocate address structure";
636 case SOCKERR_FDSET_SIZEBAD:
637 return "The calculated maximum size of the file descriptor set is bad";
638 case SOCKERR_UNKNOWNFLAG:
639 return "The flag is unknown";
640 case SOCKERR_MSGSIZE:
641 return "The datagram was too big to fit the specified buffer, so truncated";
642 case SOCKERR_NORECOVERY:
643 return "The operation failed with no recovery possible";
644 case SOCKERR_ARGSINVALID:
645 return "The arguments are invalid";
646 case SOCKERR_BADDESC:
647 return "The socket argument is not a valid file descriptor";
648 case SOCKERR_NOTSOCK:
649 return "The socket argument is not a socket";
650 case SOCKERR_HOSTENTALLOCFAIL:
651 return "Unable to allocate the hostent structure";
652 case SOCKERR_TIMEVALALLOCFAIL:
653 return "Unable to allocate the timeval structure";
654 case SOCKERR_LINGERALLOCFAIL:
655 return "Unable to allocate the linger structure";
656 case SOCKERR_IPMREQALLOCFAIL:
657 return "Unable to allocate the ipmreq structure";
658 case SOCKERR_FDSETALLOCFAIL:
659 return "Unable to allocate the fdset structure";
660 case SOCKERR_OPFAILED:
661 return "Operation failed";
662 case SOCKERR_CONNECTION_REFUSED:
663 return "Connection refused";
664 case SOCKERR_ENETUNREACH:
665 return "Network unreachable";
666 case SOCKERR_EHOSTUNREACH:
667 return "No route to host";
669 return "Broken pipe";
671 return "Permission denied (maybe missing INTERNET permission)";
674 LOGE("unknown socket error %d", anErrorNum);
675 return "unknown error";
679 static int convertError(int errorCode) {
682 return SOCKERR_BADDESC;
684 return SOCKERR_NOBUFFERS;
686 return SOCKERR_OPNOTSUPP;
688 return SOCKERR_OPTUNSUPP;
690 return SOCKERR_SOCKLEVELINVALID;
692 return SOCKERR_NOTSOCK;
694 return SOCKERR_INTERRUPTED;
696 return SOCKERR_NOTCONNECTED;
698 return SOCKERR_BADAF;
699 /* note: CONNRESET not included because it has the same
700 * value as ECONNRESET and they both map to SOCKERR_CONNRESET */
702 return SOCKERR_CONNRESET;
704 return SOCKERR_WOULDBLOCK;
705 case EPROTONOSUPPORT:
706 return SOCKERR_BADPROTO;
708 return SOCKERR_ARGSINVALID;
710 return SOCKERR_TIMEOUT;
712 return SOCKERR_CONNECTION_REFUSED;
714 return SOCKERR_ENETUNREACH;
716 return SOCKERR_EACCES;
718 return SOCKERR_EPIPE;
720 return SOCKERR_EHOSTUNREACH;
722 return SOCKERR_ADDRINUSE;
724 return SOCKERR_ADDRNOTAVAIL;
726 return SOCKERR_MSGSIZE;
728 LOGE("unclassified errno %d (%s)", errorCode, strerror(errorCode));
729 return SOCKERR_OPFAILED;
733 static int sockSelect(int nfds, fd_set *readfds, fd_set *writefds,
734 fd_set *exceptfds, struct timeval *timeout) {
736 int result = select(nfds, readfds, writefds, exceptfds, timeout);
739 if (errno == EINTR) {
740 result = SOCKERR_INTERRUPTED;
742 result = SOCKERR_OPFAILED;
744 } else if (result == 0) {
745 result = SOCKERR_TIMEOUT;
750 #define SELECT_READ_TYPE 0
751 #define SELECT_WRITE_TYPE 1
753 static int selectWait(int handle, int uSecTime, int type) {
755 struct timeval time, *timePtr;
757 int size = handle + 1;
760 FD_SET(handle, &fdset);
763 /* Use a timeout if uSecTime >= 0 */
764 memset(&time, 0, sizeof(time));
765 time.tv_usec = uSecTime;
768 /* Infinite timeout if uSecTime < 0 */
772 if (type == SELECT_READ_TYPE) {
773 result = sockSelect(size, &fdset, NULL, NULL, timePtr);
775 result = sockSelect(size, NULL, &fdset, NULL, timePtr);
780 static int pollSelectWait(JNIEnv *env, jobject fileDescriptor, int timeout, int type) {
781 /* now try reading the socket for the timespan timeout.
782 * if timeout is 0 try forever until the soclets gets ready or until an
785 int pollTimeoutUSec = 100000, pollMsec = 100;
787 int timeLeft = timeout;
788 int hasTimeout = timeout > 0 ? 1 : 0;
793 finishTime = time_msec_clock() + timeout;
798 while (poll) { /* begin polling loop */
801 * Fetch the handle every time in case the socket is closed.
803 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
805 if (handle == 0 || handle == -1) {
806 throwSocketException(env, SOCKERR_INTERRUPTED);
812 if (timeLeft - 10 < pollMsec) {
813 pollTimeoutUSec = timeLeft <= 0 ? 0 : (timeLeft * 1000);
816 result = selectWait(handle, pollTimeoutUSec, type);
819 * because we are polling at a time smaller than timeout
820 * (presumably) lets treat an interrupt and timeout the same - go
821 * see if we're done timewise, and then just try again if not.
823 if (SOCKERR_TIMEOUT == result ||
824 SOCKERR_INTERRUPTED == result) {
826 timeLeft = finishTime - time_msec_clock();
830 * Always throw the "timeout" message because that is
831 * effectively what has happened, even if we happen to
832 * have been interrupted.
834 jniThrowException(env, "java/net/SocketTimeoutException",
835 netLookupErrorString(SOCKERR_TIMEOUT));
837 continue; // try again
840 } else if (0 > result) {
841 throwSocketException(env, result);
845 } else { /* polling with no timeout (why would you do this?)*/
847 result = selectWait(handle, pollTimeoutUSec, type);
850 * if interrupted (or a timeout) just retry
852 if (SOCKERR_TIMEOUT == result ||
853 SOCKERR_INTERRUPTED == result) {
855 continue; // try again
856 } else if (0 > result) {
857 throwSocketException(env, result);
861 } /* end polling loop */
867 * Obtain the socket address family from an existing socket.
869 * @param socket the filedescriptor of the socket to examine
871 * @return an integer, the address family of the socket
873 static int getSocketAddressFamily(int socket) {
874 struct sockaddr_storage ss;
875 socklen_t namelen = sizeof(ss);
876 int ret = getsockname(socket, (struct sockaddr*) &ss, &namelen);
885 * A helper method, to set the connect context to a Long object.
887 * @param env pointer to the JNI library
888 * @param longclass Java Long Object
890 void setConnectContext(JNIEnv *env,jobject longclass,jbyte * context) {
891 jclass descriptorCLS;
892 jfieldID descriptorFID;
893 descriptorCLS = env->FindClass("java/lang/Long");
894 descriptorFID = env->GetFieldID(descriptorCLS, "value", "J");
895 env->SetLongField(longclass, descriptorFID, (jlong)((jint)context));
899 * A helper method, to get the connect context.
901 * @param env pointer to the JNI library
902 * @param longclass Java Long Object
904 jbyte *getConnectContext(JNIEnv *env, jobject longclass) {
905 jclass descriptorCLS;
906 jfieldID descriptorFID;
907 descriptorCLS = env->FindClass("java/lang/Long");
908 descriptorFID = env->GetFieldID(descriptorCLS, "value", "J");
909 return (jbyte*) ((jint)env->GetLongField(longclass, descriptorFID));
912 // typical ip checksum
913 unsigned short ip_checksum(unsigned short* buffer, int size) {
914 register unsigned short * buf = buffer;
915 register int bufleft = size;
916 register unsigned long sum = 0;
918 while (bufleft > 1) {
919 sum = sum + (*buf++);
920 bufleft = bufleft - sizeof(unsigned short );
923 sum = sum + (*(unsigned char*)buf);
925 sum = (sum >> 16) + (sum & 0xffff);
928 return (unsigned short )(~sum);
932 * Converts an IPv4 address to an IPv4-mapped IPv6 address. Performs no error
935 * @param address the address to convert. Must contain an IPv4 address.
936 * @param outputAddress the converted address. Will contain an IPv6 address.
937 * @param mapUnspecified if true, convert 0.0.0.0 to ::ffff:0:0; if false, to ::
939 static void ipv4ToMappedAddress(struct sockaddr_storage *address,
940 struct sockaddr_storage *outputAddress, bool mapUnspecified) {
941 memset(outputAddress, 0, sizeof(struct sockaddr_storage));
942 const struct sockaddr_in *sin = ((struct sockaddr_in *) address);
943 struct sockaddr_in6 *sin6 = ((struct sockaddr_in6 *) outputAddress);
944 sin6->sin6_family = AF_INET6;
945 sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
946 if (sin->sin_addr.s_addr != 0 || mapUnspecified) {
947 sin6->sin6_addr.s6_addr32[2] = htonl(0xffff);
949 sin6->sin6_port = sin->sin_port;
953 * Wrapper for connect() that converts IPv4 addresses to IPv4-mapped IPv6
954 * addresses if necessary.
956 * @param socket the filedescriptor of the socket to connect
957 * @param socketAddress the address to connect to
959 static int doConnect(int socket, struct sockaddr_storage *socketAddress) {
960 struct sockaddr_storage mappedAddress;
961 struct sockaddr_storage *realAddress;
962 if (socketAddress->ss_family == AF_INET &&
963 getSocketAddressFamily(socket) == AF_INET6) {
964 ipv4ToMappedAddress(socketAddress, &mappedAddress, true);
965 realAddress = &mappedAddress;
967 realAddress = socketAddress;
971 ret = connect(socket, (struct sockaddr *) realAddress,
972 sizeof(struct sockaddr_storage));
973 } while (ret < 0 && errno == EINTR);
978 * Wrapper for bind() that converts IPv4 addresses to IPv4-mapped IPv6
979 * addresses if necessary.
981 * @param socket the filedescriptor of the socket to connect
982 * @param socketAddress the address to connect to
984 static int doBind(int socket, struct sockaddr_storage *socketAddress) {
985 struct sockaddr_storage mappedAddress;
986 struct sockaddr_storage *realAddress;
987 if (socketAddress->ss_family == AF_INET &&
988 getSocketAddressFamily(socket) == AF_INET6) {
989 ipv4ToMappedAddress(socketAddress, &mappedAddress, false);
990 realAddress = &mappedAddress;
992 realAddress = socketAddress;
996 ret = bind(socket, (struct sockaddr *) realAddress,
997 sizeof(struct sockaddr_storage));
998 } while (ret < 0 && errno == EINTR);
1003 * Establish a connection to a peer with a timeout. This function is called
1004 * repeatedly in order to carry out the connect and to allow other tasks to
1005 * proceed on certain platforms. The caller must first call with
1006 * step = SOCKET_STEP_START, if the result is SOCKERR_NOTCONNECTED it will then
1007 * call it with step = CHECK until either another error or 0 is returned to
1008 * indicate the connect is complete. Each time the function should sleep for no
1009 * more than timeout milliseconds. If the connect succeeds or an error occurs,
1010 * the caller must always end the process by calling the function with
1011 * step = SOCKET_STEP_DONE
1013 * @param[in] portLibrary The port library.
1014 * @param[in] sock pointer to the unconnected local socket.
1015 * @param[in] addr pointer to the sockaddr, specifying remote host/port.
1016 * @param[in] timeout the timeout in milliseconds. If timeout is negative,
1017 * perform a block operation.
1018 * @param[in,out] pointer to context pointer. Filled in on first call and then
1019 * to be passed into each subsequent call.
1021 * @return 0, if no errors occurred, otherwise the (negative) error code.
1023 static int sockConnectWithTimeout(int handle, struct sockaddr_storage addr,
1024 unsigned int timeout, unsigned int step, jbyte *ctxt) {
1026 struct timeval passedTimeout;
1028 socklen_t errorValLen = sizeof(int);
1029 struct selectFDSet *context = NULL;
1031 if (SOCKET_STEP_START == step) {
1033 context = (struct selectFDSet *) ctxt;
1035 context->sock = handle;
1036 context->nfds = handle + 1;
1038 if (useAdbNetworkingForAddress(&addr)) {
1040 // LOGD("+connect to address 0x%08x (via adb)",
1041 // addr.sin_addr.s_addr);
1042 rc = adb_networking_connect_fd(handle, (struct sockaddr_in *) &addr);
1043 // LOGD("-connect ret %d errno %d (via adb)", rc, errno);
1046 /* set the socket to non-blocking */
1047 int block = JNI_TRUE;
1048 rc = ioctl(handle, FIONBIO, &block);
1050 return convertError(rc);
1053 // LOGD("+connect to address 0x%08x (via normal) on handle %d",
1054 // addr.sin_addr.s_addr, handle);
1055 rc = doConnect(handle, &addr);
1056 // LOGD("-connect to address 0x%08x (via normal) returned %d",
1057 // addr.sin_addr.s_addr, (int) rc);
1065 return SOCKERR_ALREADYBOUND;
1068 return SOCKERR_NOTCONNECTED;
1070 return convertError(rc);
1074 /* we connected right off the bat so just return */
1077 } else if (SOCKET_STEP_CHECK == step) {
1078 /* now check if we have connected yet */
1080 context = (struct selectFDSet *) ctxt;
1083 * set the timeout value to be used. Because on some unix platforms we
1084 * don't get notified when a socket is closed we only sleep for 100ms
1087 passedTimeout.tv_sec = 0;
1088 if (timeout > 100) {
1089 passedTimeout.tv_usec = 100 * 1000;
1090 } else if ((int)timeout >= 0) {
1091 passedTimeout.tv_usec = timeout * 1000;
1094 /* initialize the FD sets for the select */
1095 FD_ZERO(&(context->exceptionSet));
1096 FD_ZERO(&(context->writeSet));
1097 FD_ZERO(&(context->readSet));
1098 FD_SET(context->sock, &(context->writeSet));
1099 FD_SET(context->sock, &(context->readSet));
1100 FD_SET(context->sock, &(context->exceptionSet));
1102 rc = select(context->nfds,
1103 &(context->readSet),
1104 &(context->writeSet),
1105 &(context->exceptionSet),
1106 (int)timeout >= 0 ? &passedTimeout : NULL);
1108 /* if there is at least one descriptor ready to be checked */
1110 /* if the descriptor is in the write set we connected or failed */
1111 if (FD_ISSET(context->sock, &(context->writeSet))) {
1113 if (!FD_ISSET(context->sock, &(context->readSet))) {
1114 /* ok we have connected ok */
1117 /* ok we have more work to do to figure it out */
1118 if (getsockopt(context->sock, SOL_SOCKET, SO_ERROR,
1119 &errorVal, &errorValLen) >= 0) {
1120 return errorVal ? convertError(errorVal) : 0;
1122 return convertError(errno);
1127 /* if the descriptor is in the exception set the connect failed */
1128 if (FD_ISSET(context->sock, &(context->exceptionSet))) {
1129 if (getsockopt(context->sock, SOL_SOCKET, SO_ERROR, &errorVal,
1130 &errorValLen) >= 0) {
1131 return errorVal ? convertError(errorVal) : 0;
1134 return convertError(rc);
1137 } else if (rc < 0) {
1138 /* something went wrong with the select call */
1141 /* if it was EINTR we can just try again. Return not connected */
1143 return SOCKERR_NOTCONNECTED;
1146 /* some other error occured so look it up and return */
1147 return convertError(rc);
1151 * if we get here the timeout expired or the connect had not yet
1152 * completed just indicate that the connect is not yet complete
1154 return SOCKERR_NOTCONNECTED;
1155 } else if (SOCKET_STEP_DONE == step) {
1156 /* we are done the connect or an error occured so clean up */
1158 int block = JNI_FALSE;
1159 ioctl(handle, FIONBIO, &block);
1163 return SOCKERR_ARGSINVALID;
1168 * Helper method to get or set socket options
1170 * @param action SOCKOPT_GET to get an option, SOCKOPT_SET to set it
1171 * @param socket the file descriptor of the socket to use
1172 * @param ipv4Option the option value to use for an IPv4 socket
1173 * @param ipv6Option the option value to use for an IPv6 socket
1174 * @param optionValue the value of the socket option to get or set
1175 * @param optionLength the length of the socket option to get or set
1177 * @return the value of the socket call, or -1 on failure inside this function
1179 * @note on internal failure, the errno variable will be set appropriately
1181 static int getOrSetSocketOption(int action, int socket, int ipv4Option,
1182 int ipv6Option, void *optionValue, socklen_t *optionLength) {
1185 int family = getSocketAddressFamily(socket);
1188 option = ipv4Option;
1189 protocol = IPPROTO_IP;
1192 option = ipv6Option;
1193 protocol = IPPROTO_IPV6;
1196 errno = EAFNOSUPPORT;
1199 if (action == SOCKOPT_GET) {
1200 return getsockopt(socket, protocol, option, &optionValue, optionLength);
1201 } else if (action == SOCKOPT_SET) {
1202 return setsockopt(socket, protocol, option, &optionValue,
1211 * Find the interface index that was set for this socket by the IP_MULTICAST_IF
1212 * or IPV6_MULTICAST_IF socket option.
1214 * @param socket the socket to examine
1216 * @return the interface index, or -1 on failure
1218 * @note on internal failure, the errno variable will be set appropriately
1220 static int interfaceIndexFromMulticastSocket(int socket) {
1221 int family = getSocketAddressFamily(socket);
1222 socklen_t requestLength;
1225 if (family == AF_INET) {
1226 // IP_MULTICAST_IF returns a pointer to a struct ip_mreqn.
1227 struct ip_mreqn tempRequest;
1228 requestLength = sizeof(tempRequest);
1229 result = getsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, &tempRequest,
1231 interfaceIndex = tempRequest.imr_ifindex;
1232 } else if (family == AF_INET6) {
1233 // IPV6_MULTICAST_IF returns a pointer to an integer.
1234 requestLength = sizeof(interfaceIndex);
1235 result = getsockopt(socket, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1236 &interfaceIndex, &requestLength);
1238 errno = EAFNOSUPPORT;
1243 return interfaceIndex;
1250 * Join/Leave the nominated multicast group on the specified socket.
1251 * Implemented by setting the multicast 'add membership'/'drop membership'
1252 * option at the HY_IPPROTO_IP level on the socket.
1254 * Implementation note for multicast sockets in general:
1256 * - This code is untested, because at the time of this writing multicast can't
1257 * be properly tested on Android due to GSM routing restrictions. So it might
1258 * or might not work.
1260 * - The REUSEPORT socket option that Harmony employs is not supported on Linux
1261 * and thus also not supported on Android. It's is not needed for multicast
1262 * to work anyway (REUSEADDR should suffice).
1264 * @param env pointer to the JNI library.
1265 * @param socketP pointer to the hysocket to join/leave on.
1266 * @param optVal pointer to the InetAddress, the multicast group to join/drop.
1268 * @exception SocketException if an error occurs during the call
1270 static void mcastAddDropMembership (JNIEnv * env, int handle, jobject optVal,
1271 int ignoreIF, int setSockOptVal) {
1272 struct sockaddr_storage sockaddrP;
1274 // By default, let the system decide which interface to use.
1275 int interfaceIndex = 0;
1278 * Check whether we are getting an InetAddress or an Generic IPMreq. For now
1279 * we support both so that we will not break the tests. If an InetAddress
1280 * is passed in, only support IPv4 as obtaining an interface from an
1281 * InetAddress is complex and should be done by the Java caller.
1283 if (env->IsInstanceOf (optVal, gCachedFields.iaddr_class)) {
1285 * optVal is an InetAddress. Construct a multicast request structure
1286 * from this address. Support IPv4 only.
1288 struct ip_mreqn multicastRequest;
1289 socklen_t length = sizeof(multicastRequest);
1290 memset(&multicastRequest, 0, length);
1292 // If ignoreIF is false, determine the index of the interface to use.
1294 interfaceIndex = interfaceIndexFromMulticastSocket(handle);
1295 multicastRequest.imr_ifindex = interfaceIndex;
1296 if (interfaceIndex == -1) {
1297 throwSocketException(env, convertError(errno));
1302 // Convert the inetAddress to an IPv4 address structure.
1303 result = inetAddressToSocketAddress(env, optVal, 0, &sockaddrP);
1304 if (result < 0) // Exception has already been thrown.
1306 if (sockaddrP.ss_family != AF_INET) {
1307 throwSocketException(env, SOCKERR_BADAF);
1310 struct sockaddr_in *sin = (struct sockaddr_in *) &sockaddrP;
1311 multicastRequest.imr_multiaddr = sin->sin_addr;
1313 result = setsockopt(handle, IPPROTO_IP, setSockOptVal,
1314 &multicastRequest, length);
1316 throwSocketException (env, convertError(errno));
1321 * optVal is a GenericIPMreq object. Extract the relevant fields from
1322 * it and construct a multicast request structure from these. Support
1323 * both IPv4 and IPv6.
1326 jfieldID multiaddrID;
1327 jfieldID interfaceIdxID;
1330 // Get the multicast address to join or leave.
1331 cls = env->GetObjectClass(optVal);
1332 multiaddrID = env->GetFieldID(cls, "multiaddr", "Ljava/net/InetAddress;");
1333 multiaddr = env->GetObjectField(optVal, multiaddrID);
1335 // Get the interface index to use.
1337 interfaceIdxID = env->GetFieldID(cls, "interfaceIdx", "I");
1338 interfaceIndex = env->GetIntField(optVal, interfaceIdxID);
1341 result = inetAddressToSocketAddress(env, multiaddr, 0, &sockaddrP);
1342 if (result < 0) // Exception has already been thrown.
1345 struct ip_mreqn ipv4Request;
1346 struct ipv6_mreq ipv6Request;
1347 void *multicastRequest;
1348 socklen_t requestLength;
1350 int family = getSocketAddressFamily(handle);
1353 requestLength = sizeof(ipv4Request);
1354 memset(&ipv4Request, 0, requestLength);
1355 ipv4Request.imr_multiaddr =
1356 ((struct sockaddr_in *) &sockaddrP)->sin_addr;
1357 ipv4Request.imr_ifindex = interfaceIndex;
1358 multicastRequest = &ipv4Request;
1362 requestLength = sizeof(ipv6Request);
1363 memset(&ipv6Request, 0, requestLength);
1364 ipv6Request.ipv6mr_multiaddr =
1365 ((struct sockaddr_in6 *) &sockaddrP)->sin6_addr;
1366 ipv6Request.ipv6mr_interface = interfaceIndex;
1367 multicastRequest = &ipv6Request;
1368 level = IPPROTO_IPV6;
1371 throwSocketException (env, SOCKERR_BADAF);
1375 /* join/drop the multicast address */
1376 result = setsockopt(handle, level, setSockOptVal, multicastRequest,
1379 throwSocketException (env, convertError(errno));
1385 static void osNetworkSystem_oneTimeInitializationImpl(JNIEnv* env, jobject obj,
1386 jboolean jcl_supports_ipv6) {
1387 // LOGD("ENTER oneTimeInitializationImpl of OSNetworkSystem");
1389 char useAdbNetworkingProperty[PROPERTY_VALUE_MAX];
1390 char adbConnectedProperty[PROPERTY_VALUE_MAX];
1392 property_get("android.net.use-adb-networking", useAdbNetworkingProperty, "");
1393 property_get("adb.connected", adbConnectedProperty, "");
1395 if (strlen((char *)useAdbNetworkingProperty) > 0
1396 && strlen((char *)adbConnectedProperty) > 0) {
1397 useAdbNetworking = 1;
1400 memset(&gCachedFields, 0, sizeof(gCachedFields));
1402 // initializing InetAddress
1404 jclass iaddrclass = env->FindClass("java/net/InetAddress");
1405 if (iaddrclass == NULL) {
1406 jniThrowException(env, "java/lang/ClassNotFoundException",
1407 "java.net.InetAddress");
1410 gCachedFields.iaddr_class = (jclass) env->NewGlobalRef(iaddrclass);
1412 jclass i4addrclass = env->FindClass("java/net/Inet4Address");
1413 if (i4addrclass == NULL) {
1414 jniThrowException(env, "java/lang/ClassNotFoundException",
1415 "java.net.Inet4Address");
1418 gCachedFields.i4addr_class = (jclass) env->NewGlobalRef(i4addrclass);
1420 jmethodID i4addrclassinit = env->GetMethodID(i4addrclass, "<init>", "([B)V");
1421 if (i4addrclassinit == NULL) {
1422 jniThrowException(env, "java/lang/NoSuchMethodError", "Inet4Address.<init>(byte[])");
1425 gCachedFields.i4addr_class_init = i4addrclassinit;
1427 jmethodID iaddrgetbyaddress = env->GetStaticMethodID(iaddrclass,
1428 "getByAddress", "([B)Ljava/net/InetAddress;");
1430 if (iaddrgetbyaddress == NULL) {
1431 jniThrowException(env, "java/lang/NoSuchMethodError",
1432 "InetAddress.getByAddress(byte[] val)");
1436 gCachedFields.iaddr_getbyaddress = iaddrgetbyaddress;
1438 jfieldID iaddripaddress = env->GetFieldID(iaddrclass, "ipaddress", "[B");
1439 if (iaddripaddress == NULL) {
1440 jniThrowException(env, "java/lang/NoSuchFieldError",
1441 "Can't find field InetAddress.ipaddress");
1444 gCachedFields.iaddr_ipaddress = iaddripaddress;
1446 // get the GenericIPMreq class
1448 jclass genericipmreqclass = env->FindClass("org/apache/harmony/luni/net/GenericIPMreq");
1450 if (genericipmreqclass == NULL) {
1451 jniThrowException(env, "java/lang/ClassNotFoundException",
1452 "org.apache.harmony.luni.net.GenericIPMreq");
1456 gCachedFields.genericipmreq_class = (jclass) env->NewGlobalRef(genericipmreqclass);
1458 // initializing Integer
1460 jclass integerclass = env->FindClass("java/lang/Integer");
1462 if (integerclass == NULL) {
1463 jniThrowException(env, "java/lang/ClassNotFoundException",
1464 "java.lang.Integer");
1468 jmethodID integerclassinit = env->GetMethodID(integerclass, "<init>", "(I)V");
1470 if (integerclassinit == NULL) {
1471 jniThrowException(env, "java/lang/NoSuchMethodError",
1472 "Integer.<init>(int val)");
1476 jfieldID integerclassvalue = env->GetFieldID(integerclass, "value", "I");
1478 if (integerclassvalue == NULL) {
1479 jniThrowException(env, "java/lang/NoSuchMethodError", "Integer.value");
1483 gCachedFields.integer_class = (jclass) env->NewGlobalRef(integerclass);
1484 gCachedFields.integer_class_init = integerclassinit;
1485 gCachedFields.integer_class_value = integerclassvalue;
1487 // initializing Boolean
1489 jclass booleanclass = env->FindClass("java/lang/Boolean");
1491 if (booleanclass == NULL) {
1492 jniThrowException(env, "java/lang/ClassNotFoundException",
1493 "java.lang.Boolean");
1497 jmethodID booleanclassinit = env->GetMethodID(booleanclass, "<init>", "(Z)V");
1499 if (booleanclassinit == NULL) {
1500 jniThrowException(env, "java/lang/NoSuchMethodError",
1501 "Boolean.<init>(boolean val)");
1505 jfieldID booleanclassvalue = env->GetFieldID(booleanclass, "value", "Z");
1507 if (booleanclassvalue == NULL) {
1508 jniThrowException(env, "java/lang/NoSuchMethodError", "Boolean.value");
1512 gCachedFields.boolean_class = (jclass) env->NewGlobalRef(booleanclass);
1513 gCachedFields.boolean_class_init = booleanclassinit;
1514 gCachedFields.boolean_class_value = booleanclassvalue;
1516 // initializing Byte
1518 jclass byteclass = env->FindClass("java/lang/Byte");
1520 if (byteclass == NULL) {
1521 jniThrowException(env, "java/lang/ClassNotFoundException",
1526 jmethodID byteclassinit = env->GetMethodID(byteclass, "<init>", "(B)V");
1528 if (byteclassinit == NULL) {
1529 jniThrowException(env, "java/lang/NoSuchMethodError",
1530 "Byte.<init>(byte val)");
1534 jfieldID byteclassvalue = env->GetFieldID(byteclass, "value", "B");
1536 if (byteclassvalue == NULL) {
1537 jniThrowException(env, "java/lang/NoSuchMethodError", "Byte.value");
1541 gCachedFields.byte_class = (jclass) env->NewGlobalRef(byteclass);
1542 gCachedFields.byte_class_init = byteclassinit;
1543 gCachedFields.byte_class_value = byteclassvalue;
1545 // initializing String
1547 jclass stringclass = env->FindClass("java/lang/String");
1549 if (stringclass == NULL) {
1550 jniThrowException(env, "java/lang/ClassNotFoundException",
1551 "java.lang.String");
1555 jmethodID stringclassinit = env->GetMethodID(stringclass, "<init>", "([B)V");
1557 if (stringclassinit == NULL) {
1558 jniThrowException(env, "java/lang/NoSuchMethodError",
1559 "String.<init>(byte[] val)");
1563 gCachedFields.string_class = (jclass) env->NewGlobalRef(stringclass);
1564 gCachedFields.string_class_init = stringclassinit;
1566 // initializing ScoketImpl
1568 jclass socketimplclass = env->FindClass("java/net/SocketImpl");
1570 if (socketimplclass == NULL) {
1571 jniThrowException(env, "java/lang/ClassNotFoundException",
1572 "java.net.SocketImpl");
1576 jfieldID socketimplport = env->GetFieldID(socketimplclass, "port", "I");
1578 if (socketimplport == NULL) {
1579 jniThrowException(env, "java/lang/NoSuchFieldError", "SocketImpl.port");
1583 jfieldID socketimpladdress = env->GetFieldID(socketimplclass, "address",
1584 "Ljava/net/InetAddress;");
1586 if (socketimpladdress == NULL) {
1587 jniThrowException(env, "java/lang/NoSuchFieldError",
1588 "SocketImpl.address");
1592 gCachedFields.socketimpl_address = socketimpladdress;
1593 gCachedFields.socketimpl_port = socketimplport;
1595 gCachedFields.dpack_class = env->FindClass("java/net/DatagramPacket");
1596 if (gCachedFields.dpack_class == NULL) {
1597 jniThrowException(env, "java/lang/ClassNotFoundException",
1598 "java.net.DatagramPacket");
1602 gCachedFields.dpack_address = env->GetFieldID(gCachedFields.dpack_class,
1603 "address", "Ljava/net/InetAddress;");
1604 if (gCachedFields.dpack_address == NULL) {
1605 jniThrowException(env, "java/lang/NoSuchFieldError",
1606 "DatagramPacket.address");
1610 gCachedFields.dpack_port = env->GetFieldID(gCachedFields.dpack_class,
1612 if (gCachedFields.dpack_port == NULL) {
1613 jniThrowException(env, "java/lang/NoSuchFieldError",
1614 "DatagramPacket.port");
1618 gCachedFields.dpack_length = env->GetFieldID(gCachedFields.dpack_class,
1620 if (gCachedFields.dpack_length == NULL) {
1621 jniThrowException(env, "java/lang/NoSuchFieldError",
1622 "DatagramPacket.length");
1629 * Helper function to create a socket of the specified type and bind it to a
1630 * Java file descriptor.
1632 * @param fileDescriptor the file descriptor to bind the socket to
1633 * @param type the socket type to create, e.g., SOCK_STREAM
1635 * @return the socket file descriptor, or -1 on failure
1638 static int createSocketFileDescriptor(JNIEnv* env, jobject fileDescriptor,
1640 if (fileDescriptor == NULL) {
1641 throwNullPointerException(env);
1647 sock = socket(PF_INET6, type, 0);
1648 if (sock < 0 && errno == EAFNOSUPPORT) {
1649 sock = socket(PF_INET, type, 0);
1652 int err = convertError(errno);
1653 throwSocketException(env, err);
1655 jniSetFileDescriptorOfFD(env, fileDescriptor, sock);
1660 static void osNetworkSystem_createStreamSocketImpl(JNIEnv* env, jclass clazz,
1661 jobject fileDescriptor, jboolean preferIPv4Stack) {
1662 // LOGD("ENTER createSocketImpl");
1663 createSocketFileDescriptor(env, fileDescriptor, SOCK_STREAM);
1666 static void osNetworkSystem_createDatagramSocketImpl(JNIEnv* env, jclass clazz,
1667 jobject fileDescriptor, jboolean preferIPv4Stack) {
1668 // LOGD("ENTER createDatagramSocketImpl");
1669 createSocketFileDescriptor(env, fileDescriptor, SOCK_DGRAM);
1672 static jint osNetworkSystem_readSocketDirectImpl(JNIEnv* env, jclass clazz,
1673 jobject fileDescriptor, jint address, jint offset, jint count,
1675 // LOGD("ENTER readSocketDirectImpl");
1678 jbyte *message = (jbyte *)address + offset;
1679 int result, ret, localCount;
1681 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1683 if (handle == 0 || handle == -1) {
1684 throwSocketException(env, SOCKERR_BADSOCKET);
1688 result = selectWait(handle, timeout, SELECT_READ_TYPE);
1694 localCount = (count < 65536) ? count : 65536;
1697 ret = recv(handle, (jbyte *) message, localCount, SOCKET_NOFLAGS);
1698 } while (ret < 0 && errno == EINTR);
1702 } else if (ret == -1) {
1703 int err = convertError(errno);
1704 throwSocketException(env, err);
1710 static jint osNetworkSystem_readSocketImpl(JNIEnv* env, jclass clazz,
1711 jobject fileDescriptor, jbyteArray data, jint offset, jint count,
1713 // LOGD("ENTER readSocketImpl");
1716 int result, localCount;
1718 jbyte internalBuffer[BUFFERSIZE];
1720 localCount = (count < 65536) ? count : 65536;
1722 if (localCount > BUFFERSIZE) {
1723 message = (jbyte*)malloc(localCount * sizeof(jbyte));
1724 if (message == NULL) {
1725 jniThrowException(env, "java/lang/OutOfMemoryError",
1726 "couldn't allocate enough memory for readSocket");
1730 message = (jbyte *)internalBuffer;
1733 result = osNetworkSystem_readSocketDirectImpl(env, clazz, fileDescriptor,
1734 (jint) message, 0, localCount, timeout);
1737 env->SetByteArrayRegion(data, offset, result, (jbyte *)message);
1740 if (((jbyte *)message) != internalBuffer) {
1741 free(( jbyte *)message);
1747 static jint osNetworkSystem_writeSocketDirectImpl(JNIEnv* env, jclass clazz,
1748 jobject fileDescriptor, jint address, jint offset, jint count) {
1749 // LOGD("ENTER writeSocketDirectImpl");
1752 jbyte *message = (jbyte *)address + offset;
1753 int result = 0, sent = 0;
1759 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1761 if (handle == 0 || handle == -1) {
1762 throwSocketException(env, SOCKERR_BADSOCKET);
1766 result = send(handle, (jbyte *) message, (int) count, SOCKET_NOFLAGS);
1768 int err = convertError(errno);
1770 if (SOCKERR_WOULDBLOCK == err){
1771 jclass socketExClass,errorCodeExClass;
1772 jmethodID errorCodeExConstructor, socketExConstructor,socketExCauseMethod;
1773 jobject errorCodeEx, socketEx;
1774 const char* errorMessage = netLookupErrorString(err);
1775 jstring errorMessageString = env->NewStringUTF(errorMessage);
1777 errorCodeExClass = env->FindClass("org/apache/harmony/luni/util/ErrorCodeException");
1778 if (!errorCodeExClass){
1781 errorCodeExConstructor = env->GetMethodID(errorCodeExClass,"<init>","(I)V");
1782 if (!errorCodeExConstructor){
1785 errorCodeEx = env->NewObject(errorCodeExClass,errorCodeExConstructor,err);
1787 socketExClass = env->FindClass("java/net/SocketException");
1788 if (!socketExClass) {
1791 socketExConstructor = env->GetMethodID(socketExClass,"<init>","(Ljava/lang/String;)V");
1792 if (!socketExConstructor) {
1795 socketEx = env->NewObject(socketExClass, socketExConstructor, errorMessageString);
1796 socketExCauseMethod = env->GetMethodID(socketExClass,"initCause","(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
1797 env->CallObjectMethod(socketEx,socketExCauseMethod,errorCodeEx);
1798 env->Throw((jthrowable)socketEx);
1801 throwSocketException(env, err);
1808 static jint osNetworkSystem_writeSocketImpl(JNIEnv* env, jclass clazz,
1809 jobject fileDescriptor, jbyteArray data, jint offset, jint count) {
1810 // LOGD("ENTER writeSocketImpl");
1816 /* TODO: ARRAY PINNING */
1817 #define INTERNAL_SEND_BUFFER_MAX 512
1818 jbyte internalBuffer[INTERNAL_SEND_BUFFER_MAX];
1820 if (count > INTERNAL_SEND_BUFFER_MAX) {
1821 message = (jbyte*)malloc(count * sizeof( jbyte));
1822 if (message == NULL) {
1823 jniThrowException(env, "java/lang/OutOfMemoryError",
1824 "couldn't allocate enough memory for writeSocket");
1828 message = (jbyte *)internalBuffer;
1831 env->GetByteArrayRegion(data, offset, count, message);
1833 result = osNetworkSystem_writeSocketDirectImpl(env, clazz, fileDescriptor,
1834 (jint) message, 0, count);
1836 if (( jbyte *)message != internalBuffer) {
1837 free(( jbyte *)message);
1839 #undef INTERNAL_SEND_BUFFER_MAX
1843 static void osNetworkSystem_setNonBlockingImpl(JNIEnv* env, jclass clazz,
1844 jobject fileDescriptor, jboolean nonblocking) {
1845 // LOGD("ENTER setNonBlockingImpl");
1850 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1852 if (handle == 0 || handle == -1) {
1853 throwSocketException(env, SOCKERR_BADSOCKET);
1857 int block = nonblocking;
1859 result = ioctl(handle, FIONBIO, &block);
1862 throwSocketException(env, convertError(errno));
1866 static jint osNetworkSystem_connectSocketImpl(JNIEnv* env, jclass clazz,
1867 jobject fileDescriptor, jint trafficClass, jobject inetAddr, jint port);
1869 static jint osNetworkSystem_connectWithTimeoutSocketImpl(JNIEnv* env,
1870 jclass clazz, jobject fileDescriptor, jint timeout, jint trafficClass,
1871 jobject inetAddr, jint port, jint step, jbyteArray passContext) {
1872 // LOGD("ENTER connectWithTimeoutSocketImpl");
1876 struct sockaddr_storage address;
1877 jbyte *context = NULL;
1879 result = inetAddressToSocketAddress(env, inetAddr, port, &address);
1883 // Check if we're using adb networking and redirect in case it is used.
1884 if (useAdbNetworkingForAddress(&address)) {
1885 return osNetworkSystem_connectSocketImpl(env, clazz, fileDescriptor,
1886 trafficClass, inetAddr, port);
1889 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1890 if (handle == 0 || handle == -1) {
1891 throwSocketException(env, SOCKERR_BADDESC);
1895 context = (jbyte *)env->GetPrimitiveArrayCritical(passContext, NULL);
1898 case SOCKET_CONNECT_STEP_START:
1899 result = sockConnectWithTimeout(handle, address, 0,
1900 SOCKET_STEP_START, context);
1902 case SOCKET_CONNECT_STEP_CHECK:
1903 result = sockConnectWithTimeout(handle, address, timeout,
1904 SOCKET_STEP_CHECK, context);
1908 env->ReleasePrimitiveArrayCritical(passContext, context, JNI_ABORT);
1911 /* connected , so stop here */
1912 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, NULL);
1913 } else if (result != SOCKERR_NOTCONNECTED) {
1914 /* can not connect... */
1915 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, NULL);
1916 if (result == SOCKERR_EACCES) {
1917 jniThrowException(env, "java/lang/SecurityException",
1918 netLookupErrorString(result));
1920 jniThrowException(env, "java/net/ConnectException",
1921 netLookupErrorString(result));
1928 static void osNetworkSystem_connectStreamWithTimeoutSocketImpl(JNIEnv* env,
1929 jclass clazz, jobject fileDescriptor, jint remotePort, jint timeout,
1930 jint trafficClass, jobject inetAddr) {
1931 // LOGD("ENTER connectStreamWithTimeoutSocketImpl");
1935 struct sockaddr_storage address;
1936 jbyte *context = NULL;
1937 int remainingTimeout = timeout;
1938 int passedTimeout = 0;
1941 char hasTimeout = timeout > 0;
1943 /* if a timeout was specified calculate the finish time value */
1945 finishTime = time_msec_clock() + (int) timeout;
1948 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
1949 if (handle == 0 || handle == -1) {
1950 throwSocketException(env, SOCKERR_BADDESC);
1954 result = inetAddressToSocketAddress(env, inetAddr, remotePort, &address);
1955 if (result < 0) // Exception has already been thrown.
1958 // Check if we're using adb networking and redirect in case it is used.
1959 if (useAdbNetworkingForAddress(&address)) {
1960 int retVal = osNetworkSystem_connectSocketImpl(env, clazz,
1961 fileDescriptor, trafficClass, inetAddr, remotePort);
1963 throwSocketException(env, SOCKERR_BADSOCKET);
1969 * we will be looping checking for when we are connected so allocate
1970 * the descriptor sets that we will use
1972 context =(jbyte *) malloc(sizeof(struct selectFDSet));
1973 if (NULL == context) {
1974 throwSocketException(env, SOCKERR_NOBUFFERS);
1978 result = sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_START, context);
1980 /* ok we connected right away so we are done */
1981 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, context);
1983 } else if (result != SOCKERR_NOTCONNECTED) {
1984 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE,
1986 /* we got an error other than NOTCONNECTED so we cannot continue */
1987 if (SOCKERR_EACCES == result) {
1988 jniThrowException(env, "java/lang/SecurityException",
1989 netLookupErrorString(result));
1991 throwSocketException(env, result);
1996 while (SOCKERR_NOTCONNECTED == result) {
1997 passedTimeout = remainingTimeout;
2000 * ok now try and connect. Depending on the platform this may sleep
2001 * for up to passedTimeout milliseconds
2003 result = sockConnectWithTimeout(handle, address, passedTimeout,
2004 SOCKET_STEP_CHECK, context);
2007 * now check if the socket is still connected.
2008 * Do it here as some platforms seem to think they
2009 * are connected if the socket is closed on them.
2011 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2012 if (handle == 0 || handle == -1) {
2013 sockConnectWithTimeout(handle, address, 0,
2014 SOCKET_STEP_DONE, context);
2015 throwSocketException(env, SOCKERR_BADSOCKET);
2020 * check if we are now connected,
2021 * if so we can finish the process and return
2024 sockConnectWithTimeout(handle, address, 0,
2025 SOCKET_STEP_DONE, context);
2030 * if the error is SOCKERR_NOTCONNECTED then we have not yet
2031 * connected and we may not be done yet
2033 if (SOCKERR_NOTCONNECTED == result) {
2034 /* check if the timeout has expired */
2036 remainingTimeout = finishTime - time_msec_clock();
2037 if (remainingTimeout <= 0) {
2038 sockConnectWithTimeout(handle, address, 0,
2039 SOCKET_STEP_DONE, context);
2040 jniThrowException(env,
2041 "java/net/SocketTimeoutException",
2042 netLookupErrorString(result));
2046 remainingTimeout = 100;
2049 sockConnectWithTimeout(handle, address, remainingTimeout,
2050 SOCKET_STEP_DONE, context);
2051 if ((SOCKERR_CONNRESET == result) ||
2052 (SOCKERR_CONNECTION_REFUSED == result) ||
2053 (SOCKERR_ADDRNOTAVAIL == result) ||
2054 (SOCKERR_ADDRINUSE == result) ||
2055 (SOCKERR_ENETUNREACH == result)) {
2056 jniThrowException(env, "java/net/ConnectException",
2057 netLookupErrorString(result));
2058 } else if (SOCKERR_EACCES == result) {
2059 jniThrowException(env, "java/lang/SecurityException",
2060 netLookupErrorString(result));
2062 throwSocketException(env, result);
2070 /* free the memory for the FD set */
2071 if (context != NULL) {
2076 static jint osNetworkSystem_connectSocketImpl(JNIEnv* env, jclass clazz,
2077 jobject fileDescriptor, jint trafficClass, jobject inetAddr, jint port) {
2078 //LOGD("ENTER direct-call connectSocketImpl\n");
2080 struct sockaddr_storage address;
2084 ret = inetAddressToSocketAddress(env, inetAddr, port, &address);
2088 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2089 if (handle == 0 || handle == -1) {
2090 throwSocketException(env, SOCKERR_BADDESC);
2094 if (useAdbNetworkingForAddress(&address)) {
2096 // LOGD("+connect to address 0x%08x port %d (via adb)",
2097 // address.sin_addr.s_addr, (int) port);
2098 ret = adb_networking_connect_fd(handle, (struct sockaddr_in *) &address);
2099 // LOGD("-connect ret %d errno %d (via adb)", ret, errno);
2103 // call this method with a timeout of zero
2104 osNetworkSystem_connectStreamWithTimeoutSocketImpl(env, clazz,
2105 fileDescriptor, port, 0, trafficClass, inetAddr);
2106 if (env->ExceptionOccurred() != 0) {
2115 jniThrowException(env, "java/net/ConnectException",
2116 netLookupErrorString(convertError(errno)));
2123 static void osNetworkSystem_socketBindImpl(JNIEnv* env, jclass clazz,
2124 jobject fileDescriptor, jint port, jobject inetAddress) {
2125 // LOGD("ENTER socketBindImpl");
2127 struct sockaddr_storage sockaddress;
2131 ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddress);
2135 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2136 if (handle == 0 || handle == -1) {
2137 throwSocketException(env, SOCKERR_BADDESC);
2141 ret = doBind(handle, &sockaddress);
2143 jniThrowException(env, "java/net/BindException",
2144 netLookupErrorString(convertError(errno)));
2149 static void osNetworkSystem_listenStreamSocketImpl(JNIEnv* env, jclass clazz,
2150 jobject fileDescriptor, jint backlog) {
2151 // LOGD("ENTER listenStreamSocketImpl");
2156 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2158 if (handle == 0 || handle == -1) {
2159 throwSocketException(env, SOCKERR_BADSOCKET);
2163 ret = listen(handle, backlog);
2166 int err = convertError(errno);
2167 throwSocketException(env, err);
2172 static jint osNetworkSystem_availableStreamImpl(JNIEnv* env, jclass clazz,
2173 jobject fileDescriptor) {
2174 // LOGD("ENTER availableStreamImpl");
2177 char message[BUFFERSIZE];
2181 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2182 if (handle == 0 || handle == -1) {
2183 throwSocketException(env, SOCKERR_BADDESC);
2188 result = selectWait(handle, 1, SELECT_READ_TYPE);
2190 if (SOCKERR_TIMEOUT == result) {
2191 // The read operation timed out, so answer 0 bytes available
2193 } else if (SOCKERR_INTERRUPTED == result) {
2195 } else if (0 > result) {
2196 throwSocketException(env, result);
2199 } while (SOCKERR_INTERRUPTED == result);
2201 result = recv(handle, (jbyte *) message, BUFFERSIZE, MSG_PEEK);
2204 int err = convertError(errno);
2205 throwSocketException(env, err);
2211 static void osNetworkSystem_acceptSocketImpl(JNIEnv* env, jclass clazz,
2212 jobject fdServer, jobject newSocket, jobject fdnewSocket, jint timeout) {
2213 // LOGD("ENTER acceptSocketImpl");
2215 struct sockaddr_storage sa;
2223 if (newSocket == NULL) {
2224 throwNullPointerException(env);
2228 result = pollSelectWait(env, fdServer, timeout, SELECT_READ_TYPE);
2233 handle = jniGetFDFromFileDescriptor(env, fdServer);
2234 if (handle == 0 || handle == -1) {
2235 throwSocketException(env, SOCKERR_BADDESC);
2240 addrlen = sizeof(sa);
2241 ret = accept(handle, (struct sockaddr *) &sa, &addrlen);
2242 } while (ret < 0 && errno == EINTR);
2245 int err = convertError(errno);
2246 throwSocketException(env, err);
2253 * For network sockets, put the peer address and port in instance variables.
2254 * We don't bother to do this for UNIX domain sockets, since most peers are
2257 if (sa.ss_family == AF_INET || sa.ss_family == AF_INET6) {
2258 jobject inetAddress = socketAddressToInetAddress(env, &sa);
2261 newSocket = NULL; // Exception has already been thrown.
2265 env->SetObjectField(newSocket,
2266 gCachedFields.socketimpl_address, inetAddress);
2268 int port = getSocketAddressPort(&sa);
2269 env->SetIntField(newSocket, gCachedFields.socketimpl_port, port);
2272 jniSetFileDescriptorOfFD(env, fdnewSocket, retFD);
2275 static jboolean osNetworkSystem_supportsUrgentDataImpl(JNIEnv* env,
2276 jclass clazz, jobject fileDescriptor) {
2277 // LOGD("ENTER supportsUrgentDataImpl");
2281 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2282 if (handle == 0 || handle == -1) {
2289 static void osNetworkSystem_sendUrgentDataImpl(JNIEnv* env, jclass clazz,
2290 jobject fileDescriptor, jbyte value) {
2291 // LOGD("ENTER sendUrgentDataImpl");
2296 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2297 if (handle == 0 || handle == -1) {
2298 throwSocketException(env, SOCKERR_BADSOCKET);
2302 result = send(handle, (jbyte *) &value, 1, MSG_OOB);
2304 int err = convertError(errno);
2305 throwSocketException(env, err);
2309 static void osNetworkSystem_connectDatagramImpl2(JNIEnv* env, jclass clazz,
2310 jobject fd, jint port, jint trafficClass, jobject inetAddress) {
2311 // LOGD("ENTER connectDatagramImpl2");
2313 int handle = jniGetFDFromFileDescriptor(env, fd);
2315 struct sockaddr_storage sockAddr;
2318 ret = inetAddressToSocketAddress(env, inetAddress, port, &sockAddr);
2319 if (ret < 0) // Exception has already been thrown.
2322 ret = doConnect(handle, &sockAddr);
2324 int err = convertError(errno);
2325 throwSocketException(env, err);
2329 static void osNetworkSystem_disconnectDatagramImpl(JNIEnv* env, jclass clazz,
2331 // LOGD("ENTER disconnectDatagramImpl");
2333 int handle = jniGetFDFromFileDescriptor(env, fd);
2335 struct sockaddr_storage sockAddr;
2336 memset(&sockAddr, 0, sizeof(sockAddr));
2337 sockAddr.ss_family = AF_UNSPEC;
2339 int result = doConnect(handle, &sockAddr);
2341 int err = convertError(errno);
2342 throwSocketException(env, err);
2346 static jint osNetworkSystem_peekDatagramImpl(JNIEnv* env, jclass clazz,
2347 jobject fd, jobject sender, jint receiveTimeout) {
2348 // LOGD("ENTER peekDatagramImpl");
2352 int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
2357 int handle = jniGetFDFromFileDescriptor(env, fd);
2358 if (handle == 0 || handle == -1) {
2359 throwSocketException(env, SOCKERR_BADDESC);
2363 struct sockaddr_storage sockAddr;
2364 socklen_t sockAddrLen = sizeof(sockAddr);
2367 length = recvfrom(handle, NULL, 0, MSG_PEEK,
2368 (struct sockaddr *)&sockAddr, &sockAddrLen);
2369 } while (length < 0 && errno == EINTR);
2371 int err = convertError(errno);
2372 throwSocketException(env, err);
2376 sender = socketAddressToInetAddress(env, &sockAddr);
2377 if (sender == NULL) // Exception has already been thrown.
2380 port = getSocketAddressPort(&sockAddr);
2384 static jint osNetworkSystem_receiveDatagramDirectImpl(JNIEnv* env, jclass clazz,
2385 jobject fd, jobject packet, jint address, jint offset, jint length,
2386 jint receiveTimeout, jboolean peek) {
2387 // LOGD("ENTER receiveDatagramDirectImpl");
2389 int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
2394 int handle = jniGetFDFromFileDescriptor(env, fd);
2395 if (handle == 0 || handle == -1) {
2396 throwSocketException(env, SOCKERR_BADDESC);
2400 struct sockaddr_storage sockAddr;
2401 socklen_t sockAddrLen = sizeof(sockAddr);
2403 int mode = peek ? MSG_PEEK : 0;
2405 ssize_t actualLength;
2407 actualLength = recvfrom(handle, (char*)(address + offset), length, mode,
2408 (struct sockaddr *)&sockAddr, &sockAddrLen);
2409 } while (actualLength < 0 && errno == EINTR);
2410 if (actualLength < 0) {
2411 int err = convertError(errno);
2412 throwSocketException(env, err);
2416 if (packet != NULL) {
2417 jbyteArray addr = socketAddressToAddressBytes(env, &sockAddr);
2418 if (addr == NULL) // Exception has already been thrown.
2420 int port = getSocketAddressPort(&sockAddr);
2421 jobject sender = env->CallStaticObjectMethod(
2422 gCachedFields.iaddr_class, gCachedFields.iaddr_getbyaddress,
2424 env->SetObjectField(packet, gCachedFields.dpack_address, sender);
2425 env->SetIntField(packet, gCachedFields.dpack_port, port);
2426 env->SetIntField(packet, gCachedFields.dpack_length,
2427 (jint) actualLength);
2429 return (jint) actualLength;
2432 static jint osNetworkSystem_receiveDatagramImpl(JNIEnv* env, jclass clazz,
2433 jobject fd, jobject packet, jbyteArray data, jint offset, jint length,
2434 jint receiveTimeout, jboolean peek) {
2435 // LOGD("ENTER receiveDatagramImpl");
2437 int localLength = (length < 65536) ? length : 65536;
2438 jbyte *bytes = (jbyte*) malloc(localLength);
2439 if (bytes == NULL) {
2440 jniThrowException(env, "java/lang/OutOfMemoryError",
2441 "couldn't allocate enough memory for receiveDatagram");
2445 int actualLength = osNetworkSystem_receiveDatagramDirectImpl(env, clazz, fd,
2446 packet, (jint)bytes, 0, localLength, receiveTimeout, peek);
2448 if (actualLength > 0) {
2449 env->SetByteArrayRegion(data, offset, actualLength, bytes);
2453 return actualLength;
2456 static jint osNetworkSystem_recvConnectedDatagramDirectImpl(JNIEnv* env,
2457 jclass clazz, jobject fd, jobject packet, jint address, jint offset,
2458 jint length, jint receiveTimeout, jboolean peek) {
2459 // LOGD("ENTER receiveConnectedDatagramDirectImpl");
2461 int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
2467 int handle = jniGetFDFromFileDescriptor(env, fd);
2469 if (handle == 0 || handle == -1) {
2470 throwSocketException(env, SOCKERR_BADSOCKET);
2474 int mode = peek ? MSG_PEEK : 0;
2476 int actualLength = recvfrom(handle,
2477 (char*)(address + offset), length, mode, NULL, NULL);
2479 if (actualLength < 0) {
2480 jniThrowException(env, "java/net/PortUnreachableException", "");
2484 if ( packet != NULL) {
2485 env->SetIntField(packet, gCachedFields.dpack_length, actualLength);
2487 return actualLength;
2490 static jint osNetworkSystem_recvConnectedDatagramImpl(JNIEnv* env, jclass clazz,
2491 jobject fd, jobject packet, jbyteArray data, jint offset, jint length,
2492 jint receiveTimeout, jboolean peek) {
2493 // LOGD("ENTER receiveConnectedDatagramImpl");
2495 int localLength = (length < 65536) ? length : 65536;
2496 jbyte *bytes = (jbyte*) malloc(localLength);
2497 if (bytes == NULL) {
2498 jniThrowException(env, "java/lang/OutOfMemoryError",
2499 "couldn't allocate enough memory for recvConnectedDatagram");
2503 int actualLength = osNetworkSystem_recvConnectedDatagramDirectImpl(env,
2504 clazz, fd, packet, (jint)bytes, 0, localLength,
2505 receiveTimeout, peek);
2507 if (actualLength > 0) {
2508 env->SetByteArrayRegion(data, offset, actualLength, bytes);
2512 return actualLength;
2515 static jint osNetworkSystem_sendDatagramDirectImpl(JNIEnv* env, jclass clazz,
2516 jobject fd, jint address, jint offset, jint length, jint port,
2517 jboolean bindToDevice, jint trafficClass, jobject inetAddress) {
2518 // LOGD("ENTER sendDatagramDirectImpl");
2520 int handle = jniGetFDFromFileDescriptor(env, fd);
2522 if (handle == 0 || handle == -1) {
2523 throwSocketException(env, SOCKERR_BADSOCKET);
2527 struct sockaddr_storage receiver;
2528 if (inetAddressToSocketAddress(env, inetAddress, port, &receiver) < 0) {
2529 // Exception has already been thrown.
2535 result = sendto(handle, (char*)(address + offset), length,
2536 SOCKET_NOFLAGS, (struct sockaddr*)&receiver, sizeof(receiver));
2537 } while (result < 0 && errno == EINTR);
2539 int err = convertError(errno);
2540 if ((SOCKERR_CONNRESET == err)
2541 || (SOCKERR_CONNECTION_REFUSED == err)) {
2544 throwSocketException(env, err);
2548 return (jint) result;
2551 static jint osNetworkSystem_sendDatagramImpl(JNIEnv* env, jclass clazz,
2552 jobject fd, jbyteArray data, jint offset, jint length, jint port,
2553 jboolean bindToDevice, jint trafficClass, jobject inetAddress) {
2554 // LOGD("ENTER sendDatagramImpl");
2556 jbyte *bytes = env->GetByteArrayElements(data, NULL);
2557 int actualLength = osNetworkSystem_sendDatagramDirectImpl(env, clazz, fd,
2558 (jint)bytes, offset, length, port, bindToDevice, trafficClass,
2560 env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
2562 return actualLength;
2565 static jint osNetworkSystem_sendConnectedDatagramDirectImpl(JNIEnv* env,
2566 jclass clazz, jobject fd, jint address, jint offset, jint length,
2567 jboolean bindToDevice) {
2568 // LOGD("ENTER sendConnectedDatagramDirectImpl");
2570 int handle = jniGetFDFromFileDescriptor(env, fd);
2572 if (handle == 0 || handle == -1) {
2573 throwSocketException(env, SOCKERR_BADSOCKET);
2577 int result = send(handle, (char*)(address + offset), length, 0);
2580 int err = convertError(errno);
2581 if ((SOCKERR_CONNRESET == err) || (SOCKERR_CONNECTION_REFUSED == err)) {
2584 throwSocketException(env, err);
2591 static jint osNetworkSystem_sendConnectedDatagramImpl(JNIEnv* env, jclass clazz,
2592 jobject fd, jbyteArray data, jint offset, jint length,
2593 jboolean bindToDevice) {
2594 // LOGD("ENTER sendConnectedDatagramImpl");
2596 jbyte *bytes = env->GetByteArrayElements(data, NULL);
2597 int actualLength = osNetworkSystem_sendConnectedDatagramDirectImpl(env,
2598 clazz, fd, (jint)bytes, offset, length, bindToDevice);
2599 env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
2601 return actualLength;
2604 static void osNetworkSystem_createServerStreamSocketImpl(JNIEnv* env,
2605 jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) {
2606 // LOGD("ENTER createServerStreamSocketImpl");
2608 int handle = createSocketFileDescriptor(env, fileDescriptor, SOCK_STREAM);
2613 setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
2617 * @param timeout in milliseconds. If zero, block until data received
2619 static jint osNetworkSystem_receiveStreamImpl(JNIEnv* env, jclass clazz,
2620 jobject fileDescriptor, jbyteArray data, jint offset, jint count,
2622 // LOGD("ENTER receiveStreamImpl");
2625 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2627 if (handle == 0 || handle == -1) {
2628 throwSocketException(env, SOCKERR_BADSOCKET);
2632 // Cap read length to available buf size
2633 int spaceAvailable = env->GetArrayLength(data) - offset;
2634 int localCount = count < spaceAvailable? count : spaceAvailable;
2637 jbyte *body = env->GetByteArrayElements(data, &isCopy);
2641 tv.tv_sec = timeout / 1000;
2642 tv.tv_usec = (timeout % 1000) * 1000;
2643 setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv,
2644 sizeof(struct timeval));
2647 result = recv(handle, body + offset, localCount, SOCKET_NOFLAGS);
2648 } while (result < 0 && errno == EINTR);
2650 env->ReleaseByteArrayElements(data, body, 0);
2653 * If no bytes are read, return -1 to signal 'endOfFile'
2654 * to the Java input stream
2658 } else if (0 == result) {
2661 // If EAGAIN or EWOULDBLOCK, read timed out
2662 if (errno == EAGAIN || errno == EWOULDBLOCK) {
2663 jniThrowException(env, "java/net/SocketTimeoutException",
2664 netLookupErrorString(SOCKERR_TIMEOUT));
2666 int err = convertError(errno);
2667 throwSocketException(env, err);
2673 static jint osNetworkSystem_sendStreamImpl(JNIEnv* env, jclass clazz,
2674 jobject fileDescriptor, jbyteArray data, jint offset, jint count) {
2675 // LOGD("ENTER sendStreamImpl");
2678 int result = 0, sent = 0;
2681 jbyte *message = env->GetByteArrayElements(data, &isCopy);
2683 // Cap write length to available buf size
2684 int spaceAvailable = env->GetArrayLength(data) - offset;
2685 if (count > spaceAvailable) count = spaceAvailable;
2687 while (sent < count) {
2689 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2690 if (handle == 0 || handle == -1) {
2691 throwSocketException(env,
2692 sent == 0 ? SOCKERR_BADSOCKET : SOCKERR_INTERRUPTED);
2693 env->ReleaseByteArrayElements(data, message, 0);
2697 // LOGD("before select %d", count);
2698 selectWait(handle, SEND_RETRY_TIME, SELECT_WRITE_TYPE);
2699 result = send(handle, (jbyte *)message + offset + sent,
2700 (int) count - sent, SOCKET_NOFLAGS);
2704 if (result == EAGAIN ||result == EWOULDBLOCK) {
2705 // LOGD("write blocked %d", sent);
2708 env->ReleaseByteArrayElements(data, message, 0);
2709 int err = convertError(result);
2710 throwSocketException(env, err);
2716 env->ReleaseByteArrayElements(data, message, 0);
2720 static void osNetworkSystem_shutdownInputImpl(JNIEnv* env, jobject obj,
2721 jobject fileDescriptor) {
2722 // LOGD("ENTER shutdownInputImpl");
2727 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2729 if (handle == 0 || handle == -1) {
2730 throwSocketException(env, SOCKERR_BADSOCKET);
2734 ret = shutdown(handle, SHUT_RD);
2737 int err = convertError(errno);
2738 throwSocketException(env, err);
2743 static void osNetworkSystem_shutdownOutputImpl(JNIEnv* env, jobject obj,
2744 jobject fileDescriptor) {
2745 // LOGD("ENTER shutdownOutputImpl");
2750 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2752 if (handle == 0 || handle == -1) {
2756 ret = shutdown(handle, SHUT_WR);
2759 int err = convertError(errno);
2760 throwSocketException(env, err);
2765 static jint osNetworkSystem_sendDatagramImpl2(JNIEnv* env, jclass clazz,
2766 jobject fd, jbyteArray data, jint offset, jint length, jint port,
2767 jobject inetAddress) {
2768 // LOGD("ENTER sendDatagramImpl2");
2771 unsigned short nPort;
2772 int ret = 0, sent = 0;
2774 struct sockaddr_storage sockaddrP;
2776 if (inetAddress != NULL) {
2777 ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddrP);
2778 if (ret < 0) // Exception has already been thrown.
2781 handle = jniGetFDFromFileDescriptor(env, fd);
2782 if (handle == 0 || handle == -1) {
2783 throwSocketException(env, SOCKERR_BADDESC);
2788 message = (jbyte*) malloc(length * sizeof(jbyte));
2789 if (message == NULL) {
2790 jniThrowException(env, "java/lang/OutOfMemoryError",
2791 "couldn't allocate enough memory for readSocket");
2795 env->GetByteArrayRegion(data, offset, length, message);
2797 while (sent < length) {
2798 handle = jniGetFDFromFileDescriptor(env, fd);
2800 if (handle == 0 || handle == -1) {
2801 throwSocketException(env,
2802 sent == 0 ? SOCKERR_BADDESC : SOCKERR_INTERRUPTED);
2809 result = sendto(handle, (char *) (message + sent),
2810 (int) (length - sent), SOCKET_NOFLAGS,
2811 (struct sockaddr *) &sockaddrP, sizeof(sockaddrP));
2812 } while (result < 0 && errno == EINTR);
2814 int err = convertError(errno);
2815 throwSocketException(env, err);
2827 static jint osNetworkSystem_selectImpl(JNIEnv* env, jclass clazz,
2828 jobjectArray readFDArray, jobjectArray writeFDArray, jint countReadC,
2829 jint countWriteC, jintArray outFlags, jlong timeout) {
2830 // LOGD("ENTER selectImpl");
2832 struct timeval timeP;
2836 fd_set *fdset_read,*fdset_write;
2841 unsigned int time_sec = (unsigned int)timeout/1000;
2842 unsigned int time_msec = (unsigned int)(timeout%1000);
2844 fdset_read = (fd_set *)malloc(sizeof(fd_set));
2845 fdset_write = (fd_set *)malloc(sizeof(fd_set));
2847 FD_ZERO(fdset_read);
2848 FD_ZERO(fdset_write);
2850 for (val = 0; val<countReadC; val++) {
2852 gotFD = env->GetObjectArrayElement(readFDArray,val);
2854 handle = jniGetFDFromFileDescriptor(env, gotFD);
2856 FD_SET(handle, fdset_read);
2858 if (0 > (size - handle)) {
2863 for (val = 0; val<countWriteC; val++) {
2865 gotFD = env->GetObjectArrayElement(writeFDArray,val);
2867 handle = jniGetFDFromFileDescriptor(env, gotFD);
2869 FD_SET(handle, fdset_write);
2871 if (0 > (size - handle)) {
2876 /* the size is the max_fd + 1 */
2880 result = SOCKERR_FDSET_SIZEBAD;
2882 /* only set when timeout >= 0 (non-block)*/
2885 timeP.tv_sec = time_sec;
2886 timeP.tv_usec = time_msec*1000;
2888 result = sockSelect(size, fdset_read, fdset_write, NULL, &timeP);
2891 result = sockSelect(size, fdset_read, fdset_write, NULL, NULL);
2896 /*output the result to a int array*/
2897 flagArray = env->GetIntArrayElements(outFlags, &isCopy);
2899 for (val=0; val<countReadC; val++) {
2900 gotFD = env->GetObjectArrayElement(readFDArray,val);
2902 handle = jniGetFDFromFileDescriptor(env, gotFD);
2904 if (FD_ISSET(handle,fdset_read)) {
2905 flagArray[val] = SOCKET_OP_READ;
2907 flagArray[val] = SOCKET_OP_NONE;
2911 for (val=0; val<countWriteC; val++) {
2913 gotFD = env->GetObjectArrayElement(writeFDArray,val);
2915 handle = jniGetFDFromFileDescriptor(env, gotFD);
2917 if (FD_ISSET(handle,fdset_write)) {
2918 flagArray[val+countReadC] = SOCKET_OP_WRITE;
2920 flagArray[val+countReadC] = SOCKET_OP_NONE;
2924 env->ReleaseIntArrayElements(outFlags, flagArray, 0);
2930 /* return both correct and error result, let java handle the exception*/
2934 static jobject osNetworkSystem_getSocketLocalAddressImpl(JNIEnv* env,
2935 jclass clazz, jobject fileDescriptor, jboolean preferIPv6Addresses) {
2936 // LOGD("ENTER getSocketLocalAddressImpl");
2938 struct sockaddr_storage addr;
2939 socklen_t addrLen = sizeof(addr);
2941 memset(&addr, 0, addrLen);
2944 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2945 if (handle == 0 || handle == -1) {
2946 throwSocketException(env, SOCKERR_UNKNOWNSOCKET);
2951 result = getsockname(handle, (struct sockaddr *)&addr, &addrLen);
2953 // Spec says ignore all errors
2954 return socketAddressToInetAddress(env, &addr);
2957 static jint osNetworkSystem_getSocketLocalPortImpl(JNIEnv* env, jclass clazz,
2958 jobject fileDescriptor, jboolean preferIPv6Addresses) {
2959 // LOGD("ENTER getSocketLocalPortImpl");
2961 struct sockaddr_storage addr;
2962 socklen_t addrLen = sizeof(addr);
2964 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2967 if (handle == 0 || handle == -1) {
2968 throwSocketException(env, SOCKERR_UNKNOWNSOCKET);
2972 result = getsockname(handle, (struct sockaddr *)&addr, &addrLen);
2975 // The java spec does not indicate any exceptions on this call
2978 return getSocketAddressPort(&addr);
2982 static jobject osNetworkSystem_getSocketOptionImpl(JNIEnv* env, jclass clazz,
2983 jobject fileDescriptor, jint anOption) {
2984 // LOGD("ENTER getSocketOptionImpl");
2988 socklen_t intSize = sizeof(int);
2989 unsigned char byteValue = 0;
2990 socklen_t byteSize = sizeof(unsigned char);
2992 struct sockaddr_storage sockVal;
2993 socklen_t sockSize = sizeof(sockVal);
2995 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
2996 if (handle == 0 || handle == -1) {
2997 throwSocketException(env, SOCKERR_BADDESC);
3001 switch ((int) anOption & 0xffff) {
3002 case JAVASOCKOPT_SO_LINGER: {
3003 struct linger lingr;
3004 socklen_t size = sizeof(struct linger);
3005 result = getsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr, &size);
3007 throwSocketException(env, convertError(errno));
3010 if (!lingr.l_onoff) {
3013 intValue = lingr.l_linger;
3015 return newJavaLangInteger(env, intValue);
3017 case JAVASOCKOPT_TCP_NODELAY: {
3018 if ((anOption >> 16) & BROKEN_TCP_NODELAY) {
3021 result = getsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intValue, &intSize);
3023 throwSocketException(env, convertError(errno));
3026 return newJavaLangBoolean(env, intValue);
3028 case JAVASOCKOPT_MCAST_TTL: {
3029 if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
3030 return newJavaLangByte(env, 0);
3032 result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_MULTICAST_TTL,
3033 IPV6_MULTICAST_HOPS, &byteValue,
3036 throwSocketException(env, convertError(errno));
3039 return newJavaLangByte(env, (jbyte)(byteValue & 0xFF));
3041 case JAVASOCKOPT_MCAST_INTERFACE: {
3042 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3045 result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, &sockVal, &sockSize);
3047 throwSocketException(env, convertError(errno));
3050 // This option is IPv4-only.
3051 sockVal.ss_family = AF_INET;
3052 return socketAddressToInetAddress(env, &sockVal);
3054 case JAVASOCKOPT_IP_MULTICAST_IF2: {
3055 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3058 struct ip_mreqn multicastRequest;
3060 socklen_t optionLength;
3061 int addressFamily = getSocketAddressFamily(handle);
3062 switch (addressFamily) {
3064 optionLength = sizeof(multicastRequest);
3065 result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
3066 &multicastRequest, &optionLength);
3068 interfaceIndex = multicastRequest.imr_ifindex;
3071 optionLength = sizeof(interfaceIndex);
3072 result = getsockopt(handle, IPPROTO_IPV6, IPV6_MULTICAST_IF,
3073 &interfaceIndex, &optionLength);
3076 throwSocketException(env, SOCKERR_BADAF);
3081 throwSocketException(env, convertError(errno));
3085 return newJavaLangInteger(env, interfaceIndex);
3087 case JAVASOCKOPT_SO_SNDBUF: {
3088 result = getsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intValue, &intSize);
3090 throwSocketException(env, convertError(errno));
3093 return newJavaLangInteger(env, intValue);
3095 case JAVASOCKOPT_SO_RCVBUF: {
3096 result = getsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intValue, &intSize);
3098 throwSocketException(env, convertError(errno));
3101 return newJavaLangInteger(env, intValue);
3103 case JAVASOCKOPT_SO_BROADCAST: {
3104 result = getsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intValue, &intSize);
3106 throwSocketException(env, convertError(errno));
3109 return newJavaLangBoolean(env, intValue);
3111 case JAVASOCKOPT_SO_REUSEADDR: {
3112 result = getsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intValue, &intSize);
3114 throwSocketException(env, convertError(errno));
3117 return newJavaLangBoolean(env, intValue);
3119 case JAVASOCKOPT_SO_KEEPALIVE: {
3120 result = getsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intValue, &intSize);
3122 throwSocketException(env, convertError(errno));
3125 return newJavaLangBoolean(env, intValue);
3127 case JAVASOCKOPT_SO_OOBINLINE: {
3128 result = getsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intValue, &intSize);
3130 throwSocketException(env, convertError(errno));
3133 return newJavaLangBoolean(env, intValue);
3135 case JAVASOCKOPT_IP_MULTICAST_LOOP: {
3136 result = getOrSetSocketOption(SOCKOPT_GET, handle,
3138 IPV6_MULTICAST_LOOP, &intValue,
3141 throwSocketException(env, convertError(errno));
3144 return newJavaLangBoolean(env, intValue);
3146 case JAVASOCKOPT_IP_TOS: {
3147 result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_TOS,
3148 IPV6_TCLASS, &intValue, &intSize);
3150 throwSocketException(env, convertError(errno));
3153 return newJavaLangInteger(env, intValue);
3155 case JAVASOCKOPT_SO_RCVTIMEOUT: {
3156 struct timeval timeout;
3157 socklen_t size = sizeof(timeout);
3158 result = getsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout, &size);
3160 throwSocketException(env, convertError(errno));
3163 return newJavaLangInteger(env, timeout.tv_sec * 1000 + timeout.tv_usec/1000);
3166 throwSocketException(env, SOCKERR_OPTUNSUPP);
3173 static void osNetworkSystem_setSocketOptionImpl(JNIEnv* env, jclass clazz,
3174 jobject fileDescriptor, jint anOption, jobject optVal) {
3175 // LOGD("ENTER setSocketOptionImpl");
3179 socklen_t intSize = sizeof(int);
3180 unsigned char byteVal;
3181 socklen_t byteSize = sizeof(unsigned char);
3182 struct sockaddr_storage sockVal;
3183 int sockSize = sizeof(sockVal);
3185 if (env->IsInstanceOf(optVal, gCachedFields.integer_class)) {
3186 intVal = (int) env->GetIntField(optVal, gCachedFields.integer_class_value);
3187 } else if (env->IsInstanceOf(optVal, gCachedFields.boolean_class)) {
3188 intVal = (int) env->GetBooleanField(optVal, gCachedFields.boolean_class_value);
3189 } else if (env->IsInstanceOf(optVal, gCachedFields.byte_class)) {
3190 byteVal = (int) env->GetByteField(optVal, gCachedFields.byte_class_value);
3191 } else if (env->IsInstanceOf(optVal, gCachedFields.iaddr_class)) {
3192 if (inetAddressToSocketAddress(env, optVal, 0, &sockVal) < 0) {
3193 // Exception has already been thrown.
3196 } else if (env->IsInstanceOf(optVal, gCachedFields.genericipmreq_class)) {
3197 // we'll use optVal directly
3199 throwSocketException(env, SOCKERR_OPTUNSUPP);
3203 handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
3204 if (handle == 0 || handle == -1) {
3205 throwSocketException(env, SOCKERR_BADDESC);
3209 switch ((int) anOption & 0xffff) {
3210 case JAVASOCKOPT_SO_LINGER: {
3211 struct linger lingr;
3212 lingr.l_onoff = intVal > 0 ? 1 : 0;
3213 lingr.l_linger = intVal;
3214 result = setsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr,
3215 sizeof(struct linger));
3217 throwSocketException(env, convertError(errno));
3223 case JAVASOCKOPT_TCP_NODELAY: {
3224 if ((anOption >> 16) & BROKEN_TCP_NODELAY) {
3227 result = setsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intVal, intSize);
3229 throwSocketException(env, convertError(errno));
3235 case JAVASOCKOPT_MCAST_TTL: {
3236 if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
3239 result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_MULTICAST_TTL,
3240 IPV6_MULTICAST_HOPS, &byteVal,
3243 throwSocketException(env, convertError(errno));
3249 case JAVASOCKOPT_MCAST_ADD_MEMBERSHIP: {
3250 mcastAddDropMembership(env, handle, optVal,
3251 (anOption >> 16) & BROKEN_MULTICAST_IF, IP_ADD_MEMBERSHIP);
3255 case JAVASOCKOPT_MCAST_DROP_MEMBERSHIP: {
3256 mcastAddDropMembership(env, handle, optVal,
3257 (anOption >> 16) & BROKEN_MULTICAST_IF, IP_DROP_MEMBERSHIP);
3261 case JAVASOCKOPT_MCAST_INTERFACE: {
3262 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3265 // This call is IPv4 only.
3266 if (getSocketAddressFamily(handle) != AF_INET) {
3267 throwSocketException(env, SOCKERR_BADAF);
3270 struct ip_mreqn mcast_req;
3271 memset(&mcast_req, 0, sizeof(mcast_req));
3272 struct sockaddr_in *sin = (struct sockaddr_in *) &sockVal;
3273 mcast_req.imr_address = sin->sin_addr;
3274 result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
3275 &mcast_req, sizeof(mcast_req));
3277 throwSocketException(env, convertError(errno));
3283 case JAVASOCKOPT_IP_MULTICAST_IF2: {
3284 if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
3287 int addressFamily = getSocketAddressFamily(handle);
3288 int interfaceIndex = intVal;
3290 socklen_t optionLength;
3291 struct ip_mreqn multicastRequest;
3292 switch (addressFamily) {
3294 // IP_MULTICAST_IF expects a pointer to a struct ip_mreqn.
3295 memset(&multicastRequest, 0, sizeof(multicastRequest));
3296 multicastRequest.imr_ifindex = interfaceIndex;
3297 optionValue = &multicastRequest;
3298 optionLength = sizeof(multicastRequest);
3301 // IPV6_MULTICAST_IF expects a pointer to an integer.
3302 optionValue = &interfaceIndex;
3303 optionLength = sizeof(interfaceIndex);
3306 throwSocketException(env, SOCKERR_BADAF);
3309 result = getOrSetSocketOption(SOCKOPT_SET, handle,
3310 IP_MULTICAST_IF, IPV6_MULTICAST_IF, optionValue,
3313 throwSocketException(env, convertError(errno));
3319 case JAVASOCKOPT_SO_SNDBUF: {
3320 result = setsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intVal, intSize);
3322 throwSocketException(env, convertError(errno));
3328 case JAVASOCKOPT_SO_RCVBUF: {
3329 result = setsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intVal, intSize);
3331 throwSocketException(env, convertError(errno));
3337 case JAVASOCKOPT_SO_BROADCAST: {
3338 result = setsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intVal, intSize);
3340 throwSocketException(env, convertError(errno));
3346 case JAVASOCKOPT_SO_REUSEADDR: {
3347 result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
3349 throwSocketException(env, convertError(errno));
3354 case JAVASOCKOPT_SO_KEEPALIVE: {
3355 result = setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intVal, intSize);
3357 throwSocketException(env, convertError(errno));
3363 case JAVASOCKOPT_SO_OOBINLINE: {
3364 result = setsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intVal, intSize);
3366 throwSocketException(env, convertError(errno));
3372 case JAVASOCKOPT_IP_MULTICAST_LOOP: {
3373 result = getOrSetSocketOption(SOCKOPT_SET, handle,
3375 IPV6_MULTICAST_LOOP, &intVal,
3378 throwSocketException(env, convertError(errno));
3384 case JAVASOCKOPT_IP_TOS: {
3385 result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_TOS,
3386 IPV6_TCLASS, &intVal, &intSize);
3388 throwSocketException(env, convertError(errno));
3394 case JAVASOCKOPT_REUSEADDR_AND_REUSEPORT: {
3395 // SO_REUSEPORT doesn't need to get set on this System
3396 result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
3398 throwSocketException(env, convertError(errno));
3404 case JAVASOCKOPT_SO_RCVTIMEOUT: {
3405 struct timeval timeout;
3406 timeout.tv_sec = intVal / 1000;
3407 timeout.tv_usec = (intVal % 1000) * 1000;
3408 result = setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout,
3409 sizeof(struct timeval));
3411 throwSocketException(env, convertError(errno));
3418 throwSocketException(env, SOCKERR_OPTUNSUPP);
3423 static jint osNetworkSystem_getSocketFlagsImpl(JNIEnv* env, jclass clazz) {
3424 // LOGD("ENTER getSocketFlagsImpl");
3426 // Not implemented by harmony
3430 static void osNetworkSystem_socketCloseImpl(JNIEnv* env, jclass clazz,
3431 jobject fileDescriptor) {
3432 // LOGD("ENTER socketCloseImpl");
3434 int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
3436 if (handle == 0 || handle == -1) {
3437 throwSocketException(env, SOCKERR_BADSOCKET);
3441 jniSetFileDescriptorOfFD(env, fileDescriptor, -1);
3446 static jobject osNetworkSystem_getHostByAddrImpl(JNIEnv* env, jclass clazz,
3447 jbyteArray addrStr) {
3448 // LOGD("ENTER getHostByAddrImpl");
3450 if (addrStr == NULL) {
3451 throwNullPointerException(env);
3455 jstring address = (jstring)newJavaLangString(env, addrStr);
3457 const char* addr = env->GetStringUTFChars(address, NULL);
3459 struct hostent* ent = gethostbyaddr(addr, strlen(addr), AF_INET);
3461 if (ent != NULL && ent->h_name != NULL) {
3462 result = env->NewStringUTF(ent->h_name);
3467 env->ReleaseStringUTFChars(address, addr);
3472 static jobject osNetworkSystem_getHostByNameImpl(JNIEnv* env, jclass clazz,
3473 jstring nameStr, jboolean preferIPv6Addresses) {
3474 // LOGD("ENTER getHostByNameImpl");
3476 if (nameStr == NULL) {
3477 throwNullPointerException(env);
3481 const char* name = env->GetStringUTFChars(nameStr, NULL);
3483 if (useAdbNetworking) {
3490 // LOGD("ADB networking: +gethostbyname '%s'", name);
3492 err = adb_networking_gethostbyname(name, &(outaddr.a));
3494 env->ReleaseStringUTFChars(nameStr, name);
3496 LOGD("ADB networking: -gethostbyname err %d addr 0x%08x %u.%u.%u.%u",
3497 err, (unsigned int)outaddr.a.s_addr,
3498 outaddr.j[0],outaddr.j[1],
3499 outaddr.j[2],outaddr.j[3]);
3505 jbyteArray addr = env->NewByteArray(4);
3506 env->SetByteArrayRegion(addr, 0, 4, outaddr.j);
3511 // normal case...no adb networking
3512 struct hostent* ent = gethostbyname(name);
3514 env->ReleaseStringUTFChars(nameStr, name);
3516 if (ent != NULL && ent->h_length > 0) {
3517 jbyteArray addr = env->NewByteArray(4);
3519 memcpy(v, ent->h_addr, 4);
3520 env->SetByteArrayRegion(addr, 0, 4, v);
3528 static void osNetworkSystem_setInetAddressImpl(JNIEnv* env, jobject obj,
3529 jobject sender, jbyteArray address) {
3530 // LOGD("ENTER setInetAddressImpl");
3532 env->SetObjectField(sender, gCachedFields.iaddr_ipaddress, address);
3535 // TODO: rewrite this method in Java and make it support IPv6.
3536 static jobject osNetworkSystem_inheritedChannelImpl(JNIEnv* env, jobject obj) {
3537 // LOGD("ENTER inheritedChannelImpl");
3541 socklen_t length = sizeof(opt);
3543 struct sockaddr_in local_addr;
3544 struct sockaddr_in remote_addr;
3545 jclass channel_class, socketaddr_class, serverSocket_class, socketImpl_class;
3546 jobject channel_object = NULL, socketaddr_object, serverSocket_object;
3547 jobject fd_object, addr_object, localAddr_object, socketImpl_object;
3548 jfieldID port_field, socketaddr_field, bound_field, fd_field;
3549 jfieldID serverSocket_field, socketImpl_field, addr_field, localAddr_field;
3550 jmethodID channel_new;
3551 jbyteArray addr_array;
3552 struct sockaddr_in *sock;
3555 jboolean jtrue = JNI_TRUE;
3557 if (0 != getsockopt(socket, SOL_SOCKET, SO_TYPE, &opt, &length)) {
3560 if (SOCK_STREAM !=opt && SOCK_DGRAM !=opt) {
3565 length = sizeof(struct sockaddr);
3566 if (0 != getsockname(socket, (struct sockaddr *)&local_addr, &length)) {
3569 if (AF_INET != local_addr.sin_family || length != sizeof(struct sockaddr)) {
3572 localAddr = (jbyte*) malloc(sizeof(jbyte)*4);
3573 if (NULL == localAddr) {
3576 memcpy (localAddr, &(local_addr.sin_addr.s_addr), 4);
3578 if (0 != getpeername(socket, (struct sockaddr *)&remote_addr, &length)) {
3579 remote_addr.sin_port = 0;
3580 remote_addr.sin_addr.s_addr = 0;
3581 address = (jbyte*) malloc(sizeof(jbyte)*4);
3582 bzero(address, sizeof(jbyte)*4);
3584 if (AF_INET != remote_addr.sin_family
3585 || length != sizeof(struct sockaddr)) {
3588 address = (jbyte*) malloc(sizeof(jbyte)*4);
3589 memcpy (address, &(remote_addr.sin_addr.s_addr), 4);
3592 // analysis end, begin pack to java
3593 if (SOCK_STREAM == opt) {
3594 if (remote_addr.sin_port!=0) {
3596 channel_class = env->FindClass(
3597 "org/apache/harmony/nio/internal/SocketChannelImpl");
3598 if (NULL == channel_class) {
3602 channel_new = env->GetMethodID(channel_class, "<init>", "()V");
3603 if (NULL == channel_new) {
3606 channel_object = env->NewObject(channel_class, channel_new);
3607 if (NULL == channel_object) {
3610 // new and set FileDescript
3612 fd_field = env->GetFieldID(channel_class, "fd",
3613 "java/io/FielDescriptor");
3614 fd_object = env->GetObjectField(channel_object, fd_field);
3615 if (NULL == fd_object) {
3619 jniSetFileDescriptorOfFD(env, fd_object, socket);
3622 port_field = env->GetFieldID(channel_class, "localPort", "I");
3623 env->SetIntField(channel_object, port_field,
3624 ntohs(local_addr.sin_port));
3626 // new and set remote addr
3627 addr_array = env->NewByteArray((jsize)4);
3628 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
3629 addr_object = env->NewObject(gCachedFields.i4addr_class,
3630 gCachedFields.i4addr_class_init, addr_array);
3631 if (NULL == addr_object) {
3634 socketaddr_class = env->FindClass("java/net/InetSocketAddress");
3635 socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
3636 "Ljava/net/InetSocketAddress;");
3637 socketaddr_object = env->GetObjectField(channel_object,
3639 if (NULL == socketaddr_object) {
3644 socketaddr_class = env->FindClass("java/net/InetSocketAddress");
3645 socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
3646 "Ljava/net/InetSocketAddress;");
3647 socketaddr_object = env->GetObjectField(channel_object,
3650 localAddr_field = env->GetFieldID(channel_class, "localAddress",
3651 "Ljava/net/Inet4Address;");
3652 addr_array = env->NewByteArray((jsize)4);
3653 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, localAddr);
3654 localAddr_object = env->NewObject(gCachedFields.i4addr_class,
3655 gCachedFields.i4addr_class_init, addr_array);
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) {
3668 port_field = env->GetFieldID(socketaddr_class, "port", "I");
3669 env->SetIntField(socketaddr_object, port_field,
3670 ntohs(remote_addr.sin_port));
3673 if (0 != local_addr.sin_port) {
3674 bound_field = env->GetFieldID(channel_class, "isBound", "Z");
3675 env->SetBooleanField(channel_object, bound_field, jtrue);
3680 channel_class = env->FindClass(
3681 "org/apache/harmony/nio/internal/ServerSocketChannelImpl");
3682 if (NULL == channel_class) {
3686 channel_new = env->GetMethodID(channel_class, "<init>", "()V");
3687 if (NULL == channel_new) {
3690 channel_object = env->NewObject(channel_class, channel_new);
3691 if (NULL == channel_object) {
3695 serverSocket_field = env->GetFieldID(channel_class, "socket",
3696 "Ljava/net/ServerSocket;");
3697 serverSocket_class = env->FindClass("Ljava/net/ServerSocket;");
3698 serverSocket_object = env->GetObjectField(channel_object,
3699 serverSocket_field);
3701 if (0 != local_addr.sin_port) {
3702 bound_field = env->GetFieldID(channel_class, "isBound", "Z");
3703 env->SetBooleanField(channel_object, bound_field, jtrue);
3704 bound_field = env->GetFieldID(serverSocket_class, "isBound", "Z");
3705 env->SetBooleanField(serverSocket_object, bound_field, jtrue);
3708 socketImpl_class = env->FindClass("java/net/SocketImpl");
3709 socketImpl_field = env->GetFieldID(channel_class, "impl",
3710 "Ljava/net/SocketImpl;");
3711 socketImpl_object = env->GetObjectField(channel_object,
3713 if (NULL == socketImpl_object) {
3717 localAddr_field = env->GetFieldID(channel_class, "localAddress",
3718 "Ljava/net/InetAddress;");
3719 memset(address, 0, 4);
3720 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
3721 localAddr_object = env->NewObject(gCachedFields.i4addr_class,
3722 gCachedFields.i4addr_class_init, addr_array);
3723 if (NULL == localAddr_object) {
3726 env->SetObjectField(socketImpl_object, localAddr_field,
3728 addr_array = env->NewByteArray((jsize)4);
3729 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, localAddr);
3730 env->SetObjectField(localAddr_object,
3731 gCachedFields.iaddr_ipaddress, addr_array);
3734 port_field = env->GetFieldID(socketImpl_class, "localport", "I");
3735 env->SetIntField(socketImpl_object, port_field,
3736 ntohs(local_addr.sin_port));
3740 // new DatagramChannel
3741 channel_class = env->FindClass(
3742 "org/apache/harmony/nio/internal/DatagramChannelImpl");
3743 if (NULL == channel_class) {
3747 channel_new = env->GetMethodID(channel_class, "<init>", "()V");
3748 if (NULL == channel_new) {
3751 channel_object = env->NewObject(channel_class, channel_new);
3752 if (NULL == channel_object) {
3756 // new and set FileDescript
3757 fd_field = env->GetFieldID(channel_class, "fd", "java/io/FileDescriptor");
3758 fd_object = env->GetObjectField(channel_object, fd_field);
3759 if (NULL == fd_object) {
3763 jniSetFileDescriptorOfFD(env, fd_object, socket);
3765 port_field = env->GetFieldID(channel_class, "localPort", "I");
3766 env->SetIntField(channel_object, port_field, ntohs(local_addr.sin_port));
3768 // new and set remote addr
3769 addr_array = env->NewByteArray((jsize)4);
3770 env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
3771 addr_object = env->NewObject(gCachedFields.iaddr_class,
3772 gCachedFields.i4addr_class_init, addr_array);
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) {
3785 if (0 != local_addr.sin_port) {
3786 bound_field = env->GetFieldID(channel_class, "isBound", "Z");
3787 env->SetBooleanField(channel_object, bound_field, jtrue);
3793 return channel_object;
3799 static JNINativeMethod gMethods[] = {
3800 /* name, signature, funcPtr */
3801 { "oneTimeInitializationImpl", "(Z)V", (void*) osNetworkSystem_oneTimeInitializationImpl },
3802 { "createStreamSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createStreamSocketImpl },
3803 { "createDatagramSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createDatagramSocketImpl },
3804 { "readSocketImpl", "(Ljava/io/FileDescriptor;[BIII)I", (void*) osNetworkSystem_readSocketImpl },
3805 { "readSocketDirectImpl", "(Ljava/io/FileDescriptor;IIII)I", (void*) osNetworkSystem_readSocketDirectImpl },
3806 { "writeSocketImpl", "(Ljava/io/FileDescriptor;[BII)I", (void*) osNetworkSystem_writeSocketImpl },
3807 { "writeSocketDirectImpl", "(Ljava/io/FileDescriptor;III)I", (void*) osNetworkSystem_writeSocketDirectImpl },
3808 { "setNonBlockingImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_setNonBlockingImpl },
3809 { "connectSocketImpl", "(Ljava/io/FileDescriptor;ILjava/net/InetAddress;I)I", (void*) osNetworkSystem_connectSocketImpl },
3810 { "connectWithTimeoutSocketImpl", "(Ljava/io/FileDescriptor;IILjava/net/InetAddress;II[B)I", (void*) osNetworkSystem_connectWithTimeoutSocketImpl },
3811 { "connectStreamWithTimeoutSocketImpl","(Ljava/io/FileDescriptor;IIILjava/net/InetAddress;)V", (void*) osNetworkSystem_connectStreamWithTimeoutSocketImpl },
3812 { "socketBindImpl", "(Ljava/io/FileDescriptor;ILjava/net/InetAddress;)V", (void*) osNetworkSystem_socketBindImpl },
3813 { "listenStreamSocketImpl", "(Ljava/io/FileDescriptor;I)V", (void*) osNetworkSystem_listenStreamSocketImpl },
3814 { "availableStreamImpl", "(Ljava/io/FileDescriptor;)I", (void*) osNetworkSystem_availableStreamImpl },
3815 { "acceptSocketImpl", "(Ljava/io/FileDescriptor;Ljava/net/SocketImpl;Ljava/io/FileDescriptor;I)V",(void*) osNetworkSystem_acceptSocketImpl },
3816 { "supportsUrgentDataImpl", "(Ljava/io/FileDescriptor;)Z", (void*) osNetworkSystem_supportsUrgentDataImpl },
3817 { "sendUrgentDataImpl", "(Ljava/io/FileDescriptor;B)V", (void*) osNetworkSystem_sendUrgentDataImpl },
3818 { "connectDatagramImpl2", "(Ljava/io/FileDescriptor;IILjava/net/InetAddress;)V", (void*) osNetworkSystem_connectDatagramImpl2 },
3819 { "disconnectDatagramImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_disconnectDatagramImpl },
3820 { "peekDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)I", (void*) osNetworkSystem_peekDatagramImpl },
3821 { "receiveDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;[BIIIZ)I", (void*) osNetworkSystem_receiveDatagramImpl },
3822 { "receiveDatagramDirectImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;IIIIZ)I", (void*) osNetworkSystem_receiveDatagramDirectImpl },
3823 { "recvConnectedDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;[BIIIZ)I", (void*) osNetworkSystem_recvConnectedDatagramImpl },
3824 { "recvConnectedDatagramDirectImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;IIIIZ)I", (void*) osNetworkSystem_recvConnectedDatagramDirectImpl },
3825 { "sendDatagramImpl", "(Ljava/io/FileDescriptor;[BIIIZILjava/net/InetAddress;)I", (void*) osNetworkSystem_sendDatagramImpl },
3826 { "sendDatagramDirectImpl", "(Ljava/io/FileDescriptor;IIIIZILjava/net/InetAddress;)I", (void*) osNetworkSystem_sendDatagramDirectImpl },
3827 { "sendConnectedDatagramImpl", "(Ljava/io/FileDescriptor;[BIIZ)I", (void*) osNetworkSystem_sendConnectedDatagramImpl },
3828 { "sendConnectedDatagramDirectImpl", "(Ljava/io/FileDescriptor;IIIZ)I", (void*) osNetworkSystem_sendConnectedDatagramDirectImpl },
3829 { "createServerStreamSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createServerStreamSocketImpl },
3830 { "receiveStreamImpl", "(Ljava/io/FileDescriptor;[BIII)I", (void*) osNetworkSystem_receiveStreamImpl },
3831 { "sendStreamImpl", "(Ljava/io/FileDescriptor;[BII)I", (void*) osNetworkSystem_sendStreamImpl },
3832 { "shutdownInputImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_shutdownInputImpl },
3833 { "shutdownOutputImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_shutdownOutputImpl },
3834 { "sendDatagramImpl2", "(Ljava/io/FileDescriptor;[BIIILjava/net/InetAddress;)I", (void*) osNetworkSystem_sendDatagramImpl2 },
3835 { "selectImpl", "([Ljava/io/FileDescriptor;[Ljava/io/FileDescriptor;II[IJ)I", (void*) osNetworkSystem_selectImpl },
3836 { "getSocketLocalAddressImpl", "(Ljava/io/FileDescriptor;Z)Ljava/net/InetAddress;", (void*) osNetworkSystem_getSocketLocalAddressImpl },
3837 { "getSocketLocalPortImpl", "(Ljava/io/FileDescriptor;Z)I", (void*) osNetworkSystem_getSocketLocalPortImpl },
3838 { "getSocketOptionImpl", "(Ljava/io/FileDescriptor;I)Ljava/lang/Object;", (void*) osNetworkSystem_getSocketOptionImpl },
3839 { "setSocketOptionImpl", "(Ljava/io/FileDescriptor;ILjava/lang/Object;)V", (void*) osNetworkSystem_setSocketOptionImpl },
3840 { "getSocketFlagsImpl", "()I", (void*) osNetworkSystem_getSocketFlagsImpl },
3841 { "socketCloseImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_socketCloseImpl },
3842 { "getHostByAddrImpl", "([B)Ljava/net/InetAddress;", (void*) osNetworkSystem_getHostByAddrImpl },
3843 { "getHostByNameImpl", "(Ljava/lang/String;Z)Ljava/net/InetAddress;", (void*) osNetworkSystem_getHostByNameImpl },
3844 { "setInetAddressImpl", "(Ljava/net/InetAddress;[B)V", (void*) osNetworkSystem_setInetAddressImpl },
3845 { "inheritedChannelImpl", "()Ljava/nio/channels/Channel;", (void*) osNetworkSystem_inheritedChannelImpl },
3848 int register_org_apache_harmony_luni_platform_OSNetworkSystem(JNIEnv* env) {
3849 return jniRegisterNativeMethods(env,
3850 "org/apache/harmony/luni/platform/OSNetworkSystem",