/* * Class: java_net_DualStackPlainSocketImpl * Method: accept0 * Signature: (I[Ljava/net/InetSocketAddress;)I */ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_accept0 (JNIEnv *env, jclass clazz, jint fd, jobjectArray isaa) { int newfd, port=0; jobject isa; jobject ia; SOCKETADDRESS sa; int len = sizeof(sa); memset((char *)&sa, 0, len); newfd = accept(fd, (struct sockaddr *)&sa, &len); if (newfd == INVALID_SOCKET) { if (WSAGetLastError() == -2) { JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", "operation interrupted"); } else { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); } return -1; } ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port); (*env)->SetObjectArrayElement(env, isaa, 0, isa); return newfd; }
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 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); }
jobject SockAddrToInetSocketAddress (JNIEnv *env, struct sockaddr* sap) { int port = 0; jobject ia = NET_SockaddrToInetAddress(env, sap, &port); if (ia == NULL) return NULL; if (isaCls == 0) { initializeISA(env); CHECK_NULL_RETURN(isaCls, NULL); } return (*env)->NewObject(env, isaCls, isaCtrID, ia, port); }
/* * Class: java_net_DualStackPlainDatagramSocketImpl * Method: socketLocalAddress * Signature: (I)Ljava/lang/Object; */ JNIEXPORT jobject JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketLocalAddress (JNIEnv *env , jclass clazz, jint fd) { SOCKETADDRESS sa; int len = sizeof(sa); jobject iaObj; int port; if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) { NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name"); return NULL; } iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); return iaObj; }
JNIEXPORT jint JNICALL Java_sun_nio_ch_InheritedChannel_peerPort0(JNIEnv *env, jclass cla, jint fd) { SOCKETADDRESS sa; socklen_t len = sizeof(SOCKETADDRESS); jint remote_port = -1; if (getpeername(fd, &sa.sa, &len) == 0) { if (matchFamily(&sa.sa)) { NET_SockaddrToInetAddress(env, &sa.sa, (int *)&remote_port); } } return remote_port; }
JNIEXPORT jint JNICALL Java_sun_nio_ch_InheritedChannel_peerPort0(JNIEnv *env, jclass cla, jint fd) { struct sockaddr *sa; socklen_t sa_len; jint remote_port = -1; NET_AllocSockaddr(&sa, (int *)&sa_len); if (getpeername(fd, sa, &sa_len) == 0) { if (matchFamily(sa)) { NET_SockaddrToInetAddress(env, sa, (int *)&remote_port); } } free((void *)sa); return remote_port; }
/* * Class: java_net_DualStackPlainSocketImpl * Method: localAddress * Signature: (ILjava/net/InetAddressContainer;)V */ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_localAddress (JNIEnv *env, jclass clazz, jint fd, jobject iaContainerObj) { int port; SOCKETADDRESS sa; int len = sizeof(sa); jobject iaObj; jclass iaContainerClass; jfieldID iaFieldID; if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) { NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name"); return; } iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); CHECK_NULL(iaObj); iaContainerClass = (*env)->GetObjectClass(env, iaContainerObj); iaFieldID = (*env)->GetFieldID(env, iaContainerClass, "addr", "Ljava/net/InetAddress;"); CHECK_NULL(iaFieldID); (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj); }
/* * Class: sun_nio_ch_sctp_SctpNet * Method: getLocalAddresses0 * Signature: (I)[Ljava/net/SocketAddress; */ JNIEXPORT jobjectArray JNICALL Java_sun_nio_ch_sctp_SctpNet_getLocalAddresses0 (JNIEnv *env, jclass klass, jint fd) { void *addr_buf, *laddr; struct sockaddr* sap; int i, addrCount; jobjectArray isaa; #ifdef __solaris__ if ((addrCount = nio_sctp_getladdrs(fd, 0, (void **)&addr_buf)) == -1) { #else /* __linux__ */ if ((addrCount = nio_sctp_getladdrs(fd, 0, (struct sockaddr **)&addr_buf)) == -1) { #endif handleSocketError(env, errno); return NULL; } if (addrCount < 1) return NULL; if (isaCls == 0) { initializeISA(env); CHECK_NULL_RETURN(isaCls, NULL); } isaa = (*env)->NewObjectArray(env, addrCount, isaCls, NULL); if (isaa == NULL) { nio_sctp_freeladdrs(addr_buf); return NULL; } laddr = addr_buf; for (i=0; i<addrCount; i++) { int port = 0; jobject isa = NULL, ia; sap = (struct sockaddr*)addr_buf; ia = NET_SockaddrToInetAddress(env, sap, &port); if (ia != NULL) isa = (*env)->NewObject(env, isaCls, isaCtrID, ia, port); if (isa == NULL) break; (*env)->SetObjectArrayElement(env, isaa, i, isa); if (sap->sa_family == AF_INET) addr_buf = ((struct sockaddr_in*)addr_buf) + 1; else addr_buf = ((struct sockaddr_in6*)addr_buf) + 1; } nio_sctp_freeladdrs(laddr); return isaa; } jobjectArray getRemoteAddresses (JNIEnv *env, jint fd, sctp_assoc_t id) { void *addr_buf, *paddr; struct sockaddr* sap; int i, addrCount; jobjectArray isaa; #if __solaris__ if ((addrCount = nio_sctp_getpaddrs(fd, id, (void **)&addr_buf)) == -1) { #else /* __linux__ */ if ((addrCount = nio_sctp_getpaddrs(fd, id, (struct sockaddr**)&addr_buf)) == -1) { #endif handleSocketError(env, errno); return NULL; } if (addrCount < 1) return NULL; if (isaCls == 0) { initializeISA(env); CHECK_NULL_RETURN(isaCls, NULL); } isaa = (*env)->NewObjectArray(env, addrCount, isaCls, NULL); if (isaa == NULL) { nio_sctp_freepaddrs(addr_buf); return NULL; } paddr = addr_buf; for (i=0; i<addrCount; i++) { jobject ia, isa = NULL; int port = 0; sap = (struct sockaddr*)addr_buf; ia = NET_SockaddrToInetAddress(env, sap, &port); if (ia != NULL) isa = (*env)->NewObject(env, isaCls, isaCtrID, ia, port); if (isa == NULL) break; (*env)->SetObjectArrayElement(env, isaa, i, isa); if (sap->sa_family == AF_INET) addr_buf = ((struct sockaddr_in*)addr_buf) + 1; else addr_buf = ((struct sockaddr_in6*)addr_buf) + 1; } nio_sctp_freepaddrs(paddr); return isaa; } /* * Class: sun_nio_ch_sctp_SctpNet * Method: getRemoteAddresses0 * Signature: (II)[Ljava/net/SocketAddress; */ JNIEXPORT jobjectArray JNICALL Java_sun_nio_ch_sctp_SctpNet_getRemoteAddresses0 (JNIEnv *env, jclass klass, jint fd, jint assocId) { return getRemoteAddresses(env, fd, assocId); } /* Map the Java level option to the native level */ int mapSocketOption (jint cmd, int *level, int *optname) { static struct { jint cmd; int level; int optname; } const opts[] = { { sun_nio_ch_sctp_SctpStdSocketOption_SCTP_DISABLE_FRAGMENTS, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS }, { sun_nio_ch_sctp_SctpStdSocketOption_SCTP_EXPLICIT_COMPLETE, IPPROTO_SCTP, SCTP_EXPLICIT_EOR }, { sun_nio_ch_sctp_SctpStdSocketOption_SCTP_FRAGMENT_INTERLEAVE, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE }, { sun_nio_ch_sctp_SctpStdSocketOption_SCTP_NODELAY, IPPROTO_SCTP, SCTP_NODELAY }, { sun_nio_ch_sctp_SctpStdSocketOption_SO_SNDBUF, SOL_SOCKET, SO_SNDBUF }, { sun_nio_ch_sctp_SctpStdSocketOption_SO_RCVBUF, SOL_SOCKET, SO_RCVBUF }, { sun_nio_ch_sctp_SctpStdSocketOption_SO_LINGER, SOL_SOCKET, SO_LINGER } }; int i; for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) { if (cmd == opts[i].cmd) { *level = opts[i].level; *optname = opts[i].optname; return 0; } } /* not found */ return -1; } /* * Class: sun_nio_ch_sctp_SctpNet * Method: setIntOption0 * Signature: (III)V */ JNIEXPORT void JNICALL Java_sun_nio_ch_sctp_SctpNet_setIntOption0 (JNIEnv *env, jclass klass, jint fd, jint opt, int arg) { int klevel, kopt; int result; struct linger linger; void *parg; int arglen; if (mapSocketOption(opt, &klevel, &kopt) < 0) { JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Unsupported socket option"); return; } if (opt == sun_nio_ch_sctp_SctpStdSocketOption_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; } } else { parg = (void *)&arg; arglen = sizeof(arg); } if (NET_SetSockOpt(fd, klevel, kopt, parg, arglen) < 0) { JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "sun_nio_ch_sctp_SctpNet.setIntOption0"); } }
/* * Class: java_net_DualStackPlainDatagramSocketImpl * Method: socketReceiveOrPeekData * Signature: (ILjava/net/DatagramPacket;IZZ)I */ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketReceiveOrPeekData (JNIEnv *env, jclass clazz, jint fd, jobject dpObj, jint timeout, jboolean connected, jboolean peek) { SOCKETADDRESS sa; int sa_len = sizeof(sa); int port, rv, flags=0; char BUF[MAX_BUFFER_LEN]; char *fullPacket; BOOL retry; jlong prevTime = 0; jint packetBufferOffset, packetBufferLen; jbyteArray packetBuffer; /* if we are only peeking. Called from peekData */ if (peek) { flags = MSG_PEEK; } packetBuffer = (*env)->GetObjectField(env, dpObj, dp_bufID); packetBufferOffset = (*env)->GetIntField(env, dpObj, dp_offsetID); packetBufferLen = (*env)->GetIntField(env, dpObj, dp_bufLengthID); /* Note: the buffer needn't be greater than 65,536 (0xFFFF) * the max size of an IP packet. Anything bigger is truncated anyway. */ if (packetBufferLen > MAX_PACKET_LEN) { packetBufferLen = MAX_PACKET_LEN; } if (packetBufferLen > MAX_BUFFER_LEN) { fullPacket = (char *)malloc(packetBufferLen); if (!fullPacket) { JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); return -1; } } else { fullPacket = &(BUF[0]); } do { retry = FALSE; if (timeout) { if (prevTime == 0) { prevTime = JVM_CurrentTimeMillis(env, 0); } rv = NET_Timeout(fd, timeout); if (rv <= 0) { if (rv == 0) { JNU_ThrowByName(env,JNU_JAVANETPKG "SocketTimeoutException", "Receive timed out"); } else if (rv == JVM_IO_ERR) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); } else if (rv == JVM_IO_INTR) { JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", "operation interrupted"); } if (packetBufferLen > MAX_BUFFER_LEN) { free(fullPacket); } return -1; } } /* receive the packet */ rv = recvfrom(fd, fullPacket, packetBufferLen, flags, (struct sockaddr *)&sa, &sa_len); if (rv == SOCKET_ERROR && (WSAGetLastError() == WSAECONNRESET)) { /* An icmp port unreachable - we must receive this as Windows * does not reset the state of the socket until this has been * received. */ purgeOutstandingICMP(env, fd); if (connected) { JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", "ICMP Port Unreachable"); if (packetBufferLen > MAX_BUFFER_LEN) free(fullPacket); return -1; } else if (timeout) { /* Adjust timeout */ jlong newTime = JVM_CurrentTimeMillis(env, 0); timeout -= (jint)(newTime - prevTime); if (timeout <= 0) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", "Receive timed out"); if (packetBufferLen > MAX_BUFFER_LEN) free(fullPacket); return -1; } prevTime = newTime; } retry = TRUE; } } while (retry); port = (int) ntohs ((u_short) GET_PORT((SOCKETADDRESS *)&sa)); /* truncate the data if the packet's length is too small */ if (rv > packetBufferLen) { rv = packetBufferLen; } if (rv < 0) { if (WSAGetLastError() == WSAEMSGSIZE) { /* it is because the buffer is too small. It's UDP, it's * unreliable, it's all good. discard the rest of the * data.. */ rv = packetBufferLen; } else { /* failure */ (*env)->SetIntField(env, dpObj, dp_lengthID, 0); } } if (rv == -1) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); } else if (rv == -2) { JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", "operation interrupted"); } else if (rv < 0) { NET_ThrowCurrent(env, "Datagram receive failed"); } else { jobject packetAddress; /* * Check if there is an InetAddress already associated with this * packet. If so, we check if it is the same source address. We * can't update any existing InetAddress because it is immutable */ packetAddress = (*env)->GetObjectField(env, dpObj, dp_addressID); if (packetAddress != NULL) { if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&sa, packetAddress)) { /* force a new InetAddress to be created */ packetAddress = NULL; } } if (packetAddress == NULL) { packetAddress = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); if (packetAddress != NULL) { /* stuff the new Inetaddress into the packet */ (*env)->SetObjectField(env, dpObj, dp_addressID, packetAddress); } } if (!(*env)->ExceptionCheck(env)) { /* populate the packet */ (*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, rv, (jbyte *)fullPacket); (*env)->SetIntField(env, dpObj, dp_portID, port); (*env)->SetIntField(env, dpObj, dp_lengthID, rv); } } if (packetBufferLen > MAX_BUFFER_LEN) { free(fullPacket); } return port; }