1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 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 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 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. 15 */ 16 17 // BEGIN android-changed 18 // 19 // This file has been substantially reworked in order to provide more IPv6 20 // support and to move functionality from Java to native code where it made 21 // sense (e.g. when converting between IP addresses, socket structures, and 22 // strings, for which there exist fast and robust native implementations). 23 24 #define LOG_TAG "OSNetworkSystem" 25 26 #include "AndroidSystemNatives.h" 27 #include "JNIHelp.h" 28 #include "LocalArray.h" 29 #include "jni.h" 30 31 #include <arpa/inet.h> 32 #include <assert.h> 33 #include <errno.h> 34 #include <netdb.h> 35 #include <netinet/in.h> 36 #include <netinet/tcp.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <sys/ioctl.h> 41 #include <sys/socket.h> 42 #include <sys/time.h> 43 #include <sys/un.h> 44 #include <unistd.h> 45 46 // Temporary hack to build on systems that don't have up-to-date libc headers. 47 #ifndef IPV6_TCLASS 48 #ifdef __linux__ 49 #define IPV6_TCLASS 67 // Linux 50 #else 51 #define IPV6_TCLASS -1 // BSD(-like); TODO: Something better than this! 52 #endif 53 #endif 54 55 /* 56 * TODO: The multicast code is highly platform-dependent, and for now 57 * we just punt on anything but Linux. 58 */ 59 #ifdef __linux__ 60 #define ENABLE_MULTICAST 61 #endif 62 63 /** 64 * @name Socket Errors 65 * Error codes for socket operations 66 * 67 * @internal SOCKERR* range from -200 to -299 avoid overlap 68 */ 69 #define SOCKERR_NOTINITIALIZED -201 /* socket library uninitialized */ 70 #define SOCKERR_BADAF -202 /* bad address family */ 71 #define SOCKERR_BADPROTO -203 /* bad protocol */ 72 #define SOCKERR_BADTYPE -204 /* bad type */ 73 #define SOCKERR_SYSTEMBUSY -205 /* system busy handling requests */ 74 #define SOCKERR_SYSTEMFULL -206 /* too many sockets */ 75 #define SOCKERR_NOTCONNECTED -207 /* socket is not connected */ 76 #define SOCKERR_INTERRUPTED -208 /* the call was cancelled */ 77 #define SOCKERR_TIMEOUT -209 /* the operation timed out */ 78 #define SOCKERR_CONNRESET -210 /* the connection was reset */ 79 #define SOCKERR_WOULDBLOCK -211 /* the socket is marked as nonblocking operation would block */ 80 #define SOCKERR_ADDRNOTAVAIL -212 /* address not available */ 81 #define SOCKERR_ADDRINUSE -213 /* address already in use */ 82 #define SOCKERR_NOTBOUND -214 /* the socket is not bound */ 83 #define SOCKERR_INVALIDTIMEOUT -216 /* the specified timeout is invalid */ 84 #define SOCKERR_FDSETFULL -217 /* Unable to create an FDSET */ 85 #define SOCKERR_TIMEVALFULL -218 /* Unable to create a TIMEVAL */ 86 #define SOCKERR_REMSOCKSHUTDOWN -219 /* The remote socket has shutdown gracefully */ 87 #define SOCKERR_NOTLISTENING -220 /* listen() was not invoked prior to accept() */ 88 #define SOCKERR_NOTSTREAMSOCK -221 /* The socket does not support connection-oriented service */ 89 #define SOCKERR_ALREADYBOUND -222 /* The socket is already bound to an address */ 90 #define SOCKERR_NBWITHLINGER -223 /* The socket is marked non-blocking & SO_LINGER is non-zero */ 91 #define SOCKERR_ISCONNECTED -224 /* The socket is already connected */ 92 #define SOCKERR_NOBUFFERS -225 /* No buffer space is available */ 93 #define SOCKERR_HOSTNOTFOUND -226 /* Authoritative Answer Host not found */ 94 #define SOCKERR_NODATA -227 /* Valid name, no data record of requested type */ 95 #define SOCKERR_BOUNDORCONN -228 /* The socket has not been bound or is already connected */ 96 #define SOCKERR_OPNOTSUPP -229 /* The socket does not support the operation */ 97 #define SOCKERR_OPTUNSUPP -230 /* The socket option is not supported */ 98 #define SOCKERR_OPTARGSINVALID -231 /* The socket option arguments are invalid */ 99 #define SOCKERR_SOCKLEVELINVALID -232 /* The socket level is invalid */ 100 #define SOCKERR_TIMEOUTFAILURE -233 101 #define SOCKERR_SOCKADDRALLOCFAIL -234 /* Unable to allocate the sockaddr structure */ 102 #define SOCKERR_FDSET_SIZEBAD -235 /* The calculated maximum size of the file descriptor set is bad */ 103 #define SOCKERR_UNKNOWNFLAG -236 /* The flag is unknown */ 104 #define SOCKERR_MSGSIZE -237 /* The datagram was too big to fit the specified buffer & was truncated. */ 105 #define SOCKERR_NORECOVERY -238 /* The operation failed with no recovery possible */ 106 #define SOCKERR_ARGSINVALID -239 /* The arguments are invalid */ 107 #define SOCKERR_BADDESC -240 /* The socket argument is not a valid file descriptor */ 108 #define SOCKERR_NOTSOCK -241 /* The socket argument is not a socket */ 109 #define SOCKERR_HOSTENTALLOCFAIL -242 /* Unable to allocate the hostent structure */ 110 #define SOCKERR_TIMEVALALLOCFAIL -243 /* Unable to allocate the timeval structure */ 111 #define SOCKERR_LINGERALLOCFAIL -244 /* Unable to allocate the linger structure */ 112 #define SOCKERR_IPMREQALLOCFAIL -245 /* Unable to allocate the ipmreq structure */ 113 #define SOCKERR_FDSETALLOCFAIL -246 /* Unable to allocate the fdset structure */ 114 #define SOCKERR_OPFAILED -247 /* Operation failed */ 115 #define SOCKERR_VALUE_NULL -248 /* The value indexed was NULL */ 116 #define SOCKERR_CONNECTION_REFUSED -249 /* connection was refused */ 117 #define SOCKERR_ENETUNREACH -250 /* network is not reachable */ 118 #define SOCKERR_EACCES -251 /* permissions do not allow action on socket */ 119 #define SOCKERR_EHOSTUNREACH -252 /* no route to host */ 120 #define SOCKERR_EPIPE -253 /* broken pipe */ 121 122 #define JAVASOCKOPT_TCP_NODELAY 1 123 #define JAVASOCKOPT_IP_TOS 3 124 #define JAVASOCKOPT_SO_REUSEADDR 4 125 #define JAVASOCKOPT_SO_KEEPALIVE 8 126 #define JAVASOCKOPT_IP_MULTICAST_IF 16 127 #define JAVASOCKOPT_MCAST_TTL 17 128 #define JAVASOCKOPT_IP_MULTICAST_LOOP 18 129 #define JAVASOCKOPT_MCAST_ADD_MEMBERSHIP 19 130 #define JAVASOCKOPT_MCAST_DROP_MEMBERSHIP 20 131 #define JAVASOCKOPT_IP_MULTICAST_IF2 31 132 #define JAVASOCKOPT_SO_BROADCAST 32 133 #define JAVASOCKOPT_SO_LINGER 128 134 #define JAVASOCKOPT_REUSEADDR_AND_REUSEPORT 10001 135 #define JAVASOCKOPT_SO_SNDBUF 4097 136 #define JAVASOCKOPT_SO_RCVBUF 4098 137 #define JAVASOCKOPT_SO_RCVTIMEOUT 4102 138 #define JAVASOCKOPT_SO_OOBINLINE 4099 139 140 /* constants for calling multi-call functions */ 141 #define SOCKET_STEP_START 10 142 #define SOCKET_STEP_CHECK 20 143 #define SOCKET_STEP_DONE 30 144 145 #define BROKEN_MULTICAST_IF 1 146 #define BROKEN_MULTICAST_TTL 2 147 #define BROKEN_TCP_NODELAY 4 148 149 #define SOCKET_CONNECT_STEP_START 0 150 #define SOCKET_CONNECT_STEP_CHECK 1 151 152 #define SOCKET_OP_NONE 0 153 #define SOCKET_OP_READ 1 154 #define SOCKET_OP_WRITE 2 155 156 #define SOCKET_NOFLAGS 0 157 158 // Local constants for getOrSetSocketOption 159 #define SOCKOPT_GET 1 160 #define SOCKOPT_SET 2 161 162 struct CachedFields { 163 jfieldID fd_descriptor; 164 jclass iaddr_class; 165 jmethodID iaddr_getbyaddress; 166 jclass i4addr_class; 167 jmethodID i4addr_class_init; 168 jfieldID iaddr_ipaddress; 169 jclass genericipmreq_class; 170 jclass integer_class; 171 jmethodID integer_class_init; 172 jfieldID integer_class_value; 173 jclass boolean_class; 174 jmethodID boolean_class_init; 175 jfieldID boolean_class_value; 176 jclass byte_class; 177 jmethodID byte_class_init; 178 jfieldID byte_class_value; 179 jclass socketimpl_class; 180 jfieldID socketimpl_address; 181 jfieldID socketimpl_port; 182 jclass dpack_class; 183 jfieldID dpack_address; 184 jfieldID dpack_port; 185 jfieldID dpack_length; 186 } gCachedFields; 187 188 /* needed for connecting with timeout */ 189 struct selectFDSet { 190 int nfds; 191 int sock; 192 fd_set writeSet; 193 fd_set readSet; 194 fd_set exceptionSet; 195 }; 196 197 static const char * netLookupErrorString(int anErrorNum); 198 199 /** 200 * Throws an SocketException with the message affiliated with the errorCode. 201 * 202 * @deprecated: 'errorCode' is one of the bogus SOCKERR_ values, *not* errno. 203 * jniThrowSocketException is the better choice. 204 */ 205 static void throwSocketException(JNIEnv *env, int errorCode) { 206 jniThrowException(env, "java/net/SocketException", 207 netLookupErrorString(errorCode)); 208 } 209 210 // TODO(enh): move to JNIHelp.h 211 static void jniThrowExceptionWithErrno(JNIEnv* env, 212 const char* exceptionClassName, int error) { 213 char buf[BUFSIZ]; 214 jniThrowException(env, exceptionClassName, 215 jniStrError(error, buf, sizeof(buf))); 216 } 217 218 static void jniThrowBindException(JNIEnv* env, int error) { 219 jniThrowExceptionWithErrno(env, "java/net/BindException", error); 220 } 221 222 static void jniThrowSocketException(JNIEnv* env, int error) { 223 jniThrowExceptionWithErrno(env, "java/net/SocketException", error); 224 } 225 226 static void jniThrowSocketTimeoutException(JNIEnv* env, int error) { 227 jniThrowExceptionWithErrno(env, "java/net/SocketTimeoutException", error); 228 } 229 230 // Used by functions that shouldn't throw SocketException. (These functions 231 // aren't meant to see bad addresses, so seeing one really does imply an 232 // internal error.) 233 // TODO: fix the code (native and Java) so we don't paint ourselves into this corner. 234 static void jniThrowBadAddressFamily(JNIEnv* env) { 235 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad address family"); 236 } 237 238 static bool jniGetFd(JNIEnv* env, jobject fileDescriptor, int& fd) { 239 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 240 if (fd == -1) { 241 jniThrowSocketException(env, EBADF); 242 return false; 243 } 244 return true; 245 } 246 247 /** 248 * Converts a native address structure to a Java byte array. 249 */ 250 static jbyteArray socketAddressToByteArray(JNIEnv *env, 251 struct sockaddr_storage *address) { 252 253 void *rawAddress; 254 size_t addressLength; 255 if (address->ss_family == AF_INET) { 256 struct sockaddr_in *sin = (struct sockaddr_in *) address; 257 rawAddress = &sin->sin_addr.s_addr; 258 addressLength = 4; 259 } else if (address->ss_family == AF_INET6) { 260 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address; 261 rawAddress = &sin6->sin6_addr.s6_addr; 262 addressLength = 16; 263 } else { 264 jniThrowBadAddressFamily(env); 265 return NULL; 266 } 267 268 jbyteArray byteArray = env->NewByteArray(addressLength); 269 if (byteArray == NULL) { 270 return NULL; 271 } 272 env->SetByteArrayRegion(byteArray, 0, addressLength, (jbyte *) rawAddress); 273 274 return byteArray; 275 } 276 277 /** 278 * Returns the port number in a sockaddr_storage structure. 279 * 280 * @param address the sockaddr_storage structure to get the port from 281 * 282 * @return the port number, or -1 if the address family is unknown. 283 */ 284 static int getSocketAddressPort(struct sockaddr_storage *address) { 285 switch (address->ss_family) { 286 case AF_INET: 287 return ntohs(((struct sockaddr_in *) address)->sin_port); 288 case AF_INET6: 289 return ntohs(((struct sockaddr_in6 *) address)->sin6_port); 290 default: 291 return -1; 292 } 293 } 294 295 /** 296 * Obtain the socket address family from an existing socket. 297 * 298 * @param socket the file descriptor of the socket to examine 299 * @return an integer, the address family of the socket 300 */ 301 static int getSocketAddressFamily(int socket) { 302 sockaddr_storage ss; 303 socklen_t namelen = sizeof(ss); 304 int ret = getsockname(socket, (sockaddr*) &ss, &namelen); 305 if (ret != 0) { 306 return AF_UNSPEC; 307 } else { 308 return ss.ss_family; 309 } 310 } 311 312 jobject byteArrayToInetAddress(JNIEnv* env, jbyteArray byteArray) { 313 if (byteArray == NULL) { 314 return NULL; 315 } 316 return env->CallStaticObjectMethod(gCachedFields.iaddr_class, 317 gCachedFields.iaddr_getbyaddress, byteArray); 318 } 319 320 /** 321 * Converts a native address structure to an InetAddress object. 322 * Throws a NullPointerException or an IOException in case of 323 * error. 324 * 325 * @param sockAddress the sockaddr_storage structure to convert 326 * 327 * @return a jobject representing an InetAddress 328 */ 329 jobject socketAddressToInetAddress(JNIEnv* env, sockaddr_storage* sockAddress) { 330 jbyteArray byteArray = socketAddressToByteArray(env, sockAddress); 331 return byteArrayToInetAddress(env, byteArray); 332 } 333 334 /** 335 * Converts an IPv4 address to an IPv4-mapped IPv6 address if fd is an IPv6 336 * socket. 337 * @param fd the socket. 338 * @param sin_ss the address. 339 * @param sin6_ss scratch space where we can store the mapped address if necessary. 340 * @param mapUnspecified if true, convert 0.0.0.0 to ::ffff:0:0; if false, to :: 341 * @return either sin_ss or sin6_ss, depending on which the caller should use. 342 */ 343 static const sockaddr* convertIpv4ToMapped(int fd, 344 const sockaddr_storage* sin_ss, sockaddr_storage* sin6_ss, bool mapUnspecified) { 345 // We need to map if we have an IPv4 address but an IPv6 socket. 346 bool needsMapping = (sin_ss->ss_family == AF_INET && getSocketAddressFamily(fd) == AF_INET6); 347 if (!needsMapping) { 348 return reinterpret_cast<const sockaddr*>(sin_ss); 349 } 350 // Map the IPv4 address in sin_ss into an IPv6 address in sin6_ss. 351 const sockaddr_in* sin = reinterpret_cast<const sockaddr_in*>(sin_ss); 352 sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(sin6_ss); 353 memset(sin6, 0, sizeof(*sin6)); 354 sin6->sin6_family = AF_INET6; 355 sin6->sin6_port = sin->sin_port; 356 // TODO: mapUnspecified was introduced because kernels < 2.6.31 don't allow 357 // you to bind to ::ffff:0.0.0.0. When we move to something >= 2.6.31, we 358 // should make the code behave as if mapUnspecified were always true, and 359 // remove the parameter. 360 if (sin->sin_addr.s_addr != 0 || mapUnspecified) { 361 memset(&(sin6->sin6_addr.s6_addr[10]), 0xff, 2); 362 } 363 memcpy(&sin6->sin6_addr.s6_addr[12], &sin->sin_addr.s_addr, 4); 364 return reinterpret_cast<const sockaddr*>(sin6_ss); 365 } 366 367 /** 368 * Converts an InetAddress object and port number to a native address structure. 369 * Throws a NullPointerException or a SocketException in case of 370 * error. 371 */ 372 static bool byteArrayToSocketAddress(JNIEnv *env, 373 jbyteArray addressBytes, int port, sockaddr_storage *sockaddress) { 374 if (addressBytes == NULL) { 375 jniThrowNullPointerException(env, NULL); 376 return false; 377 } 378 379 // Convert the IP address bytes to the proper IP address type. 380 size_t addressLength = env->GetArrayLength(addressBytes); 381 memset(sockaddress, 0, sizeof(*sockaddress)); 382 if (addressLength == 4) { 383 // IPv4 address. 384 sockaddr_in *sin = reinterpret_cast<sockaddr_in*>(sockaddress); 385 sin->sin_family = AF_INET; 386 sin->sin_port = htons(port); 387 jbyte* dst = reinterpret_cast<jbyte*>(&sin->sin_addr.s_addr); 388 env->GetByteArrayRegion(addressBytes, 0, 4, dst); 389 } else if (addressLength == 16) { 390 // IPv6 address. 391 sockaddr_in6 *sin6 = reinterpret_cast<sockaddr_in6*>(sockaddress); 392 sin6->sin6_family = AF_INET6; 393 sin6->sin6_port = htons(port); 394 jbyte* dst = reinterpret_cast<jbyte*>(&sin6->sin6_addr.s6_addr); 395 env->GetByteArrayRegion(addressBytes, 0, 16, dst); 396 } else { 397 jniThrowBadAddressFamily(env); 398 return false; 399 } 400 return true; 401 } 402 403 /** 404 * Converts an InetAddress object and port number to a native address structure. 405 */ 406 static bool inetAddressToSocketAddress(JNIEnv *env, jobject inetaddress, 407 int port, sockaddr_storage *sockaddress) { 408 // Get the byte array that stores the IP address bytes in the InetAddress. 409 if (inetaddress == NULL) { 410 jniThrowNullPointerException(env, NULL); 411 return false; 412 } 413 jbyteArray addressBytes = 414 reinterpret_cast<jbyteArray>(env->GetObjectField(inetaddress, 415 gCachedFields.iaddr_ipaddress)); 416 417 return byteArrayToSocketAddress(env, addressBytes, port, sockaddress); 418 } 419 420 /** 421 * Convert a Java byte array representing an IP address to a Java string. 422 * 423 * @param addressByteArray the byte array to convert. 424 * 425 * @return a string with the textual representation of the address. 426 */ 427 static jstring osNetworkSystem_byteArrayToIpString(JNIEnv* env, jclass, 428 jbyteArray byteArray) { 429 if (byteArray == NULL) { 430 jniThrowNullPointerException(env, NULL); 431 return NULL; 432 } 433 sockaddr_storage ss; 434 if (!byteArrayToSocketAddress(env, byteArray, 0, &ss)) { 435 return NULL; 436 } 437 // TODO: getnameinfo seems to want its length parameter to be exactly 438 // sizeof(sockaddr_in) for an IPv4 address and sizeof (sockaddr_in6) for an 439 // IPv6 address. Fix getnameinfo so it accepts sizeof(sockaddr_storage), and 440 // then remove this hack. 441 int sa_size; 442 if (ss.ss_family == AF_INET) { 443 sa_size = sizeof(sockaddr_in); 444 } else if (ss.ss_family == AF_INET6) { 445 sa_size = sizeof(sockaddr_in6); 446 } else { 447 jniThrowBadAddressFamily(env); 448 return NULL; 449 } 450 char ipString[INET6_ADDRSTRLEN]; 451 int rc = getnameinfo(reinterpret_cast<sockaddr*>(&ss), sa_size, 452 ipString, sizeof(ipString), NULL, 0, NI_NUMERICHOST); 453 if (rc != 0) { 454 jniThrowException(env, "java/net/UnknownHostException", gai_strerror(rc)); 455 return NULL; 456 } 457 return env->NewStringUTF(ipString); 458 } 459 460 /** 461 * Convert a Java string representing an IP address to a Java byte array. 462 * The formats accepted are: 463 * - IPv4: 464 * - 1.2.3.4 465 * - 1.2.4 466 * - 1.4 467 * - 4 468 * - IPv6 469 * - Compressed form (2001:db8::1) 470 * - Uncompressed form (2001:db8:0:0:0:0:0:1) 471 * - IPv4-compatible (::192.0.2.0) 472 * - With an embedded IPv4 address (2001:db8::192.0.2.0). 473 * IPv6 addresses may appear in square brackets. 474 * 475 * @param addressByteArray the byte array to convert. 476 * 477 * @return a string with the textual representation of the address. 478 * 479 * @throws UnknownHostException the IP address was invalid. 480 */ 481 static jbyteArray osNetworkSystem_ipStringToByteArray(JNIEnv* env, jclass, 482 jstring javaString) { 483 if (javaString == NULL) { 484 jniThrowNullPointerException(env, NULL); 485 return NULL; 486 } 487 488 // Convert the String to UTF bytes. 489 size_t byteCount = env->GetStringUTFLength(javaString); 490 LocalArray<INET6_ADDRSTRLEN> bytes(byteCount + 1); 491 char* ipString = &bytes[0]; 492 env->GetStringUTFRegion(javaString, 0, env->GetStringLength(javaString), ipString); 493 494 // Accept IPv6 addresses (only) in square brackets for compatibility. 495 if (ipString[0] == '[' && ipString[byteCount - 1] == ']' && 496 strchr(ipString, ':') != NULL) { 497 memmove(ipString, ipString + 1, byteCount - 2); 498 ipString[byteCount - 2] = '\0'; 499 } 500 501 jbyteArray result = NULL; 502 addrinfo hints; 503 memset(&hints, 0, sizeof(hints)); 504 hints.ai_flags = AI_NUMERICHOST; 505 506 sockaddr_storage ss; 507 memset(&ss, 0, sizeof(ss)); 508 509 addrinfo* res = NULL; 510 int ret = getaddrinfo(ipString, NULL, &hints, &res); 511 if (ret == 0 && res) { 512 // Convert IPv4-mapped addresses to IPv4 addresses. 513 // The RI states "Java will never return an IPv4-mapped address". 514 sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(res->ai_addr); 515 if (res->ai_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 516 sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(&ss); 517 sin->sin_family = AF_INET; 518 sin->sin_port = sin6->sin6_port; 519 memcpy(&sin->sin_addr.s_addr, &sin6->sin6_addr.s6_addr[12], 4); 520 result = socketAddressToByteArray(env, &ss); 521 } else { 522 result = socketAddressToByteArray(env, reinterpret_cast<sockaddr_storage*>(res->ai_addr)); 523 } 524 } else { 525 // For backwards compatibility, deal with address formats that 526 // getaddrinfo does not support. For example, 1.2.3, 1.3, and even 3 are 527 // valid IPv4 addresses according to the Java API. If getaddrinfo fails, 528 // try to use inet_aton. 529 sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(&ss); 530 if (inet_aton(ipString, &sin->sin_addr)) { 531 sin->sin_family = AF_INET; 532 sin->sin_port = 0; 533 result = socketAddressToByteArray(env, &ss); 534 } 535 } 536 537 if (res) { 538 freeaddrinfo(res); 539 } 540 541 if (! result) { 542 env->ExceptionClear(); 543 jniThrowException(env, "java/net/UnknownHostException", 544 gai_strerror(ret)); 545 } 546 547 return result; 548 } 549 550 /** 551 * Answer a new java.lang.Boolean object. 552 * 553 * @param env pointer to the JNI library 554 * @param anInt the Boolean constructor argument 555 * 556 * @return the new Boolean 557 */ 558 static jobject newJavaLangBoolean(JNIEnv * env, jint anInt) { 559 jclass tempClass; 560 jmethodID tempMethod; 561 562 tempClass = gCachedFields.boolean_class; 563 tempMethod = gCachedFields.boolean_class_init; 564 return env->NewObject(tempClass, tempMethod, (jboolean) (anInt != 0)); 565 } 566 567 /** 568 * Answer a new java.lang.Byte object. 569 * 570 * @param env pointer to the JNI library 571 * @param anInt the Byte constructor argument 572 * 573 * @return the new Byte 574 */ 575 static jobject newJavaLangByte(JNIEnv * env, jbyte val) { 576 jclass tempClass; 577 jmethodID tempMethod; 578 579 tempClass = gCachedFields.byte_class; 580 tempMethod = gCachedFields.byte_class_init; 581 return env->NewObject(tempClass, tempMethod, val); 582 } 583 584 /** 585 * Answer a new java.lang.Integer object. 586 * 587 * @param env pointer to the JNI library 588 * @param anInt the Integer constructor argument 589 * 590 * @return the new Integer 591 */ 592 static jobject newJavaLangInteger(JNIEnv* env, jint anInt) { 593 return env->NewObject(gCachedFields.integer_class, gCachedFields.integer_class_init, anInt); 594 } 595 596 // Converts a number of milliseconds to a timeval. 597 static timeval toTimeval(long ms) { 598 timeval tv; 599 tv.tv_sec = ms / 1000; 600 tv.tv_usec = (ms - tv.tv_sec*1000) * 1000; 601 return tv; 602 } 603 604 // Converts a timeval to a number of milliseconds. 605 static long toMs(const timeval& tv) { 606 return tv.tv_sec * 1000 + tv.tv_usec / 1000; 607 } 608 609 /** 610 * Query OS for timestamp. 611 * Retrieve the current value of system clock and convert to milliseconds. 612 * 613 * @param[in] portLibrary The port library. 614 * 615 * @return 0 on failure, time value in milliseconds on success. 616 * @deprecated Use @ref time_hires_clock and @ref time_hires_delta 617 * 618 * technically, this should return I_64 since both timeval.tv_sec and 619 * timeval.tv_usec are long 620 */ 621 622 static int time_msec_clock() { 623 timeval tp; 624 struct timezone tzp; 625 gettimeofday(&tp, &tzp); 626 return toMs(tp); 627 } 628 629 /** 630 * Answer the errorString corresponding to the errorNumber, if available. 631 * This function will answer a default error string, if the errorNumber is not 632 * recognized. 633 * 634 * This function will have to be reworked to handle internationalization 635 * properly, removing the explicit strings. 636 * 637 * @param anErrorNum the error code to resolve to a human readable string 638 * 639 * @return a human readable error string 640 */ 641 642 static const char * netLookupErrorString(int anErrorNum) { 643 switch (anErrorNum) { 644 case SOCKERR_NOTINITIALIZED: 645 return "Socket library uninitialized"; 646 case SOCKERR_BADAF: 647 return "Bad address family"; 648 case SOCKERR_BADPROTO: 649 return "Bad protocol"; 650 case SOCKERR_BADTYPE: 651 return "Bad type"; 652 case SOCKERR_SYSTEMBUSY: 653 return "System busy handling requests"; 654 case SOCKERR_SYSTEMFULL: 655 return "Too many sockets allocated"; 656 case SOCKERR_NOTCONNECTED: 657 return "Socket is not connected"; 658 case SOCKERR_INTERRUPTED: 659 return "The system call was cancelled"; 660 case SOCKERR_TIMEOUT: 661 return "The operation timed out"; 662 case SOCKERR_CONNRESET: 663 return "The connection was reset"; 664 case SOCKERR_WOULDBLOCK: 665 return "The nonblocking operation would block"; 666 case SOCKERR_ADDRNOTAVAIL: 667 return "The address is not available"; 668 case SOCKERR_ADDRINUSE: 669 return "The address is already in use"; 670 case SOCKERR_NOTBOUND: 671 return "The socket is not bound"; 672 case SOCKERR_INVALIDTIMEOUT: 673 return "The specified timeout is invalid"; 674 case SOCKERR_FDSETFULL: 675 return "Unable to create an FDSET"; 676 case SOCKERR_TIMEVALFULL: 677 return "Unable to create a TIMEVAL"; 678 case SOCKERR_REMSOCKSHUTDOWN: 679 return "The remote socket has shutdown gracefully"; 680 case SOCKERR_NOTLISTENING: 681 return "Listen() was not invoked prior to accept()"; 682 case SOCKERR_NOTSTREAMSOCK: 683 return "The socket does not support connection-oriented service"; 684 case SOCKERR_ALREADYBOUND: 685 return "The socket is already bound to an address"; 686 case SOCKERR_NBWITHLINGER: 687 return "The socket is marked non-blocking & SO_LINGER is non-zero"; 688 case SOCKERR_ISCONNECTED: 689 return "The socket is already connected"; 690 case SOCKERR_NOBUFFERS: 691 return "No buffer space is available"; 692 case SOCKERR_HOSTNOTFOUND: 693 return "Authoritative Answer Host not found"; 694 case SOCKERR_NODATA: 695 return "Valid name, no data record of requested type"; 696 case SOCKERR_BOUNDORCONN: 697 return "The socket has not been bound or is already connected"; 698 case SOCKERR_OPNOTSUPP: 699 return "The socket does not support the operation"; 700 case SOCKERR_OPTUNSUPP: 701 return "The socket option is not supported"; 702 case SOCKERR_OPTARGSINVALID: 703 return "The socket option arguments are invalid"; 704 case SOCKERR_SOCKLEVELINVALID: 705 return "The socket level is invalid"; 706 case SOCKERR_TIMEOUTFAILURE: 707 return "The timeout operation failed"; 708 case SOCKERR_SOCKADDRALLOCFAIL: 709 return "Failed to allocate address structure"; 710 case SOCKERR_FDSET_SIZEBAD: 711 return "The calculated maximum size of the file descriptor set is bad"; 712 case SOCKERR_UNKNOWNFLAG: 713 return "The flag is unknown"; 714 case SOCKERR_MSGSIZE: 715 return "The datagram was too big to fit the specified buffer, so truncated"; 716 case SOCKERR_NORECOVERY: 717 return "The operation failed with no recovery possible"; 718 case SOCKERR_ARGSINVALID: 719 return "The arguments are invalid"; 720 case SOCKERR_BADDESC: 721 return "The socket argument is not a valid file descriptor"; 722 case SOCKERR_NOTSOCK: 723 return "The socket argument is not a socket"; 724 case SOCKERR_HOSTENTALLOCFAIL: 725 return "Unable to allocate the hostent structure"; 726 case SOCKERR_TIMEVALALLOCFAIL: 727 return "Unable to allocate the timeval structure"; 728 case SOCKERR_LINGERALLOCFAIL: 729 return "Unable to allocate the linger structure"; 730 case SOCKERR_IPMREQALLOCFAIL: 731 return "Unable to allocate the ipmreq structure"; 732 case SOCKERR_FDSETALLOCFAIL: 733 return "Unable to allocate the fdset structure"; 734 case SOCKERR_OPFAILED: 735 return "Operation failed"; 736 case SOCKERR_CONNECTION_REFUSED: 737 return "Connection refused"; 738 case SOCKERR_ENETUNREACH: 739 return "Network unreachable"; 740 case SOCKERR_EHOSTUNREACH: 741 return "No route to host"; 742 case SOCKERR_EPIPE: 743 return "Broken pipe"; 744 case SOCKERR_EACCES: 745 return "Permission denied (maybe missing INTERNET permission)"; 746 747 default: 748 LOGE("unknown socket error %d", anErrorNum); 749 return "unknown error"; 750 } 751 } 752 753 static int convertError(int errorCode) { 754 switch (errorCode) { 755 case EBADF: 756 return SOCKERR_BADDESC; 757 case ENOBUFS: 758 return SOCKERR_NOBUFFERS; 759 case EOPNOTSUPP: 760 return SOCKERR_OPNOTSUPP; 761 case ENOPROTOOPT: 762 return SOCKERR_OPTUNSUPP; 763 case EINVAL: 764 return SOCKERR_SOCKLEVELINVALID; 765 case ENOTSOCK: 766 return SOCKERR_NOTSOCK; 767 case EINTR: 768 return SOCKERR_INTERRUPTED; 769 case ENOTCONN: 770 return SOCKERR_NOTCONNECTED; 771 case EAFNOSUPPORT: 772 return SOCKERR_BADAF; 773 /* note: CONNRESET not included because it has the same 774 * value as ECONNRESET and they both map to SOCKERR_CONNRESET */ 775 case ECONNRESET: 776 return SOCKERR_CONNRESET; 777 case EAGAIN: 778 return SOCKERR_WOULDBLOCK; 779 case EPROTONOSUPPORT: 780 return SOCKERR_BADPROTO; 781 case EFAULT: 782 return SOCKERR_ARGSINVALID; 783 case ETIMEDOUT: 784 return SOCKERR_TIMEOUT; 785 case ECONNREFUSED: 786 return SOCKERR_CONNECTION_REFUSED; 787 case ENETUNREACH: 788 return SOCKERR_ENETUNREACH; 789 case EACCES: 790 return SOCKERR_EACCES; 791 case EPIPE: 792 return SOCKERR_EPIPE; 793 case EHOSTUNREACH: 794 return SOCKERR_EHOSTUNREACH; 795 case EADDRINUSE: 796 return SOCKERR_ADDRINUSE; 797 case EADDRNOTAVAIL: 798 return SOCKERR_ADDRNOTAVAIL; 799 case EMSGSIZE: 800 return SOCKERR_MSGSIZE; 801 default: 802 LOGE("unclassified errno %d (%s)", errorCode, strerror(errorCode)); 803 return SOCKERR_OPFAILED; 804 } 805 } 806 807 static int selectWait(int fd, int uSecTime) { 808 timeval tv; 809 timeval* tvp; 810 if (uSecTime >= 0) { 811 /* Use a timeout if uSecTime >= 0 */ 812 memset(&tv, 0, sizeof(tv)); 813 tv.tv_usec = uSecTime; 814 tvp = &tv; 815 } else { 816 /* Infinite timeout if uSecTime < 0 */ 817 tvp = NULL; 818 } 819 820 fd_set readFds; 821 FD_ZERO(&readFds); 822 FD_SET(fd, &readFds); 823 int result = select(fd + 1, &readFds, NULL, NULL, tvp); 824 if (result == -1) { 825 if (errno == EINTR) { 826 result = SOCKERR_INTERRUPTED; 827 } else { 828 result = SOCKERR_OPFAILED; 829 } 830 } else if (result == 0) { 831 result = SOCKERR_TIMEOUT; 832 } 833 return result; 834 } 835 836 // Returns 0 on success, not obviously meaningful negative values on error. 837 static int pollSelectWait(JNIEnv *env, jobject fileDescriptor, int timeout) { 838 /* now try reading the socket for the timeout. 839 * if timeout is 0 try forever until the sockets gets ready or until an 840 * exception occurs. 841 */ 842 int pollTimeoutUSec = 100000, pollMsec = 100; 843 int finishTime = 0; 844 int timeLeft = timeout; 845 int hasTimeout = timeout > 0 ? 1 : 0; 846 int result = 0; 847 int handle; 848 849 if (hasTimeout) { 850 finishTime = time_msec_clock() + timeout; 851 } 852 853 int poll = 1; 854 855 while (poll) { /* begin polling loop */ 856 857 /* 858 * Fetch the handle every time in case the socket is closed. 859 */ 860 handle = jniGetFDFromFileDescriptor(env, fileDescriptor); 861 if (handle == -1) { 862 jniThrowSocketException(env, EINTR); 863 return -1; 864 } 865 866 if (hasTimeout) { 867 868 if (timeLeft - 10 < pollMsec) { 869 pollTimeoutUSec = timeLeft <= 0 ? 0 : (timeLeft * 1000); 870 } 871 872 result = selectWait(handle, pollTimeoutUSec); 873 874 /* 875 * because we are polling at a time smaller than timeout 876 * (presumably) lets treat an interrupt and timeout the same - go 877 * see if we're done timewise, and then just try again if not. 878 */ 879 if (SOCKERR_TIMEOUT == result || 880 SOCKERR_INTERRUPTED == result) { 881 882 timeLeft = finishTime - time_msec_clock(); 883 884 if (timeLeft <= 0) { 885 /* 886 * Always throw the "timeout" message because that is 887 * effectively what has happened, even if we happen to 888 * have been interrupted. 889 */ 890 jniThrowSocketTimeoutException(env, ETIMEDOUT); 891 } else { 892 continue; // try again 893 } 894 895 } else if (0 > result) { 896 throwSocketException(env, result); 897 } 898 poll = 0; 899 900 } else { /* polling with no timeout (why would you do this?)*/ 901 902 result = selectWait(handle, pollTimeoutUSec); 903 904 /* 905 * if interrupted (or a timeout) just retry 906 */ 907 if (SOCKERR_TIMEOUT == result || 908 SOCKERR_INTERRUPTED == result) { 909 910 continue; // try again 911 } else if (0 > result) { 912 throwSocketException(env, result); 913 } 914 poll = 0; 915 } 916 } /* end polling loop */ 917 918 return result; 919 } 920 921 /** 922 * Wrapper for connect() that converts IPv4 addresses to IPv4-mapped IPv6 923 * addresses if necessary. 924 * 925 * @param socket the file descriptor of the socket to connect 926 * @param socketAddress the address to connect to 927 */ 928 static int doConnect(int fd, const sockaddr_storage* socketAddress) { 929 sockaddr_storage tmp; 930 const sockaddr* realAddress = convertIpv4ToMapped(fd, socketAddress, &tmp, true); 931 return TEMP_FAILURE_RETRY(connect(fd, realAddress, sizeof(sockaddr_storage))); 932 } 933 934 /** 935 * Establish a connection to a peer with a timeout. This function is called 936 * repeatedly in order to carry out the connect and to allow other tasks to 937 * proceed on certain platforms. The caller must first call with 938 * step = SOCKET_STEP_START, if the result is SOCKERR_NOTCONNECTED it will then 939 * call it with step = CHECK until either another error or 0 is returned to 940 * indicate the connect is complete. Each time the function should sleep for no 941 * more than timeout milliseconds. If the connect succeeds or an error occurs, 942 * the caller must always end the process by calling the function with 943 * step = SOCKET_STEP_DONE 944 * 945 * @param[in] portLibrary The port library. 946 * @param[in] sock pointer to the unconnected local socket. 947 * @param[in] addr pointer to the sockaddr, specifying remote host/port. 948 * @param[in] timeout the timeout in milliseconds. If timeout is negative, 949 * perform a block operation. 950 * @param[in,out] pointer to context pointer. Filled in on first call and then 951 * to be passed into each subsequent call. 952 * 953 * @return 0, if no errors occurred, otherwise the (negative) error code. 954 */ 955 // TODO: do we really want to pass 'addr' by value? 956 static int sockConnectWithTimeout(int handle, sockaddr_storage addr, 957 int timeout, unsigned int step, jbyte *ctxt) { 958 int rc = 0; 959 int errorVal; 960 socklen_t errorValLen = sizeof(int); 961 selectFDSet* context = reinterpret_cast<selectFDSet*>(ctxt); 962 963 if (SOCKET_STEP_START == step) { 964 context->sock = handle; 965 context->nfds = handle + 1; 966 967 /* set the socket to non-blocking */ 968 int block = JNI_TRUE; 969 rc = ioctl(handle, FIONBIO, &block); 970 if (rc != 0) { 971 return convertError(rc); 972 } 973 974 // LOGD("+connect to address 0x%08x (via normal) on handle %d", 975 // addr.sin_addr.s_addr, handle); 976 rc = doConnect(handle, &addr); 977 // LOGD("-connect to address 0x%08x (via normal) returned %d", 978 // addr.sin_addr.s_addr, (int) rc); 979 980 if (rc == -1) { 981 rc = errno; 982 switch (rc) { 983 case EINTR: 984 return SOCKERR_ALREADYBOUND; 985 case EAGAIN: 986 case EINPROGRESS: 987 return SOCKERR_NOTCONNECTED; 988 default: 989 return convertError(rc); 990 } 991 } 992 993 /* we connected right off the bat so just return */ 994 return rc; 995 996 } else if (SOCKET_STEP_CHECK == step) { 997 /* now check if we have connected yet */ 998 999 /* 1000 * set the timeout value to be used. Because on some unix platforms we 1001 * don't get notified when a socket is closed we only sleep for 100ms 1002 * at a time 1003 * 1004 * TODO: is this relevant for Android? 1005 */ 1006 if (timeout > 100) { 1007 timeout = 100; 1008 } 1009 timeval passedTimeout(toTimeval(timeout)); 1010 1011 /* initialize the FD sets for the select */ 1012 FD_ZERO(&(context->exceptionSet)); 1013 FD_ZERO(&(context->writeSet)); 1014 FD_ZERO(&(context->readSet)); 1015 FD_SET(context->sock, &(context->writeSet)); 1016 FD_SET(context->sock, &(context->readSet)); 1017 FD_SET(context->sock, &(context->exceptionSet)); 1018 1019 rc = select(context->nfds, 1020 &(context->readSet), 1021 &(context->writeSet), 1022 &(context->exceptionSet), 1023 timeout >= 0 ? &passedTimeout : NULL); 1024 1025 /* if there is at least one descriptor ready to be checked */ 1026 if (0 < rc) { 1027 /* if the descriptor is in the write set we connected or failed */ 1028 if (FD_ISSET(context->sock, &(context->writeSet))) { 1029 1030 if (!FD_ISSET(context->sock, &(context->readSet))) { 1031 /* ok we have connected ok */ 1032 return 0; 1033 } else { 1034 /* ok we have more work to do to figure it out */ 1035 if (getsockopt(context->sock, SOL_SOCKET, SO_ERROR, 1036 &errorVal, &errorValLen) >= 0) { 1037 return errorVal ? convertError(errorVal) : 0; 1038 } else { 1039 return convertError(errno); 1040 } 1041 } 1042 } 1043 1044 /* if the descriptor is in the exception set the connect failed */ 1045 if (FD_ISSET(context->sock, &(context->exceptionSet))) { 1046 if (getsockopt(context->sock, SOL_SOCKET, SO_ERROR, &errorVal, 1047 &errorValLen) >= 0) { 1048 return errorVal ? convertError(errorVal) : 0; 1049 } 1050 rc = errno; 1051 return convertError(rc); 1052 } 1053 1054 } else if (rc < 0) { 1055 /* something went wrong with the select call */ 1056 rc = errno; 1057 1058 /* if it was EINTR we can just try again. Return not connected */ 1059 if (EINTR == rc) { 1060 return SOCKERR_NOTCONNECTED; 1061 } 1062 1063 /* some other error occured so look it up and return */ 1064 return convertError(rc); 1065 } 1066 1067 /* 1068 * if we get here the timeout expired or the connect had not yet 1069 * completed just indicate that the connect is not yet complete 1070 */ 1071 return SOCKERR_NOTCONNECTED; 1072 } else if (SOCKET_STEP_DONE == step) { 1073 /* we are done the connect or an error occured so clean up */ 1074 if (handle != -1) { 1075 int block = JNI_FALSE; 1076 ioctl(handle, FIONBIO, &block); 1077 } 1078 return 0; 1079 } 1080 return SOCKERR_ARGSINVALID; 1081 } 1082 1083 1084 #if LOG_SOCKOPT 1085 /** 1086 * Helper method to log getsockopt/getsockopt calls. 1087 */ 1088 static const char *sockoptLevelToString(int level) { 1089 switch(level) { 1090 case SOL_SOCKET: 1091 return "SOL_SOCKET"; 1092 case IPPROTO_IP: 1093 return "IPPROTO_IP"; 1094 case IPPROTO_IPV6: 1095 return "IPPROTO_IPV6"; 1096 default: 1097 return "SOL_???"; 1098 } 1099 } 1100 #endif 1101 1102 /** 1103 * Helper method to get or set socket options 1104 * 1105 * @param action SOCKOPT_GET to get an option, SOCKOPT_SET to set it 1106 * @param socket the file descriptor of the socket to use 1107 * @param ipv4Option the option value to use for an IPv4 socket 1108 * @param ipv6Option the option value to use for an IPv6 socket 1109 * @param optionValue the value of the socket option to get or set 1110 * @param optionLength the length of the socket option to get or set 1111 * 1112 * @return the value of the socket call, or -1 on failure inside this function 1113 * 1114 * @note on internal failure, the errno variable will be set appropriately 1115 */ 1116 static int getOrSetSocketOption(int action, int socket, int ipv4Option, 1117 int ipv6Option, void *optionValue, socklen_t *optionLength) { 1118 int option; 1119 int protocol; 1120 int family = getSocketAddressFamily(socket); 1121 switch (family) { 1122 case AF_INET: 1123 option = ipv4Option; 1124 protocol = IPPROTO_IP; 1125 break; 1126 case AF_INET6: 1127 option = ipv6Option; 1128 protocol = IPPROTO_IPV6; 1129 break; 1130 default: 1131 // TODO(enh): throw Java exceptions from this method instead of just 1132 // returning error codes. 1133 errno = EAFNOSUPPORT; 1134 return -1; 1135 } 1136 1137 int ret; 1138 if (action == SOCKOPT_GET) { 1139 ret = getsockopt(socket, protocol, option, optionValue, optionLength); 1140 #if LOG_SOCKOPT 1141 LOGI("getsockopt(%d, %s, %d, %p, [%d]) = %d %s", 1142 socket, sockoptLevelToString(protocol), option, optionValue, 1143 *optionLength, ret, (ret == -1) ? strerror(errno) : ""); 1144 #endif 1145 } else if (action == SOCKOPT_SET) { 1146 ret = setsockopt(socket, protocol, option, optionValue, *optionLength); 1147 #if LOG_SOCKOPT 1148 LOGI("setsockopt(%d, %s, %d, [%d], %d) = %d %s", 1149 socket, sockoptLevelToString(protocol), option, 1150 // Note: this only works for integer options. 1151 // TODO: Use dvmPrintHexDump() to log non-integer options. 1152 *(int *)optionValue, *optionLength, ret, 1153 (ret == -1) ? strerror(errno) : ""); 1154 #endif 1155 } else { 1156 errno = EINVAL; 1157 ret = -1; 1158 } 1159 return ret; 1160 } 1161 1162 #ifdef ENABLE_MULTICAST 1163 /* 1164 * Find the interface index that was set for this socket by the IP_MULTICAST_IF 1165 * or IPV6_MULTICAST_IF socket option. 1166 * 1167 * @param socket the socket to examine 1168 * 1169 * @return the interface index, or -1 on failure 1170 * 1171 * @note on internal failure, the errno variable will be set appropriately 1172 */ 1173 static int interfaceIndexFromMulticastSocket(int socket) { 1174 int family = getSocketAddressFamily(socket); 1175 int interfaceIndex; 1176 int result; 1177 if (family == AF_INET) { 1178 // IP_MULTICAST_IF returns a pointer to a struct ip_mreqn. 1179 struct ip_mreqn tempRequest; 1180 socklen_t requestLength = sizeof(tempRequest); 1181 result = getsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, &tempRequest, 1182 &requestLength); 1183 interfaceIndex = tempRequest.imr_ifindex; 1184 } else if (family == AF_INET6) { 1185 // IPV6_MULTICAST_IF returns a pointer to an integer. 1186 socklen_t requestLength = sizeof(interfaceIndex); 1187 result = getsockopt(socket, IPPROTO_IPV6, IPV6_MULTICAST_IF, 1188 &interfaceIndex, &requestLength); 1189 } else { 1190 errno = EAFNOSUPPORT; 1191 return -1; 1192 } 1193 1194 if (result == 0) 1195 return interfaceIndex; 1196 else 1197 return -1; 1198 } 1199 1200 /** 1201 * Join/Leave the nominated multicast group on the specified socket. 1202 * Implemented by setting the multicast 'add membership'/'drop membership' 1203 * option at the HY_IPPROTO_IP level on the socket. 1204 * 1205 * Implementation note for multicast sockets in general: 1206 * 1207 * - This code is untested, because at the time of this writing multicast can't 1208 * be properly tested on Android due to GSM routing restrictions. So it might 1209 * or might not work. 1210 * 1211 * - The REUSEPORT socket option that Harmony employs is not supported on Linux 1212 * and thus also not supported on Android. It's is not needed for multicast 1213 * to work anyway (REUSEADDR should suffice). 1214 * 1215 * @param env pointer to the JNI library. 1216 * @param socketP pointer to the hysocket to join/leave on. 1217 * @param optVal pointer to the InetAddress, the multicast group to join/drop. 1218 * 1219 * @exception SocketException if an error occurs during the call 1220 */ 1221 static void mcastAddDropMembership(JNIEnv *env, int handle, jobject optVal, 1222 int ignoreIF, int setSockOptVal) { 1223 struct sockaddr_storage sockaddrP; 1224 int result; 1225 // By default, let the system decide which interface to use. 1226 int interfaceIndex = 0; 1227 1228 /* 1229 * Check whether we are getting an InetAddress or an Generic IPMreq. For now 1230 * we support both so that we will not break the tests. If an InetAddress 1231 * is passed in, only support IPv4 as obtaining an interface from an 1232 * InetAddress is complex and should be done by the Java caller. 1233 */ 1234 if (env->IsInstanceOf (optVal, gCachedFields.iaddr_class)) { 1235 /* 1236 * optVal is an InetAddress. Construct a multicast request structure 1237 * from this address. Support IPv4 only. 1238 */ 1239 struct ip_mreqn multicastRequest; 1240 socklen_t length = sizeof(multicastRequest); 1241 memset(&multicastRequest, 0, length); 1242 1243 // If ignoreIF is false, determine the index of the interface to use. 1244 if (!ignoreIF) { 1245 interfaceIndex = interfaceIndexFromMulticastSocket(handle); 1246 multicastRequest.imr_ifindex = interfaceIndex; 1247 if (interfaceIndex == -1) { 1248 jniThrowSocketException(env, errno); 1249 return; 1250 } 1251 } 1252 1253 // Convert the inetAddress to an IPv4 address structure. 1254 if (!inetAddressToSocketAddress(env, optVal, 0, &sockaddrP)) { 1255 return; 1256 } 1257 if (sockaddrP.ss_family != AF_INET) { 1258 jniThrowSocketException(env, EAFNOSUPPORT); 1259 return; 1260 } 1261 struct sockaddr_in *sin = (struct sockaddr_in *) &sockaddrP; 1262 multicastRequest.imr_multiaddr = sin->sin_addr; 1263 1264 result = setsockopt(handle, IPPROTO_IP, setSockOptVal, 1265 &multicastRequest, length); 1266 if (0 != result) { 1267 jniThrowSocketException(env, errno); 1268 return; 1269 } 1270 } else { 1271 /* 1272 * optVal is a GenericIPMreq object. Extract the relevant fields from 1273 * it and construct a multicast request structure from these. Support 1274 * both IPv4 and IPv6. 1275 */ 1276 jclass cls; 1277 jfieldID multiaddrID; 1278 jfieldID interfaceIdxID; 1279 jobject multiaddr; 1280 1281 // Get the multicast address to join or leave. 1282 cls = env->GetObjectClass(optVal); 1283 multiaddrID = env->GetFieldID(cls, "multiaddr", "Ljava/net/InetAddress;"); 1284 multiaddr = env->GetObjectField(optVal, multiaddrID); 1285 1286 // Get the interface index to use. 1287 if (! ignoreIF) { 1288 interfaceIdxID = env->GetFieldID(cls, "interfaceIdx", "I"); 1289 interfaceIndex = env->GetIntField(optVal, interfaceIdxID); 1290 } 1291 LOGI("mcastAddDropMembership interfaceIndex=%i", interfaceIndex); 1292 1293 if (!inetAddressToSocketAddress(env, multiaddr, 0, &sockaddrP)) { 1294 return; 1295 } 1296 1297 int family = getSocketAddressFamily(handle); 1298 1299 // Handle IPv4 multicast on an IPv6 socket. 1300 if (family == AF_INET6 && sockaddrP.ss_family == AF_INET) { 1301 family = AF_INET; 1302 } 1303 1304 struct ip_mreqn ipv4Request; 1305 struct ipv6_mreq ipv6Request; 1306 void *multicastRequest; 1307 socklen_t requestLength; 1308 int level; 1309 switch (family) { 1310 case AF_INET: 1311 requestLength = sizeof(ipv4Request); 1312 memset(&ipv4Request, 0, requestLength); 1313 ipv4Request.imr_multiaddr = 1314 ((struct sockaddr_in *) &sockaddrP)->sin_addr; 1315 ipv4Request.imr_ifindex = interfaceIndex; 1316 multicastRequest = &ipv4Request; 1317 level = IPPROTO_IP; 1318 break; 1319 case AF_INET6: 1320 // setSockOptVal is passed in by the caller and may be IPv4-only 1321 if (setSockOptVal == IP_ADD_MEMBERSHIP) { 1322 setSockOptVal = IPV6_ADD_MEMBERSHIP; 1323 } 1324 if (setSockOptVal == IP_DROP_MEMBERSHIP) { 1325 setSockOptVal == IPV6_DROP_MEMBERSHIP; 1326 } 1327 requestLength = sizeof(ipv6Request); 1328 memset(&ipv6Request, 0, requestLength); 1329 ipv6Request.ipv6mr_multiaddr = 1330 ((struct sockaddr_in6 *) &sockaddrP)->sin6_addr; 1331 ipv6Request.ipv6mr_interface = interfaceIndex; 1332 multicastRequest = &ipv6Request; 1333 level = IPPROTO_IPV6; 1334 break; 1335 default: 1336 jniThrowSocketException(env, EAFNOSUPPORT); 1337 return; 1338 } 1339 1340 /* join/drop the multicast address */ 1341 result = setsockopt(handle, level, setSockOptVal, multicastRequest, 1342 requestLength); 1343 if (0 != result) { 1344 jniThrowSocketException(env, errno); 1345 return; 1346 } 1347 } 1348 } 1349 #endif // def ENABLE_MULTICAST 1350 1351 static bool initCachedFields(JNIEnv* env) { 1352 memset(&gCachedFields, 0, sizeof(gCachedFields)); 1353 struct CachedFields *c = &gCachedFields; 1354 1355 struct classInfo { 1356 jclass *clazz; 1357 const char *name; 1358 } classes[] = { 1359 {&c->iaddr_class, "java/net/InetAddress"}, 1360 {&c->i4addr_class, "java/net/Inet4Address"}, 1361 {&c->genericipmreq_class, "org/apache/harmony/luni/net/GenericIPMreq"}, 1362 {&c->integer_class, "java/lang/Integer"}, 1363 {&c->boolean_class, "java/lang/Boolean"}, 1364 {&c->byte_class, "java/lang/Byte"}, 1365 {&c->socketimpl_class, "java/net/SocketImpl"}, 1366 {&c->dpack_class, "java/net/DatagramPacket"} 1367 }; 1368 for (unsigned i = 0; i < sizeof(classes) / sizeof(classes[0]); i++) { 1369 classInfo c = classes[i]; 1370 jclass tempClass = env->FindClass(c.name); 1371 if (tempClass == NULL) return false; 1372 *c.clazz = (jclass) env->NewGlobalRef(tempClass); 1373 } 1374 1375 struct methodInfo { 1376 jmethodID *method; 1377 jclass clazz; 1378 const char *name; 1379 const char *signature; 1380 bool isStatic; 1381 } methods[] = { 1382 {&c->i4addr_class_init, c->i4addr_class, "<init>", "([B)V", false}, 1383 {&c->integer_class_init, c->integer_class, "<init>", "(I)V", false}, 1384 {&c->boolean_class_init, c->boolean_class, "<init>", "(Z)V", false}, 1385 {&c->byte_class_init, c->byte_class, "<init>", "(B)V", false}, 1386 {&c->iaddr_getbyaddress, c->iaddr_class, "getByAddress", 1387 "([B)Ljava/net/InetAddress;", true} 1388 }; 1389 for (unsigned i = 0; i < sizeof(methods) / sizeof(methods[0]); i++) { 1390 methodInfo m = methods[i]; 1391 if (m.isStatic) { 1392 *m.method = env->GetStaticMethodID(m.clazz, m.name, m.signature); 1393 } else { 1394 *m.method = env->GetMethodID(m.clazz, m.name, m.signature); 1395 } 1396 if (*m.method == NULL) return false; 1397 } 1398 1399 struct fieldInfo { 1400 jfieldID *field; 1401 jclass clazz; 1402 const char *name; 1403 const char *type; 1404 } fields[] = { 1405 {&c->iaddr_ipaddress, c->iaddr_class, "ipaddress", "[B"}, 1406 {&c->integer_class_value, c->integer_class, "value", "I"}, 1407 {&c->boolean_class_value, c->boolean_class, "value", "Z"}, 1408 {&c->byte_class_value, c->byte_class, "value", "B"}, 1409 {&c->socketimpl_port, c->socketimpl_class, "port", "I"}, 1410 {&c->socketimpl_address, c->socketimpl_class, "address", 1411 "Ljava/net/InetAddress;"}, 1412 {&c->dpack_address, c->dpack_class, "address", 1413 "Ljava/net/InetAddress;"}, 1414 {&c->dpack_port, c->dpack_class, "port", "I"}, 1415 {&c->dpack_length, c->dpack_class, "length", "I"} 1416 }; 1417 for (unsigned i = 0; i < sizeof(fields) / sizeof(fields[0]); i++) { 1418 fieldInfo f = fields[i]; 1419 *f.field = env->GetFieldID(f.clazz, f.name, f.type); 1420 if (*f.field == NULL) return false; 1421 } 1422 return true; 1423 } 1424 1425 /** 1426 * Helper function to create a socket of the specified type and bind it to a 1427 * Java file descriptor. 1428 * 1429 * @param fileDescriptor the file descriptor to bind the socket to 1430 * @param type the socket type to create, e.g., SOCK_STREAM 1431 * @throws SocketException an error occurred when creating the socket 1432 * 1433 * @return the socket file descriptor. On failure, an exception is thrown and 1434 * a negative value is returned. 1435 * 1436 */ 1437 static int createSocketFileDescriptor(JNIEnv* env, jobject fileDescriptor, 1438 int type) { 1439 if (fileDescriptor == NULL) { 1440 jniThrowNullPointerException(env, NULL); 1441 errno = EBADF; 1442 return -1; 1443 } 1444 1445 int sock; 1446 sock = socket(PF_INET6, type, 0); 1447 if (sock < 0 && errno == EAFNOSUPPORT) { 1448 sock = socket(PF_INET, type, 0); 1449 } 1450 if (sock < 0) { 1451 jniThrowSocketException(env, errno); 1452 return sock; 1453 } 1454 jniSetFileDescriptorOfFD(env, fileDescriptor, sock); 1455 return sock; 1456 } 1457 1458 static void osNetworkSystem_createStreamSocketImpl(JNIEnv* env, jclass clazz, 1459 jobject fileDescriptor, jboolean preferIPv4Stack) { 1460 // LOGD("ENTER createSocketImpl"); 1461 createSocketFileDescriptor(env, fileDescriptor, SOCK_STREAM); 1462 } 1463 1464 static void osNetworkSystem_createDatagramSocketImpl(JNIEnv* env, jclass clazz, 1465 jobject fileDescriptor, jboolean preferIPv4Stack) { 1466 // LOGD("ENTER createDatagramSocketImpl"); 1467 createSocketFileDescriptor(env, fileDescriptor, SOCK_DGRAM); 1468 } 1469 1470 static jint osNetworkSystem_readSocketDirectImpl(JNIEnv* env, jclass clazz, 1471 jobject fileDescriptor, jint address, jint count, jint timeout) { 1472 // LOGD("ENTER readSocketDirectImpl"); 1473 1474 int fd; 1475 if (!jniGetFd(env, fileDescriptor, fd)) { 1476 return 0; 1477 } 1478 1479 if (timeout != 0) { 1480 int result = selectWait(fd, timeout * 1000); 1481 if (result < 0) { 1482 return 0; 1483 } 1484 } 1485 1486 jbyte* dst = reinterpret_cast<jbyte*>(static_cast<uintptr_t>(address)); 1487 ssize_t bytesReceived = 1488 TEMP_FAILURE_RETRY(recv(fd, dst, count, SOCKET_NOFLAGS)); 1489 if (bytesReceived == 0) { 1490 return -1; 1491 } else if (bytesReceived == -1) { 1492 if (errno == EAGAIN || errno == EWOULDBLOCK) { 1493 // We were asked to read a non-blocking socket with no data 1494 // available, so report "no bytes read". 1495 return 0; 1496 } else { 1497 jniThrowSocketException(env, errno); 1498 return 0; 1499 } 1500 } 1501 return bytesReceived; 1502 } 1503 1504 static jint osNetworkSystem_readSocketImpl(JNIEnv* env, jclass clazz, 1505 jobject fileDescriptor, jbyteArray byteArray, jint offset, jint count, 1506 jint timeout) { 1507 // LOGD("ENTER readSocketImpl"); 1508 1509 jbyte* bytes = env->GetByteArrayElements(byteArray, NULL); 1510 if (bytes == NULL) { 1511 return -1; 1512 } 1513 jint address = 1514 static_cast<jint>(reinterpret_cast<uintptr_t>(bytes + offset)); 1515 int result = osNetworkSystem_readSocketDirectImpl(env, clazz, 1516 fileDescriptor, address, count, timeout); 1517 env->ReleaseByteArrayElements(byteArray, bytes, 0); 1518 return result; 1519 } 1520 1521 static jint osNetworkSystem_writeSocketDirectImpl(JNIEnv* env, jclass clazz, 1522 jobject fileDescriptor, jint address, jint offset, jint count) { 1523 // LOGD("ENTER writeSocketDirectImpl"); 1524 1525 if (count <= 0) { 1526 return 0; 1527 } 1528 1529 int fd; 1530 if (!jniGetFd(env, fileDescriptor, fd)) { 1531 return 0; 1532 } 1533 1534 jbyte* message = reinterpret_cast<jbyte*>(static_cast<uintptr_t>(address + offset)); 1535 int bytesSent = send(fd, message, count, SOCKET_NOFLAGS); 1536 if (bytesSent == -1) { 1537 if (errno == EAGAIN || errno == EWOULDBLOCK) { 1538 // We were asked to write to a non-blocking socket, but were told 1539 // it would block, so report "no bytes written". 1540 return 0; 1541 } else { 1542 jniThrowSocketException(env, errno); 1543 return 0; 1544 } 1545 } 1546 return bytesSent; 1547 } 1548 1549 static jint osNetworkSystem_writeSocketImpl(JNIEnv* env, jclass clazz, 1550 jobject fileDescriptor, jbyteArray byteArray, jint offset, jint count) { 1551 // LOGD("ENTER writeSocketImpl"); 1552 1553 jbyte* bytes = env->GetByteArrayElements(byteArray, NULL); 1554 if (bytes == NULL) { 1555 return -1; 1556 } 1557 jint address = static_cast<jint>(reinterpret_cast<uintptr_t>(bytes)); 1558 int result = osNetworkSystem_writeSocketDirectImpl(env, clazz, 1559 fileDescriptor, address, offset, count); 1560 env->ReleaseByteArrayElements(byteArray, bytes, 0); 1561 return result; 1562 } 1563 1564 static void osNetworkSystem_setNonBlockingImpl(JNIEnv* env, jclass clazz, 1565 jobject fileDescriptor, jboolean nonblocking) { 1566 // LOGD("ENTER setNonBlockingImpl"); 1567 1568 int handle; 1569 if (!jniGetFd(env, fileDescriptor, handle)) { 1570 return; 1571 } 1572 1573 int block = nonblocking; 1574 int rc = ioctl(handle, FIONBIO, &block); 1575 if (rc == -1) { 1576 jniThrowSocketException(env, errno); 1577 } 1578 } 1579 1580 static jint osNetworkSystem_connectWithTimeoutSocketImpl(JNIEnv* env, 1581 jclass clazz, jobject fileDescriptor, jint timeout, jint trafficClass, 1582 jobject inetAddr, jint port, jint step, jbyteArray passContext) { 1583 // LOGD("ENTER connectWithTimeoutSocketImpl"); 1584 1585 sockaddr_storage address; 1586 if (!inetAddressToSocketAddress(env, inetAddr, port, &address)) { 1587 return -1; 1588 } 1589 1590 int handle; 1591 if (!jniGetFd(env, fileDescriptor, handle)) { 1592 return -1; 1593 } 1594 1595 jbyte* context = env->GetByteArrayElements(passContext, NULL); 1596 int result = 0; 1597 switch (step) { 1598 case SOCKET_CONNECT_STEP_START: 1599 result = sockConnectWithTimeout(handle, address, 0, 1600 SOCKET_STEP_START, context); 1601 break; 1602 case SOCKET_CONNECT_STEP_CHECK: 1603 result = sockConnectWithTimeout(handle, address, timeout, 1604 SOCKET_STEP_CHECK, context); 1605 break; 1606 default: 1607 assert(false); 1608 } 1609 env->ReleaseByteArrayElements(passContext, context, 0); 1610 1611 if (result == 0) { 1612 /* connected , so stop here */ 1613 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, NULL); 1614 } else if (result != SOCKERR_NOTCONNECTED) { 1615 /* can not connect... */ 1616 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, NULL); 1617 if (result == SOCKERR_EACCES) { 1618 jniThrowException(env, "java/lang/SecurityException", 1619 netLookupErrorString(result)); 1620 } else { 1621 jniThrowException(env, "java/net/ConnectException", 1622 netLookupErrorString(result)); 1623 } 1624 } 1625 1626 return result; 1627 } 1628 1629 static void osNetworkSystem_connectStreamWithTimeoutSocketImpl(JNIEnv* env, 1630 jclass clazz, jobject fileDescriptor, jint remotePort, jint timeout, 1631 jint trafficClass, jobject inetAddr) { 1632 // LOGD("ENTER connectStreamWithTimeoutSocketImpl"); 1633 1634 int result = 0; 1635 struct sockaddr_storage address; 1636 jbyte *context = NULL; 1637 int remainingTimeout = timeout; 1638 int passedTimeout = 0; 1639 int finishTime = 0; 1640 int blocking = 0; 1641 char hasTimeout = timeout > 0; 1642 1643 /* if a timeout was specified calculate the finish time value */ 1644 if (hasTimeout) { 1645 finishTime = time_msec_clock() + (int) timeout; 1646 } 1647 1648 int handle; 1649 if (!jniGetFd(env, fileDescriptor, handle)) { 1650 return; 1651 } 1652 1653 if (!inetAddressToSocketAddress(env, inetAddr, remotePort, &address)) { 1654 return; 1655 } 1656 1657 /* 1658 * we will be looping checking for when we are connected so allocate 1659 * the descriptor sets that we will use 1660 */ 1661 context =(jbyte *) malloc(sizeof(struct selectFDSet)); 1662 if (context == NULL) { 1663 jniThrowException(env, "java/lang/OutOfMemoryError", "native heap"); 1664 return; 1665 } 1666 1667 result = sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_START, context); 1668 if (0 == result) { 1669 /* ok we connected right away so we are done */ 1670 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, context); 1671 goto bail; 1672 } else if (result != SOCKERR_NOTCONNECTED) { 1673 sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, 1674 context); 1675 /* we got an error other than NOTCONNECTED so we cannot continue */ 1676 if (SOCKERR_EACCES == result) { 1677 jniThrowException(env, "java/lang/SecurityException", 1678 netLookupErrorString(result)); 1679 } else { 1680 throwSocketException(env, result); 1681 } 1682 goto bail; 1683 } 1684 1685 while (SOCKERR_NOTCONNECTED == result) { 1686 passedTimeout = remainingTimeout; 1687 1688 /* 1689 * ok now try and connect. Depending on the platform this may sleep 1690 * for up to passedTimeout milliseconds 1691 */ 1692 result = sockConnectWithTimeout(handle, address, passedTimeout, 1693 SOCKET_STEP_CHECK, context); 1694 1695 /* 1696 * now check if the socket is still connected. 1697 * Do it here as some platforms seem to think they 1698 * are connected if the socket is closed on them. 1699 */ 1700 handle = jniGetFDFromFileDescriptor(env, fileDescriptor); 1701 if (handle == -1) { 1702 sockConnectWithTimeout(handle, address, 0, 1703 SOCKET_STEP_DONE, context); 1704 jniThrowSocketException(env, EBADF); 1705 goto bail; 1706 } 1707 1708 /* 1709 * check if we are now connected, 1710 * if so we can finish the process and return 1711 */ 1712 if (0 == result) { 1713 sockConnectWithTimeout(handle, address, 0, 1714 SOCKET_STEP_DONE, context); 1715 goto bail; 1716 } 1717 1718 /* 1719 * if the error is SOCKERR_NOTCONNECTED then we have not yet 1720 * connected and we may not be done yet 1721 */ 1722 if (SOCKERR_NOTCONNECTED == result) { 1723 /* check if the timeout has expired */ 1724 if (hasTimeout) { 1725 remainingTimeout = finishTime - time_msec_clock(); 1726 if (remainingTimeout <= 0) { 1727 sockConnectWithTimeout(handle, address, 0, 1728 SOCKET_STEP_DONE, context); 1729 jniThrowSocketTimeoutException(env, ENOTCONN); 1730 goto bail; 1731 } 1732 } else { 1733 remainingTimeout = 100; 1734 } 1735 } else { 1736 sockConnectWithTimeout(handle, address, remainingTimeout, 1737 SOCKET_STEP_DONE, context); 1738 if ((SOCKERR_CONNRESET == result) || 1739 (SOCKERR_CONNECTION_REFUSED == result) || 1740 (SOCKERR_ADDRNOTAVAIL == result) || 1741 (SOCKERR_ADDRINUSE == result) || 1742 (SOCKERR_ENETUNREACH == result)) { 1743 jniThrowException(env, "java/net/ConnectException", 1744 netLookupErrorString(result)); 1745 } else if (SOCKERR_EACCES == result) { 1746 jniThrowException(env, "java/lang/SecurityException", 1747 netLookupErrorString(result)); 1748 } else { 1749 throwSocketException(env, result); 1750 } 1751 goto bail; 1752 } 1753 } 1754 1755 bail: 1756 1757 /* free the memory for the FD set */ 1758 if (context != NULL) { 1759 free(context); 1760 } 1761 } 1762 1763 static void osNetworkSystem_socketBindImpl(JNIEnv* env, jclass clazz, 1764 jobject fileDescriptor, jint port, jobject inetAddress) { 1765 // LOGD("ENTER socketBindImpl"); 1766 1767 sockaddr_storage socketAddress; 1768 if (!inetAddressToSocketAddress(env, inetAddress, port, &socketAddress)) { 1769 return; 1770 } 1771 1772 int fd; 1773 if (!jniGetFd(env, fileDescriptor, fd)) { 1774 return; 1775 } 1776 1777 sockaddr_storage tmp; 1778 const sockaddr* realAddress = convertIpv4ToMapped(fd, &socketAddress, &tmp, false); 1779 int rc = TEMP_FAILURE_RETRY(bind(fd, realAddress, sizeof(sockaddr_storage))); 1780 if (rc == -1) { 1781 jniThrowBindException(env, errno); 1782 } 1783 } 1784 1785 static void osNetworkSystem_listenStreamSocketImpl(JNIEnv* env, jclass clazz, 1786 jobject fileDescriptor, jint backlog) { 1787 // LOGD("ENTER listenStreamSocketImpl"); 1788 1789 int handle; 1790 if (!jniGetFd(env, fileDescriptor, handle)) { 1791 return; 1792 } 1793 1794 int rc = listen(handle, backlog); 1795 if (rc == -1) { 1796 jniThrowSocketException(env, errno); 1797 return; 1798 } 1799 } 1800 1801 static jint osNetworkSystem_availableStreamImpl(JNIEnv* env, jclass clazz, 1802 jobject fileDescriptor) { 1803 // LOGD("ENTER availableStreamImpl"); 1804 1805 int handle; 1806 if (!jniGetFd(env, fileDescriptor, handle)) { 1807 return 0; 1808 } 1809 1810 int result; 1811 do { 1812 result = selectWait(handle, 1); 1813 1814 if (SOCKERR_TIMEOUT == result) { 1815 // The read operation timed out, so answer 0 bytes available 1816 return 0; 1817 } else if (SOCKERR_INTERRUPTED == result) { 1818 continue; 1819 } else if (0 > result) { 1820 throwSocketException(env, result); 1821 return 0; 1822 } 1823 } while (SOCKERR_INTERRUPTED == result); 1824 1825 char message[2048]; 1826 result = recv(handle, (jbyte *) message, sizeof(message), MSG_PEEK); 1827 1828 if (0 > result) { 1829 jniThrowSocketException(env, errno); 1830 return 0; 1831 } 1832 return result; 1833 } 1834 1835 static void osNetworkSystem_acceptSocketImpl(JNIEnv* env, jclass, 1836 jobject serverFileDescriptor, 1837 jobject newSocket, jobject clientFileDescriptor, jint timeout) { 1838 // LOGD("ENTER acceptSocketImpl"); 1839 1840 if (newSocket == NULL) { 1841 jniThrowNullPointerException(env, NULL); 1842 return; 1843 } 1844 1845 int rc = pollSelectWait(env, serverFileDescriptor, timeout); 1846 if (rc < 0) { 1847 return; 1848 } 1849 1850 int serverFd; 1851 if (!jniGetFd(env, serverFileDescriptor, serverFd)) { 1852 return; 1853 } 1854 1855 sockaddr_storage sa; 1856 socklen_t addrlen = sizeof(sa); 1857 int clientFd = TEMP_FAILURE_RETRY(accept(serverFd, 1858 reinterpret_cast<sockaddr*>(&sa), &addrlen)); 1859 if (clientFd == -1) { 1860 jniThrowSocketException(env, errno); 1861 return; 1862 } 1863 1864 /* 1865 * For network sockets, put the peer address and port in instance variables. 1866 * We don't bother to do this for UNIX domain sockets, since most peers are 1867 * anonymous anyway. 1868 */ 1869 if (sa.ss_family == AF_INET || sa.ss_family == AF_INET6) { 1870 jobject inetAddress = socketAddressToInetAddress(env, &sa); 1871 if (inetAddress == NULL) { 1872 close(clientFd); 1873 return; 1874 } 1875 1876 env->SetObjectField(newSocket, 1877 gCachedFields.socketimpl_address, inetAddress); 1878 1879 int port = getSocketAddressPort(&sa); 1880 env->SetIntField(newSocket, gCachedFields.socketimpl_port, port); 1881 } 1882 1883 jniSetFileDescriptorOfFD(env, clientFileDescriptor, clientFd); 1884 } 1885 1886 static jboolean osNetworkSystem_supportsUrgentDataImpl(JNIEnv* env, 1887 jclass clazz, jobject fileDescriptor) { 1888 // LOGD("ENTER supportsUrgentDataImpl"); 1889 1890 // TODO(enh): do we really need to exclude the invalid file descriptor case? 1891 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 1892 return (fd == -1) ? JNI_FALSE : JNI_TRUE; 1893 } 1894 1895 static void osNetworkSystem_sendUrgentDataImpl(JNIEnv* env, jclass clazz, 1896 jobject fileDescriptor, jbyte value) { 1897 // LOGD("ENTER sendUrgentDataImpl"); 1898 1899 int handle; 1900 if (!jniGetFd(env, fileDescriptor, handle)) { 1901 return; 1902 } 1903 1904 int rc = send(handle, &value, 1, MSG_OOB); 1905 if (rc == -1) { 1906 jniThrowSocketException(env, errno); 1907 } 1908 } 1909 1910 static void osNetworkSystem_connectDatagramImpl2(JNIEnv* env, jclass, 1911 jobject fileDescriptor, jint port, jint trafficClass, jobject inetAddress) { 1912 // LOGD("ENTER connectDatagramImpl2"); 1913 1914 sockaddr_storage sockAddr; 1915 if (!inetAddressToSocketAddress(env, inetAddress, port, &sockAddr)) { 1916 return; 1917 } 1918 1919 int fd; 1920 if (!jniGetFd(env, fileDescriptor, fd)) { 1921 return; 1922 } 1923 1924 int ret = doConnect(fd, &sockAddr); 1925 if (ret < 0) { 1926 jniThrowSocketException(env, errno); 1927 } 1928 } 1929 1930 static void osNetworkSystem_disconnectDatagramImpl(JNIEnv* env, jclass, 1931 jobject fileDescriptor) { 1932 // LOGD("ENTER disconnectDatagramImpl"); 1933 1934 int fd; 1935 if (!jniGetFd(env, fileDescriptor, fd)) { 1936 return; 1937 } 1938 1939 sockaddr_storage sockAddr; 1940 memset(&sockAddr, 0, sizeof(sockAddr)); 1941 sockAddr.ss_family = AF_UNSPEC; 1942 1943 int result = doConnect(fd, &sockAddr); 1944 if (result < 0) { 1945 jniThrowSocketException(env, errno); 1946 } 1947 } 1948 1949 static void osNetworkSystem_setInetAddressImpl(JNIEnv* env, jobject, 1950 jobject sender, jbyteArray address) { 1951 // LOGD("ENTER setInetAddressImpl"); 1952 1953 env->SetObjectField(sender, gCachedFields.iaddr_ipaddress, address); 1954 } 1955 1956 static jint osNetworkSystem_peekDatagramImpl(JNIEnv* env, jclass clazz, 1957 jobject fileDescriptor, jobject sender, jint receiveTimeout) { 1958 // LOGD("ENTER peekDatagramImpl"); 1959 1960 int result = pollSelectWait(env, fileDescriptor, receiveTimeout); 1961 if (result < 0) { 1962 return 0; 1963 } 1964 1965 int fd; 1966 if (!jniGetFd(env, fileDescriptor, fd)) { 1967 return 0; 1968 } 1969 1970 sockaddr_storage sockAddr; 1971 socklen_t sockAddrLen = sizeof(sockAddr); 1972 ssize_t length = TEMP_FAILURE_RETRY(recvfrom(fd, NULL, 0, MSG_PEEK, 1973 reinterpret_cast<sockaddr*>(&sockAddr), &sockAddrLen)); 1974 if (length == -1) { 1975 jniThrowSocketException(env, errno); 1976 return 0; 1977 } 1978 1979 // We update the byte[] in the 'sender' InetAddress, and return the port. 1980 // This awful API is public in the RI, so there's no point returning 1981 // InetSocketAddress here instead. 1982 jbyteArray senderAddressArray = socketAddressToByteArray(env, &sockAddr); 1983 if (sender == NULL) { 1984 return -1; 1985 } 1986 osNetworkSystem_setInetAddressImpl(env, NULL, sender, senderAddressArray); 1987 return getSocketAddressPort(&sockAddr); 1988 } 1989 1990 static jint osNetworkSystem_receiveDatagramDirectImpl(JNIEnv* env, jclass clazz, 1991 jobject fileDescriptor, jobject packet, jint address, jint offset, 1992 jint length, jint receiveTimeout, jboolean peek) { 1993 // LOGD("ENTER receiveDatagramDirectImpl"); 1994 1995 int result = pollSelectWait(env, fileDescriptor, receiveTimeout); 1996 if (result < 0) { 1997 return 0; 1998 } 1999 2000 int fd; 2001 if (!jniGetFd(env, fileDescriptor, fd)) { 2002 return 0; 2003 } 2004 2005 char* buf = 2006 reinterpret_cast<char*>(static_cast<uintptr_t>(address + offset)); 2007 const int mode = peek ? MSG_PEEK : 0; 2008 sockaddr_storage sockAddr; 2009 socklen_t sockAddrLen = sizeof(sockAddr); 2010 ssize_t actualLength = TEMP_FAILURE_RETRY(recvfrom(fd, buf, length, mode, 2011 reinterpret_cast<sockaddr*>(&sockAddr), &sockAddrLen)); 2012 if (actualLength == -1) { 2013 jniThrowSocketException(env, errno); 2014 return 0; 2015 } 2016 2017 if (packet != NULL) { 2018 jbyteArray addr = socketAddressToByteArray(env, &sockAddr); 2019 if (addr == NULL) { 2020 return 0; 2021 } 2022 int port = getSocketAddressPort(&sockAddr); 2023 jobject sender = env->CallStaticObjectMethod( 2024 gCachedFields.iaddr_class, gCachedFields.iaddr_getbyaddress, 2025 addr); 2026 env->SetObjectField(packet, gCachedFields.dpack_address, sender); 2027 env->SetIntField(packet, gCachedFields.dpack_port, port); 2028 env->SetIntField(packet, gCachedFields.dpack_length, 2029 (jint) actualLength); 2030 } 2031 return (jint) actualLength; 2032 } 2033 2034 static jint osNetworkSystem_receiveDatagramImpl(JNIEnv* env, jclass clazz, 2035 jobject fd, jobject packet, jbyteArray data, jint offset, jint length, 2036 jint receiveTimeout, jboolean peek) { 2037 // LOGD("ENTER receiveDatagramImpl"); 2038 2039 int localLength = (length < 65536) ? length : 65536; 2040 jbyte *bytes = (jbyte*) malloc(localLength); 2041 if (bytes == NULL) { 2042 jniThrowException(env, "java/lang/OutOfMemoryError", 2043 "couldn't allocate enough memory for receiveDatagram"); 2044 return 0; 2045 } 2046 2047 int actualLength = osNetworkSystem_receiveDatagramDirectImpl(env, clazz, fd, 2048 packet, (jint)bytes, 0, localLength, receiveTimeout, peek); 2049 2050 if (actualLength > 0) { 2051 env->SetByteArrayRegion(data, offset, actualLength, bytes); 2052 } 2053 free(bytes); 2054 2055 return actualLength; 2056 } 2057 2058 static jint osNetworkSystem_recvConnectedDatagramDirectImpl(JNIEnv* env, 2059 jclass clazz, jobject fileDescriptor, jobject packet, 2060 jint address, jint offset, jint length, 2061 jint receiveTimeout, jboolean peek) { 2062 // LOGD("ENTER receiveConnectedDatagramDirectImpl"); 2063 2064 int result = pollSelectWait(env, fileDescriptor, receiveTimeout); 2065 if (result < 0) { 2066 return 0; 2067 } 2068 2069 int fd; 2070 if (!jniGetFd(env, fileDescriptor, fd)) { 2071 return 0; 2072 } 2073 2074 char* buf = reinterpret_cast<char*>(static_cast<uintptr_t>(address + offset)); 2075 int mode = peek ? MSG_PEEK : 0; 2076 int actualLength = recvfrom(fd, buf, length, mode, NULL, NULL); 2077 if (actualLength < 0) { 2078 jniThrowException(env, "java/net/PortUnreachableException", ""); 2079 return 0; 2080 } 2081 2082 if (packet != NULL) { 2083 env->SetIntField(packet, gCachedFields.dpack_length, actualLength); 2084 } 2085 return actualLength; 2086 } 2087 2088 static jint osNetworkSystem_recvConnectedDatagramImpl(JNIEnv* env, jclass clazz, 2089 jobject fd, jobject packet, jbyteArray data, jint offset, jint length, 2090 jint receiveTimeout, jboolean peek) { 2091 // LOGD("ENTER receiveConnectedDatagramImpl"); 2092 2093 int localLength = (length < 65536) ? length : 65536; 2094 jbyte *bytes = (jbyte*) malloc(localLength); 2095 if (bytes == NULL) { 2096 jniThrowException(env, "java/lang/OutOfMemoryError", 2097 "couldn't allocate enough memory for recvConnectedDatagram"); 2098 return 0; 2099 } 2100 2101 int actualLength = osNetworkSystem_recvConnectedDatagramDirectImpl(env, 2102 clazz, fd, packet, (jint)bytes, 0, localLength, 2103 receiveTimeout, peek); 2104 2105 if (actualLength > 0) { 2106 env->SetByteArrayRegion(data, offset, actualLength, bytes); 2107 } 2108 free(bytes); 2109 2110 return actualLength; 2111 } 2112 2113 static jint osNetworkSystem_sendDatagramDirectImpl(JNIEnv* env, jclass clazz, 2114 jobject fileDescriptor, jint address, jint offset, jint length, 2115 jint port, 2116 jboolean bindToDevice, jint trafficClass, jobject inetAddress) { 2117 // LOGD("ENTER sendDatagramDirectImpl"); 2118 2119 int fd; 2120 if (!jniGetFd(env, fileDescriptor, fd)) { 2121 return -1; 2122 } 2123 2124 sockaddr_storage receiver; 2125 if (!inetAddressToSocketAddress(env, inetAddress, port, &receiver)) { 2126 return -1; 2127 } 2128 2129 char* buf = 2130 reinterpret_cast<char*>(static_cast<uintptr_t>(address + offset)); 2131 ssize_t bytesSent = TEMP_FAILURE_RETRY(sendto(fd, buf, length, 2132 SOCKET_NOFLAGS, 2133 reinterpret_cast<sockaddr*>(&receiver), sizeof(receiver))); 2134 if (bytesSent == -1) { 2135 if (errno == ECONNRESET || errno == ECONNREFUSED) { 2136 return 0; 2137 } else { 2138 jniThrowSocketException(env, errno); 2139 } 2140 } 2141 return bytesSent; 2142 } 2143 2144 static jint osNetworkSystem_sendDatagramImpl(JNIEnv* env, jclass clazz, 2145 jobject fd, jbyteArray data, jint offset, jint length, jint port, 2146 jboolean bindToDevice, jint trafficClass, jobject inetAddress) { 2147 // LOGD("ENTER sendDatagramImpl"); 2148 2149 jbyte *bytes = env->GetByteArrayElements(data, NULL); 2150 int actualLength = osNetworkSystem_sendDatagramDirectImpl(env, clazz, fd, 2151 (jint)bytes, offset, length, port, bindToDevice, trafficClass, 2152 inetAddress); 2153 env->ReleaseByteArrayElements(data, bytes, JNI_ABORT); 2154 2155 return actualLength; 2156 } 2157 2158 static jint osNetworkSystem_sendConnectedDatagramDirectImpl(JNIEnv* env, 2159 jclass clazz, jobject fileDescriptor, 2160 jint address, jint offset, jint length, 2161 jboolean bindToDevice) { 2162 // LOGD("ENTER sendConnectedDatagramDirectImpl"); 2163 2164 int fd; 2165 if (!jniGetFd(env, fileDescriptor, fd)) { 2166 return 0; 2167 } 2168 2169 char* buf = 2170 reinterpret_cast<char*>(static_cast<uintptr_t>(address + offset)); 2171 ssize_t bytesSent = TEMP_FAILURE_RETRY(send(fd, buf, length, 0)); 2172 if (bytesSent == -1) { 2173 if (errno == ECONNRESET || errno == ECONNREFUSED) { 2174 return 0; 2175 } else { 2176 jniThrowSocketException(env, errno); 2177 } 2178 } 2179 return bytesSent; 2180 } 2181 2182 static jint osNetworkSystem_sendConnectedDatagramImpl(JNIEnv* env, jclass clazz, 2183 jobject fd, jbyteArray data, jint offset, jint length, 2184 jboolean bindToDevice) { 2185 // LOGD("ENTER sendConnectedDatagramImpl"); 2186 2187 jbyte *bytes = env->GetByteArrayElements(data, NULL); 2188 int actualLength = osNetworkSystem_sendConnectedDatagramDirectImpl(env, 2189 clazz, fd, (jint)bytes, offset, length, bindToDevice); 2190 env->ReleaseByteArrayElements(data, bytes, JNI_ABORT); 2191 2192 return actualLength; 2193 } 2194 2195 static void osNetworkSystem_createServerStreamSocketImpl(JNIEnv* env, 2196 jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) { 2197 // LOGD("ENTER createServerStreamSocketImpl"); 2198 2199 int handle = createSocketFileDescriptor(env, fileDescriptor, SOCK_STREAM); 2200 if (handle < 0) { 2201 return; 2202 } 2203 2204 int value = 1; 2205 setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int)); 2206 } 2207 2208 static void doShutdown(JNIEnv* env, jobject fileDescriptor, int how) { 2209 int fd; 2210 if (!jniGetFd(env, fileDescriptor, fd)) { 2211 return; 2212 } 2213 int rc = shutdown(fd, how); 2214 if (rc == -1) { 2215 jniThrowSocketException(env, errno); 2216 } 2217 } 2218 2219 static void osNetworkSystem_shutdownInputImpl(JNIEnv* env, jobject, 2220 jobject fileDescriptor) { 2221 doShutdown(env, fileDescriptor, SHUT_RD); 2222 } 2223 2224 static void osNetworkSystem_shutdownOutputImpl(JNIEnv* env, jobject, 2225 jobject fileDescriptor) { 2226 doShutdown(env, fileDescriptor, SHUT_WR); 2227 } 2228 2229 static jint osNetworkSystem_sendDatagramImpl2(JNIEnv* env, jclass clazz, 2230 jobject fileDescriptor, jbyteArray data, jint offset, jint length, 2231 jint port, jobject inetAddress) { 2232 // LOGD("ENTER sendDatagramImpl2"); 2233 2234 sockaddr_storage sockAddr; 2235 if (inetAddress != NULL) { 2236 if (!inetAddressToSocketAddress(env, inetAddress, port, &sockAddr)) { 2237 return -1; 2238 } 2239 } 2240 2241 int fd; 2242 if (!jniGetFd(env, fileDescriptor, fd)) { 2243 return 0; 2244 } 2245 2246 jbyte* message = (jbyte*) malloc(length * sizeof(jbyte)); 2247 if (message == NULL) { 2248 jniThrowException(env, "java/lang/OutOfMemoryError", 2249 "couldn't allocate enough memory for readSocket"); 2250 return 0; 2251 } 2252 2253 env->GetByteArrayRegion(data, offset, length, message); 2254 2255 int totalBytesSent = 0; 2256 while (totalBytesSent < length) { 2257 ssize_t bytesSent = TEMP_FAILURE_RETRY(sendto(fd, 2258 message + totalBytesSent, length - totalBytesSent, 2259 SOCKET_NOFLAGS, 2260 reinterpret_cast<sockaddr*>(&sockAddr), sizeof(sockAddr))); 2261 if (bytesSent == -1) { 2262 jniThrowSocketException(env, errno); 2263 free(message); 2264 return 0; 2265 } 2266 2267 totalBytesSent += bytesSent; 2268 } 2269 2270 free(message); 2271 return totalBytesSent; 2272 } 2273 2274 static bool initFdSet(JNIEnv* env, jobjectArray fdArray, jint count, fd_set* fdSet, int* maxFd) { 2275 for (int i = 0; i < count; ++i) { 2276 jobject fileDescriptor = env->GetObjectArrayElement(fdArray, i); 2277 if (fileDescriptor == NULL) { 2278 return false; 2279 } 2280 2281 const int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 2282 if (fd < 0 || fd > 1024) { 2283 LOGE("selectImpl: ignoring invalid fd %i", fd); 2284 continue; 2285 } 2286 2287 FD_SET(fd, fdSet); 2288 2289 if (fd > *maxFd) { 2290 *maxFd = fd; 2291 } 2292 } 2293 return true; 2294 } 2295 2296 /* 2297 * Note: fdSet has to be non-const because although on Linux FD_ISSET() is sane 2298 * and takes a const fd_set*, it takes fd_set* on Mac OS. POSIX is not on our 2299 * side here: 2300 * http://www.opengroup.org/onlinepubs/000095399/functions/select.html 2301 */ 2302 static bool translateFdSet(JNIEnv* env, jobjectArray fdArray, jint count, fd_set& fdSet, jint* flagArray, size_t offset, jint op) { 2303 for (int i = 0; i < count; ++i) { 2304 jobject fileDescriptor = env->GetObjectArrayElement(fdArray, i); 2305 if (fileDescriptor == NULL) { 2306 return false; 2307 } 2308 2309 const int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 2310 const bool valid = fd >= 0 && fd < 1024; 2311 2312 if (valid && FD_ISSET(fd, &fdSet)) { 2313 flagArray[i + offset] = op; 2314 } else { 2315 flagArray[i + offset] = SOCKET_OP_NONE; 2316 } 2317 } 2318 return true; 2319 } 2320 2321 static jboolean osNetworkSystem_selectImpl(JNIEnv* env, jclass clazz, 2322 jobjectArray readFDArray, jobjectArray writeFDArray, jint countReadC, 2323 jint countWriteC, jintArray outFlags, jlong timeoutMs) { 2324 // LOGD("ENTER selectImpl"); 2325 2326 // Initialize the fd_sets. 2327 int maxFd = -1; 2328 fd_set readFds; 2329 fd_set writeFds; 2330 FD_ZERO(&readFds); 2331 FD_ZERO(&writeFds); 2332 bool initialized = initFdSet(env, readFDArray, countReadC, &readFds, &maxFd) && 2333 initFdSet(env, writeFDArray, countWriteC, &writeFds, &maxFd); 2334 if (!initialized) { 2335 return -1; 2336 } 2337 2338 // Initialize the timeout, if any. 2339 timeval tv; 2340 timeval* tvp = NULL; 2341 if (timeoutMs >= 0) { 2342 tv = toTimeval(timeoutMs); 2343 tvp = &tv; 2344 } 2345 2346 // Perform the select. 2347 int result = select(maxFd + 1, &readFds, &writeFds, NULL, tvp); 2348 if (result == 0) { 2349 // Timeout. 2350 return JNI_FALSE; 2351 } else if (result == -1) { 2352 // Error. 2353 if (errno == EINTR) { 2354 return JNI_FALSE; 2355 } else { 2356 jniThrowSocketException(env, errno); 2357 return JNI_FALSE; 2358 } 2359 } 2360 2361 // Translate the result into the int[] we're supposed to fill in. 2362 jint* flagArray = env->GetIntArrayElements(outFlags, NULL); 2363 if (flagArray == NULL) { 2364 return JNI_FALSE; 2365 } 2366 bool okay = translateFdSet(env, readFDArray, countReadC, readFds, flagArray, 0, SOCKET_OP_READ) && 2367 translateFdSet(env, writeFDArray, countWriteC, writeFds, flagArray, countReadC, SOCKET_OP_WRITE); 2368 env->ReleaseIntArrayElements(outFlags, flagArray, 0); 2369 return okay; 2370 } 2371 2372 static jobject osNetworkSystem_getSocketLocalAddressImpl(JNIEnv* env, 2373 jclass, jobject fileDescriptor) { 2374 // LOGD("ENTER getSocketLocalAddressImpl"); 2375 2376 int fd; 2377 if (!jniGetFd(env, fileDescriptor, fd)) { 2378 return NULL; 2379 } 2380 2381 sockaddr_storage addr; 2382 socklen_t addrLen = sizeof(addr); 2383 memset(&addr, 0, addrLen); 2384 int rc = getsockname(fd, (sockaddr*) &addr, &addrLen); 2385 if (rc == -1) { 2386 // TODO: the public API doesn't allow failure, so this whole method 2387 // represents a broken design. In practice, though, getsockname can't 2388 // fail unless we give it invalid arguments. 2389 LOGE("getsockname failed: %s (errno=%i)", strerror(errno), errno); 2390 return NULL; 2391 } 2392 return socketAddressToInetAddress(env, &addr); 2393 } 2394 2395 static jint osNetworkSystem_getSocketLocalPortImpl(JNIEnv* env, jclass, 2396 jobject fileDescriptor) { 2397 // LOGD("ENTER getSocketLocalPortImpl"); 2398 2399 int fd; 2400 if (!jniGetFd(env, fileDescriptor, fd)) { 2401 return 0; 2402 } 2403 2404 sockaddr_storage addr; 2405 socklen_t addrLen = sizeof(addr); 2406 memset(&addr, 0, addrLen); 2407 int rc = getsockname(fd, (sockaddr*) &addr, &addrLen); 2408 if (rc == -1) { 2409 // TODO: the public API doesn't allow failure, so this whole method 2410 // represents a broken design. In practice, though, getsockname can't 2411 // fail unless we give it invalid arguments. 2412 LOGE("getsockname failed: %s (errno=%i)", strerror(errno), errno); 2413 return 0; 2414 } 2415 return getSocketAddressPort(&addr); 2416 } 2417 2418 static jobject osNetworkSystem_getSocketOptionImpl(JNIEnv* env, jclass clazz, 2419 jobject fileDescriptor, jint anOption) { 2420 // LOGD("ENTER getSocketOptionImpl"); 2421 2422 int intValue = 0; 2423 socklen_t intSize = sizeof(int); 2424 int result; 2425 struct sockaddr_storage sockVal; 2426 socklen_t sockSize = sizeof(sockVal); 2427 2428 int handle; 2429 if (!jniGetFd(env, fileDescriptor, handle)) { 2430 return 0; 2431 } 2432 2433 switch ((int) anOption & 0xffff) { 2434 case JAVASOCKOPT_SO_LINGER: { 2435 struct linger lingr; 2436 socklen_t size = sizeof(struct linger); 2437 result = getsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr, &size); 2438 if (0 != result) { 2439 jniThrowSocketException(env, errno); 2440 return NULL; 2441 } 2442 if (!lingr.l_onoff) { 2443 intValue = -1; 2444 } else { 2445 intValue = lingr.l_linger; 2446 } 2447 return newJavaLangInteger(env, intValue); 2448 } 2449 2450 case JAVASOCKOPT_TCP_NODELAY: { 2451 if ((anOption >> 16) & BROKEN_TCP_NODELAY) { 2452 return NULL; 2453 } 2454 result = getsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intValue, &intSize); 2455 if (0 != result) { 2456 jniThrowSocketException(env, errno); 2457 return NULL; 2458 } 2459 return newJavaLangBoolean(env, intValue); 2460 } 2461 2462 case JAVASOCKOPT_SO_SNDBUF: { 2463 result = getsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intValue, &intSize); 2464 if (0 != result) { 2465 jniThrowSocketException(env, errno); 2466 return NULL; 2467 } 2468 return newJavaLangInteger(env, intValue); 2469 } 2470 2471 case JAVASOCKOPT_SO_RCVBUF: { 2472 result = getsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intValue, &intSize); 2473 if (0 != result) { 2474 jniThrowSocketException(env, errno); 2475 return NULL; 2476 } 2477 return newJavaLangInteger(env, intValue); 2478 } 2479 2480 case JAVASOCKOPT_SO_BROADCAST: { 2481 result = getsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intValue, &intSize); 2482 if (0 != result) { 2483 jniThrowSocketException(env, errno); 2484 return NULL; 2485 } 2486 return newJavaLangBoolean(env, intValue); 2487 } 2488 2489 case JAVASOCKOPT_SO_REUSEADDR: { 2490 result = getsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intValue, &intSize); 2491 if (0 != result) { 2492 jniThrowSocketException(env, errno); 2493 return NULL; 2494 } 2495 return newJavaLangBoolean(env, intValue); 2496 } 2497 2498 case JAVASOCKOPT_SO_KEEPALIVE: { 2499 result = getsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intValue, &intSize); 2500 if (0 != result) { 2501 jniThrowSocketException(env, errno); 2502 return NULL; 2503 } 2504 return newJavaLangBoolean(env, intValue); 2505 } 2506 2507 case JAVASOCKOPT_SO_OOBINLINE: { 2508 result = getsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intValue, &intSize); 2509 if (0 != result) { 2510 jniThrowSocketException(env, errno); 2511 return NULL; 2512 } 2513 return newJavaLangBoolean(env, intValue); 2514 } 2515 2516 case JAVASOCKOPT_IP_TOS: { 2517 result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_TOS, 2518 IPV6_TCLASS, &intValue, &intSize); 2519 if (0 != result) { 2520 jniThrowSocketException(env, errno); 2521 return NULL; 2522 } 2523 return newJavaLangInteger(env, intValue); 2524 } 2525 2526 case JAVASOCKOPT_SO_RCVTIMEOUT: { 2527 struct timeval timeout; 2528 socklen_t size = sizeof(timeout); 2529 result = getsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout, &size); 2530 if (0 != result) { 2531 jniThrowSocketException(env, errno); 2532 return NULL; 2533 } 2534 return newJavaLangInteger(env, toMs(timeout)); 2535 } 2536 2537 #ifdef ENABLE_MULTICAST 2538 case JAVASOCKOPT_MCAST_TTL: { 2539 if ((anOption >> 16) & BROKEN_MULTICAST_TTL) { 2540 return newJavaLangByte(env, 0); 2541 } 2542 // Java uses a byte to store the TTL, but the kernel uses an int. 2543 result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_MULTICAST_TTL, 2544 IPV6_MULTICAST_HOPS, &intValue, 2545 &intSize); 2546 if (0 != result) { 2547 jniThrowSocketException(env, errno); 2548 return NULL; 2549 } 2550 return newJavaLangByte(env, (jbyte)(intValue & 0xFF)); 2551 } 2552 2553 case JAVASOCKOPT_IP_MULTICAST_IF: { 2554 if ((anOption >> 16) & BROKEN_MULTICAST_IF) { 2555 return NULL; 2556 } 2557 result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, 2558 &sockVal, &sockSize); 2559 if (result == -1) { 2560 jniThrowSocketException(env, errno); 2561 return NULL; 2562 } 2563 if (sockVal.ss_family != AF_INET) { 2564 // Java expects an AF_INET INADDR_ANY, but Linux just returns AF_UNSPEC. 2565 jbyteArray inAddrAny = env->NewByteArray(4); // { 0, 0, 0, 0 } 2566 return byteArrayToInetAddress(env, inAddrAny); 2567 } 2568 return socketAddressToInetAddress(env, &sockVal); 2569 } 2570 2571 case JAVASOCKOPT_IP_MULTICAST_IF2: { 2572 if ((anOption >> 16) & BROKEN_MULTICAST_IF) { 2573 return NULL; 2574 } 2575 struct ip_mreqn multicastRequest; 2576 int interfaceIndex = 0; 2577 socklen_t optionLength; 2578 int addressFamily = getSocketAddressFamily(handle); 2579 switch (addressFamily) { 2580 case AF_INET: 2581 optionLength = sizeof(multicastRequest); 2582 result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, 2583 &multicastRequest, &optionLength); 2584 if (result == 0) 2585 interfaceIndex = multicastRequest.imr_ifindex; 2586 break; 2587 case AF_INET6: 2588 optionLength = sizeof(interfaceIndex); 2589 result = getsockopt(handle, IPPROTO_IPV6, IPV6_MULTICAST_IF, 2590 &interfaceIndex, &optionLength); 2591 break; 2592 default: 2593 jniThrowSocketException(env, EAFNOSUPPORT); 2594 return NULL; 2595 } 2596 2597 if (0 != result) { 2598 jniThrowSocketException(env, errno); 2599 return NULL; 2600 } 2601 return newJavaLangInteger(env, interfaceIndex); 2602 } 2603 2604 case JAVASOCKOPT_IP_MULTICAST_LOOP: { 2605 result = getOrSetSocketOption(SOCKOPT_GET, handle, 2606 IP_MULTICAST_LOOP, 2607 IPV6_MULTICAST_LOOP, &intValue, 2608 &intSize); 2609 if (0 != result) { 2610 jniThrowSocketException(env, errno); 2611 return NULL; 2612 } 2613 return newJavaLangBoolean(env, intValue); 2614 } 2615 #else 2616 case JAVASOCKOPT_MCAST_TTL: 2617 case JAVASOCKOPT_IP_MULTICAST_IF: 2618 case JAVASOCKOPT_IP_MULTICAST_IF2: 2619 case JAVASOCKOPT_IP_MULTICAST_LOOP: { 2620 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL); 2621 return NULL; 2622 } 2623 #endif // def ENABLE_MULTICAST 2624 2625 default: { 2626 jniThrowSocketException(env, ENOPROTOOPT); 2627 return NULL; 2628 } 2629 } 2630 2631 } 2632 2633 static void osNetworkSystem_setSocketOptionImpl(JNIEnv* env, jclass clazz, 2634 jobject fileDescriptor, jint anOption, jobject optVal) { 2635 // LOGD("ENTER setSocketOptionImpl"); 2636 2637 int result; 2638 int intVal; 2639 socklen_t intSize = sizeof(int); 2640 struct sockaddr_storage sockVal; 2641 int sockSize = sizeof(sockVal); 2642 2643 if (env->IsInstanceOf(optVal, gCachedFields.integer_class)) { 2644 intVal = (int) env->GetIntField(optVal, gCachedFields.integer_class_value); 2645 } else if (env->IsInstanceOf(optVal, gCachedFields.boolean_class)) { 2646 intVal = (int) env->GetBooleanField(optVal, gCachedFields.boolean_class_value); 2647 } else if (env->IsInstanceOf(optVal, gCachedFields.byte_class)) { 2648 // TTL uses a byte in Java, but the kernel still wants an int. 2649 intVal = (int) env->GetByteField(optVal, gCachedFields.byte_class_value); 2650 } else if (env->IsInstanceOf(optVal, gCachedFields.iaddr_class)) { 2651 if (!inetAddressToSocketAddress(env, optVal, 0, &sockVal)) { 2652 return; 2653 } 2654 } else if (env->IsInstanceOf(optVal, gCachedFields.genericipmreq_class)) { 2655 // we'll use optVal directly 2656 } else { 2657 jniThrowSocketException(env, ENOPROTOOPT); 2658 return; 2659 } 2660 2661 int handle; 2662 if (!jniGetFd(env, fileDescriptor, handle)) { 2663 return; 2664 } 2665 2666 switch ((int) anOption & 0xffff) { 2667 case JAVASOCKOPT_SO_LINGER: { 2668 struct linger lingr; 2669 lingr.l_onoff = intVal > 0 ? 1 : 0; 2670 lingr.l_linger = intVal; 2671 result = setsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr, 2672 sizeof(struct linger)); 2673 if (0 != result) { 2674 jniThrowSocketException(env, errno); 2675 return; 2676 } 2677 break; 2678 } 2679 2680 case JAVASOCKOPT_TCP_NODELAY: { 2681 if ((anOption >> 16) & BROKEN_TCP_NODELAY) { 2682 return; 2683 } 2684 result = setsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intVal, intSize); 2685 if (0 != result) { 2686 jniThrowSocketException(env, errno); 2687 return; 2688 } 2689 break; 2690 } 2691 2692 case JAVASOCKOPT_SO_SNDBUF: { 2693 result = setsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intVal, intSize); 2694 if (0 != result) { 2695 jniThrowSocketException(env, errno); 2696 return; 2697 } 2698 break; 2699 } 2700 2701 case JAVASOCKOPT_SO_RCVBUF: { 2702 result = setsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intVal, intSize); 2703 if (0 != result) { 2704 jniThrowSocketException(env, errno); 2705 return; 2706 } 2707 break; 2708 } 2709 2710 case JAVASOCKOPT_SO_BROADCAST: { 2711 result = setsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intVal, intSize); 2712 if (0 != result) { 2713 jniThrowSocketException(env, errno); 2714 return; 2715 } 2716 break; 2717 } 2718 2719 case JAVASOCKOPT_SO_REUSEADDR: { 2720 result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize); 2721 if (0 != result) { 2722 jniThrowSocketException(env, errno); 2723 return; 2724 } 2725 break; 2726 } 2727 case JAVASOCKOPT_SO_KEEPALIVE: { 2728 result = setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intVal, intSize); 2729 if (0 != result) { 2730 jniThrowSocketException(env, errno); 2731 return; 2732 } 2733 break; 2734 } 2735 2736 case JAVASOCKOPT_SO_OOBINLINE: { 2737 result = setsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intVal, intSize); 2738 if (0 != result) { 2739 jniThrowSocketException(env, errno); 2740 return; 2741 } 2742 break; 2743 } 2744 2745 case JAVASOCKOPT_IP_TOS: { 2746 result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_TOS, 2747 IPV6_TCLASS, &intVal, &intSize); 2748 if (0 != result) { 2749 jniThrowSocketException(env, errno); 2750 return; 2751 } 2752 break; 2753 } 2754 2755 case JAVASOCKOPT_REUSEADDR_AND_REUSEPORT: { 2756 // SO_REUSEPORT doesn't need to get set on this System 2757 result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize); 2758 if (0 != result) { 2759 jniThrowSocketException(env, errno); 2760 return; 2761 } 2762 break; 2763 } 2764 2765 case JAVASOCKOPT_SO_RCVTIMEOUT: { 2766 timeval timeout(toTimeval(intVal)); 2767 result = setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout, 2768 sizeof(struct timeval)); 2769 if (0 != result) { 2770 jniThrowSocketException(env, errno); 2771 return; 2772 } 2773 break; 2774 } 2775 2776 #ifdef ENABLE_MULTICAST 2777 case JAVASOCKOPT_MCAST_TTL: { 2778 if ((anOption >> 16) & BROKEN_MULTICAST_TTL) { 2779 return; 2780 } 2781 result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_MULTICAST_TTL, 2782 IPV6_MULTICAST_HOPS, &intVal, 2783 &intSize); 2784 if (0 != result) { 2785 jniThrowSocketException(env, errno); 2786 return; 2787 } 2788 break; 2789 } 2790 2791 case JAVASOCKOPT_MCAST_ADD_MEMBERSHIP: { 2792 mcastAddDropMembership(env, handle, optVal, 2793 (anOption >> 16) & BROKEN_MULTICAST_IF, IP_ADD_MEMBERSHIP); 2794 break; 2795 } 2796 2797 case JAVASOCKOPT_MCAST_DROP_MEMBERSHIP: { 2798 mcastAddDropMembership(env, handle, optVal, 2799 (anOption >> 16) & BROKEN_MULTICAST_IF, IP_DROP_MEMBERSHIP); 2800 break; 2801 } 2802 2803 case JAVASOCKOPT_IP_MULTICAST_IF: { 2804 if ((anOption >> 16) & BROKEN_MULTICAST_IF) { 2805 return; 2806 } 2807 // This call is IPv4 only. The socket may be IPv6, but the address 2808 // that identifies the interface to join must be an IPv4 address. 2809 if (sockVal.ss_family != AF_INET) { 2810 jniThrowSocketException(env, EAFNOSUPPORT); 2811 return; 2812 } 2813 struct ip_mreqn mcast_req; 2814 memset(&mcast_req, 0, sizeof(mcast_req)); 2815 struct sockaddr_in *sin = (struct sockaddr_in *) &sockVal; 2816 mcast_req.imr_address = sin->sin_addr; 2817 result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, 2818 &mcast_req, sizeof(mcast_req)); 2819 if (0 != result) { 2820 jniThrowSocketException(env, errno); 2821 return; 2822 } 2823 break; 2824 } 2825 2826 case JAVASOCKOPT_IP_MULTICAST_IF2: { 2827 if ((anOption >> 16) & BROKEN_MULTICAST_IF) { 2828 return; 2829 } 2830 int addressFamily = getSocketAddressFamily(handle); 2831 int interfaceIndex = intVal; 2832 void *optionValue; 2833 socklen_t optionLength; 2834 struct ip_mreqn multicastRequest; 2835 switch (addressFamily) { 2836 case AF_INET: 2837 // IP_MULTICAST_IF expects a pointer to a struct ip_mreqn. 2838 memset(&multicastRequest, 0, sizeof(multicastRequest)); 2839 multicastRequest.imr_ifindex = interfaceIndex; 2840 optionValue = &multicastRequest; 2841 optionLength = sizeof(multicastRequest); 2842 break; 2843 case AF_INET6: 2844 // IPV6_MULTICAST_IF expects a pointer to an integer. 2845 optionValue = &interfaceIndex; 2846 optionLength = sizeof(interfaceIndex); 2847 break; 2848 default: 2849 jniThrowSocketException(env, EAFNOSUPPORT); 2850 return; 2851 } 2852 result = getOrSetSocketOption(SOCKOPT_SET, handle, 2853 IP_MULTICAST_IF, IPV6_MULTICAST_IF, optionValue, 2854 &optionLength); 2855 if (0 != result) { 2856 jniThrowSocketException(env, errno); 2857 return; 2858 } 2859 break; 2860 } 2861 2862 case JAVASOCKOPT_IP_MULTICAST_LOOP: { 2863 result = getOrSetSocketOption(SOCKOPT_SET, handle, 2864 IP_MULTICAST_LOOP, 2865 IPV6_MULTICAST_LOOP, &intVal, 2866 &intSize); 2867 if (0 != result) { 2868 jniThrowSocketException(env, errno); 2869 return; 2870 } 2871 break; 2872 } 2873 #else 2874 case JAVASOCKOPT_MCAST_TTL: 2875 case JAVASOCKOPT_MCAST_ADD_MEMBERSHIP: 2876 case JAVASOCKOPT_MCAST_DROP_MEMBERSHIP: 2877 case JAVASOCKOPT_IP_MULTICAST_IF: 2878 case JAVASOCKOPT_IP_MULTICAST_IF2: 2879 case JAVASOCKOPT_IP_MULTICAST_LOOP: { 2880 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL); 2881 return; 2882 } 2883 #endif // def ENABLE_MULTICAST 2884 2885 default: { 2886 jniThrowSocketException(env, ENOPROTOOPT); 2887 } 2888 } 2889 } 2890 2891 static jint osNetworkSystem_getSocketFlagsImpl(JNIEnv* env, jclass clazz) { 2892 // LOGD("ENTER getSocketFlagsImpl"); 2893 2894 // Not implemented by harmony 2895 return 0; 2896 } 2897 2898 static void osNetworkSystem_socketCloseImpl(JNIEnv* env, jclass clazz, 2899 jobject fileDescriptor) { 2900 // LOGD("ENTER socketCloseImpl"); 2901 2902 int fd; 2903 if (!jniGetFd(env, fileDescriptor, fd)) { 2904 return; 2905 } 2906 2907 jniSetFileDescriptorOfFD(env, fileDescriptor, -1); 2908 2909 close(fd); 2910 } 2911 2912 static jobject osNetworkSystem_inheritedChannel(JNIEnv* env, jobject obj) { 2913 // Android never has stdin/stdout connected to a socket. 2914 return NULL; 2915 } 2916 2917 /* 2918 * JNI registration. 2919 */ 2920 static JNINativeMethod gMethods[] = { 2921 /* name, signature, funcPtr */ 2922 { "createStreamSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createStreamSocketImpl }, 2923 { "createDatagramSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createDatagramSocketImpl }, 2924 { "readSocketImpl", "(Ljava/io/FileDescriptor;[BIII)I", (void*) osNetworkSystem_readSocketImpl }, 2925 { "readSocketDirectImpl", "(Ljava/io/FileDescriptor;III)I", (void*) osNetworkSystem_readSocketDirectImpl }, 2926 { "writeSocketImpl", "(Ljava/io/FileDescriptor;[BII)I", (void*) osNetworkSystem_writeSocketImpl }, 2927 { "writeSocketDirectImpl", "(Ljava/io/FileDescriptor;III)I", (void*) osNetworkSystem_writeSocketDirectImpl }, 2928 { "setNonBlockingImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_setNonBlockingImpl }, 2929 { "connectWithTimeoutSocketImpl", "(Ljava/io/FileDescriptor;IILjava/net/InetAddress;II[B)I", (void*) osNetworkSystem_connectWithTimeoutSocketImpl }, 2930 { "connectStreamWithTimeoutSocketImpl","(Ljava/io/FileDescriptor;IIILjava/net/InetAddress;)V", (void*) osNetworkSystem_connectStreamWithTimeoutSocketImpl }, 2931 { "socketBindImpl", "(Ljava/io/FileDescriptor;ILjava/net/InetAddress;)V", (void*) osNetworkSystem_socketBindImpl }, 2932 { "listenStreamSocketImpl", "(Ljava/io/FileDescriptor;I)V", (void*) osNetworkSystem_listenStreamSocketImpl }, 2933 { "availableStreamImpl", "(Ljava/io/FileDescriptor;)I", (void*) osNetworkSystem_availableStreamImpl }, 2934 { "acceptSocketImpl", "(Ljava/io/FileDescriptor;Ljava/net/SocketImpl;Ljava/io/FileDescriptor;I)V",(void*) osNetworkSystem_acceptSocketImpl }, 2935 { "supportsUrgentDataImpl", "(Ljava/io/FileDescriptor;)Z", (void*) osNetworkSystem_supportsUrgentDataImpl }, 2936 { "sendUrgentDataImpl", "(Ljava/io/FileDescriptor;B)V", (void*) osNetworkSystem_sendUrgentDataImpl }, 2937 { "connectDatagramImpl2", "(Ljava/io/FileDescriptor;IILjava/net/InetAddress;)V", (void*) osNetworkSystem_connectDatagramImpl2 }, 2938 { "disconnectDatagramImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_disconnectDatagramImpl }, 2939 { "peekDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)I", (void*) osNetworkSystem_peekDatagramImpl }, 2940 { "receiveDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;[BIIIZ)I", (void*) osNetworkSystem_receiveDatagramImpl }, 2941 { "receiveDatagramDirectImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;IIIIZ)I", (void*) osNetworkSystem_receiveDatagramDirectImpl }, 2942 { "recvConnectedDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;[BIIIZ)I", (void*) osNetworkSystem_recvConnectedDatagramImpl }, 2943 { "recvConnectedDatagramDirectImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;IIIIZ)I", (void*) osNetworkSystem_recvConnectedDatagramDirectImpl }, 2944 { "sendDatagramImpl", "(Ljava/io/FileDescriptor;[BIIIZILjava/net/InetAddress;)I", (void*) osNetworkSystem_sendDatagramImpl }, 2945 { "sendDatagramDirectImpl", "(Ljava/io/FileDescriptor;IIIIZILjava/net/InetAddress;)I", (void*) osNetworkSystem_sendDatagramDirectImpl }, 2946 { "sendConnectedDatagramImpl", "(Ljava/io/FileDescriptor;[BIIZ)I", (void*) osNetworkSystem_sendConnectedDatagramImpl }, 2947 { "sendConnectedDatagramDirectImpl", "(Ljava/io/FileDescriptor;IIIZ)I", (void*) osNetworkSystem_sendConnectedDatagramDirectImpl }, 2948 { "createServerStreamSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createServerStreamSocketImpl }, 2949 { "shutdownInputImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_shutdownInputImpl }, 2950 { "shutdownOutputImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_shutdownOutputImpl }, 2951 { "sendDatagramImpl2", "(Ljava/io/FileDescriptor;[BIIILjava/net/InetAddress;)I", (void*) osNetworkSystem_sendDatagramImpl2 }, 2952 { "selectImpl", "([Ljava/io/FileDescriptor;[Ljava/io/FileDescriptor;II[IJ)Z", (void*) osNetworkSystem_selectImpl }, 2953 { "getSocketLocalAddressImpl", "(Ljava/io/FileDescriptor;)Ljava/net/InetAddress;", (void*) osNetworkSystem_getSocketLocalAddressImpl }, 2954 { "getSocketLocalPortImpl", "(Ljava/io/FileDescriptor;)I", (void*) osNetworkSystem_getSocketLocalPortImpl }, 2955 { "getSocketOptionImpl", "(Ljava/io/FileDescriptor;I)Ljava/lang/Object;", (void*) osNetworkSystem_getSocketOptionImpl }, 2956 { "setSocketOptionImpl", "(Ljava/io/FileDescriptor;ILjava/lang/Object;)V", (void*) osNetworkSystem_setSocketOptionImpl }, 2957 { "getSocketFlagsImpl", "()I", (void*) osNetworkSystem_getSocketFlagsImpl }, 2958 { "socketCloseImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_socketCloseImpl }, 2959 { "setInetAddressImpl", "(Ljava/net/InetAddress;[B)V", (void*) osNetworkSystem_setInetAddressImpl }, 2960 { "inheritedChannel", "()Ljava/nio/channels/Channel;", (void*) osNetworkSystem_inheritedChannel }, 2961 { "byteArrayToIpString", "([B)Ljava/lang/String;", (void*) osNetworkSystem_byteArrayToIpString }, 2962 { "ipStringToByteArray", "(Ljava/lang/String;)[B", (void*) osNetworkSystem_ipStringToByteArray }, 2963 }; 2964 2965 int register_org_apache_harmony_luni_platform_OSNetworkSystem(JNIEnv* env) { 2966 return initCachedFields(env) && jniRegisterNativeMethods(env, 2967 "org/apache/harmony/luni/platform/OSNetworkSystem", 2968 gMethods, 2969 NELEM(gMethods)); 2970 } 2971 // END android-changed 2972