[multiple changes]

1999-05-26  Bryce McKinlay <bryce@albatross.co.nz>
	* java/net/DatagramSocket.java (getSoTimeout): Verify class type.
	* java/net/DatagramSocketImpl.java (getOption): Made abstract.
	(setOption): Made abstract.
	* java/net/PlainDatagramSocketImpl.java: Mirror SocketOptions fields
	to avoid cpp conflicts in native code.
	* java/net/PlainSocketImpl.java: Mirror SocketOptions fields to avoid
	cpp conflicts in native code.
	* java/net/ServerSocket.java (toString): Prepended "ServerSocket".
	* java/net/Socket.java (getLocalAddress): Implemented.
	(setTcpNoDelay): Implemented.
	(getTcpNoDelay): Implemented.
	(setSoLinger): Implemented.
	(getSoLinger): Implemented.
	(getSoTimeout): Verify class type.
	(setSendBufferSize): Implemented.
	(getSendBufferSize): Implemented.
	(setReceiveBufferSize): Implemented.
	(getReceiveBufferSize): Implemented.
	(toString): Prepended "Socket".
	* java/net/SocketImpl.java (toString): Rewritten.
	(getOption): Made abstract.
	(setOption): Made abstract.
	* java/net/natPlainSocketImpl.cc (connect): Set localport properly.
	(setOption): Implemented.
	(getOption): Implemented.
1999-05-26  Warren Levy  <warrenl@cygnus.com>
	* java/net/DatagramSocket.java (DatagramSocket): Get local host
	address when null.  Set SO_REUSEADDR for multicasts.
	(getSoTimeout): Implemented.
	(setSoTimeout): Implemented.
	* java/net/DatagramSocketImpl.java: Implement SocketOptions interface.
	* java/net/MulticastSocket.java (getInterface): Implemented.
	(setInterface): Implemented.
	(setTimeToLive): Check for invalid ttl.
	(joinGroup): Verify multicast address and security.
	(leaveGroup): Verify multicast address and security.
	(send): Implemented.
	* java/net/PlainDatagramSocketImpl.java (timeout): Added.
	(iface): Added.
	(ttl): Added.
	(setOption): Added.
	(getOption): Added.
	(mcastGrp): Added.
	(getTTL): Implemented as non-native.
	(setTTL): ditto.
	(join): ditto.
	(leave): ditto.
	* java/net/ServerSocket.java (setSoTimeout): Implemented.
	(getSoTimeout): Implemented.
	(setSocketFactory): Made synchronized.
	* java/net/Socket.java (setSoTimeout): Implemented.
	(getSoTimeout): Implemented.
	(close): Made synchronized.
	(setSocketImplFactory): Made synchronized.
	* java/net/SocketImpl.java: Implement SocketOptions interface.
	* java/net/natInetAddress.cc: Corrected module name at top of file.
	* java/net/natPlainDatagramSocketImpl.cc (McastReq): Added union.
	(bind): Added FIXME.
	(peek): Implemented.
	(setTTL): Removed.
	(getTTL): Removed.
	(join): Removed.
	(leave): Removed.
	(mcastGrp): Added.
	(setOption): Implemented for SO_REUSEADDR.
	(getOption): Implemented for SO_REUSEADDR.

From-SVN: r27184
This commit is contained in:
Warren Levy 1999-05-26 17:00:06 +00:00
parent de4abb91d1
commit f2ed9e9656
13 changed files with 608 additions and 88 deletions

View File

