1 /*
   2  * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <sys/types.h>
  27 #include <sys/socket.h>
  28 #include <string.h>
  29 #include <netinet/in.h>
  30 #include <netinet/tcp.h>
  31 
  32 #include "jni.h"
  33 #include "jni_util.h"
  34 #include "jvm.h"
  35 #include "jlong.h"
  36 #include "sun_nio_ch_Net.h"
  37 #include "net_util.h"
  38 #include "net_util_md.h"
  39 #include "nio_util.h"
  40 #include "nio.h"
  41 
  42 /**
  43  * Definitions for source-specific multicast to allow for building
  44  * with older header files.
  45  */
  46 
  47 #ifdef __solaris__
  48 
  49 #ifndef IP_BLOCK_SOURCE
  50 
  51 #define IP_BLOCK_SOURCE                 0x15
  52 #define IP_UNBLOCK_SOURCE               0x16
  53 #define IP_ADD_SOURCE_MEMBERSHIP        0x17
  54 #define IP_DROP_SOURCE_MEMBERSHIP       0x18
  55 
  56 #define MCAST_BLOCK_SOURCE              0x2b
  57 #define MCAST_UNBLOCK_SOURCE            0x2c
  58 #define MCAST_JOIN_SOURCE_GROUP         0x2d
  59 #define MCAST_LEAVE_SOURCE_GROUP        0x2e
  60 
  61 #endif  /* IP_BLOCK_SOURCE */
  62 
  63 struct my_ip_mreq_source {
  64         struct in_addr  imr_multiaddr;
  65         struct in_addr  imr_sourceaddr;
  66         struct in_addr  imr_interface;
  67 };
  68 
  69 /*
  70  * Use #pragma pack() construct to force 32-bit alignment on amd64.
  71  */
  72 #if defined(amd64)
  73 #pragma pack(4)
  74 #endif
  75 
  76 struct my_group_source_req {
  77         uint32_t                gsr_interface;  /* interface index */
  78         struct sockaddr_storage gsr_group;      /* group address */
  79         struct sockaddr_storage gsr_source;     /* source address */
  80 };
  81 
  82 #if defined(amd64)
  83 #pragma pack()
  84 #endif
  85 
  86 #endif  /* __solaris__ */
  87 
  88 
  89 #ifdef __linux__
  90 
  91 #ifndef IP_BLOCK_SOURCE
  92 
  93 #define IP_BLOCK_SOURCE                 38
  94 #define IP_UNBLOCK_SOURCE               37
  95 #define IP_ADD_SOURCE_MEMBERSHIP        39
  96 #define IP_DROP_SOURCE_MEMBERSHIP       40
  97 
  98 #define MCAST_BLOCK_SOURCE              43
  99 #define MCAST_UNBLOCK_SOURCE            44
 100 #define MCAST_JOIN_SOURCE_GROUP         42
 101 #define MCAST_LEAVE_SOURCE_GROUP        45
 102 
 103 #endif  /* IP_BLOCK_SOURCE */
 104 
 105 struct my_ip_mreq_source {
 106         struct in_addr  imr_multiaddr;
 107         struct in_addr  imr_interface;
 108         struct in_addr  imr_sourceaddr;
 109 };
 110 
 111 struct my_group_source_req {
 112         uint32_t                gsr_interface;  /* interface index */
 113         struct sockaddr_storage gsr_group;      /* group address */
 114         struct sockaddr_storage gsr_source;     /* source address */
 115 };
 116 
 117 #endif   /* __linux__ */
 118 
 119 
 120 #define COPY_INET6_ADDRESS(env, source, target) \
 121     (*env)->GetByteArrayRegion(env, source, 0, 16, target)
 122 
 123 /*
 124  * Copy IPv6 group, interface index, and IPv6 source address
 125  * into group_source_req structure.
 126  */
 127 #ifdef AF_INET6
 128 static void initGroupSourceReq(JNIEnv* env, jbyteArray group, jint index,
 129                                jbyteArray source, struct my_group_source_req* req)
 130 {
 131     struct sockaddr_in6* sin6;
 132 
 133     req->gsr_interface = (uint32_t)index;
 134 
 135     sin6 = (struct sockaddr_in6*)&(req->gsr_group);
 136     sin6->sin6_family = AF_INET6;
 137     COPY_INET6_ADDRESS(env, group, (jbyte*)&(sin6->sin6_addr));
 138 
 139     sin6 = (struct sockaddr_in6*)&(req->gsr_source);
 140     sin6->sin6_family = AF_INET6;
 141     COPY_INET6_ADDRESS(env, source, (jbyte*)&(sin6->sin6_addr));
 142 }
 143 #endif
 144 
 145 JNIEXPORT void JNICALL
 146 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
 147 {
 148     /* Here because Windows native code does need to init IDs */
 149 }
 150 
 151 JNIEXPORT jboolean JNICALL
 152 Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)
 153 {
 154     return (ipv6_available()) ? JNI_TRUE : JNI_FALSE;
 155 }
 156 
 157 JNIEXPORT int JNICALL
 158 Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
 159                             jboolean stream, jboolean reuse)
 160 {
 161     int fd;
 162     int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
 163 #ifdef AF_INET6
 164     int domain = (ipv6_available() && preferIPv6) ? AF_INET6 : AF_INET;
 165 #else
 166     int domain = AF_INET;
 167 #endif
 168 
 169     fd = socket(domain, type, 0);
 170     if (fd < 0) {
 171         return handleSocketError(env, errno);
 172     }
 173 
 174 #ifdef AF_INET6
 175     /* Disable IPV6_V6ONLY to ensure dual-socket support */
 176     if (domain == AF_INET6) {
 177         int arg = 0;
 178         if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
 179                        sizeof(int)) < 0) {
 180             JNU_ThrowByNameWithLastError(env,
 181                                          JNU_JAVANETPKG "SocketException",
 182                                          "sun.nio.ch.Net.setIntOption");
 183             close(fd);
 184             return -1;
 185         }
 186     }
 187 #endif
 188 
 189     if (reuse) {
 190         int arg = 1;
 191         if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
 192                        sizeof(arg)) < 0) {
 193             JNU_ThrowByNameWithLastError(env,
 194                                          JNU_JAVANETPKG "SocketException",
 195                                          "sun.nio.ch.Net.setIntOption");
 196             close(fd);
 197             return -1;
 198         }
 199     }
 200 #if defined(__linux__) && defined(AF_INET6)
 201     /* By default, Linux uses the route default */
 202     if (domain == AF_INET6 && type == SOCK_DGRAM) {
 203         int arg = 1;
 204         if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &arg,
 205                        sizeof(arg)) < 0) {
 206             JNU_ThrowByNameWithLastError(env,
 207                                          JNU_JAVANETPKG "SocketException",
 208                                          "sun.nio.ch.Net.setIntOption");
 209             close(fd);
 210             return -1;
 211         }
 212     }
 213 #endif
 214     return fd;
 215 }
 216 
 217 JNIEXPORT void JNICALL
 218 Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
 219                           jobject fdo, jobject iao, int port)
 220 {
 221     SOCKADDR sa;
 222     int sa_len = SOCKADDR_LEN;
 223     int rv = 0;
 224 
 225     if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) {
 226       return;
 227     }
 228 
 229     rv = NET_Bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
 230     if (rv != 0) {
 231         handleSocketError(env, errno);
 232     }
 233 }
 234 
 235 JNIEXPORT void JNICALL
 236 Java_sun_nio_ch_Net_listen(JNIEnv *env, jclass cl, jobject fdo, jint backlog)
 237 {
 238     if (listen(fdval(env, fdo), backlog) < 0)
 239         handleSocketError(env, errno);
 240 }
 241 
 242 JNIEXPORT jint JNICALL
 243 Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
 244                              jobject fdo, jobject iao, jint port)
 245 {
 246     SOCKADDR sa;
 247     int sa_len = SOCKADDR_LEN;
 248     int rv;
 249 
 250     if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa,
 251                                   &sa_len, preferIPv6) != 0)
 252     {
 253       return IOS_THROWN;
 254     }
 255 
 256     rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
 257     if (rv != 0) {
 258         if (errno == EINPROGRESS) {
 259             return IOS_UNAVAILABLE;
 260         } else if (errno == EINTR) {
 261             return IOS_INTERRUPTED;
 262         }
 263         return handleSocketError(env, errno);
 264     }
 265     return 1;
 266 }
 267 
 268 JNIEXPORT jint JNICALL
 269 Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
 270 {
 271     SOCKADDR sa;
 272     socklen_t sa_len = SOCKADDR_LEN;
 273     if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
 274         handleSocketError(env, errno);
 275         return -1;
 276     }
 277     return NET_GetPortFromSockaddr((struct sockaddr *)&sa);
 278 }
 279 
 280 JNIEXPORT jobject JNICALL
 281 Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
 282 {
 283     SOCKADDR sa;
 284     socklen_t sa_len = SOCKADDR_LEN;
 285     int port;
 286     if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
 287         handleSocketError(env, errno);
 288         return NULL;
 289     }
 290     return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
 291 }
 292 
 293 JNIEXPORT jint JNICALL
 294 Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
 295                                   jboolean mayNeedConversion, jint level, jint opt)
 296 {
 297     int result;
 298     struct linger linger;
 299     u_char carg;
 300     void *arg;
 301     socklen_t arglen;
 302     int n;
 303 
 304     /* Option value is an int except for a few specific cases */
 305 
 306     arg = (void *)&result;
 307     arglen = sizeof(result);
 308 
 309     if (level == IPPROTO_IP &&
 310         (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {
 311         arg = (void*)&carg;
 312         arglen = sizeof(carg);
 313     }
 314 
 315     if (level == SOL_SOCKET && opt == SO_LINGER) {
 316         arg = (void *)&linger;
 317         arglen = sizeof(linger);
 318     }
 319 
 320     if (mayNeedConversion) {
 321         n = NET_GetSockOpt(fdval(env, fdo), level, opt, arg, (int*)&arglen);
 322     } else {
 323         n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen);
 324     }
 325     if (n < 0) {
 326         JNU_ThrowByNameWithLastError(env,
 327                                      JNU_JAVANETPKG "SocketException",
 328                                      "sun.nio.ch.Net.getIntOption");
 329         return -1;
 330     }
 331 
 332     if (level == IPPROTO_IP &&
 333         (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP))
 334     {
 335         return (jint)carg;
 336     }
 337 
 338     if (level == SOL_SOCKET && opt == SO_LINGER)
 339         return linger.l_onoff ? (jint)linger.l_linger : (jint)-1;
 340 
 341     return (jint)result;
 342 }
 343 
 344 JNIEXPORT void JNICALL
 345 Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
 346                                   jboolean mayNeedConversion, jint level, jint opt, jint arg)
 347 {
 348     int result;
 349     struct linger linger;
 350     u_char carg;
 351     void *parg;
 352     int arglen, n;
 353 
 354     /* Option value is an int except for a few specific cases */
 355 
 356     parg = (void*)&arg;
 357     arglen = sizeof(arg);
 358 
 359     if (level == IPPROTO_IP &&
 360         (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {
 361         parg = (void*)&carg;
 362         arglen = sizeof(carg);
 363         carg = (u_char)arg;
 364     }
 365 
 366     if (level == SOL_SOCKET && opt == SO_LINGER) {
 367         parg = (void *)&linger;
 368         arglen = sizeof(linger);
 369         if (arg >= 0) {
 370             linger.l_onoff = 1;
 371             linger.l_linger = arg;
 372         } else {
 373             linger.l_onoff = 0;
 374             linger.l_linger = 0;
 375         }
 376     }
 377 
 378     if (mayNeedConversion) {
 379         n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen);
 380     } else {
 381         n = setsockopt(fdval(env, fdo), level, opt, parg, arglen);
 382     }
 383     if (n < 0) {
 384         JNU_ThrowByNameWithLastError(env,
 385                                      JNU_JAVANETPKG "SocketException",
 386                                      "sun.nio.ch.Net.setIntOption");
 387     }
 388 }
 389 
 390 JNIEXPORT jint JNICALL
 391 Java_sun_nio_ch_Net_joinOrDrop4(JNIEnv *env, jobject this, jboolean join, jobject fdo,
 392                                 jint group, jint interf, jint source)
 393 {
 394     struct ip_mreq mreq;
 395     struct my_ip_mreq_source mreq_source;
 396     int opt, n, optlen;
 397     void* optval;
 398 
 399     if (source == 0) {
 400         mreq.imr_multiaddr.s_addr = htonl(group);
 401         mreq.imr_interface.s_addr = htonl(interf);
 402         opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
 403         optval = (void*)&mreq;
 404         optlen = sizeof(mreq);
 405     } else {
 406         mreq_source.imr_multiaddr.s_addr = htonl(group);
 407         mreq_source.imr_sourceaddr.s_addr = htonl(source);
 408         mreq_source.imr_interface.s_addr = htonl(interf);
 409         opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP;
 410         optval = (void*)&mreq_source;
 411         optlen = sizeof(mreq_source);
 412     }
 413 
 414     n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen);
 415     if (n < 0) {
 416         if (join && (errno == ENOPROTOOPT))
 417             return IOS_UNAVAILABLE;
 418         handleSocketError(env, errno);
 419     }
 420     return 0;
 421 }
 422 
 423 JNIEXPORT jint JNICALL
 424 Java_sun_nio_ch_Net_blockOrUnblock4(JNIEnv *env, jobject this, jboolean block, jobject fdo,
 425                                     jint group, jint interf, jint source)
 426 {
 427     struct my_ip_mreq_source mreq_source;
 428     int n;
 429     int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE;
 430 
 431     mreq_source.imr_multiaddr.s_addr = htonl(group);
 432     mreq_source.imr_sourceaddr.s_addr = htonl(source);
 433     mreq_source.imr_interface.s_addr = htonl(interf);
 434 
 435     n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt,
 436                    (void*)&mreq_source, sizeof(mreq_source));
 437     if (n < 0) {
 438         if (block && (errno == ENOPROTOOPT))
 439             return IOS_UNAVAILABLE;
 440         handleSocketError(env, errno);
 441     }
 442     return 0;
 443 }
 444 
 445 JNIEXPORT jint JNICALL
 446 Java_sun_nio_ch_Net_joinOrDrop6(JNIEnv *env, jobject this, jboolean join, jobject fdo,
 447                                 jbyteArray group, jint index, jbyteArray source)
 448 {
 449 #ifdef AF_INET6
 450     struct ipv6_mreq mreq6;
 451     struct my_group_source_req req;
 452     int opt, n, optlen;
 453     void* optval;
 454 
 455     if (source == NULL) {
 456         COPY_INET6_ADDRESS(env, group, (jbyte*)&(mreq6.ipv6mr_multiaddr));
 457         mreq6.ipv6mr_interface = (int)index;
 458         opt = (join) ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
 459         optval = (void*)&mreq6;
 460         optlen = sizeof(mreq6);
 461     } else {
 462 #ifdef __linux__
 463         /* Include-mode filtering broken on Linux at least to 2.6.24 */
 464         return IOS_UNAVAILABLE;
 465 #else
 466         initGroupSourceReq(env, group, index, source, &req);
 467         opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP;
 468         optval = (void*)&req;
 469         optlen = sizeof(req);
 470 #endif
 471     }
 472 
 473     n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, optval, optlen);
 474     if (n < 0) {
 475         if (join && (errno == ENOPROTOOPT))
 476             return IOS_UNAVAILABLE;
 477         handleSocketError(env, errno);
 478     }
 479     return 0;
 480 #else
 481     JNU_ThrowInternalError(env, "Should not get here");
 482     return IOS_THROWN;
 483 #endif  /* AF_INET6 */
 484 }
 485 
 486 JNIEXPORT jint JNICALL
 487 Java_sun_nio_ch_Net_blockOrUnblock6(JNIEnv *env, jobject this, jboolean block, jobject fdo,
 488                                     jbyteArray group, jint index, jbyteArray source)
 489 {
 490 #ifdef AF_INET6
 491     struct my_group_source_req req;
 492     int n;
 493     int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE;
 494 
 495     initGroupSourceReq(env, group, index, source, &req);
 496 
 497     n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt,
 498         (void*)&req, sizeof(req));
 499     if (n < 0) {
 500         if (block && (errno == ENOPROTOOPT))
 501             return IOS_UNAVAILABLE;
 502         handleSocketError(env, errno);
 503     }
 504     return 0;
 505 #else
 506     JNU_ThrowInternalError(env, "Should not get here");
 507     return IOS_THROWN;
 508 #endif
 509 }
 510 
 511 JNIEXPORT void JNICALL
 512 Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint interf)
 513 {
 514     struct in_addr in;
 515     int arglen = sizeof(struct in_addr);
 516     int n;
 517 
 518     in.s_addr = htonl(interf);
 519 
 520     n = setsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF,
 521                    (void*)&(in.s_addr), arglen);
 522     if (n < 0) {
 523         handleSocketError(env, errno);
 524     }
 525 }
 526 
 527 JNIEXPORT jint JNICALL
 528 Java_sun_nio_ch_Net_getInterface4(JNIEnv* env, jobject this, jobject fdo)
 529 {
 530     struct in_addr in;
 531     socklen_t arglen = sizeof(struct in_addr);
 532     int n;
 533 
 534     n = getsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, (void*)&in, &arglen);
 535     if (n < 0) {
 536         handleSocketError(env, errno);
 537         return -1;
 538     }
 539     return ntohl(in.s_addr);
 540 }
 541 
 542 JNIEXPORT void JNICALL
 543 Java_sun_nio_ch_Net_setInterface6(JNIEnv* env, jobject this, jobject fdo, jint index)
 544 {
 545     int value = (jint)index;
 546     int arglen = sizeof(value);
 547     int n;
 548 
 549     n = setsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF,
 550                    (void*)&(index), arglen);
 551     if (n < 0) {
 552         handleSocketError(env, errno);
 553     }
 554 }
 555 
 556 JNIEXPORT jint JNICALL
 557 Java_sun_nio_ch_Net_getInterface6(JNIEnv* env, jobject this, jobject fdo)
 558 {
 559     int index;
 560     socklen_t arglen = sizeof(index);
 561     int n;
 562 
 563     n = getsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF, (void*)&index, &arglen);
 564     if (n < 0) {
 565         handleSocketError(env, errno);
 566         return -1;
 567     }
 568     return (jint)index;
 569 }
 570 
 571 JNIEXPORT void JNICALL
 572 Java_sun_nio_ch_Net_shutdown(JNIEnv *env, jclass cl, jobject fdo, jint jhow)
 573 {
 574     int how = (jhow == sun_nio_ch_Net_SHUT_RD) ? SHUT_RD :
 575         (jhow == sun_nio_ch_Net_SHUT_WR) ? SHUT_WR : SHUT_RDWR;
 576     if ((shutdown(fdval(env, fdo), how) < 0) && (errno != ENOTCONN))
 577         handleSocketError(env, errno);
 578 }
 579 
 580 /* Declared in nio_util.h */
 581 
 582 jint
 583 handleSocketError(JNIEnv *env, jint errorValue)
 584 {
 585     char *xn;
 586     switch (errorValue) {
 587         case EINPROGRESS:       /* Non-blocking connect */
 588             return 0;
 589         case EPROTO:
 590             xn = JNU_JAVANETPKG "ProtocolException";
 591             break;
 592         case ECONNREFUSED:
 593             xn = JNU_JAVANETPKG "ConnectException";
 594             break;
 595         case ETIMEDOUT:
 596             xn = JNU_JAVANETPKG "ConnectException";
 597             break;
 598         case EHOSTUNREACH:
 599             xn = JNU_JAVANETPKG "NoRouteToHostException";
 600             break;
 601         case EADDRINUSE:  /* Fall through */
 602         case EADDRNOTAVAIL:
 603             xn = JNU_JAVANETPKG "BindException";
 604             break;
 605         default:
 606             xn = JNU_JAVANETPKG "SocketException";
 607             break;
 608     }
 609     errno = errorValue;
 610     JNU_ThrowByNameWithLastError(env, xn, "NioSocketError");
 611     return IOS_THROWN;
 612 }