JNIEXPORT void JNICALL Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo, jboolean mayNeedConversion, jint level, jint opt, jint arg) { struct linger linger; char *parg; int arglen, n; if (level == SOL_SOCKET && opt == SO_LINGER) { parg = (char *)&linger; arglen = sizeof(linger); if (arg >= 0) { linger.l_onoff = 1; linger.l_linger = (unsigned short)arg; } else { linger.l_onoff = 0; linger.l_linger = 0; } } else { parg = (char *)&arg; arglen = sizeof(arg); } if (mayNeedConversion) { n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen); } else { n = setsockopt(fdval(env, fdo), level, opt, parg, arglen); } if (n < 0) handleSocketError(env, WSAGetLastError()); }
JNIEXPORT void JNICALL Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo, jboolean mayNeedConversion, jint level, jint opt, jint arg, jboolean isIPv6) { int result; struct linger linger; u_char carg; void *parg; socklen_t arglen; int n; /* Option value is an int except for a few specific cases */ parg = (void*)&arg; arglen = sizeof(arg); if (level == IPPROTO_IP && (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) { parg = (void*)&carg; arglen = sizeof(carg); carg = (u_char)arg; } if (level == SOL_SOCKET && opt == SO_LINGER) { parg = (void *)&linger; arglen = sizeof(linger); if (arg >= 0) { linger.l_onoff = 1; linger.l_linger = arg; } else { linger.l_onoff = 0; linger.l_linger = 0; } } if (mayNeedConversion) { n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen); } else { n = setsockopt(fdval(env, fdo), level, opt, parg, arglen); } if (n < 0) { JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "sun.nio.ch.Net.setIntOption"); } #ifdef __linux__ if (level == IPPROTO_IPV6 && opt == IPV6_TCLASS && isIPv6) { // set the V4 option also setsockopt(fdval(env, fdo), IPPROTO_IP, IP_TOS, parg, arglen); } #endif }
JNIEXPORT jint JNICALL Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo, jboolean mayNeedConversion, jint level, jint opt) { int result; struct linger linger; u_char carg; void *arg; socklen_t arglen; int n; /* Option value is an int except for a few specific cases */ arg = (void *)&result; arglen = sizeof(result); if (level == IPPROTO_IP && (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) { arg = (void*)&carg; arglen = sizeof(carg); } if (level == SOL_SOCKET && opt == SO_LINGER) { arg = (void *)&linger; arglen = sizeof(linger); } if (mayNeedConversion) { n = NET_GetSockOpt(fdval(env, fdo), level, opt, arg, (int*)&arglen); } else { n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen); } if (n < 0) { JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "sun.nio.ch.Net.getIntOption"); return -1; } if (level == IPPROTO_IP && (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) { return (jint)carg; } if (level == SOL_SOCKET && opt == SO_LINGER) return linger.l_onoff ? (jint)linger.l_linger : (jint)-1; return (jint)result; }
JNIEXPORT void JNICALL Java_sun_nio_ch_Net_listen(JNIEnv *env, jclass cl, jobject fdo, jint backlog) { if (listen(fdval(env,fdo), backlog) == SOCKET_ERROR) { NET_ThrowNew(env, WSAGetLastError(), "listen"); } }
JNIEXPORT jlong JNICALL Java_sun_nio_ch_DatagramDispatcher_writev0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) { jint fd = fdval(env, fdo); struct iovec *iov = (struct iovec *)jlong_to_ptr(address); struct msghdr m; ssize_t result = 0; if (len > 16) { len = 16; } m.msg_name = NULL; m.msg_namelen = 0; m.msg_iov = iov; m.msg_iovlen = len; #ifdef __solaris__ m.msg_accrights = NULL; m.msg_accrightslen = 0; #endif #ifdef __linux__ m.msg_control = NULL; m.msg_controllen = 0; #endif result = sendmsg(fd, &m, 0); if (result < 0 && errno == ECONNREFUSED) { JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", 0); return -2; } return convertLongReturnVal(env, (jlong)result, JNI_FALSE); }
JNIEXPORT jint JNICALL Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6, jobject fdo, jobject iao, jint port) { SOCKETADDRESS sa; int rv; int sa_len; SOCKET s = (SOCKET)fdval(env, fdo); if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) { return IOS_THROWN; } rv = connect(s, (struct sockaddr *)&sa, sa_len); if (rv != 0) { int err = WSAGetLastError(); if (err == WSAEINPROGRESS || err == WSAEWOULDBLOCK) { return IOS_UNAVAILABLE; } NET_ThrowNew(env, err, "connect"); return IOS_THROWN; } else { /* Enable WSAECONNRESET errors when a UDP socket is connected */ int type = 0, optlen = sizeof(type); rv = getsockopt(s, SOL_SOCKET, SO_TYPE, (char*)&type, &optlen); if (rv == 0 && type == SOCK_DGRAM) { setConnectionReset(s, TRUE); } } return 1; }
JNIEXPORT jint JNICALL Java_sun_nio_ch_Net_connect(JNIEnv *env, jclass clazz, jobject fdo, jobject iao, jint port, jint trafficClass) { SOCKADDR sa; int sa_len = SOCKADDR_LEN; int rv; NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa, &sa_len); #ifdef AF_INET6 #if 0 if (trafficClass != 0 && ipv6_available()) { /* ## FIX */ NET_SetTrafficClass((struct sockaddr *)&sa, trafficClass); } #endif #endif rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len); if (rv != 0) { if (errno == EINPROGRESS) { return IOS_UNAVAILABLE; } else if (errno == EINTR) { return IOS_INTERRUPTED; } return handleSocketError(env, errno); } return 1; }
JNIEXPORT void JNICALL Java_sun_nio_ch_IOUtil_configureBlocking(JNIEnv *env, jclass clazz, jobject fdo, jboolean blocking) { if (configureBlocking(fdval(env, fdo), blocking) < 0) JNU_ThrowIOExceptionWithLastError(env, "Configure blocking failed"); }
JNIEXPORT jint JNICALL Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6, jobject fdo, jobject iao, jint port) { SOCKADDR sa; int sa_len = SOCKADDR_LEN; int rv; if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa, &sa_len, preferIPv6) != 0) { return IOS_THROWN; } rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len); if (rv != 0) { if (errno == EINPROGRESS) { return IOS_UNAVAILABLE; } else if (errno == EINTR) { return IOS_INTERRUPTED; } return handleSocketError(env, errno); } return 1; }
JNIEXPORT jobject JNICALL Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo) { SOCKADDR sa; socklen_t sa_len = SOCKADDR_LEN; int port; if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) { #ifdef _ALLBSD_SOURCE /* * XXXBSD: * ECONNRESET is specific to the BSDs. We can not return an error, * as the calling Java code with raise a java.lang.Error with the expectation * that getsockname() will never fail. According to the Single UNIX Specification, * it shouldn't fail. As such, we just fill in generic Linux-compatible values. */ if (errno == ECONNRESET) { struct sockaddr_in *sin; sin = (struct sockaddr_in *) &sa; bzero(sin, sizeof(*sin)); sin->sin_len = sizeof(struct sockaddr_in); sin->sin_family = AF_INET; sin->sin_port = htonl(0); sin->sin_addr.s_addr = INADDR_ANY; } else { handleSocketError(env, errno); return NULL; } #else /* _ALLBSD_SOURCE */ handleSocketError(env, errno); return NULL; #endif /* _ALLBSD_SOURCE */ } return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); }
JNIEXPORT void JNICALL Java_sun_nio_ch_SocketDispatcher_close0(JNIEnv *env, jclass clazz, jobject fdo) { jint fd = fdval(env, fdo); if (closesocket(fd) == SOCKET_ERROR) { JNU_ThrowIOExceptionWithLastError(env, "Socket close failed"); } }
JNIEXPORT jint JNICALL Java_sun_nio_ch_FileDispatcher_pwrite0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len, jlong offset) { jint fd = fdval(env, fdo); void *buf = (void *)jlong_to_ptr(address); return convertReturnVal(env, pwrite64(fd, buf, len, offset), JNI_FALSE); }
JNIEXPORT void JNICALL Java_sun_nio_ch_FileDispatcher_preClose0(JNIEnv *env, jclass clazz, jobject fdo) { jint fd = fdval(env, fdo); if (preCloseFD >= 0) { if (dup2(preCloseFD, fd) < 0) JNU_ThrowIOExceptionWithLastError(env, "dup2 failed"); } }
JNIEXPORT jint JNICALL Java_sun_nio_ch_FileDispatcher_read0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) { jint fd = fdval(env, fdo); void *buf = (void *)jlong_to_ptr(address); return convertReturnVal(env, read(fd, buf, len), JNI_TRUE); }
JNIEXPORT jlong JNICALL Java_sun_nio_ch_SocketDispatcher_readv0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) { /* set up */ int i = 0; DWORD read = 0; DWORD flags = 0; jint fd = fdval(env, fdo); struct iovec *iovp = (struct iovec *)address; WSABUF *bufs = malloc(len * sizeof(WSABUF)); jint rem = MAX_BUFFER_SIZE; if (bufs == 0) { JNU_ThrowOutOfMemoryError(env, 0); return IOS_THROWN; } /* copy iovec into WSABUF */ for(i=0; i<len; i++) { jint iov_len = iovp[i].iov_len; if (iov_len > rem) iov_len = rem; bufs[i].buf = (char *)iovp[i].iov_base; bufs[i].len = (u_long)iov_len; rem -= iov_len; if (rem == 0) { len = i+1; break; } } /* read into the buffers */ i = WSARecv((SOCKET)fd, /* Socket */ bufs, /* pointers to the buffers */ (DWORD)len, /* number of buffers to process */ &read, /* receives number of bytes read */ &flags, /* no flags */ 0, /* no overlapped sockets */ 0); /* no completion routine */ /* clean up */ free(bufs); if (i != 0) { int theErr = (jint)WSAGetLastError(); if (theErr == WSAEWOULDBLOCK) { return IOS_UNAVAILABLE; } JNU_ThrowIOExceptionWithLastError(env, "Vector read failed"); return IOS_THROWN; } return convertLongReturnVal(env, (jlong)read, JNI_TRUE); }
JNIEXPORT jint JNICALL Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo) { SOCKADDR sa; int sa_len = SOCKADDR_LEN; if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) { handleSocketError(env, errno); return -1; } return NET_GetPortFromSockaddr((struct sockaddr *)&sa); }
JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileDispatcher_writev0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) { jint fd = fdval(env, fdo); struct iovec *iov = (struct iovec *)jlong_to_ptr(address); if (len > 16) { len = 16; } return convertLongReturnVal(env, writev(fd, iov, len), JNI_FALSE); }
JNIEXPORT jint JNICALL Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo, jboolean mayNeedConversion, jint level, jint opt) { int result = 0; struct linger linger; char *arg; int arglen, n; if (level == SOL_SOCKET && opt == SO_LINGER) { arg = (char *)&linger; arglen = sizeof(linger); } else { arg = (char *)&result; arglen = sizeof(result); } /** * HACK: IP_TOS is deprecated on Windows and querying the option * returns a protocol error. NET_GetSockOpt handles this and uses * a fallback mechanism. */ if (level == IPPROTO_IP && opt == IP_TOS) { mayNeedConversion = JNI_TRUE; } if (mayNeedConversion) { n = NET_GetSockOpt(fdval(env, fdo), level, opt, arg, &arglen); } else { n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen); } if (n < 0) { handleSocketError(env, WSAGetLastError()); return IOS_THROWN; } if (level == SOL_SOCKET && opt == SO_LINGER) return linger.l_onoff ? linger.l_linger : -1; else return result; }
JNIEXPORT jobject JNICALL Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo) { SOCKADDR sa; int sa_len = SOCKADDR_LEN; int port; if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) { handleSocketError(env, errno); return NULL; } return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); }
JNIEXPORT jobject JNICALL Java_sun_nio_ch_Net_remoteInetAddress(JNIEnv *env, jclass clazz, jobject fdo) { SOCKETADDRESS sa; int sa_len = sizeof(sa); int port; if (getpeername(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) { NET_ThrowNew(env, WSAGetLastError(), "getsockname"); return NULL; } return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); }
JNIEXPORT jint JNICALL Java_sun_nio_ch_DatagramDispatcher_write0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) { jint fd = fdval(env, fdo); void *buf = (void *)jlong_to_ptr(address); int result = send(fd, buf, len, 0); if (result < 0 && errno == ECONNREFUSED) { JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", 0); return -2; } return convertReturnVal(env, result, JNI_FALSE); }
JNIEXPORT void JNICALL Java_sun_nio_ch_SocketDispatcher_preClose0(JNIEnv *env, jclass clazz, jobject fdo) { jint fd = fdval(env, fdo); struct linger l; int len = sizeof(l); if (getsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&l, &len) == 0) { if (l.l_onoff == 0) { WSASendDisconnect(fd, NULL); } } }
JNIEXPORT jint JNICALL Java_sun_nio_ch_SocketDispatcher_write0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint total) { /* set up */ int i = 0; DWORD written = 0; jint count = 0; jint fd = fdval(env, fdo); WSABUF buf; do { /* limit size */ jint len = total - count; if (len > MAX_BUFFER_SIZE) len = MAX_BUFFER_SIZE; /* copy iovec into WSABUF */ buf.buf = (char *)address; buf.len = (u_long)len; /* write from the buffer */ i = WSASend((SOCKET)fd, /* Socket */ &buf, /* pointers to the buffers */ (DWORD)1, /* number of buffers to process */ &written, /* receives number of bytes written */ 0, /* no flags */ 0, /* no overlapped sockets */ 0); /* no completion routine */ if (i == SOCKET_ERROR) { if (count > 0) { /* can't throw exception when some bytes have been written */ break; } else { int theErr = (jint)WSAGetLastError(); if (theErr == WSAEWOULDBLOCK) { return IOS_UNAVAILABLE; } JNU_ThrowIOExceptionWithLastError(env, "Write failed"); return IOS_THROWN; } } count += written; address += written; } while ((count < total) && (written == MAX_BUFFER_SIZE)); return count; }
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); } }
JNIEXPORT void JNICALL Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jobject fdo, jboolean preferIPv6, jboolean isExclBind, jobject iao, jint port) { SOCKETADDRESS sa; int rv; int sa_len; if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) { return; } rv = NET_WinBind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len, isExclBind); if (rv == SOCKET_ERROR) NET_ThrowNew(env, WSAGetLastError(), "bind"); }
JNIEXPORT jint JNICALL Java_sun_nio_ch_Net_remotePort(JNIEnv *env, jclass clazz, jobject fdo) { SOCKETADDRESS sa; int sa_len = sizeof(sa); if (getpeername(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) { int error = WSAGetLastError(); if (error == WSAEINVAL) { return 0; } NET_ThrowNew(env, error, "getsockname"); return IOS_THROWN; } return NET_GetPortFromSockaddr((struct sockaddr *)&sa); }
JNIEXPORT jlong JNICALL Java_sun_nio_ch_DatagramDispatcher_readv0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) { /* set up */ int i = 0; DWORD read = 0; DWORD flags = 0; jint fd = fdval(env, fdo); struct iovec *iovp = (struct iovec *)address; WSABUF *bufs = malloc(len * sizeof(WSABUF)); /* copy iovec into WSABUF */ for(i=0; i<len; i++) { bufs[i].buf = (char *)iovp[i].iov_base; bufs[i].len = (u_long)iovp[i].iov_len; } /* read into the buffers */ i = WSARecv((SOCKET)fd, /* Socket */ bufs, /* pointers to the buffers */ (DWORD)len, /* number of buffers to process */ &read, /* receives number of bytes read */ &flags, /* no flags */ 0, /* no overlapped sockets */ 0); /* no completion routine */ /* clean up */ free(bufs); if (i != 0) { int theErr = (jint)WSAGetLastError(); if (theErr == WSAEWOULDBLOCK) { return IOS_UNAVAILABLE; } if (theErr == WSAECONNRESET) { purgeOutstandingICMP(env, clazz, fd); JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", 0); return IOS_THROWN; } JNU_ThrowIOExceptionWithLastError(env, "Write failed"); return IOS_THROWN; } return convertLongReturnVal(env, (jlong)read, JNI_TRUE); }
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 jint JNICALL Java_sun_nio_ch_DatagramDispatcher_read0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) { /* set up */ int i = 0; DWORD read = 0; DWORD flags = 0; jint fd = fdval(env, fdo); WSABUF buf; /* destination buffer and size */ buf.buf = (char *)address; buf.len = (u_long)len; /* read into the buffers */ i = WSARecv((SOCKET)fd, /* Socket */ &buf, /* pointers to the buffers */ (DWORD)1, /* number of buffers to process */ &read, /* receives number of bytes read */ &flags, /* no flags */ 0, /* no overlapped sockets */ 0); /* no completion routine */ if (i == SOCKET_ERROR) { int theErr = (jint)WSAGetLastError(); if (theErr == WSAEWOULDBLOCK) { return IOS_UNAVAILABLE; } if (theErr == WSAECONNRESET) { purgeOutstandingICMP(env, clazz, fd); JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", 0); return IOS_THROWN; } JNU_ThrowIOExceptionWithLastError(env, "Write failed"); return IOS_THROWN; } return convertReturnVal(env, (jint)read, JNI_TRUE); }
JNIEXPORT jint JNICALL Java_sun_nio_ch_SocketDispatcher_read0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) { /* set up */ int i = 0; DWORD read = 0; DWORD flags = 0; jint fd = fdval(env, fdo); WSABUF buf; /* limit size */ if (len > MAX_BUFFER_SIZE) len = MAX_BUFFER_SIZE; /* destination buffer and size */ buf.buf = (char *)address; buf.len = (u_long)len; /* read into the buffers */ i = WSARecv((SOCKET)fd, /* Socket */ &buf, /* pointers to the buffers */ (DWORD)1, /* number of buffers to process */ &read, /* receives number of bytes read */ &flags, /* no flags */ 0, /* no overlapped sockets */ 0); /* no completion routine */ if (i == SOCKET_ERROR) { int theErr = (jint)WSAGetLastError(); if (theErr == WSAEWOULDBLOCK) { return IOS_UNAVAILABLE; } JNU_ThrowIOExceptionWithLastError(env, "Read failed"); return IOS_THROWN; } return convertReturnVal(env, (jint)read, JNI_TRUE); }