JNIEXPORT void JNICALL Java_sun_nio_ch_Net_bind(JNIEnv *env, jclass clazz, /* ## Needs rest of PSI gunk */ jobject fdo, jobject ia, int port) { SOCKADDR sa; int sa_len = SOCKADDR_LEN; int rv = 0; NET_InetAddressToSockaddr(env, ia, port, (struct sockaddr *)&sa, &sa_len); rv = NET_Bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len); if (rv != 0) { handleSocketError(env, errno); } }
/* * Class: java_net_DualStackPlainSocketImpl * Method: bind0 * Signature: (ILjava/net/InetAddress;I)V */ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_bind0 (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) { SOCKETADDRESS sa; int rv; int sa_len = sizeof(sa); if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa, &sa_len, JNI_TRUE) != 0) { return; } rv = NET_Bind(fd, (struct sockaddr *)&sa, sa_len); if (rv == SOCKET_ERROR) NET_ThrowNew(env, WSAGetLastError(), "JVM_Bind"); }
JNIEXPORT void JNICALL Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jobject fdo, jboolean preferIPv6, jboolean useExclBind, jobject iao, int port) { SOCKADDR sa; int sa_len = SOCKADDR_LEN; int rv = 0; if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) { return; } rv = NET_Bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len); if (rv != 0) { handleSocketError(env, errno); } }
JNIEXPORT int JNICALL NET_BindV6(struct ipv6bind* b) { int fd=-1, ofd=-1, rv, len; /* need to defer close until new sockets created */ int close_fd=-1, close_ofd=-1; SOCKETADDRESS oaddr; /* other address to bind */ int family = b->addr->him.sa_family; int ofamily; u_short port; /* requested port parameter */ u_short bound_port; if (family == AF_INET && (b->addr->him4.sin_addr.s_addr != INADDR_ANY)) { /* bind to v4 only */ int ret; ret = NET_Bind (b->ipv4_fd, (struct sockaddr *)b->addr, sizeof (struct sockaddr_in)); if (ret == SOCKET_ERROR) { CLOSE_SOCKETS_AND_RETURN; } closesocket (b->ipv6_fd); b->ipv6_fd = -1; return 0; } if (family == AF_INET6 && (!IN6_IS_ADDR_ANY(&b->addr->him6.sin6_addr))) { /* bind to v6 only */ int ret; ret = NET_Bind (b->ipv6_fd, (struct sockaddr *)b->addr, sizeof (struct SOCKADDR_IN6)); if (ret == SOCKET_ERROR) { CLOSE_SOCKETS_AND_RETURN; } closesocket (b->ipv4_fd); b->ipv4_fd = -1; return 0; } /* We need to bind on both stacks, with the same port number */ memset (&oaddr, 0, sizeof(oaddr)); if (family == AF_INET) { ofamily = AF_INET6; fd = b->ipv4_fd; ofd = b->ipv6_fd; port = (u_short)GET_PORT (b->addr); IN6ADDR_SETANY (&oaddr.him6); oaddr.him6.sin6_port = port; } else { ofamily = AF_INET; ofd = b->ipv4_fd; fd = b->ipv6_fd; port = (u_short)GET_PORT (b->addr); oaddr.him4.sin_family = AF_INET; oaddr.him4.sin_port = port; oaddr.him4.sin_addr.s_addr = INADDR_ANY; } rv = NET_Bind (fd, (struct sockaddr *)b->addr, SOCKETADDRESS_LEN(b->addr)); if (rv == SOCKET_ERROR) { CLOSE_SOCKETS_AND_RETURN; } /* get the port and set it in the other address */ len = SOCKETADDRESS_LEN(b->addr); if (getsockname(fd, (struct sockaddr *)b->addr, &len) == -1) { CLOSE_SOCKETS_AND_RETURN; } bound_port = GET_PORT (b->addr); SET_PORT (&oaddr, bound_port); if ((rv=NET_Bind (ofd, (struct sockaddr *) &oaddr, SOCKETADDRESS_LEN (&oaddr))) == SOCKET_ERROR) { int retries; int sotype, arglen=sizeof(sotype); /* no retries unless, the request was for any free port */ if (port != 0) { CLOSE_SOCKETS_AND_RETURN; } getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen); #define SOCK_RETRIES 50 /* 50 is an arbitrary limit, just to ensure that this * cannot be an endless loop. Would expect socket creation to * succeed sooner. */ for (retries = 0; retries < SOCK_RETRIES; retries ++) { int len; close_fd = fd; fd = -1; close_ofd = ofd; ofd = -1; b->ipv4_fd = SOCKET_ERROR; b->ipv6_fd = SOCKET_ERROR; /* create two new sockets */ fd = socket (family, sotype, 0); if (fd == SOCKET_ERROR) { CLOSE_SOCKETS_AND_RETURN; } ofd = socket (ofamily, sotype, 0); if (ofd == SOCKET_ERROR) { CLOSE_SOCKETS_AND_RETURN; } /* bind random port on first socket */ SET_PORT (&oaddr, 0); rv = NET_Bind (ofd, (struct sockaddr *)&oaddr, SOCKETADDRESS_LEN(&oaddr)); if (rv == SOCKET_ERROR) { CLOSE_SOCKETS_AND_RETURN; } /* close the original pair of sockets before continuing */ closesocket (close_fd); closesocket (close_ofd); close_fd = close_ofd = -1; /* bind new port on second socket */ len = SOCKETADDRESS_LEN(&oaddr); if (getsockname(ofd, (struct sockaddr *)&oaddr, &len) == -1) { CLOSE_SOCKETS_AND_RETURN; } bound_port = GET_PORT (&oaddr); SET_PORT (b->addr, bound_port); rv = NET_Bind (fd, (struct sockaddr *)b->addr, SOCKETADDRESS_LEN(b->addr)); if (rv != SOCKET_ERROR) { if (family == AF_INET) { b->ipv4_fd = fd; b->ipv6_fd = ofd; } else { b->ipv4_fd = ofd; b->ipv6_fd = fd; } return 0; } } CLOSE_SOCKETS_AND_RETURN; } return 0; }