354 */
355 len = sizeof(sa);
356 memset((char *)&sa, 0, len);
357
358 if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
359 if (WSAGetLastError() == WSAENOTSOCK) {
360 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
361 "Socket closed");
362 } else {
363 NET_ThrowNew(env, WSAGetLastError(), "getsockname failed");
364 }
365 return;
366 }
367 localport = (jint) ntohs((u_short)GET_PORT(&sa));
368 (*env)->SetIntField(env, this, psi_localportID, (int) localport);
369 }
370 }
371
372 /*
373 * Class: java_net_DualStackPlainSocketImpl
374 * Method: localAddress
375 * Signature: (ILjava/net/InetAddressContainer;)V
376 */
377 JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_localAddress
378 (JNIEnv *env, jclass clazz, jint fd, jobject iaContainerObj) {
379 int port;
380 SOCKETADDRESS sa;
381 int len = sizeof(sa);
382 jobject iaObj;
383 jclass iaContainerClass;
384 jfieldID iaFieldID;
385
386 if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
387 NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
388 return;
389 }
390 iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
391 CHECK_NULL(iaObj);
392
393 iaContainerClass = (*env)->GetObjectClass(env, iaContainerObj);
394 iaFieldID = (*env)->GetFieldID(env, iaContainerClass, "addr", "Ljava/net/InetAddress;");
395 CHECK_NULL(iaFieldID);
396 (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
397 }
398
399 /*
400 * Class: java_net_DualStackPlainSocketImpl
401 * Method: socketListen
402 * Signature: (I)V
403 */
404 JNIEXPORT void JNICALL
405 Java_java_net_DualStackPlainSocketImpl_socketListen
406 (JNIEnv *env, jobject this, jint count)
407 {
408 /* this FileDescriptor fd field */
409 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
410 /* fdObj's int fd field */
411 int fd = INVALID_SOCKET;
412
413 if (IS_NULL(fdObj)) {
414 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
415 "socket closed");
416 return;
417 }
418
419 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
420
602 JNIEXPORT void JNICALL
603 Java_java_net_DualStackPlainSocketImpl_socketShutdown(JNIEnv *env, jobject this,
604 jint howto)
605 {
606
607 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
608 jint fd;
609
610 if (IS_NULL(fdObj)) {
611 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
612 "socket already closed");
613 return;
614 } else {
615 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
616 }
617 shutdown(fd, howto);
618 }
619
620 /*
621 * Class: java_net_DualStackPlainSocketImpl
622 * Method: getIntOption
623 * Signature: (II)I
624 */
625 JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_getIntOption
626 (JNIEnv *env, jclass clazz, jint fd, jint cmd)
627 {
628 int level = 0, opt = 0;
629 int result=0;
630 struct linger linger = {0, 0};
631 char *arg;
632 int arglen;
633
634 if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
635 JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
636 return -1;
637 }
638
639 if (opt == java_net_SocketOptions_SO_LINGER) {
640 arg = (char *)&linger;
641 arglen = sizeof(linger);
642 } else {
643 arg = (char *)&result;
644 arglen = sizeof(result);
645 }
646
647 if (NET_GetSockOpt(fd, level, opt, arg, &arglen) < 0) {
648 NET_ThrowNew(env, WSAGetLastError(), "getsockopt");
649 return -1;
650 }
651
652 if (opt == java_net_SocketOptions_SO_LINGER)
653 return linger.l_onoff ? linger.l_linger : -1;
654 else
655 return result;
656 }
657
658 /*
659 * Class: java_net_DualStackPlainSocketImpl
660 * Method: socketNativeSetOption
661 * Signature: (IZLjava/lang/Object;)V
662 */
663 JNIEXPORT void JNICALL
664 Java_java_net_DualStackPlainSocketImpl_socketNativeSetOption
665 (JNIEnv *env, jobject this, jint cmd, jboolean on, jobject value)
666 {
667 /* The fd field */
668 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
669
670 jint fd;
671 int level = 0, optname = 0, optlen = 0;
672 union {
673 int i;
674 struct linger ling;
675 } optval;
676
677 memset((char *)&optval, 0, sizeof(optval));
678
679 /*
689 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
690 return;
691 }
692
693 if (cmd == java_net_SocketOptions_SO_TIMEOUT) {
694 // timeout implemented through select.
695 return;
696 }
697
698 /*
699 * Map the Java level socket option to the platform specific
700 * level and option name.
701 */
702 if (NET_MapSocketOption(cmd, &level, &optname)) {
703 JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
704 return;
705 }
706
707 switch (cmd) {
708
709 case java_net_SocketOptions_TCP_NODELAY :
710 case java_net_SocketOptions_SO_OOBINLINE :
711 case java_net_SocketOptions_SO_KEEPALIVE :
712 case java_net_SocketOptions_SO_REUSEADDR :
713 optval.i = (on ? 1 : 0);
714 optlen = sizeof(optval.i);
715 break;
716
717 case java_net_SocketOptions_SO_SNDBUF :
718 case java_net_SocketOptions_SO_RCVBUF :
719 case java_net_SocketOptions_IP_TOS :
720 {
721 jclass cls;
722 jfieldID fid;
723
724 cls = (*env)->FindClass(env, "java/lang/Integer");
725 CHECK_NULL(cls);
726 fid = (*env)->GetFieldID(env, cls, "value", "I");
727 CHECK_NULL(fid);
728
729 optval.i = (*env)->GetIntField(env, value, fid);
730 optlen = sizeof(optval.i);
731 }
732 break;
733
734 case java_net_SocketOptions_SO_LINGER :
735 {
736 jclass cls;
737 jfieldID fid;
738
739 cls = (*env)->FindClass(env, "java/lang/Integer");
756 default: /* shouldn't get here */
757 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
758 "Option not supported by DualStackPlainSocketImpl");
759 return;
760 }
761
762 if (NET_SetSockOpt(fd, level, optname, (void *)&optval, optlen) < 0) {
763 NET_ThrowNew(env, WSAGetLastError(), "setsockopt");
764 }
765 }
766
767 /*
768 * Class: java_net_DualStackPlainSocketImpl
769 * Method: socketNativeGetOption
770 * Signature: (ILjava/lang/Object;)I
771 */
772 JNIEXPORT jint JNICALL
773 Java_java_net_DualStackPlainSocketImpl_socketNativeGetOption
774 (JNIEnv *env, jobject this, jint opt, jobject iaContainerObj)
775 {
776 return -1;
777 }
778
779 /*
780 * Class: java_net_DualStackPlainSocketImpl
781 * Method: socketSendUrgentData
782 * Signature: (B)V
783 */
784 JNIEXPORT void JNICALL
785 Java_java_net_DualStackPlainSocketImpl_socketSendUrgentData(JNIEnv *env, jobject this,
786 jint data) {
787 /* The fd field */
788 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
789 int n, fd;
790 unsigned char d = (unsigned char) data & 0xff;
791
792 if (IS_NULL(fdObj)) {
793 JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
794 return;
795 } else {
796 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
|
354 */
355 len = sizeof(sa);
356 memset((char *)&sa, 0, len);
357
358 if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
359 if (WSAGetLastError() == WSAENOTSOCK) {
360 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
361 "Socket closed");
362 } else {
363 NET_ThrowNew(env, WSAGetLastError(), "getsockname failed");
364 }
365 return;
366 }
367 localport = (jint) ntohs((u_short)GET_PORT(&sa));
368 (*env)->SetIntField(env, this, psi_localportID, (int) localport);
369 }
370 }
371
372 /*
373 * Class: java_net_DualStackPlainSocketImpl
374 * Method: socketListen
375 * Signature: (I)V
376 */
377 JNIEXPORT void JNICALL
378 Java_java_net_DualStackPlainSocketImpl_socketListen
379 (JNIEnv *env, jobject this, jint count)
380 {
381 /* this FileDescriptor fd field */
382 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
383 /* fdObj's int fd field */
384 int fd = INVALID_SOCKET;
385
386 if (IS_NULL(fdObj)) {
387 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
388 "socket closed");
389 return;
390 }
391
392 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
393
575 JNIEXPORT void JNICALL
576 Java_java_net_DualStackPlainSocketImpl_socketShutdown(JNIEnv *env, jobject this,
577 jint howto)
578 {
579
580 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
581 jint fd;
582
583 if (IS_NULL(fdObj)) {
584 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
585 "socket already closed");
586 return;
587 } else {
588 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
589 }
590 shutdown(fd, howto);
591 }
592
593 /*
594 * Class: java_net_DualStackPlainSocketImpl
595 * Method: socketNativeSetOption
596 * Signature: (IZLjava/lang/Object;)V
597 */
598 JNIEXPORT void JNICALL
599 Java_java_net_DualStackPlainSocketImpl_socketNativeSetOption
600 (JNIEnv *env, jobject this, jint cmd, jboolean on, jobject value)
601 {
602 /* The fd field */
603 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
604
605 jint fd;
606 int level = 0, optname = 0, optlen = 0;
607 union {
608 int i;
609 struct linger ling;
610 } optval;
611
612 memset((char *)&optval, 0, sizeof(optval));
613
614 /*
624 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
625 return;
626 }
627
628 if (cmd == java_net_SocketOptions_SO_TIMEOUT) {
629 // timeout implemented through select.
630 return;
631 }
632
633 /*
634 * Map the Java level socket option to the platform specific
635 * level and option name.
636 */
637 if (NET_MapSocketOption(cmd, &level, &optname)) {
638 JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
639 return;
640 }
641
642 switch (cmd) {
643
644 case java_net_SocketOptions_TCP_NODELAY:
645 case java_net_SocketOptions_SO_OOBINLINE:
646 case java_net_SocketOptions_SO_KEEPALIVE:
647 case java_net_SocketOptions_SO_REUSEADDR:
648 optval.i = (on ? 1 : 0);
649 optlen = sizeof(optval.i);
650 break;
651
652 case java_net_SocketOptions_SO_SNDBUF:
653 case java_net_SocketOptions_SO_RCVBUF:
654 case java_net_SocketOptions_IP_TOS:
655 {
656 jclass cls;
657 jfieldID fid;
658
659 cls = (*env)->FindClass(env, "java/lang/Integer");
660 CHECK_NULL(cls);
661 fid = (*env)->GetFieldID(env, cls, "value", "I");
662 CHECK_NULL(fid);
663
664 optval.i = (*env)->GetIntField(env, value, fid);
665 optlen = sizeof(optval.i);
666 }
667 break;
668
669 case java_net_SocketOptions_SO_LINGER :
670 {
671 jclass cls;
672 jfieldID fid;
673
674 cls = (*env)->FindClass(env, "java/lang/Integer");
691 default: /* shouldn't get here */
692 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
693 "Option not supported by DualStackPlainSocketImpl");
694 return;
695 }
696
697 if (NET_SetSockOpt(fd, level, optname, (void *)&optval, optlen) < 0) {
698 NET_ThrowNew(env, WSAGetLastError(), "setsockopt");
699 }
700 }
701
702 /*
703 * Class: java_net_DualStackPlainSocketImpl
704 * Method: socketNativeGetOption
705 * Signature: (ILjava/lang/Object;)I
706 */
707 JNIEXPORT jint JNICALL
708 Java_java_net_DualStackPlainSocketImpl_socketNativeGetOption
709 (JNIEnv *env, jobject this, jint opt, jobject iaContainerObj)
710 {
711 /* The fd field */
712 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
713
714 int fd;
715 int level = 0, optname = 0, optlen = 0;
716 union {
717 int i;
718 struct linger ling;
719 } optval;
720
721 /*
722 * Get SOCKET and check it hasn't been closed
723 */
724 if (IS_NULL(fdObj)) {
725 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
726 return -1;
727 } else {
728 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
729 }
730 if (fd < 0) {
731 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
732 return -1;
733 }
734 memset((char *)&optval, 0, sizeof(optval));
735
736 /*
737 * SO_BINDADDR isn't a socket option
738 */
739 if (opt == java_net_SocketOptions_SO_BINDADDR) {
740 SOCKETADDRESS sa;
741 int len = sizeof(sa);
742 int port;
743 jobject iaObj;
744 jclass iaContainerClass;
745 jfieldID iaFieldID;
746
747 if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
748 NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
749 return -1;
750 }
751 iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
752 CHECK_NULL_RETURN(iaObj, -1);
753
754 iaContainerClass = (*env)->GetObjectClass(env, iaContainerObj);
755 iaFieldID = (*env)->GetFieldID(env, iaContainerClass, "addr", "Ljava/net/InetAddress;");
756 CHECK_NULL_RETURN(iaFieldID, -1);
757 (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
758 return 0; /* notice change from before */
759 }
760
761 /*
762 * Map the Java level socket option to the platform specific
763 * level and option name.
764 */
765 if (NET_MapSocketOption(opt, &level, &optname)) {
766 JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
767 return -1;
768 }
769
770 /*
771 * Args are int except for SO_LINGER
772 */
773 if (opt == java_net_SocketOptions_SO_LINGER) {
774 optlen = sizeof(optval.ling);
775 } else {
776 optlen = sizeof(optval.i);
777 optval.i = 0;
778 }
779
780 if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) {
781 NET_ThrowNew(env, WSAGetLastError(), "getsockopt");
782 return -1;
783 }
784
785 switch (opt) {
786 case java_net_SocketOptions_SO_LINGER:
787 return (optval.ling.l_onoff ? optval.ling.l_linger: -1);
788
789 case java_net_SocketOptions_SO_SNDBUF:
790 case java_net_SocketOptions_SO_RCVBUF:
791 case java_net_SocketOptions_IP_TOS:
792 return optval.i;
793
794 case java_net_SocketOptions_TCP_NODELAY:
795 case java_net_SocketOptions_SO_OOBINLINE:
796 case java_net_SocketOptions_SO_KEEPALIVE:
797 case java_net_SocketOptions_SO_REUSEADDR:
798 return (optval.i == 0) ? -1 : 1;
799
800 default: /* shouldn't get here */
801 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
802 "Option not supported by TwoStacksPlainSocketImpl");
803 return -1;
804 }
805 }
806
807 /*
808 * Class: java_net_DualStackPlainSocketImpl
809 * Method: socketSendUrgentData
810 * Signature: (B)V
811 */
812 JNIEXPORT void JNICALL
813 Java_java_net_DualStackPlainSocketImpl_socketSendUrgentData(JNIEnv *env, jobject this,
814 jint data) {
815 /* The fd field */
816 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
817 int n, fd;
818 unsigned char d = (unsigned char) data & 0xff;
819
820 if (IS_NULL(fdObj)) {
821 JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
822 return;
823 } else {
824 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
|