@ -1,3 +1,74 @@
1999-05-26 Bryce McKinlay <bryce@albatross.co.nz>
* java/net/DatagramSocket.java (getSoTimeout): Verify class type.
* java/net/DatagramSocketImpl.java (getOption): Made abstract.
(setOption): Made abstract.
* java/net/PlainDatagramSocketImpl.java: Mirror SocketOptions fields
to avoid cpp conflicts in native code.
* java/net/PlainSocketImpl.java: Mirror SocketOptions fields to avoid
cpp conflicts in native code.
* java/net/ServerSocket.java (toString): Prepended "ServerSocket".
* java/net/Socket.java (getLocalAddress): Implemented.
(setTcpNoDelay): Implemented.
(getTcpNoDelay): Implemented.
(setSoLinger): Implemented.
(getSoLinger): Implemented.
(getSoTimeout): Verify class type.
(setSendBufferSize): Implemented.
(getSendBufferSize): Implemented.
(setReceiveBufferSize): Implemented.
(getReceiveBufferSize): Implemented.
(toString): Prepended "Socket".
* java/net/SocketImpl.java (toString): Rewritten.
(getOption): Made abstract.
(setOption): Made abstract.
* java/net/natPlainSocketImpl.cc (connect): Set localport properly.
(setOption): Implemented.
(getOption): Implemented.
1999-05-26 Warren Levy <warrenl@cygnus.com>
* java/net/DatagramSocket.java (DatagramSocket): Get local host
address when null. Set SO_REUSEADDR for multicasts.
(getSoTimeout): Implemented.
(setSoTimeout): Implemented.
* java/net/DatagramSocketImpl.java: Implement SocketOptions interface.
* java/net/MulticastSocket.java (getInterface): Implemented.
(setInterface): Implemented.
(setTimeToLive): Check for invalid ttl.
(joinGroup): Verify multicast address and security.
(leaveGroup): Verify multicast address and security.
(send): Implemented.
* java/net/PlainDatagramSocketImpl.java (timeout): Added.
(iface): Added.
(ttl): Added.
(setOption): Added.
(getOption): Added.
(mcastGrp): Added.
(getTTL): Implemented as non-native.
(setTTL): ditto.
(join): ditto.
(leave): ditto.
* java/net/ServerSocket.java (setSoTimeout): Implemented.
(getSoTimeout): Implemented.
(setSocketFactory): Made synchronized.
* java/net/Socket.java (setSoTimeout): Implemented.
(getSoTimeout): Implemented.
(close): Made synchronized.
(setSocketImplFactory): Made synchronized.
* java/net/SocketImpl.java: Implement SocketOptions interface.
* java/net/natInetAddress.cc: Corrected module name at top of file.
* java/net/natPlainDatagramSocketImpl.cc (McastReq): Added union.
(bind): Added FIXME.
(peek): Implemented.
(setTTL): Removed.
(getTTL): Removed.
(join): Removed.
(leave): Removed.
(mcastGrp): Added.
(setOption): Implemented for SO_REUSEADDR.
(getOption): Implemented for SO_REUSEADDR.
1999-05-24 Tom Tromey <tromey@cygnus.com>
* java/util/ResourceBundle.java (getBundle): Throw

View File

@ -56,12 +56,19 @@ public class DatagramSocket
// TBD: if this is right then the same should be done in Socket().
try
{
impl.bind(port, laddr == null ? InetAddress.getLocalHost() : laddr);
if (laddr == null)
laddr = InetAddress.getLocalHost();
}
catch (UnknownHostException e)
{
throw new BindException(e.getMessage());
}
// For multicasting, set the socket to be reused (Stevens pp. 195-6).
if (this instanceof MulticastSocket)
impl.setOption(SocketOptions.SO_REUSEADDR, new Boolean(true));
impl.bind(port, laddr);
this.laddr = laddr;
}
@ -82,8 +89,11 @@ public class DatagramSocket
public synchronized int getSoTimeout() throws SocketException
{
// FIXME: TODO - DatagramSocket.getSoTimeout
throw new SocketException("DatagramSocket.getSoTimeout - not yet implemented");
Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT);
if (timeout instanceof Integer)
return ((Integer)timeout).intValue();
else
return 0;
}
public synchronized void receive(DatagramPacket p) throws IOException
@ -114,8 +124,10 @@ public class DatagramSocket
public synchronized void setSoTimeout(int timeout) throws SocketException
{
// FIXME: TODO - DatagramSocket.setSoTimeout
throw new SocketException("DatagramSocket.setSoTimeout - not yet implemented");
if (timeout < 0)
throw new IllegalArgumentException("Invalid timeout: " + timeout);
impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
}
// JDK1.2

View File

