838 * WARNING: THIS NEEDS LOCKING. ALSO: SHOULD WE CHECK for fd being
839 * -1 already?
840 */
841 if (IS_NULL(fdObj)) {
842 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
843 "socket already closed");
844 return;
845 } else {
846 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
847 }
848 shutdown(fd, howto);
849 }
850
851
852 /*
853 * Class: java_net_PlainSocketImpl
854 * Method: socketSetOption0
855 * Signature: (IZLjava/lang/Object;)V
856 */
857 JNIEXPORT void JNICALL
858 Java_java_net_PlainSocketImpl_socketSetOption0(JNIEnv *env, jobject this,
859 jint cmd, jboolean on,
860 jobject value) {
861 int fd;
862 int level, optname, optlen;
863 union {
864 int i;
865 struct linger ling;
866 } optval;
867
868 /*
869 * Check that socket hasn't been closed
870 */
871 fd = getFD(env, this);
872 if (fd < 0) {
873 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
874 "Socket closed");
875 return;
876 }
877
878 /*
879 * SO_TIMEOUT is a NOOP on Solaris/Linux
880 */
881 if (cmd == java_net_SocketOptions_SO_TIMEOUT) {
882 return;
883 }
884
885 /*
886 * Map the Java level socket option to the platform specific
887 * level and option name.
888 */
889 if (NET_MapSocketOption(cmd, &level, &optname)) {
890 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
891 return;
892 }
893
894 switch (cmd) {
895 case java_net_SocketOptions_SO_SNDBUF :
896 case java_net_SocketOptions_SO_RCVBUF :
897 case java_net_SocketOptions_SO_LINGER :
898 case java_net_SocketOptions_IP_TOS :
899 {
900 jclass cls;
901 jfieldID fid;
902
903 cls = (*env)->FindClass(env, "java/lang/Integer");
904 CHECK_NULL(cls);
905 fid = (*env)->GetFieldID(env, cls, "value", "I");
906 CHECK_NULL(fid);
907
908 if (cmd == java_net_SocketOptions_SO_LINGER) {
909 if (on) {
910 optval.ling.l_onoff = 1;
934 if (errno == EINVAL) {
935 // On Solaris setsockopt will set errno to EINVAL if the socket
936 // is closed. The default error message is then confusing
937 char fullMsg[128];
938 jio_snprintf(fullMsg, sizeof(fullMsg), "Invalid option or socket reset by remote peer");
939 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg);
940 return;
941 }
942 #endif /* __solaris__ */
943 JNU_ThrowByNameWithMessageAndLastError
944 (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
945 }
946 }
947
948 /*
949 * Class: java_net_PlainSocketImpl
950 * Method: socketGetOption
951 * Signature: (I)I
952 */
953 JNIEXPORT jint JNICALL
954 Java_java_net_PlainSocketImpl_socketGetOption(JNIEnv *env, jobject this,
955 jint cmd, jobject iaContainerObj) {
956
957 int fd;
958 int level, optname, optlen;
959 union {
960 int i;
961 struct linger ling;
962 } optval;
963
964 /*
965 * Check that socket hasn't been closed
966 */
967 fd = getFD(env, this);
968 if (fd < 0) {
969 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
970 "Socket closed");
971 return -1;
972 }
973
974 /*
975 * SO_BINDADDR isn't a socket option
976 */
987 if (getsockname(fd, (struct sockaddr *)&him, &len) < 0) {
988 JNU_ThrowByNameWithMessageAndLastError
989 (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
990 return -1;
991 }
992 iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
993 CHECK_NULL_RETURN(iaObj, -1);
994
995 iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj);
996 iaFieldID = (*env)->GetFieldID(env, iaCntrClass, "addr", "Ljava/net/InetAddress;");
997 CHECK_NULL_RETURN(iaFieldID, -1);
998 (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
999 return 0; /* notice change from before */
1000 }
1001
1002 /*
1003 * Map the Java level socket option to the platform specific
1004 * level and option name.
1005 */
1006 if (NET_MapSocketOption(cmd, &level, &optname)) {
1007 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
1008 return -1;
1009 }
1010
1011 /*
1012 * Args are int except for SO_LINGER
1013 */
1014 if (cmd == java_net_SocketOptions_SO_LINGER) {
1015 optlen = sizeof(optval.ling);
1016 } else {
1017 optlen = sizeof(optval.i);
1018 }
1019
1020 if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) {
1021 JNU_ThrowByNameWithMessageAndLastError
1022 (env, JNU_JAVANETPKG "SocketException", "Error getting socket option");
1023 return -1;
1024 }
1025
1026 switch (cmd) {
1027 case java_net_SocketOptions_SO_LINGER:
|
838 * WARNING: THIS NEEDS LOCKING. ALSO: SHOULD WE CHECK for fd being
839 * -1 already?
840 */
841 if (IS_NULL(fdObj)) {
842 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
843 "socket already closed");
844 return;
845 } else {
846 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
847 }
848 shutdown(fd, howto);
849 }
850
851
852 /*
853 * Class: java_net_PlainSocketImpl
854 * Method: socketSetOption0
855 * Signature: (IZLjava/lang/Object;)V
856 */
857 JNIEXPORT void JNICALL
858 Java_java_net_PlainSocketImpl_socketSetOption0
859 (JNIEnv *env, jobject this, jint cmd, jboolean on, jobject value)
860 {
861 int fd;
862 int level, optname, optlen;
863 union {
864 int i;
865 struct linger ling;
866 } optval;
867
868 /*
869 * Check that socket hasn't been closed
870 */
871 fd = getFD(env, this);
872 if (fd < 0) {
873 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
874 "Socket closed");
875 return;
876 }
877
878 /*
879 * SO_TIMEOUT is a NOOP on Solaris/Linux
880 */
881 if (cmd == java_net_SocketOptions_SO_TIMEOUT) {
882 return;
883 }
884
885 /*
886 * Map the Java level socket option to the platform specific
887 * level and option name.
888 */
889 if (NET_MapSocketOption(cmd, &level, &optname)) {
890 JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
891 return;
892 }
893
894 switch (cmd) {
895 case java_net_SocketOptions_SO_SNDBUF :
896 case java_net_SocketOptions_SO_RCVBUF :
897 case java_net_SocketOptions_SO_LINGER :
898 case java_net_SocketOptions_IP_TOS :
899 {
900 jclass cls;
901 jfieldID fid;
902
903 cls = (*env)->FindClass(env, "java/lang/Integer");
904 CHECK_NULL(cls);
905 fid = (*env)->GetFieldID(env, cls, "value", "I");
906 CHECK_NULL(fid);
907
908 if (cmd == java_net_SocketOptions_SO_LINGER) {
909 if (on) {
910 optval.ling.l_onoff = 1;
934 if (errno == EINVAL) {
935 // On Solaris setsockopt will set errno to EINVAL if the socket
936 // is closed. The default error message is then confusing
937 char fullMsg[128];
938 jio_snprintf(fullMsg, sizeof(fullMsg), "Invalid option or socket reset by remote peer");
939 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg);
940 return;
941 }
942 #endif /* __solaris__ */
943 JNU_ThrowByNameWithMessageAndLastError
944 (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
945 }
946 }
947
948 /*
949 * Class: java_net_PlainSocketImpl
950 * Method: socketGetOption
951 * Signature: (I)I
952 */
953 JNIEXPORT jint JNICALL
954 Java_java_net_PlainSocketImpl_socketGetOption
955 (JNIEnv *env, jobject this, jint cmd, jobject iaContainerObj)
956 {
957 int fd;
958 int level, optname, optlen;
959 union {
960 int i;
961 struct linger ling;
962 } optval;
963
964 /*
965 * Check that socket hasn't been closed
966 */
967 fd = getFD(env, this);
968 if (fd < 0) {
969 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
970 "Socket closed");
971 return -1;
972 }
973
974 /*
975 * SO_BINDADDR isn't a socket option
976 */
987 if (getsockname(fd, (struct sockaddr *)&him, &len) < 0) {
988 JNU_ThrowByNameWithMessageAndLastError
989 (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
990 return -1;
991 }
992 iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
993 CHECK_NULL_RETURN(iaObj, -1);
994
995 iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj);
996 iaFieldID = (*env)->GetFieldID(env, iaCntrClass, "addr", "Ljava/net/InetAddress;");
997 CHECK_NULL_RETURN(iaFieldID, -1);
998 (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
999 return 0; /* notice change from before */
1000 }
1001
1002 /*
1003 * Map the Java level socket option to the platform specific
1004 * level and option name.
1005 */
1006 if (NET_MapSocketOption(cmd, &level, &optname)) {
1007 JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
1008 return -1;
1009 }
1010
1011 /*
1012 * Args are int except for SO_LINGER
1013 */
1014 if (cmd == java_net_SocketOptions_SO_LINGER) {
1015 optlen = sizeof(optval.ling);
1016 } else {
1017 optlen = sizeof(optval.i);
1018 }
1019
1020 if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) {
1021 JNU_ThrowByNameWithMessageAndLastError
1022 (env, JNU_JAVANETPKG "SocketException", "Error getting socket option");
1023 return -1;
1024 }
1025
1026 switch (cmd) {
1027 case java_net_SocketOptions_SO_LINGER:
|