/*
 * 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;
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 7
0
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);
}
Ejemplo n.º 10
0
/*
 * 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;
}