@ -23,9 +23,7 @@ import java.io.FileDescriptor;
* Status: Believed complete and correct.
*/
// JDK1.2: needs to implement SocketOptions.
// JDK1.2: public abstract class DatagramSocketImpl implements SocketOptions
public abstract class DatagramSocketImpl
public abstract class DatagramSocketImpl implements SocketOptions
{
protected int localport;
protected FileDescriptor fd;
@ -48,6 +46,10 @@ public abstract class DatagramSocketImpl
protected abstract void join(InetAddress inetaddr) throws IOException;
protected abstract void leave(InetAddress inetaddr) throws IOException;
public abstract Object getOption(int optID) throws SocketException;
public abstract void setOption(int optID, Object value)
throws SocketException;
protected FileDescriptor getFileDescriptor()
{
return fd;

View File

@ -25,7 +25,8 @@ import java.io.IOException;
public class MulticastSocket extends DatagramSocket
{
// FIXME: the local addr bound to the multicast socket can be reused;
// unlike unicast sockets. see p.1159 JCL book.
// unlike unicast sockets. It binds to any available network interface.
// See p.1159 JCL book.
public MulticastSocket() throws IOException
{
@ -39,13 +40,16 @@ public class MulticastSocket extends DatagramSocket
public InetAddress getInterface() throws SocketException
{
// FIXME: TODO - MulticastSocket.getInterface
throw new SocketException("MulticastSocket.getInterface - not yet implemented");
// FIXME: Is it possible that an InetAddress wasn't returned from getOption?
return (InetAddress) impl.getOption(SocketOptions.IP_MULTICAST_IF);
}
// Deprecated in JDK1.2
public byte getTTL() throws IOException
{
// Use getTTL here rather than getTimeToLive in case we're using an impl
// other than the default PlainDatagramSocketImpl and it doesn't have
// getTimeToLive yet.
return impl.getTTL();
}
@ -57,35 +61,66 @@ public class MulticastSocket extends DatagramSocket
public void setInterface(InetAddress inf) throws SocketException
{
// FIXME: TODO - MulticastSocket.setInterface
throw new SocketException("MulticastSocket.setInterface - not yet implemented");
impl.setOption(SocketOptions.IP_MULTICAST_IF, inf);
}
// Deprecated in JDK1.2
public void setTTL(byte ttl) throws IOException
{
// Use setTTL here rather than setTimeToLive in case we're using an impl
// other than the default PlainDatagramSocketImpl and it doesn't have
// setTimeToLive yet.
impl.setTTL(ttl);
}
// JDK1.2
public void setTimeToLive(int ttl) throws IOException
{
if (ttl < 0 || ttl > 255)
throw new IllegalArgumentException("Invalid ttl: " + ttl);
impl.setTimeToLive(ttl);
}
public void joinGroup(InetAddress mcastaddr) throws IOException
{
if (! mcastaddr.isMulticastAddress())
throw new IOException("Not a Multicast address");
SecurityManager s = System.getSecurityManager();
if (s != null)
s.checkMulticast(mcastaddr);
impl.join(mcastaddr);
}
public void leaveGroup(InetAddress mcastaddr) throws IOException
{
if (! mcastaddr.isMulticastAddress())
throw new IOException("Not a Multicast address");
SecurityManager s = System.getSecurityManager();
if (s != null)
s.checkMulticast(mcastaddr);
impl.leave(mcastaddr);
}
public void send(DatagramPacket p, byte ttl) throws IOException
public synchronized void send(DatagramPacket p, byte ttl) throws IOException
{
// FIXME: use ttl instead of getTTL() for time to live.
SecurityManager s = System.getSecurityManager();
if (s != null)
{
InetAddress addr = p.getAddress();
if (addr.isMulticastAddress())
s.checkMulticast(addr, ttl);
else
s.checkConnect(addr.getHostAddress(), p.getPort());
}
int oldttl = impl.getTimeToLive();
impl.setTimeToLive(((int) ttl) & 0xFF);
impl.send(p);
impl.setTimeToLive(oldttl);
}
}

View File

@ -24,13 +24,28 @@ import java.io.IOException;
class PlainDatagramSocketImpl extends DatagramSocketImpl
{
// These fields are mirrored for use in native code to avoid cpp conflicts
// when the #defines in system header files are the same as the public fields.
static final int _Jv_TCP_NODELAY_ = SocketOptions.TCP_NODELAY,
_Jv_SO_BINDADDR_ = SocketOptions.SO_BINDADDR,
_Jv_SO_REUSEADDR_ = SocketOptions.SO_REUSEADDR,
_Jv_IP_MULTICAST_IF_ = SocketOptions.IP_MULTICAST_IF,
_Jv_SO_LINGER_ = SocketOptions.SO_LINGER,
_Jv_SO_TIMEOUT_ = SocketOptions.SO_TIMEOUT,
_Jv_SO_SNDBUF_ = SocketOptions.SO_SNDBUF,
_Jv_SO_RCVBUF_ = SocketOptions.SO_RCVBUF;
int fnum = -1;
InetAddress address; // TBD: DatagramSocket.getLocalAddress()?
// FIXME: These values are set/read by setOption/getOption.
int timeout = 0;
InetAddress iface = null;
int ttl = -1;
// FIXME: Probably should have bind (and create?) calls from DatagramSocket
// constuctor. If so, then same change should be made to the corresponding
// Socket (non-datagram) classes. This allows the implementation more
// compleete control over how the socket is set up and used (e.g. connect,
// complete control over how the socket is set up and used (e.g. connect,
// setting options, etc.).
public PlainDatagramSocketImpl()
{
@ -40,17 +55,39 @@ class PlainDatagramSocketImpl extends DatagramSocketImpl
throws SocketException;
protected native void create() throws SocketException;
protected native int peek(InetAddress i) throws IOException;
protected native void setTTL(byte ttl) throws IOException;
protected native byte getTTL() throws IOException;
protected native void setTimeToLive(int ttl) throws IOException;
protected native int getTimeToLive() throws IOException;
protected native void join(InetAddress inetaddr) throws IOException;
protected native void leave(InetAddress inetaddr) throws IOException;
protected native void send(DatagramPacket p) throws IOException;
protected native void receive(DatagramPacket p) throws IOException;
public native void setOption(int optID, Object value) throws SocketException;
public native Object getOption(int optID) throws SocketException;
private native void mcastGrp(InetAddress inetaddr, boolean join)
throws IOException;
protected void close() throws IOException
{
fd.close();
}
// Deprecated in JDK 1.2.
protected byte getTTL() throws IOException
{
return (byte) getTimeToLive();
}
// Deprecated in JDK 1.2.
protected void setTTL(byte ttl) throws IOException
{
setTimeToLive(((int) ttl) & 0xFF);
}
protected void join(InetAddress inetaddr) throws IOException
{
mcastGrp(inetaddr, true);
}
protected void leave(InetAddress inetaddr) throws IOException
{
mcastGrp(inetaddr, false);
}
}

View File

@ -24,8 +24,23 @@ import java.io.*;
class PlainSocketImpl extends SocketImpl
{
// These fields are mirrored for use in native code to avoid cpp conflicts
// when the #defines in system header files are the same as the public fields.
static final int _Jv_TCP_NODELAY_ = SocketOptions.TCP_NODELAY,
_Jv_SO_BINDADDR_ = SocketOptions.SO_BINDADDR,
_Jv_SO_REUSEADDR_ = SocketOptions.SO_REUSEADDR,
_Jv_IP_MULTICAST_IF_ = SocketOptions.IP_MULTICAST_IF,
_Jv_SO_LINGER_ = SocketOptions.SO_LINGER,
_Jv_SO_TIMEOUT_ = SocketOptions.SO_TIMEOUT,
_Jv_SO_SNDBUF_ = SocketOptions.SO_SNDBUF,
_Jv_SO_RCVBUF_ = SocketOptions.SO_RCVBUF;
int fnum = -1;
public native void setOption(int optID, Object value) throws SocketException;
public native Object getOption(int optID) throws SocketException;
protected native void create (boolean stream) throws IOException;
protected void connect (String host, int port) throws IOException

View File

@ -1,4 +1,4 @@
// Socket.java
// ServerSocket.java
/* Copyright (C) 1999 Cygnus Solutions
@ -14,8 +14,7 @@ details. */
*/
/** Written using on-line Java Platform 1.2 API Specification.
* Status: I believe all methods are implemented, but many
* of them just throw an exception.
* Status: I believe all methods are implemented.
*/
package java.net;
@ -81,25 +80,31 @@ public class ServerSocket
impl.close();
}
public void setSoTimeout (int timeout) throws SocketException
public synchronized void setSoTimeout (int timeout) throws SocketException
{
throw new InternalError("ServerSocket.setSoTimeout not implemented");
if (timeout < 0)
throw new IllegalArgumentException("Invalid timeout: " + timeout);
impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
}
public int getSoTimeout () throws SocketException
public synchronized int getSoTimeout () throws SocketException
{
throw new InternalError("ServerSocket.getSoTimeout not implemented");
Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT);
if (timeout instanceof Integer)
return ((Integer)timeout).intValue();
else
return 0;
}
public String toString ()
{
return impl.toString();
return "ServerSocket" + impl.toString();
}
public static void setSocketFactory (SocketImplFactory fac)
public static synchronized void setSocketFactory (SocketImplFactory fac)
throws IOException
{
factory = fac;
}
}

View File

@ -14,8 +14,7 @@ details. */
*/
/** Written using on-line Java Platform 1.2 API Specification.
* Status: I believe all methods are implemented, but many
* of them just throw an exception.
* Status: I believe all methods are implemented.
*/
package java.net;
@ -116,9 +115,18 @@ public class Socket
public InetAddress getLocalAddress ()
{
// There doesn't seem to be any way to implement this
// using a (generic) SocketImpl ... What am I missing?
throw new InternalError("Socket.getLocalAddres not implemented");
InetAddress localAddress;
try
{
localAddress = (InetAddress)impl.getOption(SocketOptions.SO_BINDADDR);
}
catch (SocketException x)
{
// (hopefully) shouldn't happen
System.err.println(x);
throw new java.lang.InternalError("Error in PlainSocketImpl.getOption");
}
return localAddress;
}
public int getPort ()
@ -143,65 +151,98 @@ public class Socket
public void setTcpNoDelay (boolean on) throws SocketException
{
throw new InternalError("Socket.setTcpNoDelay not implemented");
impl.setOption( SocketOptions.TCP_NODELAY, new Boolean(on) );
}
public boolean getTcpNoDelay() throws SocketException
{
throw new InternalError("Socket.getTcpNoDelay not implemented");
Boolean bool = (Boolean)impl.getOption( SocketOptions.TCP_NODELAY );
return bool.booleanValue();
}
public void setSoLinger(boolean on, int linger) throws SocketException
{
throw new InternalError("Socket.setSoLinger not implemented");
if ( on && (linger >= 0) )
{
if (linger > 65535)
linger = 65535;
impl.setOption( SocketOptions.SO_LINGER, new Integer(linger) );
}
else if ( on && (linger < 0) )
throw new IllegalArgumentException("SO_LINGER must be >= 0");
else
impl.setOption( SocketOptions.SO_LINGER, new Boolean(false) );
}
public int getSoLinger() throws SocketException
{
throw new InternalError("Socket.getSoLinger not implemented");
Object linger = impl.getOption(SocketOptions.SO_LINGER);
if (linger instanceof Integer)
return ((Integer)linger).intValue();
else
return -1;
}
public void setSoTimeout (int timeout) throws SocketException
public synchronized void setSoTimeout (int timeout) throws SocketException
{
throw new InternalError("Socket.setSoTimeout not implemented");
if (timeout < 0)
throw new IllegalArgumentException("Invalid timeout: " + timeout);
impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
}
public int getSoTimeout () throws SocketException
public synchronized int getSoTimeout () throws SocketException
{
throw new InternalError("Socket.getSoTimeout not implemented");
Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT);
if (timeout instanceof Integer)
return ((Integer)timeout).intValue();
else
return 0;
}
// JDK1.2
public void setSendBufferSize (int size) throws SocketException
{
throw new InternalError("Socket.setSendBufferSize not implemented");
if (size <= 0)
throw new IllegalArgumentException("Invalid buffer size: " + size);
impl.setOption(SocketOptions.SO_SNDBUF, new Integer(size));
}
// JDK1.2
public int getSendBufferSize () throws SocketException
{
throw new InternalError("Socket.getSendBufferSize not implemented");
Integer buf = (Integer)impl.getOption(SocketOptions.SO_SNDBUF);
return buf.intValue();
}
// JDK1.2
public void setReceiveBufferSize (int size) throws SocketException
{
throw new InternalError("Socket.setReceiveBufferSize not implemented");
if (size <= 0)
throw new IllegalArgumentException("Invalid buffer size: " + size);
impl.setOption(SocketOptions.SO_RCVBUF, new Integer(size));
}
// JDK1.2
public int getReceiveBufferSize () throws SocketException
{
throw new InternalError("Socket.getReceiveBufferSize not implemented");
Integer buf = (Integer)impl.getOption(SocketOptions.SO_RCVBUF);
return buf.intValue();
}
public void close () throws IOException
public synchronized void close () throws IOException
{
impl.close();
}
public String toString ()
{
return impl.toString();
return "Socket" + impl.toString();
}
public static void setSocketImplFactory (SocketImplFactory fac)
public static synchronized void setSocketImplFactory (SocketImplFactory fac)
throws IOException
{
factory = fac;

View File

@ -17,12 +17,10 @@ import java.io.*;
*/
/** Written using on-line Java Platform 1.2 API Specification.
* Believed complete and correct, except for implementation of toString.
* Believed complete and correct.
*/
// JDK1.2: needs to implement SocketOptions.
// JDK1.2: public abstract class SocketImpl implements SocketOptions
public abstract class SocketImpl
public abstract class SocketImpl implements SocketOptions
{
protected InetAddress address;
@ -65,8 +63,14 @@ public abstract class SocketImpl
protected int getLocalPort () { return localport; }
public abstract Object getOption(int optID) throws SocketException;
public abstract void setOption(int optID, Object value)
throws SocketException;
public String toString ()
{
return super.toString(); // FIXME
return "[addr=" + address.toString() + ",port=" + Integer.toString(port) +
",localport=" + Integer.toString(localport) + "]";
}
}

View File

@ -29,10 +29,10 @@ public abstract interface SocketOptions
public static final int SO_LINGER = 0x80;
public static final int SO_TIMEOUT = 0x1006;
// JDK1.2
// JDK1.2
public static final int SO_SNDBUF = 0x1001;
// JDK1.2
// JDK1.2
public static final int SO_RCVBUF = 0x1002;
public void setOption(int optID, Object value) throws SocketException;

View File

@ -1,4 +1,4 @@
// natClass.cc - Implementation of java.lang.Class native methods.
// natInetAddress.cc
/* Copyright (C) 1998, 1999 Cygnus Solutions

View File

@ -23,6 +23,7 @@ details. */
#include <java/net/PlainDatagramSocketImpl.h>
#include <java/net/InetAddress.h>
#include <java/net/DatagramPacket.h>
#include <java/lang/Boolean.h>
#ifndef HAVE_SOCKLEN_T
typedef int socklen_t;
@ -36,6 +37,15 @@ union SockAddr
#endif
};
union McastReq
{
struct ip_mreq mreq;
#ifdef HAVE_INET6
struct ipv6_mreq mreq6;
#endif
};
// FIXME: routines here and/or in natPlainSocketImpl.cc could throw
// NoRouteToHostException; also consider UnknownHostException, ConnectException.
@ -58,6 +68,7 @@ void
java::net::PlainDatagramSocketImpl::bind (jint lport,
java::net::InetAddress *host)
{
// FIXME: prob. need to do a setsockopt with SO_BROADCAST to allow multicast.
union SockAddr u;
jbyteArray haddress = host->address;
jbyte *bytes = elements (haddress);
@ -97,9 +108,41 @@ java::net::PlainDatagramSocketImpl::bind (jint lport,
jint
java::net::PlainDatagramSocketImpl::peek (java::net::InetAddress *i)
{
// FIXME: TODO - PlainDatagramSocketImpl::peek
// throws IOException;
return 0;
// FIXME: Deal with Multicast and if the socket is connected.
union SockAddr u;
socklen_t addrlen = sizeof(u);
ssize_t retlen =
::recvfrom (fnum, (char *) NULL, 0, MSG_PEEK, (sockaddr*) &u,
&addrlen);
if (retlen < 0)
goto error;
// FIXME: Deal with Multicast addressing and if the socket is connected.
jbyteArray raddr;
jint rport;
if (u.address.sin_family == AF_INET)
{
raddr = JvNewByteArray (4);
memcpy (elements (raddr), &u.address.sin_addr, 4);
rport = ntohs (u.address.sin_port);
}
#ifdef HAVE_INET6
else if (u.address.sin_family == AF_INET6)
{
raddr = JvNewByteArray (16);
memcpy (elements (raddr), &u.address6.sin6_addr, 16);
rport = ntohs (u.address6.sin6_port);
}
#endif
else
goto error;
// FIXME: Multicast: s->address = new InetAddress (raddr, NULL);
i->address = raddr;
return rport;
error:
char msg[100];
char* strerr = strerror (errno);
sprintf (msg, "DatagramSocketImpl.peek: %.*s", 80, strerr);
JvThrow (new java::io::IOException (JvNewStringUTF (msg)));
}
void
@ -182,21 +225,6 @@ java::net::PlainDatagramSocketImpl::receive (java::net::DatagramPacket *p)
JvThrow (new java::io::IOException (JvNewStringUTF (msg)));
}
void
java::net::PlainDatagramSocketImpl::setTTL (jbyte ttl)
{
// FIXME: TODO - :PlainDatagramSocketImpl::setTTL
// throws IOException;
}
jbyte
java::net::PlainDatagramSocketImpl::getTTL ()
{
// FIXME: TODO - PlainDatagramSocketImpl::getTTL
// throws IOException;
return 0;
}
void
java::net::PlainDatagramSocketImpl::setTimeToLive (jint ttl)
{
@ -213,15 +241,86 @@ java::net::PlainDatagramSocketImpl::getTimeToLive ()
}
void
java::net::PlainDatagramSocketImpl::join (java::net::InetAddress *inetaddr)
java::net::PlainDatagramSocketImpl::mcastGrp (java::net::InetAddress *inetaddr,
jboolean join)
{
// throws IOException;
// FIXME: TODO - PlainDatagramSocketImpl::join
union McastReq u;
jbyteArray haddress = inetaddr->address;
jbyte *bytes = elements (haddress);
int len = haddress->length;
int level, opname;
const char *ptr;
if (len == 4)
{
level = IPPROTO_IP;
opname = join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
memcpy (&u.mreq.imr_multiaddr, bytes, len);
// FIXME: If a non-default interface is set, use it; see Stevens p. 501.
u.mreq.imr_interface.s_addr = htonl (INADDR_ANY);
len = sizeof (struct ip_mreq);
ptr = (const char *) &u.mreq;
}
#ifdef HAVE_INET6
else if (len == 16)
{
level = IPPROTO_IPV6;
opname = join ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
memcpy (&u.mreq6.ipv6mr_multiaddr, bytes, len);
// FIXME: If a non-default interface is set, use it; see Stevens p. 501.
u.mreq6.ipv6mr_interface = 0;
len = sizeof (struct ipv6_mreq);
ptr = (const char *) &u.mreq6;
}
#endif
else
goto error;
if (::setsockopt (fnum, level, opname, ptr, len) == 0)
return;
error:
char msg[100];
char* strerr = strerror (errno);
sprintf (msg, "DatagramSocketImpl.%s: %.*s", join ? "join" : "leave", 80,
strerr);
JvThrow (new java::io::IOException (JvNewStringUTF (msg)));
}
void
java::net::PlainDatagramSocketImpl::leave (java::net::InetAddress *inetaddr)
java::net::PlainDatagramSocketImpl::setOption (jint optID,
java::lang::Object *value)
{
// throws IOException;
// FIXME: TODO - PlainDatagramSocketImpl::leave
if (optID == _Jv_SO_REUSEADDR_)
{
// FIXME: Is it possible that a Boolean wasn't passed in?
const int on = (((java::lang::Boolean *) value)->booleanValue()) ? 1 : 0;
if (::setsockopt (fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &on,
sizeof (int)) == 0)
return;
}
else
errno = ENOPROTOOPT;
char msg[100];
char* strerr = strerror (errno);
sprintf (msg, "DatagramSocketImpl.setOption: %.*s", 80, strerr);
JvThrow (new java::net::SocketException (JvNewStringUTF (msg)));
}
java::lang::Object *
java::net::PlainDatagramSocketImpl::getOption (jint optID)
{
if (optID == _Jv_SO_REUSEADDR_)
{
int on;
socklen_t len;
if (::getsockopt (fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &on,
(socklen_t *) &len) == 0)
return new java::lang::Boolean (on == 1);
}
else
errno = ENOPROTOOPT;
char msg[100];
char* strerr = strerror (errno);
sprintf (msg, "DatagramSocketImpl.getOption: %.*s", 80, strerr);
JvThrow (new java::net::SocketException (JvNewStringUTF (msg)));
}

View File

@ -11,17 +11,25 @@ details. */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <cni.h>
#include <javaprims.h>
#include <java/io/IOException.h>
#include <java/io/FileDescriptor.h>
#include <java/net/BindException.h>
#include <java/net/ConnectException.h>
#include <java/net/PlainSocketImpl.h>
#include <java/net/InetAddress.h>
#include <java/net/SocketException.h>
#include <java/lang/InternalError.h>
#include <java/lang/Object.h>
#include <java/lang/Boolean.h>
#include <java/lang/Class.h>
#include <java/lang/Integer.h>
#ifndef HAVE_SOCKLEN_T
typedef int socklen_t;
@ -93,6 +101,7 @@ void
java::net::PlainSocketImpl::connect (java::net::InetAddress *host, jint rport)
{
union SockAddr u;
socklen_t addrlen = sizeof(u);
jbyteArray haddress = host->address;
jbyte *bytes = elements (haddress);
int len = haddress->length;
@ -115,12 +124,14 @@ java::net::PlainSocketImpl::connect (java::net::InetAddress *host, jint rport)
#endif
else
goto error;
if (::connect (fnum, ptr, len) == 0)
{
address = host;
port = rport;
return;
}
if (::connect (fnum, ptr, len) != 0)
goto error;
address = host;
port = rport;
if (::getsockname (fnum, (sockaddr*) &u, &addrlen) != 0)
goto error;
localport = ntohs (u.address.sin_port);
return;
error:
char msg[100];
char* strerr = strerror (errno);
@ -178,3 +189,191 @@ java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl *s)
sprintf (msg, "SocketImpl.accept: %.*s", 80, strerr);
JvThrow (new java::io::IOException (JvNewStringUTF (msg)));
}
void
java::net::PlainSocketImpl::setOption (jint optID, java::lang::Object *value)
{
int val;
socklen_t val_len = sizeof (val);
if ( _Jv_IsInstanceOf(value,
java::lang::Class::forName(JvNewStringUTF("java.lang.Boolean"))))
{
java::lang::Boolean *boolobj =
static_cast<java::lang::Boolean *> (value);
if (boolobj->booleanValue())
val = 1;
else
{
if (optID == _Jv_SO_LINGER_)
val = -1;
else
val = 0;
}
}
else // assume value is an Integer
{
java::lang::Integer *intobj =
static_cast<java::lang::Integer *> (value);
val = (int) intobj->intValue();
}
switch (optID)
{
case _Jv_TCP_NODELAY_ :
#ifdef TCP_NODELAY
if (::setsockopt (fnum, IPPROTO_TCP, TCP_NODELAY, (char *) &val,
val_len) != 0)
goto error;
#else
JvThrow (new java::lang::InternalError (
JvNewStringUTF ("TCP_NODELAY not supported")));
#endif /* TCP_NODELAY */
return;
case _Jv_SO_LINGER_ :
#ifdef SO_LINGER
struct linger l_val;
l_val.l_onoff = (val != -1);
l_val.l_linger = val;
if (::setsockopt (fnum, SOL_SOCKET, SO_LINGER, (char *) &l_val,
sizeof(l_val)) != 0)
goto error;
#else
JvThrow (new java::lang::InternalError (
JvNewStringUTF ("SO_LINGER not supported")));
#endif /* SO_LINGER */
return;
case _Jv_SO_SNDBUF_ :
case _Jv_SO_RCVBUF_ :
#if defined(SO_SNDBUF) && defined(SO_RCVBUF)
int opt;
optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
if (::setsockopt (fnum, SOL_SOCKET, opt, (char *) &val, val_len) != 0)
goto error;
#else
JvThrow (new java::lang::InternalError (
JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported")));
#endif
return;
case _Jv_SO_BINDADDR_ :
JvThrow (new java::net::SocketException (
JvNewStringUTF ("SO_BINDADDR: read only option")));
return;
case _Jv_IP_MULTICAST_IF_ :
JvThrow (new java::lang::InternalError (
JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP")));
return;
case _Jv_SO_REUSEADDR_ :
JvThrow (new java::lang::InternalError (
JvNewStringUTF ("SO_REUSEADDR: option not implemented")));
return;
case _Jv_SO_TIMEOUT_ :
JvThrow (new java::lang::InternalError (
JvNewStringUTF ("SO_TIMEOUT: option not implemented")));
return;
default :
errno = ENOPROTOOPT;
}
error:
char msg[100];
char* strerr = strerror (errno);
sprintf (msg, "SocketImpl.setOption: %.*s", 80, strerr);
JvThrow (new java::net::SocketException (JvNewStringUTF (msg)));
}
java::lang::Object *
java::net::PlainSocketImpl::getOption (jint optID)
{
int val;
socklen_t val_len = sizeof(val);
union SockAddr u;
socklen_t addrlen = sizeof(u);
struct linger l_val;
socklen_t l_val_len = sizeof(l_val);
switch (optID)
{
#ifdef TCP_NODELAY
case _Jv_TCP_NODELAY_ :
if (::getsockopt (fnum, IPPROTO_TCP, TCP_NODELAY, (char *) &val,
&val_len) != 0)
goto error;
else
return new java::lang::Boolean (val != 0);
#else
JvThrow (new java::lang::InternalError (
JvNewStringUTF ("TCP_NODELAY not supported")));
#endif
break;
case _Jv_SO_LINGER_ :
#ifdef SO_LINGER
if (::getsockopt (fnum, SOL_SOCKET, SO_LINGER, (char *) &l_val,
&l_val_len) != 0)
goto error;
if (l_val.l_onoff)
return new java::lang::Integer (l_val.l_linger);
else
return new java::lang::Boolean (false);
#else
JvThrow (new java::lang::InternalError (
JvNewStringUTF ("SO_LINGER not supported")));
#endif
break;
case _Jv_SO_RCVBUF_ :
case _Jv_SO_SNDBUF_ :
#if defined(SO_SNDBUF) && defined(SO_RCVBUF)
int opt;
optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
if (::getsockopt (fnum, SOL_SOCKET, opt, (char *) &val, &val_len) != 0)
goto error;
else
return new java::lang::Integer (val);
#else
JvThrow (new java::lang::InternalError (
JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported")));
#endif
break;
case _Jv_SO_BINDADDR_:
jbyteArray laddr;
if (::getsockname (fnum, (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
goto error;
return new java::net::InetAddress (laddr, NULL);
break;
case _Jv_IP_MULTICAST_IF_ :
JvThrow (new java::lang::InternalError (
JvNewStringUTF ("IP_MULTICAST_IF: option not implemented")));
break;
case _Jv_SO_REUSEADDR_ :
JvThrow (new java::lang::InternalError (
JvNewStringUTF ("SO_REUSEADDR: option not implemented")));
break;
case _Jv_SO_TIMEOUT_ :
JvThrow (new java::lang::InternalError (
JvNewStringUTF ("SO_TIMEOUT: option not implemented")));
break;
default :
errno = ENOPROTOOPT;
}
error:
char msg[100];
char* strerr = strerror (errno);
sprintf (msg, "SocketImpl.getOption: %.*s", 80, strerr);
JvThrow (new java::net::SocketException (JvNewStringUTF (msg)));
}