This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Re: Patch: IP_MULTICAST_LOOP support
On Mon, 2005-01-31 at 13:03 -0700, Tom Tromey wrote:
> >>>>> "Anthony" == Anthony Green <green@redhat.com> writes:
>
> >> http://www.linux.org/docs/ldp/howto/Multicast-HOWTO-6.html
> >> ... the 'val' argument must be an 'unsigned char'.
>
> Anthony> "must be"? I thought there was some flexibility here, as we
> Anthony> also pass the size of 'val' as the last argument.
>
> Yeah, I wonder about that. It is conceivable that the kernel just
> checks the value and if it is not '1', returns EINVAL. Could you
> check this? I'm ok with an actual test or with just looking at the
> kernel source. Or I suppose finding a definitive source for the docs,
> SUS or something.
The LSB says that it must be an integer.
http://refspecs.freestandards.org/LSB_2.0.1/LSB-generic/LSB-generic.txt
"IP_MULTICAST_LOOP
Sets a boolean flag indicating whether multicast packets originating
locally should be looped back to the local sockets. optval is a pointer to
an integer which contains the new flag value."
> I also wonder whether the getsockopt code for this option is correct.
No. See attached revised patch.
> Anthony> The attached patch also enables the SO_REUSEADDR option. I
> Anthony> think this was disabled in error..
>
> I tracked this down to the very beginnings of our java.net, as written
> by Warren. My random googling shows that this is probably incorrect
> though.
>
> This part of the patch is fine as far as it goes... but could you
> also fix the getsockopt part?
Ok, see attached.
Thanks,
AG
2005-01-31 Anthony Green <green@redhat.com>
* gnu/java/net/natPlainDatagramSocketImplPosix.cc (getOption):
Support IP_MULTICAST_LOOP.
(setOption): Support IP_MULTICAST_LOOP.
* gnu/java/net/natPlainSocketImplPosix.cc (setOption): Add
SO_REUSEADDR support.
(getOption): Support SO_REUSEADDR.
Index: gnu/java/net/natPlainDatagramSocketImplPosix.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/net/natPlainDatagramSocketImplPosix.cc,v
retrieving revision 1.7
diff -c -u -p -r1.7 natPlainDatagramSocketImplPosix.cc
--- gnu/java/net/natPlainDatagramSocketImplPosix.cc 17 Mar 2004 08:10:28 -0000 1.7
+++ gnu/java/net/natPlainDatagramSocketImplPosix.cc 1 Feb 2005 04:47:02 -0000
@@ -602,9 +602,27 @@ gnu::java::net::PlainDatagramSocketImpl:
return;
case _Jv_IP_MULTICAST_LOOP_ :
- throw new ::java::net::SocketException (
- JvNewStringUTF ("IP_MULTICAST_LOOP: not yet implemented"));
- return;
+ haddress = ((::java::net::InetAddress *) value)->addr;
+ len = haddress->length;
+ if (len == 4)
+ {
+ level = IPPROTO_IP;
+ opname = IP_MULTICAST_LOOP;
+ }
+#if defined (HAVE_INET6) && defined (IPV6_MULTICAST_LOOP)
+ else if (len == 16)
+ {
+ level = IPPROTO_IPV6;
+ opname = IPV6_MULTICAST_LOOP;
+ }
+#endif
+ else
+ throw
+ new ::java::net::SocketException (JvNewStringUTF ("invalid address length"));
+ if (::setsockopt (native_fd, level, opname, (char *) &val,
+ val_len) != 0)
+ goto error;
+ return;
case _Jv_IP_TOS_ :
if (::setsockopt (native_fd, SOL_SOCKET, IP_TOS, (char *) &val,
@@ -631,6 +649,7 @@ gnu::java::net::PlainDatagramSocketImpl:
socklen_t val_len = sizeof(val);
union SockAddr u;
socklen_t addrlen = sizeof(u);
+ int level, opname;
switch (optID)
{
@@ -738,8 +757,47 @@ gnu::java::net::PlainDatagramSocketImpl:
break;
case _Jv_IP_MULTICAST_LOOP_ :
- if (::getsockopt (native_fd, SOL_SOCKET, IP_MULTICAST_LOOP, (char *) &val,
- &val_len) != 0)
+ // cache the local address
+ if (localAddress == NULL)
+ {
+ jbyteArray laddr;
+ if (::getsockname (native_fd, (sockaddr*) &u, &addrlen) != 0)
+ goto error;
+ if (u.address.sin_family == AF_INET)
+ {
+ laddr = JvNewByteArray (4);
+ memcpy (elements (laddr), &u.address.sin_addr, 4);
+ }
+#ifdef HAVE_INET6
+ else if (u.address.sin_family == AF_INET6)
+ {
+ laddr = JvNewByteArray (16);
+ memcpy (elements (laddr), &u.address6.sin6_addr, 16);
+ }
+#endif
+ else
+ throw new ::java::net::SocketException (
+ JvNewStringUTF ("invalid family"));
+ localAddress = new ::java::net::InetAddress (laddr, NULL);
+
+ }
+ if (localAddress->addr->length == 4)
+ {
+ level = IPPROTO_IP;
+ opname = IP_MULTICAST_LOOP;
+ }
+#if defined (HAVE_INET6) && defined (IPV6_MULTICAST_LOOP)
+ else if (localAddress->addr->length == 16)
+ {
+ level = IPPROTO_IPV6;
+ opname = IPV6_MULTICAST_LOOP;
+ }
+#endif
+ else
+ throw
+ new ::java::net::SocketException (JvNewStringUTF ("invalid address length"));
+ if (::getsockopt (native_fd, level, opname, (char *) &val,
+ &val_len) != 0)
goto error;
return new ::java::lang::Boolean (val != 0);
Index: gnu/java/net/natPlainSocketImplPosix.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/net/natPlainSocketImplPosix.cc,v
retrieving revision 1.10
diff -c -u -p -r1.10 natPlainSocketImplPosix.cc
--- gnu/java/net/natPlainSocketImplPosix.cc 22 Oct 2004 15:27:04 -0000 1.10
+++ gnu/java/net/natPlainSocketImplPosix.cc 1 Feb 2005 04:47:02 -0000
@@ -637,9 +637,14 @@ gnu::java::net::PlainSocketImpl::setOpti
return;
case _Jv_SO_REUSEADDR_ :
- throw new ::java::net::SocketException (
- JvNewStringUTF ("SO_REUSEADDR: not valid for TCP"));
- return;
+#if defined(SO_REUSEADDR)
+ if (::setsockopt (native_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
+ val_len) != 0)
+ goto error;
+#else
+ throw new ::java::lang::InternalError (
+ JvNewStringUTF ("SO_REUSEADDR not supported"));
+#endif
case _Jv_SO_TIMEOUT_ :
timeout = val;
@@ -780,8 +785,14 @@ gnu::java::net::PlainSocketImpl::getOpti
break;
case _Jv_SO_REUSEADDR_ :
- throw new ::java::net::SocketException
- (JvNewStringUTF ("SO_REUSEADDR: not valid for TCP"));
+#if defined(SO_REUSEADDR)
+ if (::getsockopt (native_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
+ &val_len) != 0)
+ goto error;
+#else
+ throw new ::java::lang::InternalError (
+ JvNewStringUTF ("SO_REUSEADDR not supported"));
+#endif
break;
case _Jv_SO_TIMEOUT_ :