DatagramSocket.java, [...]: Use gnu.java.net.Plain*SocketImpl instead of java.net.PlainSocketImpl.
2003-09-10 Michael Koch <konqueror@gmx.de> * java/net/DatagramSocket.java, java/net/MulticastSocket.java, java/net/ServerSocket.java, java/net/Socket.java: Use gnu.java.net.Plain*SocketImpl instead of java.net.PlainSocketImpl. * java/net/PlainDatagramSocketImpl.java, java/net/PlainSocketImpl.java, java/net/SocketInputStream.java, java/net/SocketOutputStream.java, java/net/natPlainDatagramSocketImplNoNet.cc, java/net/natPlainDatagramSocketImplPosix.cc, java/net/natPlainDatagramSocketImplWin32.cc, java/net/natPlainSocketImplNoNet.cc, java/net/natPlainSocketImplPosix.cc, java/net/natPlainSocketImplWin32.cc: Removed. * gnu/java/net/PlainDatagramSocketImpl.java, gnu/java/net/PlainSocketImpl.java, gnu/java/net/SocketInputStream.java, gnu/java/net/SocketOutputStream.java, gnu/java/net/natPlainDatagramSocketImplNoNet.cc, gnu/java/net/natPlainDatagramSocketImplPosix.cc, gnu/java/net/natPlainDatagramSocketImplWin32.cc, gnu/java/net/natPlainSocketImplNoNet.cc, gnu/java/net/natPlainSocketImplPosix.cc, gnu/java/net/natPlainSocketImplWin32.cc: New files (moved from java/net). * configure.in: Create links for gnu/java/net/natPlain*SocketImpl.cc instead of java/net/natPlain*SocketImpl.cc. * configure: Regenerated. * Makefile.am: Moved files from java/net to gnu/java/net. * Makefile.in: Regenerated. From-SVN: r71274
This commit is contained in:
parent
520abf6930
commit
4a503716e0
21 changed files with 956 additions and 898 deletions
|
@ -35,8 +35,10 @@ this exception to your version of the library, but you are not
|
|||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package java.net;
|
||||
|
||||
import gnu.java.net.PlainDatagramSocketImpl;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.nio.channels.IllegalBlockingModeException;
|
||||
|
@ -266,38 +268,30 @@ public class DatagramSocket
|
|||
*/
|
||||
public InetAddress getLocalAddress()
|
||||
{
|
||||
// FIXME: JCL p. 510 says this should call checkConnect. But what
|
||||
// string should be used as the hostname? Maybe this is just a side
|
||||
// effect of calling InetAddress.getLocalHost.
|
||||
//
|
||||
// And is getOption with SO_BINDADDR the right way to get the address?
|
||||
// Doesn't seem to be since this method doesn't throw a SocketException
|
||||
// and SO_BINADDR can throw one.
|
||||
//
|
||||
// Also see RETURNS section in JCL p. 510 about returning any local
|
||||
// addr "if the current execution context is not allowed to connect to
|
||||
// the network interface that is actually bound to this datagram socket."
|
||||
// How is that done? via InetAddress.getLocalHost? But that throws
|
||||
// an UnknownHostException and this method doesn't.
|
||||
//
|
||||
// if (s != null)
|
||||
// s.checkConnect("localhost", -1);
|
||||
if (impl == null
|
||||
|| closed)
|
||||
return null;
|
||||
|
||||
InetAddress result;
|
||||
|
||||
try
|
||||
{
|
||||
return (InetAddress)impl.getOption(SocketOptions.SO_BINDADDR);
|
||||
result = (InetAddress) impl.getOption (SocketOptions.SO_BINDADDR);
|
||||
|
||||
SecurityManager s = System.getSecurityManager();
|
||||
if (s != null)
|
||||
s.checkConnect (result.getHostName(), -1);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
catch (SecurityException e)
|
||||
{
|
||||
result = InetAddress.ANY_IF;
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
result = InetAddress.ANY_IF;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return InetAddress.getLocalHost();
|
||||
}
|
||||
catch (UnknownHostException ex)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -36,8 +36,10 @@ this exception to your version of the library, but you are not
|
|||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package java.net;
|
||||
|
||||
import gnu.java.net.PlainDatagramSocketImpl;
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
|
||||
|
|
|
@ -1,272 +0,0 @@
|
|||
/* PlainDatagramSocketImpl.java -- Default DatagramSocket implementation
|
||||
Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.IOException;
|
||||
import gnu.classpath.Configuration;
|
||||
|
||||
/**
|
||||
* Written using on-line Java Platform 1.2 API Specification, as well
|
||||
* as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
|
||||
* Status: Believed complete and correct.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is the default socket implementation for datagram sockets.
|
||||
* It makes native calls to C routines that implement BSD style
|
||||
* SOCK_DGRAM sockets in the AF_INET family.
|
||||
*
|
||||
* @author Aaron M. Renn <arenn@urbanophile.com>
|
||||
* @author Warren Levy <warrenl@cygnus.com>
|
||||
*/
|
||||
class PlainDatagramSocketImpl extends DatagramSocketImpl
|
||||
{
|
||||
// Static initializer to load native library
|
||||
static
|
||||
{
|
||||
if (Configuration.INIT_LOAD_LIBRARY)
|
||||
{
|
||||
System.loadLibrary("javanet");
|
||||
}
|
||||
}
|
||||
|
||||
// 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_SO_BROADCAST_ = SocketOptions.SO_BROADCAST,
|
||||
_Jv_SO_OOBINLINE_ = SocketOptions.SO_OOBINLINE,
|
||||
_Jv_IP_MULTICAST_IF_ = SocketOptions.IP_MULTICAST_IF,
|
||||
_Jv_IP_MULTICAST_IF2_ = SocketOptions.IP_MULTICAST_IF2,
|
||||
_Jv_IP_MULTICAST_LOOP_ = SocketOptions.IP_MULTICAST_LOOP,
|
||||
_Jv_IP_TOS_ = SocketOptions.IP_TOS,
|
||||
_Jv_SO_LINGER_ = SocketOptions.SO_LINGER,
|
||||
_Jv_SO_TIMEOUT_ = SocketOptions.SO_TIMEOUT,
|
||||
_Jv_SO_SNDBUF_ = SocketOptions.SO_SNDBUF,
|
||||
_Jv_SO_RCVBUF_ = SocketOptions.SO_RCVBUF,
|
||||
_Jv_SO_KEEPALIVE_ = SocketOptions.SO_KEEPALIVE;
|
||||
|
||||
/**
|
||||
* This is the actual underlying file descriptor
|
||||
*/
|
||||
int fnum = -1;
|
||||
|
||||
// FIXME: Is this necessary? Could it help w/ DatagramSocket.getLocalAddress?
|
||||
// InetAddress address;
|
||||
|
||||
// localAddress cache
|
||||
InetAddress localAddress;
|
||||
|
||||
// 'timeout' is set/read by setOption/getOption.
|
||||
int timeout = 0;
|
||||
|
||||
/**
|
||||
* Default do nothing constructor
|
||||
*/
|
||||
public PlainDatagramSocketImpl()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds this socket to a particular port and interface
|
||||
*
|
||||
* @param port The port to bind to
|
||||
* @param addr The address to bind to
|
||||
*
|
||||
* @exception SocketException If an error occurs
|
||||
*/
|
||||
protected native void bind(int lport, InetAddress laddr)
|
||||
throws SocketException;
|
||||
|
||||
protected native void connect (InetAddress i, int port)
|
||||
throws SocketException;
|
||||
|
||||
protected native void disconnect ();
|
||||
|
||||
/**
|
||||
* Creates a new datagram socket
|
||||
*
|
||||
* @exception SocketException If an error occurs
|
||||
*/
|
||||
protected native void create() throws SocketException;
|
||||
|
||||
protected native int peek(InetAddress i) throws IOException;
|
||||
|
||||
protected native int peekData (DatagramPacket dp) throws IOException;
|
||||
|
||||
/**
|
||||
* Sets the Time to Live value for the socket
|
||||
*
|
||||
* @param ttl The new TTL value
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected native void setTimeToLive(int ttl) throws IOException;
|
||||
|
||||
/**
|
||||
* Gets the Time to Live value for the socket
|
||||
*
|
||||
* @return The TTL value
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected native int getTimeToLive() throws IOException;
|
||||
|
||||
/**
|
||||
* Sends a packet of data to a remote host
|
||||
*
|
||||
* @param packet The packet to send
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected native void send(DatagramPacket p) throws IOException;
|
||||
|
||||
/**
|
||||
* Receives a UDP packet from the network
|
||||
*
|
||||
* @param packet The packet to fill in with the data received
|
||||
*
|
||||
* @exception IOException IOException If an error occurs
|
||||
*/
|
||||
protected native void receive(DatagramPacket p) throws IOException;
|
||||
|
||||
/**
|
||||
* Sets the value of an option on the socket
|
||||
*
|
||||
* @param option_id The identifier of the option to set
|
||||
* @param val The value of the option to set
|
||||
*
|
||||
* @exception SocketException If an error occurs
|
||||
*/
|
||||
public native void setOption(int optID, Object value) throws SocketException;
|
||||
|
||||
/**
|
||||
* Retrieves the value of an option on the socket
|
||||
*
|
||||
* @param option_id The identifier of the option to retrieve
|
||||
*
|
||||
* @return The value of the option
|
||||
*
|
||||
* @exception SocketException If an error occurs
|
||||
*/
|
||||
public native Object getOption(int optID) throws SocketException;
|
||||
|
||||
private native void mcastGrp(InetAddress inetaddr, NetworkInterface netIf,
|
||||
boolean join) throws IOException;
|
||||
|
||||
/**
|
||||
* Closes the socket
|
||||
*/
|
||||
protected native void close();
|
||||
|
||||
/**
|
||||
* Gets the Time to Live value for the socket
|
||||
*
|
||||
* @return The TTL value
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*
|
||||
* @deprecated 1.2
|
||||
*/
|
||||
protected byte getTTL() throws IOException
|
||||
{
|
||||
return (byte) getTimeToLive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Time to Live value for the socket
|
||||
*
|
||||
* @param ttl The new TTL value
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*
|
||||
* @deprecated 1.2
|
||||
*/
|
||||
protected void setTTL(byte ttl) throws IOException
|
||||
{
|
||||
setTimeToLive(((int) ttl) & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins a multicast group
|
||||
*
|
||||
* @param addr The group to join
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void join(InetAddress inetaddr) throws IOException
|
||||
{
|
||||
mcastGrp(inetaddr, null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Leaves a multicast group
|
||||
*
|
||||
* @param addr The group to leave
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void leave(InetAddress inetaddr) throws IOException
|
||||
{
|
||||
mcastGrp(inetaddr, null, false);
|
||||
}
|
||||
|
||||
protected void joinGroup (SocketAddress mcastaddr, NetworkInterface netIf)
|
||||
throws IOException
|
||||
{
|
||||
mcastGrp(((InetSocketAddress)mcastaddr).getAddress(), netIf, true);
|
||||
}
|
||||
|
||||
protected void leaveGroup (SocketAddress mcastaddr, NetworkInterface netIf)
|
||||
throws IOException
|
||||
{
|
||||
mcastGrp(((InetSocketAddress)mcastaddr).getAddress(), netIf, false);
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
if (fnum != -1)
|
||||
close();
|
||||
}
|
||||
super.finalize();
|
||||
}
|
||||
}
|
|
@ -1,395 +0,0 @@
|
|||
/* PlainSocketImpl.java -- Default socket implementation
|
||||
Copyright (C) 1998, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import gnu.classpath.Configuration;
|
||||
|
||||
/**
|
||||
* Written using on-line Java Platform 1.2 API Specification, as well
|
||||
* as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
|
||||
* Status: Believed complete and correct.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Unless the application installs its own SocketImplFactory, this is the
|
||||
* default socket implemetation that will be used. It simply uses a
|
||||
* combination of Java and native routines to implement standard BSD
|
||||
* style sockets of family AF_INET and types SOCK_STREAM and SOCK_DGRAM
|
||||
*
|
||||
* @author Per Bothner <bothner@cygnus.com>
|
||||
* @author Nic Ferrier <nferrier@tapsellferrier.co.uk>
|
||||
* @author Aaron M. Renn <arenn@urbanophile.com>
|
||||
*/
|
||||
class PlainSocketImpl extends SocketImpl
|
||||
{
|
||||
// Static initializer to load native library.
|
||||
static
|
||||
{
|
||||
if (Configuration.INIT_LOAD_LIBRARY)
|
||||
{
|
||||
System.loadLibrary("javanet");
|
||||
}
|
||||
}
|
||||
|
||||
// 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_SO_BROADCAST_ = SocketOptions.SO_BROADCAST,
|
||||
_Jv_SO_OOBINLINE_ = SocketOptions.SO_OOBINLINE,
|
||||
_Jv_IP_MULTICAST_IF_ = SocketOptions.IP_MULTICAST_IF,
|
||||
_Jv_IP_MULTICAST_IF2_ = SocketOptions.IP_MULTICAST_IF2,
|
||||
_Jv_IP_MULTICAST_LOOP_ = SocketOptions.IP_MULTICAST_LOOP,
|
||||
_Jv_IP_TOS_ = SocketOptions.IP_TOS,
|
||||
_Jv_SO_LINGER_ = SocketOptions.SO_LINGER,
|
||||
_Jv_SO_TIMEOUT_ = SocketOptions.SO_TIMEOUT,
|
||||
_Jv_SO_SNDBUF_ = SocketOptions.SO_SNDBUF,
|
||||
_Jv_SO_RCVBUF_ = SocketOptions.SO_RCVBUF,
|
||||
_Jv_SO_KEEPALIVE_ = SocketOptions.SO_KEEPALIVE;
|
||||
|
||||
/**
|
||||
* The OS file handle representing the socket.
|
||||
* This is used for reads and writes to/from the socket and
|
||||
* to close it.
|
||||
*
|
||||
* When the socket is closed this is reset to -1.
|
||||
*/
|
||||
int fnum = -1;
|
||||
|
||||
// This value is set/read by setOption/getOption.
|
||||
int timeout = 0;
|
||||
|
||||
// localAddress cache
|
||||
InetAddress localAddress;
|
||||
|
||||
/**
|
||||
* A cached copy of the in stream for reading from the socket.
|
||||
*/
|
||||
private InputStream in;
|
||||
|
||||
/**
|
||||
* A cached copy of the out stream for writing to the socket.
|
||||
*/
|
||||
private OutputStream out;
|
||||
|
||||
/**
|
||||
* Default do nothing constructor
|
||||
*/
|
||||
public PlainSocketImpl()
|
||||
{
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
if (fnum != -1)
|
||||
try
|
||||
{
|
||||
close();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified option on a socket to the passed in object. For
|
||||
* options that take an integer argument, the passed in object is an
|
||||
* Integer. The option_id parameter is one of the defined constants in
|
||||
* this interface.
|
||||
*
|
||||
* @param option_id The identifier of the option
|
||||
* @param val The value to set the option to
|
||||
*
|
||||
* @exception SocketException If an error occurs
|
||||
*/
|
||||
public native void setOption(int optID, Object value) throws SocketException;
|
||||
|
||||
/**
|
||||
* Returns the current setting of the specified option. The Object returned
|
||||
* will be an Integer for options that have integer values. The option_id
|
||||
* is one of the defined constants in this interface.
|
||||
*
|
||||
* @param option_id The option identifier
|
||||
*
|
||||
* @return The current value of the option
|
||||
*
|
||||
* @exception SocketException If an error occurs
|
||||
*/
|
||||
public native Object getOption(int optID) throws SocketException;
|
||||
|
||||
public native void shutdownInput () throws IOException;
|
||||
|
||||
public native void shutdownOutput () throws IOException;
|
||||
|
||||
/**
|
||||
* Creates a new socket that is not bound to any local address/port and
|
||||
* is not connected to any remote address/port. This will be created as
|
||||
* a stream socket if the stream parameter is true, or a datagram socket
|
||||
* if the stream parameter is false.
|
||||
*
|
||||
* @param stream true for a stream socket, false for a datagram socket
|
||||
*/
|
||||
protected native void create (boolean stream) throws IOException;
|
||||
|
||||
/**
|
||||
* Connects to the remote hostname and port specified as arguments.
|
||||
*
|
||||
* @param hostname The remote hostname to connect to
|
||||
* @param port The remote port to connect to
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void connect (String host, int port) throws IOException
|
||||
{
|
||||
connect (new InetSocketAddress (InetAddress.getByName(host), port), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the remote address and port specified as arguments.
|
||||
*
|
||||
* @param addr The remote address to connect to
|
||||
* @param port The remote port to connect to
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void connect (InetAddress host, int port) throws IOException
|
||||
{
|
||||
connect (new InetSocketAddress (host, port), 0);
|
||||
}
|
||||
|
||||
protected native void connect (SocketAddress addr, int timeout)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Binds to the specified port on the specified addr. Note that this addr
|
||||
* must represent a local IP address. **** How bind to INADDR_ANY? ****
|
||||
*
|
||||
* @param addr The address to bind to
|
||||
* @param port The port number to bind to
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected native void bind (InetAddress host, int port) throws IOException;
|
||||
|
||||
/**
|
||||
* Starts listening for connections on a socket. The queuelen parameter
|
||||
* is how many pending connections will queue up waiting to be serviced
|
||||
* before being accept'ed. If the queue of pending requests exceeds this
|
||||
* number, additional connections will be refused.
|
||||
*
|
||||
* @param queuelen The length of the pending connection queue
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected native void listen (int backlog) throws IOException;
|
||||
|
||||
private native void accept (PlainSocketImpl s) throws IOException;
|
||||
|
||||
/**
|
||||
* Accepts a new connection on this socket and returns in in the
|
||||
* passed in SocketImpl.
|
||||
*
|
||||
* @param impl The SocketImpl object to accept this connection.
|
||||
*/
|
||||
protected void accept (SocketImpl s) throws IOException
|
||||
{
|
||||
accept((PlainSocketImpl) s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes that the caller can read from this socket
|
||||
* without blocking.
|
||||
*
|
||||
* @return The number of readable bytes before blocking
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected native int available() throws IOException;
|
||||
|
||||
/**
|
||||
* Closes the socket. This will cause any InputStream or OutputStream
|
||||
* objects for this Socket to be closed as well.
|
||||
* <p>
|
||||
* Note that if the SO_LINGER option is set on this socket, then the
|
||||
* operation could block.
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected native void close () throws IOException;
|
||||
|
||||
protected native void sendUrgentData(int data)
|
||||
throws IOException;
|
||||
|
||||
native int read() throws IOException;
|
||||
|
||||
/**
|
||||
* Internal method used by SocketInputStream for reading data from
|
||||
* the connection. Reads up to len bytes of data into the buffer
|
||||
* buf starting at offset bytes into the buffer.
|
||||
*
|
||||
* @return The actual number of bytes read or -1 if end of stream.
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
native int read(byte[] buffer, int offset, int count)
|
||||
throws IOException;
|
||||
|
||||
native void write(int c) throws IOException;
|
||||
|
||||
/**
|
||||
* Internal method used by SocketOuputStream for writing data to
|
||||
* the connection. Writes up to len bytes of data from the buffer
|
||||
* buf starting at offset bytes into the buffer.
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
native void write(byte[] buffer, int offset, int count)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Returns an InputStream object for reading from this socket. This will
|
||||
* be an instance of SocketInputStream.
|
||||
*
|
||||
* @return An input stream attached to the socket.
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected synchronized InputStream getInputStream() throws IOException
|
||||
{
|
||||
if (in == null)
|
||||
in = new SocketInputStream();
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an OutputStream object for writing to this socket. This will
|
||||
* be an instance of SocketOutputStream.
|
||||
*
|
||||
* @return An output stream attached to the socket.
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected synchronized OutputStream getOutputStream() throws IOException
|
||||
{
|
||||
if (out == null)
|
||||
out = new SocketOutputStream();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* A stream which reads from the socket implementation.
|
||||
*
|
||||
* @author Nic Ferrier <nferrier@tapsellferrier.co.uk>
|
||||
*/
|
||||
class SocketInputStream
|
||||
extends InputStream
|
||||
{
|
||||
SocketInputStream()
|
||||
{
|
||||
}
|
||||
|
||||
public final void close() throws IOException
|
||||
{
|
||||
PlainSocketImpl.this.close();
|
||||
}
|
||||
|
||||
public final int available() throws IOException
|
||||
{
|
||||
return PlainSocketImpl.this.available();
|
||||
}
|
||||
|
||||
public final int read() throws IOException
|
||||
{
|
||||
return PlainSocketImpl.this.read();
|
||||
}
|
||||
|
||||
public final int read(byte[] buffer, int offset, int length)
|
||||
throws IOException
|
||||
{
|
||||
return PlainSocketImpl.this.read(buffer, offset, length);
|
||||
}
|
||||
|
||||
public final int read(byte[] buffer)
|
||||
throws IOException
|
||||
{
|
||||
return PlainSocketImpl.this.read(buffer, 0, buffer.length);
|
||||
}
|
||||
}
|
||||
|
||||
/** A stream which writes to the socket implementation.
|
||||
*
|
||||
* @author Nic Ferrier <nferrier@tapsellferrier.co.uk>
|
||||
*/
|
||||
class SocketOutputStream
|
||||
extends OutputStream
|
||||
{
|
||||
public final void close() throws IOException
|
||||
{
|
||||
PlainSocketImpl.this.close();
|
||||
}
|
||||
|
||||
public final void write(int c) throws IOException
|
||||
{
|
||||
PlainSocketImpl.this.write(c);
|
||||
}
|
||||
|
||||
public final void write(byte[] buffer, int offset, int length)
|
||||
throws IOException
|
||||
{
|
||||
PlainSocketImpl.this.write(buffer, offset, length);
|
||||
}
|
||||
|
||||
public final void write(byte[] buffer)
|
||||
throws IOException
|
||||
{
|
||||
PlainSocketImpl.this.write(buffer, 0, buffer.length);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/* ServerSocket.java -- Class for implementing server side sockets
|
||||
Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1998, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
|
@ -35,8 +35,10 @@ this exception to your version of the library, but you are not
|
|||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package java.net;
|
||||
|
||||
import gnu.java.net.PlainSocketImpl;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.IllegalBlockingModeException;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Socket.java -- Client socket implementation
|
||||
Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1998, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
|
@ -35,8 +35,10 @@ this exception to your version of the library, but you are not
|
|||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package java.net;
|
||||
|
||||
import gnu.java.net.PlainSocketImpl;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
|
|
@ -1,204 +0,0 @@
|
|||
/* SocketInputStream.java -- An InputStream for Sockets
|
||||
Copyright (C) 1998, 2000, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This class contains an implementation of <code>InputStream</code> for
|
||||
* sockets. It in an internal only class used by <code>PlainSocketImpl</code>.
|
||||
*
|
||||
* @author Aaron M. Renn (arenn@urbanophile.com)
|
||||
*/
|
||||
class SocketInputStream extends InputStream
|
||||
{
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Instance Variables
|
||||
*/
|
||||
|
||||
/**
|
||||
* The PlainSocketImpl object this stream is associated with
|
||||
*/
|
||||
private PlainSocketImpl impl;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Constructors
|
||||
*/
|
||||
|
||||
/**
|
||||
* Builds an instance of this class from a PlainSocketImpl object
|
||||
*/
|
||||
protected
|
||||
SocketInputStream(PlainSocketImpl impl)
|
||||
{
|
||||
this.impl = impl;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Instance Methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the number of bytes available to be read before blocking
|
||||
*/
|
||||
public int
|
||||
available() throws IOException
|
||||
{
|
||||
return(impl.available());
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Determines if "mark" functionality is supported on this stream. For
|
||||
* sockets, this is always false. Note that the superclass default is
|
||||
* false, but it is overridden out of safety concerns and/or paranoia.
|
||||
*/
|
||||
public boolean
|
||||
markSupported()
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Do nothing mark method since we don't support this functionality. Again,
|
||||
* overriding out of paranoia.
|
||||
*
|
||||
* @param readlimit In theory, the number of bytes we can read before the mark becomes invalid
|
||||
*/
|
||||
public void
|
||||
mark(int readlimit)
|
||||
{
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Since we don't support mark, this method always throws an exception
|
||||
*
|
||||
* @exception IOException Everytime since we don't support this functionality
|
||||
*/
|
||||
public void
|
||||
reset() throws IOException
|
||||
{
|
||||
throw new IOException("Socket InputStreams do not support mark/reset");
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* This method not only closes the stream, it closes the underlying socket
|
||||
* (and thus any connection) and invalidates any other Input/Output streams
|
||||
* for the underlying impl object
|
||||
*/
|
||||
public void
|
||||
close() throws IOException
|
||||
{
|
||||
impl.close();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Reads the next byte of data and returns it as an int.
|
||||
*
|
||||
* @return The byte read (as an int) or -1 if end of stream);
|
||||
*
|
||||
* @exception IOException If an error occurs.
|
||||
*/
|
||||
public int
|
||||
read() throws IOException
|
||||
{
|
||||
byte buf[] = new byte[1];
|
||||
|
||||
int bytes_read = read(buf, 0, buf.length);
|
||||
|
||||
if (bytes_read != -1)
|
||||
return(buf[0] & 0xFF);
|
||||
else
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Reads up to buf.length bytes of data into the caller supplied buffer.
|
||||
*
|
||||
* @return The actual number of bytes read or -1 if end of stream
|
||||
*
|
||||
* @exception IOException If an error occurs.
|
||||
*/
|
||||
public int
|
||||
read(byte[] buf) throws IOException
|
||||
{
|
||||
return(read(buf, 0, buf.length));
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Reads up to len bytes of data into the caller supplied buffer starting
|
||||
* at offset bytes from the start of the buffer
|
||||
*
|
||||
* @return The number of bytes actually read or -1 if end of stream
|
||||
*
|
||||
* @exception IOException If an error occurs.
|
||||
*/
|
||||
public int
|
||||
read(byte[] buf, int offset, int len) throws IOException
|
||||
{
|
||||
int bytes_read = impl.read(buf, offset, len);
|
||||
if (bytes_read == 0)
|
||||
return(-1);
|
||||
|
||||
return(bytes_read);
|
||||
}
|
||||
|
||||
} // class SocketInputStream
|
||||
|
|
@ -1,165 +0,0 @@
|
|||
/* SocketOutputStream.java -- OutputStream for PlainSocketImpl
|
||||
Copyright (C) 1998,2000 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This class is used internally by <code>PlainSocketImpl</code> to be the
|
||||
* <code>OutputStream</code> subclass returned by its
|
||||
* <code>getOutputStream method</code>. It expects only to be used in that
|
||||
* context.
|
||||
*
|
||||
* @author Aaron M. Renn (arenn@urbanophile.com)
|
||||
*/
|
||||
class SocketOutputStream extends OutputStream
|
||||
{
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Instance Variables
|
||||
*/
|
||||
|
||||
/**
|
||||
* The PlainSocketImpl object this stream is associated with
|
||||
*/
|
||||
private PlainSocketImpl impl;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Constructors
|
||||
*/
|
||||
|
||||
/**
|
||||
* Build an instance of this class from a PlainSocketImpl object
|
||||
*/
|
||||
protected
|
||||
SocketOutputStream(PlainSocketImpl impl)
|
||||
{
|
||||
this.impl = impl;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Instance Methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* This method closes the stream and the underlying socket connection. This
|
||||
* action also effectively closes any other InputStream or OutputStream
|
||||
* object associated with the connection.
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
public void
|
||||
close() throws IOException
|
||||
{
|
||||
impl.close();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Hmmm, we don't seem to have a flush() method in Socket impl, so just
|
||||
* return for now, but this might need to be looked at later.
|
||||
*
|
||||
* @exception IOException Can't happen
|
||||
*/
|
||||
public void
|
||||
flush() throws IOException
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Writes a byte (passed in as an int) to the given output stream
|
||||
*
|
||||
* @param b The byte to write
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
public void
|
||||
write(int b) throws IOException
|
||||
{
|
||||
byte buf[] = new byte[1];
|
||||
|
||||
Integer i = new Integer(b);
|
||||
buf[0] = i.byteValue();
|
||||
|
||||
write(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Write an array of bytes to the output stream
|
||||
*
|
||||
* @param buf The array of bytes to write
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
public void
|
||||
write(byte[] buf) throws IOException
|
||||
{
|
||||
write(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Writes len number of bytes from the array buf to the stream starting
|
||||
* at offset bytes into the buffer.
|
||||
*
|
||||
* @param buf The buffer
|
||||
* @param offset Offset into the buffer to start writing from
|
||||
* @param len The number of bytes to write
|
||||
*/
|
||||
public void
|
||||
write(byte[] buf, int offset, int len) throws IOException
|
||||
{
|
||||
impl.write(buf, offset, len);
|
||||
}
|
||||
|
||||
} // class SocketOutputStream
|
||||
|
|
@ -1,119 +0,0 @@
|
|||
/* Copyright (C) 2003 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
#include <config.h>
|
||||
#include <platform.h>
|
||||
|
||||
#include <java/io/IOException.h>
|
||||
#include <java/lang/Object.h>
|
||||
#include <java/net/BindException.h>
|
||||
#include <java/net/DatagramPacket.h>
|
||||
#include <java/net/InetAddress.h>
|
||||
#include <java/net/NetworkInterface.h>
|
||||
#include <java/net/PlainDatagramSocketImpl.h>
|
||||
#include <java/net/SocketException.h>
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::create ()
|
||||
{
|
||||
throw new SocketException (
|
||||
JvNewStringLatin1 ("DatagramSocketImpl.create: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::bind (jint, java::net::InetAddress *)
|
||||
{
|
||||
throw new BindException (
|
||||
JvNewStringLatin1 ("DatagramSocketImpl.bind: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::connect (java::net::InetAddress *, jint)
|
||||
{
|
||||
throw new SocketException (
|
||||
JvNewStringLatin1 ("DatagramSocketImpl.connect: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::disconnect ()
|
||||
{
|
||||
throw new SocketException (
|
||||
JvNewStringLatin1 ("DatagramSocketImpl.disconnect: unimplemented"));
|
||||
}
|
||||
|
||||
jint
|
||||
java::net::PlainDatagramSocketImpl::peek (java::net::InetAddress *)
|
||||
{
|
||||
throw new java::io::IOException (
|
||||
JvNewStringLatin1 ("DatagramSocketImpl.peek: unimplemented"));
|
||||
}
|
||||
|
||||
jint
|
||||
java::net::PlainDatagramSocketImpl::peekData(java::net::DatagramPacket *)
|
||||
{
|
||||
throw new java::io::IOException (
|
||||
JvNewStringLatin1 ("DatagramSocketImpl.peekData: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::close ()
|
||||
{
|
||||
throw new java::io::IOException (
|
||||
JvNewStringLatin1 ("DatagramSocketImpl.close: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::send (java::net::DatagramPacket *)
|
||||
{
|
||||
throw new java::io::IOException (
|
||||
JvNewStringLatin1 ("DatagramSocketImpl.send: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::receive (java::net::DatagramPacket *)
|
||||
{
|
||||
throw new java::io::IOException (
|
||||
JvNewStringLatin1 ("DatagramSocketImpl.receive: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::setTimeToLive (jint)
|
||||
{
|
||||
throw new java::io::IOException (
|
||||
JvNewStringLatin1 ("DatagramSocketImpl.setTimeToLive: unimplemented"));
|
||||
}
|
||||
|
||||
jint
|
||||
java::net::PlainDatagramSocketImpl::getTimeToLive ()
|
||||
{
|
||||
throw new java::io::IOException (
|
||||
JvNewStringLatin1 ("DatagramSocketImpl.getTimeToLive: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::mcastGrp (java::net::InetAddress *,
|
||||
java::net::NetworkInterface *,
|
||||
jboolean)
|
||||
{
|
||||
throw new java::io::IOException (
|
||||
JvNewStringLatin1 ("DatagramSocketImpl.mcastGrp: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::setOption (jint, java::lang::Object *)
|
||||
{
|
||||
throw new SocketException (
|
||||
JvNewStringLatin1 ("DatagramSocketImpl.setOption: unimplemented"));
|
||||
}
|
||||
|
||||
java::lang::Object *
|
||||
java::net::PlainDatagramSocketImpl::getOption (jint)
|
||||
{
|
||||
throw new SocketException (
|
||||
JvNewStringLatin1 ("DatagramSocketImpl.getOption: unimplemented"));
|
||||
}
|
|
@ -1,750 +0,0 @@
|
|||
/* Copyright (C) 2003 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
#include <config.h>
|
||||
#include <platform.h>
|
||||
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#if HAVE_BSTRING_H
|
||||
// Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2
|
||||
#include <bstring.h>
|
||||
#endif
|
||||
|
||||
#include <gcj/cni.h>
|
||||
#include <java/io/IOException.h>
|
||||
#include <java/io/InterruptedIOException.h>
|
||||
#include <java/net/BindException.h>
|
||||
#include <java/net/SocketException.h>
|
||||
#include <java/net/PlainDatagramSocketImpl.h>
|
||||
#include <java/net/InetAddress.h>
|
||||
#include <java/net/NetworkInterface.h>
|
||||
#include <java/net/DatagramPacket.h>
|
||||
#include <java/net/PortUnreachableException.h>
|
||||
#include <java/lang/InternalError.h>
|
||||
#include <java/lang/Object.h>
|
||||
#include <java/lang/Boolean.h>
|
||||
#include <java/lang/Integer.h>
|
||||
|
||||
union SockAddr
|
||||
{
|
||||
struct sockaddr_in address;
|
||||
#ifdef HAVE_INET6
|
||||
struct sockaddr_in6 address6;
|
||||
#endif
|
||||
};
|
||||
|
||||
union McastReq
|
||||
{
|
||||
#if HAVE_STRUCT_IP_MREQ
|
||||
struct ip_mreq mreq;
|
||||
#endif
|
||||
#if HAVE_STRUCT_IPV6_MREQ
|
||||
struct ipv6_mreq mreq6;
|
||||
#endif
|
||||
};
|
||||
|
||||
union InAddr
|
||||
{
|
||||
struct in_addr addr;
|
||||
#ifdef HAVE_INET6
|
||||
struct in6_addr addr6;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
// FIXME: routines here and/or in natPlainSocketImpl.cc could throw
|
||||
// NoRouteToHostException; also consider UnknownHostException, ConnectException.
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::create ()
|
||||
{
|
||||
int sock = _Jv_socket (AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (sock < 0)
|
||||
{
|
||||
char* strerr = strerror (errno);
|
||||
throw new java::net::SocketException (JvNewStringUTF (strerr));
|
||||
}
|
||||
|
||||
_Jv_platform_close_on_exec (sock);
|
||||
|
||||
// We use fnum in place of fd here. From leaving fd null we avoid
|
||||
// the double close problem in FileDescriptor.finalize.
|
||||
fnum = sock;
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::bind (jint lport,
|
||||
java::net::InetAddress *host)
|
||||
{
|
||||
union SockAddr u;
|
||||
struct sockaddr *ptr = (struct sockaddr *) &u.address;
|
||||
// FIXME: Use getaddrinfo() to get actual protocol instead of assuming ipv4.
|
||||
jbyteArray haddress = host->addr;
|
||||
jbyte *bytes = elements (haddress);
|
||||
int len = haddress->length;
|
||||
|
||||
if (len == 4)
|
||||
{
|
||||
u.address.sin_family = AF_INET;
|
||||
|
||||
if (host != NULL)
|
||||
memcpy (&u.address.sin_addr, bytes, len);
|
||||
else
|
||||
u.address.sin_addr.s_addr = htonl (INADDR_ANY);
|
||||
|
||||
len = sizeof (struct sockaddr_in);
|
||||
u.address.sin_port = htons (lport);
|
||||
}
|
||||
#ifdef HAVE_INET6
|
||||
else if (len == 16)
|
||||
{
|
||||
u.address6.sin6_family = AF_INET6;
|
||||
memcpy (&u.address6.sin6_addr, bytes, len);
|
||||
len = sizeof (struct sockaddr_in6);
|
||||
u.address6.sin6_port = htons (lport);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
|
||||
|
||||
if (_Jv_bind (fnum, ptr, len) == 0)
|
||||
{
|
||||
socklen_t addrlen = sizeof(u);
|
||||
|
||||
if (lport != 0)
|
||||
localPort = lport;
|
||||
else if (::getsockname (fnum, (sockaddr*) &u, &addrlen) == 0)
|
||||
localPort = ntohs (u.address.sin_port);
|
||||
else
|
||||
goto error;
|
||||
|
||||
/* Allow broadcast by default. */
|
||||
int broadcast = 1;
|
||||
if (::setsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &broadcast,
|
||||
sizeof (broadcast)) != 0)
|
||||
goto error;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
error:
|
||||
char* strerr = strerror (errno);
|
||||
throw new java::net::BindException (JvNewStringUTF (strerr));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::connect (java::net::InetAddress *, jint)
|
||||
{
|
||||
throw new ::java::lang::InternalError (JvNewStringLatin1 (
|
||||
"PlainDatagramSocketImpl::connect: not implemented yet"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::disconnect ()
|
||||
{
|
||||
throw new ::java::lang::InternalError (JvNewStringLatin1 (
|
||||
"PlainDatagramSocketImpl::disconnect: not implemented yet"));
|
||||
}
|
||||
|
||||
jint
|
||||
java::net::PlainDatagramSocketImpl::peek (java::net::InetAddress *i)
|
||||
{
|
||||
// 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
|
||||
throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
|
||||
|
||||
i->addr = raddr;
|
||||
return rport;
|
||||
error:
|
||||
char* strerr = strerror (errno);
|
||||
|
||||
if (errno == ECONNREFUSED)
|
||||
throw new PortUnreachableException (JvNewStringUTF (strerr));
|
||||
|
||||
throw new java::io::IOException (JvNewStringUTF (strerr));
|
||||
}
|
||||
|
||||
jint
|
||||
java::net::PlainDatagramSocketImpl::peekData(java::net::DatagramPacket *p)
|
||||
{
|
||||
// FIXME: Deal with Multicast and if the socket is connected.
|
||||
union SockAddr u;
|
||||
socklen_t addrlen = sizeof(u);
|
||||
jbyte *dbytes = elements (p->getData());
|
||||
ssize_t retlen = 0;
|
||||
|
||||
// Do timeouts via select since SO_RCVTIMEO is not always available.
|
||||
if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
|
||||
{
|
||||
fd_set rset;
|
||||
struct timeval tv;
|
||||
FD_ZERO(&rset);
|
||||
FD_SET(fnum, &rset);
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
int retval;
|
||||
if ((retval = _Jv_select (fnum + 1, &rset, NULL, NULL, &tv)) < 0)
|
||||
goto error;
|
||||
else if (retval == 0)
|
||||
throw new java::io::InterruptedIOException ();
|
||||
}
|
||||
|
||||
retlen =
|
||||
::recvfrom (fnum, (char *) dbytes, p->getLength(), 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
|
||||
throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
|
||||
|
||||
p->setAddress (new InetAddress (raddr, NULL));
|
||||
p->setPort (rport);
|
||||
p->setLength ((jint) retlen);
|
||||
return rport;
|
||||
|
||||
error:
|
||||
char* strerr = strerror (errno);
|
||||
|
||||
if (errno == ECONNREFUSED)
|
||||
throw new PortUnreachableException (JvNewStringUTF (strerr));
|
||||
|
||||
throw new java::io::IOException (JvNewStringUTF (strerr));
|
||||
}
|
||||
|
||||
// Close(shutdown) the socket.
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::close ()
|
||||
{
|
||||
// Avoid races from asynchronous finalization.
|
||||
JvSynchronize sync (this);
|
||||
|
||||
// The method isn't declared to throw anything, so we disregard
|
||||
// the return value.
|
||||
_Jv_close (fnum);
|
||||
fnum = -1;
|
||||
timeout = 0;
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::send (java::net::DatagramPacket *p)
|
||||
{
|
||||
// FIXME: Deal with Multicast and if the socket is connected.
|
||||
jint rport = p->getPort();
|
||||
union SockAddr u;
|
||||
jbyteArray haddress = p->getAddress()->addr;
|
||||
jbyte *bytes = elements (haddress);
|
||||
int len = haddress->length;
|
||||
struct sockaddr *ptr = (struct sockaddr *) &u.address;
|
||||
jbyte *dbytes = elements (p->getData());
|
||||
if (len == 4)
|
||||
{
|
||||
u.address.sin_family = AF_INET;
|
||||
memcpy (&u.address.sin_addr, bytes, len);
|
||||
len = sizeof (struct sockaddr_in);
|
||||
u.address.sin_port = htons (rport);
|
||||
}
|
||||
#ifdef HAVE_INET6
|
||||
else if (len == 16)
|
||||
{
|
||||
u.address6.sin6_family = AF_INET6;
|
||||
memcpy (&u.address6.sin6_addr, bytes, len);
|
||||
len = sizeof (struct sockaddr_in6);
|
||||
u.address6.sin6_port = htons (rport);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
|
||||
|
||||
if (::sendto (fnum, (char *) dbytes, p->getLength(), 0, ptr, len) >= 0)
|
||||
return;
|
||||
|
||||
char* strerr = strerror (errno);
|
||||
|
||||
if (errno == ECONNREFUSED)
|
||||
throw new PortUnreachableException (JvNewStringUTF (strerr));
|
||||
|
||||
throw new java::io::IOException (JvNewStringUTF (strerr));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::receive (java::net::DatagramPacket *p)
|
||||
{
|
||||
// FIXME: Deal with Multicast and if the socket is connected.
|
||||
union SockAddr u;
|
||||
socklen_t addrlen = sizeof(u);
|
||||
jbyte *dbytes = elements (p->getData());
|
||||
ssize_t retlen = 0;
|
||||
|
||||
// Do timeouts via select since SO_RCVTIMEO is not always available.
|
||||
if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
|
||||
{
|
||||
fd_set rset;
|
||||
struct timeval tv;
|
||||
FD_ZERO(&rset);
|
||||
FD_SET(fnum, &rset);
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
int retval;
|
||||
if ((retval = _Jv_select (fnum + 1, &rset, NULL, NULL, &tv)) < 0)
|
||||
goto error;
|
||||
else if (retval == 0)
|
||||
throw new java::io::InterruptedIOException ();
|
||||
}
|
||||
|
||||
retlen =
|
||||
::recvfrom (fnum, (char *) dbytes, p->getLength(), 0, (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
|
||||
throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
|
||||
|
||||
p->setAddress (new InetAddress (raddr, NULL));
|
||||
p->setPort (rport);
|
||||
p->setLength ((jint) retlen);
|
||||
return;
|
||||
|
||||
error:
|
||||
char* strerr = strerror (errno);
|
||||
|
||||
if (errno == ECONNREFUSED)
|
||||
throw new PortUnreachableException (JvNewStringUTF (strerr));
|
||||
|
||||
throw new java::io::IOException (JvNewStringUTF (strerr));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::setTimeToLive (jint ttl)
|
||||
{
|
||||
// Assumes IPPROTO_IP rather than IPPROTO_IPV6 since socket created is IPv4.
|
||||
char val = (char) ttl;
|
||||
socklen_t val_len = sizeof(val);
|
||||
|
||||
if (::setsockopt (fnum, IPPROTO_IP, IP_MULTICAST_TTL, &val, val_len) == 0)
|
||||
return;
|
||||
|
||||
char* strerr = strerror (errno);
|
||||
throw new java::io::IOException (JvNewStringUTF (strerr));
|
||||
}
|
||||
|
||||
jint
|
||||
java::net::PlainDatagramSocketImpl::getTimeToLive ()
|
||||
{
|
||||
// Assumes IPPROTO_IP rather than IPPROTO_IPV6 since socket created is IPv4.
|
||||
char val;
|
||||
socklen_t val_len = sizeof(val);
|
||||
|
||||
if (::getsockopt (fnum, IPPROTO_IP, IP_MULTICAST_TTL, &val, &val_len) == 0)
|
||||
return ((int) val) & 0xFF;
|
||||
|
||||
char* strerr = strerror (errno);
|
||||
throw new java::io::IOException (JvNewStringUTF (strerr));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::mcastGrp (java::net::InetAddress *inetaddr,
|
||||
java::net::NetworkInterface *,
|
||||
jboolean join)
|
||||
{
|
||||
// FIXME: implement use of NetworkInterface
|
||||
|
||||
union McastReq u;
|
||||
jbyteArray haddress = inetaddr->addr;
|
||||
jbyte *bytes = elements (haddress);
|
||||
int len = haddress->length;
|
||||
int level, opname;
|
||||
const char *ptr;
|
||||
if (0)
|
||||
;
|
||||
#if HAVE_STRUCT_IP_MREQ
|
||||
else 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.
|
||||
// Maybe not, see note in last paragraph at bottom of Stevens p. 497.
|
||||
u.mreq.imr_interface.s_addr = htonl (INADDR_ANY);
|
||||
len = sizeof (struct ip_mreq);
|
||||
ptr = (const char *) &u.mreq;
|
||||
}
|
||||
#endif
|
||||
#if HAVE_STRUCT_IPV6_MREQ
|
||||
else if (len == 16)
|
||||
{
|
||||
level = IPPROTO_IPV6;
|
||||
|
||||
/* Prefer new RFC 2553 names. */
|
||||
#ifndef IPV6_JOIN_GROUP
|
||||
#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
|
||||
#endif
|
||||
#ifndef IPV6_LEAVE_GROUP
|
||||
#define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
|
||||
#endif
|
||||
|
||||
opname = join ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP;
|
||||
memcpy (&u.mreq6.ipv6mr_multiaddr, bytes, len);
|
||||
// FIXME: If a non-default interface is set, use it; see Stevens p. 501.
|
||||
// Maybe not, see note in last paragraph at bottom of Stevens p. 497.
|
||||
u.mreq6.ipv6mr_interface = 0;
|
||||
len = sizeof (struct ipv6_mreq);
|
||||
ptr = (const char *) &u.mreq6;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
|
||||
|
||||
if (::setsockopt (fnum, level, opname, ptr, len) == 0)
|
||||
return;
|
||||
|
||||
char* strerr = strerror (errno);
|
||||
throw new java::io::IOException (JvNewStringUTF (strerr));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::setOption (jint optID,
|
||||
java::lang::Object *value)
|
||||
{
|
||||
int val;
|
||||
socklen_t val_len = sizeof (val);
|
||||
|
||||
if (fnum < 0)
|
||||
throw new java::net::SocketException (JvNewStringUTF ("Socket closed"));
|
||||
|
||||
if (_Jv_IsInstanceOf (value, &java::lang::Boolean::class$))
|
||||
{
|
||||
java::lang::Boolean *boolobj =
|
||||
static_cast<java::lang::Boolean *> (value);
|
||||
val = boolobj->booleanValue() ? 1 : 0;
|
||||
}
|
||||
else if (_Jv_IsInstanceOf (value, &java::lang::Integer::class$))
|
||||
{
|
||||
java::lang::Integer *intobj =
|
||||
static_cast<java::lang::Integer *> (value);
|
||||
val = (int) intobj->intValue();
|
||||
}
|
||||
// Else assume value to be an InetAddress for use with IP_MULTICAST_IF.
|
||||
|
||||
switch (optID)
|
||||
{
|
||||
case _Jv_TCP_NODELAY_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("TCP_NODELAY not valid for UDP"));
|
||||
return;
|
||||
case _Jv_SO_LINGER_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("SO_LINGER not valid for UDP"));
|
||||
return;
|
||||
case _Jv_SO_KEEPALIVE_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("SO_KEEPALIVE not valid for UDP"));
|
||||
return;
|
||||
|
||||
case _Jv_SO_BROADCAST_ :
|
||||
if (::setsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &val,
|
||||
val_len) != 0)
|
||||
goto error;
|
||||
break;
|
||||
|
||||
case _Jv_SO_OOBINLINE_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("SO_OOBINLINE: not valid for UDP"));
|
||||
break;
|
||||
|
||||
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
|
||||
throw new java::lang::InternalError (
|
||||
JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
|
||||
#endif
|
||||
return;
|
||||
case _Jv_SO_REUSEADDR_ :
|
||||
#if defined(SO_REUSEADDR)
|
||||
if (::setsockopt (fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
|
||||
val_len) != 0)
|
||||
goto error;
|
||||
#else
|
||||
throw new java::lang::InternalError (
|
||||
JvNewStringUTF ("SO_REUSEADDR not supported"));
|
||||
#endif
|
||||
return;
|
||||
case _Jv_SO_BINDADDR_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("SO_BINDADDR: read only option"));
|
||||
return;
|
||||
case _Jv_IP_MULTICAST_IF_ :
|
||||
union InAddr u;
|
||||
jbyteArray haddress;
|
||||
jbyte *bytes;
|
||||
int len;
|
||||
int level, opname;
|
||||
const char *ptr;
|
||||
|
||||
haddress = ((java::net::InetAddress *) value)->addr;
|
||||
bytes = elements (haddress);
|
||||
len = haddress->length;
|
||||
if (len == 4)
|
||||
{
|
||||
level = IPPROTO_IP;
|
||||
opname = IP_MULTICAST_IF;
|
||||
memcpy (&u.addr, bytes, len);
|
||||
len = sizeof (struct in_addr);
|
||||
ptr = (const char *) &u.addr;
|
||||
}
|
||||
// Tru64 UNIX V5.0 has struct sockaddr_in6, but no IPV6_MULTICAST_IF
|
||||
#if defined (HAVE_INET6) && defined (IPV6_MULTICAST_IF)
|
||||
else if (len == 16)
|
||||
{
|
||||
level = IPPROTO_IPV6;
|
||||
opname = IPV6_MULTICAST_IF;
|
||||
memcpy (&u.addr6, bytes, len);
|
||||
len = sizeof (struct in6_addr);
|
||||
ptr = (const char *) &u.addr6;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
throw
|
||||
new java::net::SocketException (JvNewStringUTF ("invalid length"));
|
||||
|
||||
if (::setsockopt (fnum, level, opname, ptr, len) != 0)
|
||||
goto error;
|
||||
return;
|
||||
|
||||
case _Jv_IP_MULTICAST_IF2_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("IP_MULTICAST_IF2: not yet implemented"));
|
||||
break;
|
||||
|
||||
case _Jv_IP_MULTICAST_LOOP_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("IP_MULTICAST_LOOP: not yet implemented"));
|
||||
break;
|
||||
|
||||
case _Jv_IP_TOS_ :
|
||||
if (::setsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val,
|
||||
val_len) != 0)
|
||||
goto error;
|
||||
return;
|
||||
|
||||
case _Jv_SO_TIMEOUT_ :
|
||||
timeout = val;
|
||||
return;
|
||||
default :
|
||||
errno = ENOPROTOOPT;
|
||||
}
|
||||
|
||||
error:
|
||||
char* strerr = strerror (errno);
|
||||
throw new java::net::SocketException (JvNewStringUTF (strerr));
|
||||
}
|
||||
|
||||
java::lang::Object *
|
||||
java::net::PlainDatagramSocketImpl::getOption (jint optID)
|
||||
{
|
||||
int val;
|
||||
socklen_t val_len = sizeof(val);
|
||||
union SockAddr u;
|
||||
socklen_t addrlen = sizeof(u);
|
||||
|
||||
switch (optID)
|
||||
{
|
||||
case _Jv_TCP_NODELAY_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("TCP_NODELAY not valid for UDP"));
|
||||
break;
|
||||
case _Jv_SO_LINGER_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("SO_LINGER not valid for UDP"));
|
||||
break;
|
||||
case _Jv_SO_KEEPALIVE_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("SO_KEEPALIVE not valid for UDP"));
|
||||
break;
|
||||
|
||||
case _Jv_SO_BROADCAST_ :
|
||||
if (::getsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &val,
|
||||
&val_len) != 0)
|
||||
goto error;
|
||||
return new java::lang::Boolean (val != 0);
|
||||
|
||||
case _Jv_SO_OOBINLINE_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("SO_OOBINLINE not valid for UDP"));
|
||||
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
|
||||
throw new java::lang::InternalError (
|
||||
JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
|
||||
#endif
|
||||
break;
|
||||
case _Jv_SO_BINDADDR_:
|
||||
// cache the local address
|
||||
if (localAddress == NULL)
|
||||
{
|
||||
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
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("invalid family"));
|
||||
localAddress = new java::net::InetAddress (laddr, NULL);
|
||||
}
|
||||
return localAddress;
|
||||
break;
|
||||
case _Jv_SO_REUSEADDR_ :
|
||||
#if defined(SO_REUSEADDR)
|
||||
if (::getsockopt (fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
|
||||
&val_len) != 0)
|
||||
goto error;
|
||||
return new java::lang::Boolean (val != 0);
|
||||
#else
|
||||
throw new java::lang::InternalError (
|
||||
JvNewStringUTF ("SO_REUSEADDR not supported"));
|
||||
#endif
|
||||
break;
|
||||
case _Jv_IP_MULTICAST_IF_ :
|
||||
#ifdef HAVE_INET_NTOA
|
||||
struct in_addr inaddr;
|
||||
socklen_t inaddr_len;
|
||||
char *bytes;
|
||||
|
||||
inaddr_len = sizeof(inaddr);
|
||||
if (::getsockopt (fnum, IPPROTO_IP, IP_MULTICAST_IF, (char *) &inaddr,
|
||||
&inaddr_len) != 0)
|
||||
goto error;
|
||||
|
||||
bytes = inet_ntoa (inaddr);
|
||||
|
||||
return java::net::InetAddress::getByName (JvNewStringLatin1 (bytes));
|
||||
#else
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("IP_MULTICAST_IF: not available - no inet_ntoa()"));
|
||||
#endif
|
||||
break;
|
||||
case _Jv_SO_TIMEOUT_ :
|
||||
return new java::lang::Integer (timeout);
|
||||
break;
|
||||
|
||||
case _Jv_IP_MULTICAST_IF2_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("IP_MULTICAST_IF2: not yet implemented"));
|
||||
break;
|
||||
|
||||
case _Jv_IP_MULTICAST_LOOP_ :
|
||||
if (::getsockopt (fnum, SOL_SOCKET, IP_MULTICAST_LOOP, (char *) &val,
|
||||
&val_len) != 0)
|
||||
goto error;
|
||||
return new java::lang::Boolean (val != 0);
|
||||
|
||||
case _Jv_IP_TOS_ :
|
||||
if (::getsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val,
|
||||
&val_len) != 0)
|
||||
goto error;
|
||||
return new java::lang::Integer (val);
|
||||
|
||||
default :
|
||||
errno = ENOPROTOOPT;
|
||||
}
|
||||
|
||||
error:
|
||||
char* strerr = strerror (errno);
|
||||
throw new java::net::SocketException (JvNewStringUTF (strerr));
|
||||
}
|
|
@ -1,704 +0,0 @@
|
|||
/* Copyright (C) 2003 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
#include <config.h>
|
||||
#include <platform.h>
|
||||
#include <string.h>
|
||||
|
||||
#if HAVE_BSTRING_H
|
||||
// Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2
|
||||
#include <bstring.h>
|
||||
#endif
|
||||
|
||||
#include <java/io/IOException.h>
|
||||
#include <java/io/InterruptedIOException.h>
|
||||
#include <java/net/BindException.h>
|
||||
#include <java/net/SocketException.h>
|
||||
#include <java/net/PlainDatagramSocketImpl.h>
|
||||
#include <java/net/InetAddress.h>
|
||||
#include <java/net/NetworkInterface.h>
|
||||
#include <java/net/DatagramPacket.h>
|
||||
#include <java/net/PortUnreachableException.h>
|
||||
#include <java/net/SocketTimeoutException.h>
|
||||
#include <java/lang/InternalError.h>
|
||||
#include <java/lang/Object.h>
|
||||
#include <java/lang/Boolean.h>
|
||||
#include <java/lang/Integer.h>
|
||||
|
||||
union SockAddr
|
||||
{
|
||||
struct sockaddr_in address;
|
||||
#ifdef HAVE_INET6
|
||||
struct sockaddr_in6 address6;
|
||||
#endif
|
||||
};
|
||||
|
||||
union McastReq
|
||||
{
|
||||
#if HAVE_STRUCT_IP_MREQ
|
||||
struct ip_mreq mreq;
|
||||
#endif
|
||||
#if HAVE_STRUCT_IPV6_MREQ
|
||||
struct ipv6_mreq mreq6;
|
||||
#endif
|
||||
};
|
||||
|
||||
union InAddr
|
||||
{
|
||||
struct in_addr addr;
|
||||
#ifdef HAVE_INET6
|
||||
struct in6_addr addr6;
|
||||
#endif
|
||||
};
|
||||
|
||||
// FIXME: routines here and/or in natPlainSocketImpl.cc could throw
|
||||
// NoRouteToHostException; also consider UnknownHostException, ConnectException.
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::create ()
|
||||
{
|
||||
SOCKET sock = ::socket (AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (sock == INVALID_SOCKET)
|
||||
{
|
||||
_Jv_ThrowSocketException ();
|
||||
}
|
||||
|
||||
_Jv_platform_close_on_exec (sock);
|
||||
|
||||
// We use fnum in place of fd here. From leaving fd null we avoid
|
||||
// the double close problem in FileDescriptor.finalize.
|
||||
fnum = (int) sock;
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::bind (jint lport,
|
||||
java::net::InetAddress *host)
|
||||
{
|
||||
union SockAddr u;
|
||||
struct sockaddr *ptr = (struct sockaddr *) &u.address;
|
||||
// FIXME: Use getaddrinfo() to get actual protocol instead of assuming ipv4.
|
||||
jbyteArray haddress = host->addr;
|
||||
jbyte *bytes = elements (haddress);
|
||||
int len = haddress->length;
|
||||
|
||||
if (len == 4)
|
||||
{
|
||||
u.address.sin_family = AF_INET;
|
||||
|
||||
if (host != NULL)
|
||||
memcpy (&u.address.sin_addr, bytes, len);
|
||||
else
|
||||
u.address.sin_addr.s_addr = htonl (INADDR_ANY);
|
||||
|
||||
len = sizeof (struct sockaddr_in);
|
||||
u.address.sin_port = htons (lport);
|
||||
}
|
||||
#ifdef HAVE_INET6
|
||||
else if (len == 16)
|
||||
{
|
||||
u.address6.sin6_family = AF_INET6;
|
||||
memcpy (&u.address6.sin6_addr, bytes, len);
|
||||
len = sizeof (struct sockaddr_in6);
|
||||
u.address6.sin6_port = htons (lport);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
|
||||
|
||||
if (::bind (fnum, ptr, len) == 0)
|
||||
{
|
||||
socklen_t addrlen = sizeof(u);
|
||||
|
||||
if (lport != 0)
|
||||
localPort = lport;
|
||||
else if (::getsockname (fnum, (sockaddr*) &u, &addrlen) == 0)
|
||||
localPort = ntohs (u.address.sin_port);
|
||||
else
|
||||
goto error;
|
||||
|
||||
/* Allow broadcast by default. */
|
||||
int broadcast = 1;
|
||||
if (::setsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &broadcast,
|
||||
sizeof (broadcast)) != 0)
|
||||
goto error;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
error:
|
||||
DWORD dwErrorCode = WSAGetLastError ();
|
||||
throw new java::net::BindException (_Jv_WinStrError (dwErrorCode));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::connect (java::net::InetAddress *, jint)
|
||||
{
|
||||
throw new ::java::lang::InternalError (JvNewStringLatin1 (
|
||||
"PlainDatagramSocketImpl::connect: not implemented yet"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::disconnect ()
|
||||
{
|
||||
throw new ::java::lang::InternalError (JvNewStringLatin1 (
|
||||
"PlainDatagramSocketImpl::disconnect: not implemented yet"));
|
||||
}
|
||||
|
||||
jint
|
||||
java::net::PlainDatagramSocketImpl::peek (java::net::InetAddress *i)
|
||||
{
|
||||
// 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
|
||||
throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
|
||||
|
||||
i->addr = raddr;
|
||||
return rport;
|
||||
error:
|
||||
DWORD dwErrorCode = WSAGetLastError ();
|
||||
if (dwErrorCode == WSAECONNRESET)
|
||||
throw new PortUnreachableException (_Jv_WinStrError (dwErrorCode));
|
||||
|
||||
_Jv_ThrowIOException ();
|
||||
return -1;
|
||||
// we should never get here
|
||||
}
|
||||
|
||||
jint
|
||||
java::net::PlainDatagramSocketImpl::peekData(java::net::DatagramPacket *p)
|
||||
{
|
||||
// FIXME: Deal with Multicast and if the socket is connected.
|
||||
union SockAddr u;
|
||||
socklen_t addrlen = sizeof(u);
|
||||
jbyte *dbytes = elements (p->getData());
|
||||
ssize_t retlen = 0;
|
||||
|
||||
if (timeout > 0)
|
||||
{
|
||||
int nRet= ::setsockopt(fnum, SOL_SOCKET, SO_RCVTIMEO,
|
||||
(char*)&timeout, sizeof(timeout));
|
||||
if (nRet != NO_ERROR)
|
||||
goto error;
|
||||
}
|
||||
|
||||
retlen =
|
||||
::recvfrom (fnum, (char *) dbytes, p->getLength(), MSG_PEEK, (sockaddr*) &u,
|
||||
&addrlen);
|
||||
if (retlen == SOCKET_ERROR)
|
||||
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
|
||||
throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
|
||||
|
||||
p->setAddress (new InetAddress (raddr, NULL));
|
||||
p->setPort (rport);
|
||||
p->setLength ((jint) retlen);
|
||||
return rport;
|
||||
|
||||
error:
|
||||
DWORD dwErrorCode = WSAGetLastError ();
|
||||
if (dwErrorCode == WSAECONNRESET)
|
||||
throw new PortUnreachableException (_Jv_WinStrError (dwErrorCode));
|
||||
else if (dwErrorCode == WSAETIMEDOUT)
|
||||
throw new java::net::SocketTimeoutException (_Jv_WinStrError (dwErrorCode));
|
||||
else
|
||||
_Jv_ThrowIOException ();
|
||||
|
||||
return -1;
|
||||
// we should never get here
|
||||
}
|
||||
|
||||
// Close(shutdown) the socket.
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::close ()
|
||||
{
|
||||
// Avoid races from asynchronous finalization.
|
||||
JvSynchronize sync (this);
|
||||
|
||||
// The method isn't declared to throw anything, so we disregard
|
||||
// the return value.
|
||||
::closesocket (fnum);
|
||||
fnum = -1;
|
||||
timeout = 0;
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::send (java::net::DatagramPacket *p)
|
||||
{
|
||||
// FIXME: Deal with Multicast and if the socket is connected.
|
||||
jint rport = p->getPort();
|
||||
union SockAddr u;
|
||||
jbyteArray haddress = p->getAddress()->addr;
|
||||
jbyte *bytes = elements (haddress);
|
||||
int len = haddress->length;
|
||||
struct sockaddr *ptr = (struct sockaddr *) &u.address;
|
||||
jbyte *dbytes = elements (p->getData());
|
||||
if (len == 4)
|
||||
{
|
||||
u.address.sin_family = AF_INET;
|
||||
memcpy (&u.address.sin_addr, bytes, len);
|
||||
len = sizeof (struct sockaddr_in);
|
||||
u.address.sin_port = htons (rport);
|
||||
}
|
||||
#ifdef HAVE_INET6
|
||||
else if (len == 16)
|
||||
{
|
||||
u.address6.sin6_family = AF_INET6;
|
||||
memcpy (&u.address6.sin6_addr, bytes, len);
|
||||
len = sizeof (struct sockaddr_in6);
|
||||
u.address6.sin6_port = htons (rport);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
|
||||
|
||||
if (::sendto (fnum, (char *) dbytes, p->getLength(), 0, ptr, len) >= 0)
|
||||
return;
|
||||
|
||||
DWORD dwErrorCode = WSAGetLastError ();
|
||||
if (dwErrorCode == WSAECONNRESET)
|
||||
throw new PortUnreachableException (_Jv_WinStrError (dwErrorCode));
|
||||
|
||||
_Jv_ThrowIOException ();
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::receive (java::net::DatagramPacket *p)
|
||||
{
|
||||
// FIXME: Deal with Multicast and if the socket is connected.
|
||||
union SockAddr u;
|
||||
socklen_t addrlen = sizeof(u);
|
||||
jbyte *dbytes = elements (p->getData());
|
||||
ssize_t retlen = 0;
|
||||
|
||||
if (timeout > 0)
|
||||
{
|
||||
// This implementation doesn't allow specifying an infinite
|
||||
// timeout after specifying a finite one, but Sun's JDK 1.4.1
|
||||
// didn't seem to allow this either....
|
||||
int nRet= ::setsockopt(fnum, SOL_SOCKET, SO_RCVTIMEO,
|
||||
(char*)&timeout, sizeof(timeout));
|
||||
if (nRet != NO_ERROR)
|
||||
goto error;
|
||||
}
|
||||
|
||||
retlen =
|
||||
::recvfrom (fnum, (char *) dbytes, p->getLength(), 0, (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
|
||||
throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
|
||||
|
||||
p->setAddress (new InetAddress (raddr, NULL));
|
||||
p->setPort (rport);
|
||||
p->setLength ((jint) retlen);
|
||||
return;
|
||||
|
||||
error:
|
||||
DWORD dwErrorCode = WSAGetLastError();
|
||||
if (dwErrorCode == WSAECONNRESET)
|
||||
throw new PortUnreachableException (_Jv_WinStrError (dwErrorCode));
|
||||
else if (dwErrorCode == WSAETIMEDOUT)
|
||||
throw new java::net::SocketTimeoutException (_Jv_WinStrError (dwErrorCode));
|
||||
else
|
||||
throw new java::io::IOException (_Jv_WinStrError (dwErrorCode));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::setTimeToLive (jint ttl)
|
||||
{
|
||||
// Assumes IPPROTO_IP rather than IPPROTO_IPV6 since socket created is IPv4.
|
||||
char val = (char) ttl;
|
||||
socklen_t val_len = sizeof(val);
|
||||
|
||||
if (::setsockopt (fnum, IPPROTO_IP, IP_MULTICAST_TTL, &val, val_len) == 0)
|
||||
return;
|
||||
|
||||
_Jv_ThrowIOException ();
|
||||
}
|
||||
|
||||
jint
|
||||
java::net::PlainDatagramSocketImpl::getTimeToLive ()
|
||||
{
|
||||
// Assumes IPPROTO_IP rather than IPPROTO_IPV6 since socket created is IPv4.
|
||||
char val;
|
||||
socklen_t val_len = sizeof(val);
|
||||
|
||||
if (::getsockopt (fnum, IPPROTO_IP, IP_MULTICAST_TTL, &val, &val_len) == 0)
|
||||
return ((int) val) & 0xFF;
|
||||
|
||||
_Jv_ThrowIOException ();
|
||||
|
||||
return -1;
|
||||
// we should never get here
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::mcastGrp (java::net::InetAddress *inetaddr,
|
||||
java::net::NetworkInterface *,
|
||||
jboolean)
|
||||
{
|
||||
// FIXME: implement use of NetworkInterface
|
||||
jbyteArray haddress = inetaddr->addr;
|
||||
int len = haddress->length;
|
||||
int level, opname;
|
||||
const char *ptr;
|
||||
if (0)
|
||||
;
|
||||
#if HAVE_STRUCT_IP_MREQ
|
||||
else 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.
|
||||
// Maybe not, see note in last paragraph at bottom of Stevens p. 497.
|
||||
u.mreq.imr_interface.s_addr = htonl (INADDR_ANY);
|
||||
len = sizeof (struct ip_mreq);
|
||||
ptr = (const char *) &u.mreq;
|
||||
}
|
||||
#endif
|
||||
#if HAVE_STRUCT_IPV6_MREQ
|
||||
else if (len == 16)
|
||||
{
|
||||
level = IPPROTO_IPV6;
|
||||
|
||||
/* Prefer new RFC 2553 names. */
|
||||
#ifndef IPV6_JOIN_GROUP
|
||||
#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
|
||||
#endif
|
||||
#ifndef IPV6_LEAVE_GROUP
|
||||
#define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
|
||||
#endif
|
||||
|
||||
opname = join ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP;
|
||||
memcpy (&u.mreq6.ipv6mr_multiaddr, bytes, len);
|
||||
// FIXME: If a non-default interface is set, use it; see Stevens p. 501.
|
||||
// Maybe not, see note in last paragraph at bottom of Stevens p. 497.
|
||||
u.mreq6.ipv6mr_interface = 0;
|
||||
len = sizeof (struct ipv6_mreq);
|
||||
ptr = (const char *) &u.mreq6;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
|
||||
|
||||
if (::setsockopt (fnum, level, opname, ptr, len) == 0)
|
||||
return;
|
||||
|
||||
_Jv_ThrowIOException ();
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainDatagramSocketImpl::setOption (jint optID,
|
||||
java::lang::Object *value)
|
||||
{
|
||||
int val;
|
||||
socklen_t val_len = sizeof (val);
|
||||
|
||||
if (fnum < 0)
|
||||
throw new java::net::SocketException (JvNewStringUTF ("Socket closed"));
|
||||
|
||||
if (_Jv_IsInstanceOf (value, &java::lang::Boolean::class$))
|
||||
{
|
||||
java::lang::Boolean *boolobj =
|
||||
static_cast<java::lang::Boolean *> (value);
|
||||
val = boolobj->booleanValue() ? 1 : 0;
|
||||
}
|
||||
else if (_Jv_IsInstanceOf (value, &java::lang::Integer::class$))
|
||||
{
|
||||
java::lang::Integer *intobj =
|
||||
static_cast<java::lang::Integer *> (value);
|
||||
val = (int) intobj->intValue();
|
||||
}
|
||||
// Else assume value to be an InetAddress for use with IP_MULTICAST_IF.
|
||||
|
||||
switch (optID)
|
||||
{
|
||||
case _Jv_TCP_NODELAY_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("TCP_NODELAY not valid for UDP"));
|
||||
return;
|
||||
case _Jv_SO_LINGER_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("SO_LINGER not valid for UDP"));
|
||||
return;
|
||||
case _Jv_SO_KEEPALIVE_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("SO_KEEPALIVE not valid for UDP"));
|
||||
return;
|
||||
|
||||
case _Jv_SO_BROADCAST_ :
|
||||
if (::setsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &val,
|
||||
val_len) != 0)
|
||||
goto error;
|
||||
break;
|
||||
|
||||
case _Jv_SO_OOBINLINE_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("SO_OOBINLINE: not valid for UDP"));
|
||||
break;
|
||||
|
||||
case _Jv_SO_SNDBUF_ :
|
||||
case _Jv_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;
|
||||
return;
|
||||
case _Jv_SO_REUSEADDR_ :
|
||||
if (::setsockopt (fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
|
||||
val_len) != 0)
|
||||
goto error;
|
||||
return;
|
||||
case _Jv_SO_BINDADDR_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("SO_BINDADDR: read only option"));
|
||||
return;
|
||||
case _Jv_IP_MULTICAST_IF_ :
|
||||
union InAddr u;
|
||||
jbyteArray haddress;
|
||||
jbyte *bytes;
|
||||
int len;
|
||||
int level, opname;
|
||||
const char *ptr;
|
||||
|
||||
haddress = ((java::net::InetAddress *) value)->addr;
|
||||
bytes = elements (haddress);
|
||||
len = haddress->length;
|
||||
if (len == 4)
|
||||
{
|
||||
level = IPPROTO_IP;
|
||||
opname = IP_MULTICAST_IF;
|
||||
memcpy (&u.addr, bytes, len);
|
||||
len = sizeof (struct in_addr);
|
||||
ptr = (const char *) &u.addr;
|
||||
}
|
||||
// Tru64 UNIX V5.0 has struct sockaddr_in6, but no IPV6_MULTICAST_IF
|
||||
#if defined (HAVE_INET6) && defined (IPV6_MULTICAST_IF)
|
||||
else if (len == 16)
|
||||
{
|
||||
level = IPPROTO_IPV6;
|
||||
opname = IPV6_MULTICAST_IF;
|
||||
memcpy (&u.addr6, bytes, len);
|
||||
len = sizeof (struct in6_addr);
|
||||
ptr = (const char *) &u.addr6;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
throw
|
||||
new java::net::SocketException (JvNewStringUTF ("invalid length"));
|
||||
|
||||
if (::setsockopt (fnum, level, opname, ptr, len) != 0)
|
||||
goto error;
|
||||
return;
|
||||
|
||||
case _Jv_IP_MULTICAST_IF2_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("IP_MULTICAST_IF2: not yet implemented"));
|
||||
break;
|
||||
|
||||
case _Jv_IP_MULTICAST_LOOP_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("IP_MULTICAST_LOOP: not yet implemented"));
|
||||
break;
|
||||
|
||||
case _Jv_IP_TOS_ :
|
||||
if (::setsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val,
|
||||
val_len) != 0)
|
||||
goto error;
|
||||
return;
|
||||
|
||||
case _Jv_SO_TIMEOUT_ :
|
||||
timeout = val;
|
||||
return;
|
||||
default :
|
||||
WSASetLastError (WSAENOPROTOOPT);
|
||||
}
|
||||
|
||||
error:
|
||||
_Jv_ThrowSocketException ();
|
||||
}
|
||||
|
||||
java::lang::Object *
|
||||
java::net::PlainDatagramSocketImpl::getOption (jint optID)
|
||||
{
|
||||
int val;
|
||||
socklen_t val_len = sizeof(val);
|
||||
union SockAddr u;
|
||||
socklen_t addrlen = sizeof(u);
|
||||
|
||||
switch (optID)
|
||||
{
|
||||
case _Jv_TCP_NODELAY_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("TCP_NODELAY not valid for UDP"));
|
||||
break;
|
||||
case _Jv_SO_LINGER_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("SO_LINGER not valid for UDP"));
|
||||
break;
|
||||
case _Jv_SO_KEEPALIVE_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("SO_KEEPALIVE not valid for UDP"));
|
||||
break;
|
||||
|
||||
case _Jv_SO_BROADCAST_ :
|
||||
if (::getsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &val,
|
||||
&val_len) != 0)
|
||||
goto error;
|
||||
return new java::lang::Boolean (val != 0);
|
||||
|
||||
case _Jv_SO_OOBINLINE_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("SO_OOBINLINE not valid for UDP"));
|
||||
break;
|
||||
|
||||
case _Jv_SO_RCVBUF_ :
|
||||
case _Jv_SO_SNDBUF_ :
|
||||
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);
|
||||
break;
|
||||
case _Jv_SO_BINDADDR_:
|
||||
// cache the local address
|
||||
if (localAddress == NULL)
|
||||
{
|
||||
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
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("invalid family"));
|
||||
localAddress = new java::net::InetAddress (laddr, NULL);
|
||||
}
|
||||
return localAddress;
|
||||
break;
|
||||
case _Jv_SO_REUSEADDR_ :
|
||||
if (::getsockopt (fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
|
||||
&val_len) != 0)
|
||||
goto error;
|
||||
return new java::lang::Boolean (val != 0);
|
||||
break;
|
||||
case _Jv_IP_MULTICAST_IF_ :
|
||||
struct in_addr inaddr;
|
||||
socklen_t inaddr_len;
|
||||
char *bytes;
|
||||
|
||||
inaddr_len = sizeof(inaddr);
|
||||
if (::getsockopt (fnum, IPPROTO_IP, IP_MULTICAST_IF, (char *) &inaddr,
|
||||
&inaddr_len) != 0)
|
||||
goto error;
|
||||
|
||||
bytes = inet_ntoa (inaddr);
|
||||
|
||||
return java::net::InetAddress::getByName (JvNewStringLatin1 (bytes));
|
||||
break;
|
||||
case _Jv_SO_TIMEOUT_ :
|
||||
return new java::lang::Integer (timeout);
|
||||
break;
|
||||
|
||||
case _Jv_IP_MULTICAST_IF2_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("IP_MULTICAST_IF2: not yet implemented"));
|
||||
break;
|
||||
|
||||
case _Jv_IP_MULTICAST_LOOP_ :
|
||||
if (::getsockopt (fnum, SOL_SOCKET, IP_MULTICAST_LOOP, (char *) &val,
|
||||
&val_len) != 0)
|
||||
goto error;
|
||||
return new java::lang::Boolean (val != 0);
|
||||
|
||||
case _Jv_IP_TOS_ :
|
||||
if (::getsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val,
|
||||
&val_len) != 0)
|
||||
goto error;
|
||||
return new java::lang::Integer (val);
|
||||
|
||||
default :
|
||||
WSASetLastError (WSAENOPROTOOPT);
|
||||
}
|
||||
|
||||
error:
|
||||
_Jv_ThrowSocketException ();
|
||||
return 0;
|
||||
// we should never get here
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
/* Copyright (C) 2003 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
#include <config.h>
|
||||
#include <platform.h>
|
||||
|
||||
#include <java/io/IOException.h>
|
||||
#include <java/net/BindException.h>
|
||||
#include <java/net/ConnectException.h>
|
||||
#include <java/net/PlainSocketImpl.h>
|
||||
#include <java/net/SocketException.h>
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::create (jboolean)
|
||||
{
|
||||
throw new java::io::IOException (
|
||||
JvNewStringLatin1 ("SocketImpl.create: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::bind (java::net::InetAddress *, jint)
|
||||
{
|
||||
throw new BindException (
|
||||
JvNewStringLatin1 ("SocketImpl.bind: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::connect (java::net::SocketAddress *, jint)
|
||||
{
|
||||
throw new ConnectException (
|
||||
JvNewStringLatin1 ("SocketImpl.connect: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::listen (jint)
|
||||
{
|
||||
throw new java::io::IOException (
|
||||
JvNewStringLatin1 ("SocketImpl.listen: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl *)
|
||||
{
|
||||
throw new java::io::IOException (
|
||||
JvNewStringLatin1 ("SocketImpl.accept: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::setOption (jint, java::lang::Object *)
|
||||
{
|
||||
throw new SocketException (
|
||||
JvNewStringLatin1 ("SocketImpl.setOption: unimplemented"));
|
||||
}
|
||||
|
||||
java::lang::Object *
|
||||
java::net::PlainSocketImpl::getOption (jint)
|
||||
{
|
||||
throw new SocketException (
|
||||
JvNewStringLatin1 ("SocketImpl.getOption: unimplemented"));
|
||||
}
|
||||
|
||||
jint
|
||||
java::net::PlainSocketImpl::read(void)
|
||||
{
|
||||
throw new SocketException (
|
||||
JvNewStringLatin1 ("SocketImpl.read: unimplemented"));
|
||||
}
|
||||
|
||||
jint
|
||||
java::net::PlainSocketImpl::read(jbyteArray buffer, jint offset, jint count)
|
||||
{
|
||||
throw new SocketException (
|
||||
JvNewStringLatin1 ("SocketImpl.read: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::write(jint b)
|
||||
{
|
||||
throw new SocketException (
|
||||
JvNewStringLatin1 ("SocketImpl.write: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::write(jbyteArray b, jint offset, jint len)
|
||||
{
|
||||
throw new SocketException (
|
||||
JvNewStringLatin1 ("SocketImpl.write: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::sendUrgentData(jint data)
|
||||
{
|
||||
throw new SocketException (
|
||||
JvNewStringLatin1 ("SocketImpl.sendUrgentData: unimplemented"));
|
||||
}
|
||||
|
||||
jint
|
||||
java::net::PlainSocketImpl::available(void)
|
||||
{
|
||||
throw new SocketException (
|
||||
JvNewStringLatin1 ("SocketImpl.available: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::close(void)
|
||||
{
|
||||
throw new SocketException (
|
||||
JvNewStringLatin1 ("SocketImpl.close: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::shutdownInput (void)
|
||||
{
|
||||
throw new SocketException (
|
||||
JvNewStringLatin1 ("SocketImpl.shutdownInput: unimplemented"));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::shutdownOutput (void)
|
||||
{
|
||||
throw new SocketException (
|
||||
JvNewStringLatin1 ("SocketImpl.shutdownOutput: unimplemented"));
|
||||
}
|
|
@ -1,857 +0,0 @@
|
|||
/* Copyright (C) 2003 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
#include <config.h>
|
||||
#include <platform.h>
|
||||
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#define BSD_COMP /* Get FIONREAD on Solaris2. */
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
// Pick up FIONREAD on Solaris 2.5.
|
||||
#ifdef HAVE_SYS_FILIO_H
|
||||
#include <sys/filio.h>
|
||||
#endif
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#if HAVE_BSTRING_H
|
||||
// Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2
|
||||
#include <bstring.h>
|
||||
#endif
|
||||
|
||||
#include <gcj/cni.h>
|
||||
#include <gcj/javaprims.h>
|
||||
#include <java/io/IOException.h>
|
||||
#include <java/io/InterruptedIOException.h>
|
||||
#include <java/net/BindException.h>
|
||||
#include <java/net/ConnectException.h>
|
||||
#include <java/net/PlainSocketImpl.h>
|
||||
#include <java/net/InetAddress.h>
|
||||
#include <java/net/InetSocketAddress.h>
|
||||
#include <java/net/SocketException.h>
|
||||
#include <java/net/SocketTimeoutException.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>
|
||||
#include <java/lang/Thread.h>
|
||||
#include <java/lang/NullPointerException.h>
|
||||
#include <java/lang/ArrayIndexOutOfBoundsException.h>
|
||||
#include <java/lang/IllegalArgumentException.h>
|
||||
|
||||
union SockAddr
|
||||
{
|
||||
struct sockaddr_in address;
|
||||
#ifdef HAVE_INET6
|
||||
struct sockaddr_in6 address6;
|
||||
#endif
|
||||
};
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::create (jboolean stream)
|
||||
{
|
||||
int sock = _Jv_socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0);
|
||||
|
||||
if (sock < 0)
|
||||
{
|
||||
char* strerr = strerror (errno);
|
||||
throw new java::io::IOException (JvNewStringUTF (strerr));
|
||||
}
|
||||
|
||||
_Jv_platform_close_on_exec (sock);
|
||||
|
||||
// We use fnum in place of fd here. From leaving fd null we avoid
|
||||
// the double close problem in FileDescriptor.finalize.
|
||||
fnum = sock;
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::bind (java::net::InetAddress *host, jint lport)
|
||||
{
|
||||
union SockAddr u;
|
||||
struct sockaddr *ptr = (struct sockaddr *) &u.address;
|
||||
jbyteArray haddress = host->addr;
|
||||
jbyte *bytes = elements (haddress);
|
||||
int len = haddress->length;
|
||||
int i = 1;
|
||||
|
||||
if (len == 4)
|
||||
{
|
||||
u.address.sin_family = AF_INET;
|
||||
|
||||
if (host != NULL)
|
||||
memcpy (&u.address.sin_addr, bytes, len);
|
||||
else
|
||||
u.address.sin_addr.s_addr = htonl (INADDR_ANY);
|
||||
|
||||
len = sizeof (struct sockaddr_in);
|
||||
u.address.sin_port = htons (lport);
|
||||
}
|
||||
#ifdef HAVE_INET6
|
||||
else if (len == 16)
|
||||
{
|
||||
u.address6.sin6_family = AF_INET6;
|
||||
memcpy (&u.address6.sin6_addr, bytes, len);
|
||||
len = sizeof (struct sockaddr_in6);
|
||||
u.address6.sin6_port = htons (lport);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
|
||||
|
||||
// Enable SO_REUSEADDR, so that servers can reuse ports left in TIME_WAIT.
|
||||
::setsockopt(fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &i, sizeof(i));
|
||||
|
||||
if (_Jv_bind (fnum, ptr, len) == 0)
|
||||
{
|
||||
address = host;
|
||||
socklen_t addrlen = sizeof(u);
|
||||
|
||||
if (lport != 0)
|
||||
localport = lport;
|
||||
else if (::getsockname (fnum, (sockaddr*) &u, &addrlen) == 0)
|
||||
localport = ntohs (u.address.sin_port);
|
||||
else
|
||||
goto error;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
error:
|
||||
char* strerr = strerror (errno);
|
||||
throw new java::net::BindException (JvNewStringUTF (strerr));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::connect (java::net::SocketAddress *addr,
|
||||
jint timeout)
|
||||
{
|
||||
java::net::InetSocketAddress *tmp = (java::net::InetSocketAddress*) addr;
|
||||
java::net::InetAddress *host = tmp->getAddress();
|
||||
jint rport = tmp->getPort();
|
||||
|
||||
union SockAddr u;
|
||||
socklen_t addrlen = sizeof(u);
|
||||
jbyteArray haddress = host->addr;
|
||||
jbyte *bytes = elements (haddress);
|
||||
int len = haddress->length;
|
||||
struct sockaddr *ptr = (struct sockaddr *) &u.address;
|
||||
if (len == 4)
|
||||
{
|
||||
u.address.sin_family = AF_INET;
|
||||
memcpy (&u.address.sin_addr, bytes, len);
|
||||
len = sizeof (struct sockaddr_in);
|
||||
u.address.sin_port = htons (rport);
|
||||
}
|
||||
#ifdef HAVE_INET6
|
||||
else if (len == 16)
|
||||
{
|
||||
u.address6.sin6_family = AF_INET6;
|
||||
memcpy (&u.address6.sin6_addr, bytes, len);
|
||||
len = sizeof (struct sockaddr_in6);
|
||||
u.address6.sin6_port = htons (rport);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
|
||||
|
||||
if (timeout > 0)
|
||||
{
|
||||
int flags = ::fcntl (fnum, F_GETFL);
|
||||
::fcntl (fnum, F_SETFL, flags | O_NONBLOCK);
|
||||
|
||||
if ((_Jv_connect (fnum, ptr, len) != 0) && (errno != EINPROGRESS))
|
||||
goto error;
|
||||
|
||||
fd_set fset;
|
||||
struct timeval tv;
|
||||
FD_ZERO(&fset);
|
||||
FD_SET(fnum, &fset);
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
int retval;
|
||||
|
||||
if ((retval = _Jv_select (fnum + 1, &fset, &fset, NULL, &tv)) < 0)
|
||||
goto error;
|
||||
else if (retval == 0)
|
||||
throw new java::net::SocketTimeoutException
|
||||
(JvNewStringUTF ("Connect timed out"));
|
||||
// Set the socket back into a blocking state.
|
||||
::fcntl (fnum, F_SETFL, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_Jv_connect (fnum, ptr, len) != 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
address = host;
|
||||
port = rport;
|
||||
|
||||
// A bind may not have been done on this socket; if so, set localport now.
|
||||
if (localport == 0)
|
||||
{
|
||||
if (::getsockname (fnum, (sockaddr*) &u, &addrlen) == 0)
|
||||
localport = ntohs (u.address.sin_port);
|
||||
else
|
||||
goto error;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
char* strerr = strerror (errno);
|
||||
throw new java::net::ConnectException (JvNewStringUTF (strerr));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::listen (jint backlog)
|
||||
{
|
||||
if (::listen (fnum, backlog) != 0)
|
||||
{
|
||||
char* strerr = strerror (errno);
|
||||
throw new java::io::IOException (JvNewStringUTF (strerr));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl *s)
|
||||
{
|
||||
union SockAddr u;
|
||||
socklen_t addrlen = sizeof(u);
|
||||
int new_socket = 0;
|
||||
|
||||
// Do timeouts via select since SO_RCVTIMEO is not always available.
|
||||
if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
|
||||
{
|
||||
fd_set fset;
|
||||
struct timeval tv;
|
||||
FD_ZERO(&fset);
|
||||
FD_SET(fnum, &fset);
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
int retval;
|
||||
if ((retval = _Jv_select (fnum + 1, &fset, &fset, NULL, &tv)) < 0)
|
||||
goto error;
|
||||
else if (retval == 0)
|
||||
throw new java::net::SocketTimeoutException (
|
||||
JvNewStringUTF("Accept timed out"));
|
||||
}
|
||||
|
||||
new_socket = _Jv_accept (fnum, (sockaddr*) &u, &addrlen);
|
||||
|
||||
if (new_socket < 0)
|
||||
goto error;
|
||||
|
||||
_Jv_platform_close_on_exec (new_socket);
|
||||
|
||||
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
|
||||
throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
|
||||
|
||||
s->fnum = new_socket;
|
||||
s->localport = localport;
|
||||
s->address = new InetAddress (raddr, NULL);
|
||||
s->port = rport;
|
||||
return;
|
||||
|
||||
error:
|
||||
char* strerr = strerror (errno);
|
||||
throw new java::io::IOException (JvNewStringUTF (strerr));
|
||||
}
|
||||
|
||||
// Close(shutdown) the socket.
|
||||
void
|
||||
java::net::PlainSocketImpl::close()
|
||||
{
|
||||
// Avoid races from asynchronous finalization.
|
||||
JvSynchronize sync (this);
|
||||
|
||||
// should we use shutdown here? how would that effect so_linger?
|
||||
int res = _Jv_close (fnum);
|
||||
|
||||
if (res == -1)
|
||||
{
|
||||
// These three errors are not errors according to tests performed
|
||||
// on the reference implementation.
|
||||
if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF)
|
||||
throw new java::io::IOException (JvNewStringUTF (strerror (errno)));
|
||||
}
|
||||
// Safe place to reset the file pointer.
|
||||
fnum = -1;
|
||||
timeout = 0;
|
||||
}
|
||||
|
||||
// Write a byte to the socket.
|
||||
void
|
||||
java::net::PlainSocketImpl::write(jint b)
|
||||
{
|
||||
jbyte d =(jbyte) b;
|
||||
int r = 0;
|
||||
|
||||
while (r != 1)
|
||||
{
|
||||
r = _Jv_write (fnum, &d, 1);
|
||||
if (r == -1)
|
||||
{
|
||||
if (java::lang::Thread::interrupted())
|
||||
{
|
||||
java::io::InterruptedIOException *iioe
|
||||
= new java::io::InterruptedIOException
|
||||
(JvNewStringLatin1 (strerror (errno)));
|
||||
iioe->bytesTransferred = 0;
|
||||
throw iioe;
|
||||
}
|
||||
// Some errors should not cause exceptions.
|
||||
if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF)
|
||||
throw new java::io::IOException (JvNewStringUTF (strerror (errno)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write some bytes to the socket.
|
||||
void
|
||||
java::net::PlainSocketImpl::write(jbyteArray b, jint offset, jint len)
|
||||
{
|
||||
if (! b)
|
||||
throw new java::lang::NullPointerException;
|
||||
if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
|
||||
throw new java::lang::ArrayIndexOutOfBoundsException;
|
||||
|
||||
jbyte *bytes = elements (b) + offset;
|
||||
int written = 0;
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
int r = _Jv_write (fnum, bytes, len);
|
||||
|
||||
if (r == -1)
|
||||
{
|
||||
if (java::lang::Thread::interrupted())
|
||||
{
|
||||
java::io::InterruptedIOException *iioe
|
||||
= new java::io::InterruptedIOException
|
||||
(JvNewStringLatin1 (strerror (errno)));
|
||||
iioe->bytesTransferred = written;
|
||||
throw iioe;
|
||||
}
|
||||
// Some errors should not cause exceptions.
|
||||
if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF)
|
||||
throw new java::io::IOException (JvNewStringUTF (strerror (errno)));
|
||||
break;
|
||||
}
|
||||
|
||||
written += r;
|
||||
len -= r;
|
||||
bytes += r;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::sendUrgentData (jint)
|
||||
{
|
||||
throw new SocketException (JvNewStringLatin1 (
|
||||
"PlainSocketImpl: sending of urgent data not supported by this socket"));
|
||||
}
|
||||
|
||||
// Read a single byte from the socket.
|
||||
jint
|
||||
java::net::PlainSocketImpl::read(void)
|
||||
{
|
||||
jbyte b;
|
||||
|
||||
// Do timeouts via select.
|
||||
if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
|
||||
{
|
||||
// Create the file descriptor set.
|
||||
fd_set read_fds;
|
||||
FD_ZERO (&read_fds);
|
||||
FD_SET (fnum,&read_fds);
|
||||
// Create the timeout struct based on our internal timeout value.
|
||||
struct timeval timeout_value;
|
||||
timeout_value.tv_sec = timeout / 1000;
|
||||
timeout_value.tv_usec = (timeout % 1000) * 1000;
|
||||
// Select on the fds.
|
||||
int sel_retval =
|
||||
_Jv_select (fnum + 1, &read_fds, NULL, NULL, &timeout_value);
|
||||
// If select returns 0 we've waited without getting data...
|
||||
// that means we've timed out.
|
||||
if (sel_retval == 0)
|
||||
throw new java::net::SocketTimeoutException
|
||||
(JvNewStringUTF ("read timed out") );
|
||||
// If select returns ok we know we either got signalled or read some data...
|
||||
// either way we need to try to read.
|
||||
}
|
||||
|
||||
int r = _Jv_read (fnum, &b, 1);
|
||||
|
||||
if (r == 0)
|
||||
return -1;
|
||||
|
||||
if (java::lang::Thread::interrupted())
|
||||
{
|
||||
java::io::InterruptedIOException *iioe =
|
||||
new java::io::InterruptedIOException
|
||||
(JvNewStringUTF("read interrupted"));
|
||||
iioe->bytesTransferred = r == -1 ? 0 : r;
|
||||
throw iioe;
|
||||
}
|
||||
else if (r == -1)
|
||||
{
|
||||
// Some errors cause us to return end of stream...
|
||||
if (errno == ENOTCONN)
|
||||
return -1;
|
||||
|
||||
// Other errors need to be signalled.
|
||||
throw new java::io::IOException (JvNewStringUTF (strerror (errno)));
|
||||
}
|
||||
|
||||
return b & 0xFF;
|
||||
}
|
||||
|
||||
// Read count bytes into the buffer, starting at offset.
|
||||
jint
|
||||
java::net::PlainSocketImpl::read(jbyteArray buffer, jint offset, jint count)
|
||||
{
|
||||
if (! buffer)
|
||||
throw new java::lang::NullPointerException;
|
||||
|
||||
jsize bsize = JvGetArrayLength (buffer);
|
||||
|
||||
if (offset < 0 || count < 0 || offset + count > bsize)
|
||||
throw new java::lang::ArrayIndexOutOfBoundsException;
|
||||
|
||||
jbyte *bytes = elements (buffer) + offset;
|
||||
|
||||
// Do timeouts via select.
|
||||
if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
|
||||
{
|
||||
// Create the file descriptor set.
|
||||
fd_set read_fds;
|
||||
FD_ZERO (&read_fds);
|
||||
FD_SET (fnum, &read_fds);
|
||||
// Create the timeout struct based on our internal timeout value.
|
||||
struct timeval timeout_value;
|
||||
timeout_value.tv_sec = timeout / 1000;
|
||||
timeout_value.tv_usec =(timeout % 1000) * 1000;
|
||||
// Select on the fds.
|
||||
int sel_retval =
|
||||
_Jv_select (fnum + 1, &read_fds, NULL, NULL, &timeout_value);
|
||||
// We're only interested in the 0 return.
|
||||
// error returns still require us to try to read
|
||||
// the socket to see what happened.
|
||||
if (sel_retval == 0)
|
||||
{
|
||||
java::net::SocketTimeoutException *timeoutException =
|
||||
new java::net::SocketTimeoutException
|
||||
(JvNewStringUTF ("read timed out"));
|
||||
throw timeoutException;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the socket.
|
||||
int r = ::recv (fnum, (char *) bytes, count, 0);
|
||||
|
||||
if (r == 0)
|
||||
return -1;
|
||||
|
||||
if (java::lang::Thread::interrupted())
|
||||
{
|
||||
java::io::InterruptedIOException *iioe =
|
||||
new java::io::InterruptedIOException
|
||||
(JvNewStringUTF ("read interrupted"));
|
||||
iioe->bytesTransferred = r == -1 ? 0 : r;
|
||||
throw iioe;
|
||||
}
|
||||
else if (r == -1)
|
||||
{
|
||||
// Some errors cause us to return end of stream...
|
||||
if (errno == ENOTCONN)
|
||||
return -1;
|
||||
|
||||
// Other errors need to be signalled.
|
||||
throw new java::io::IOException (JvNewStringUTF (strerror (errno)));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// How many bytes are available?
|
||||
jint
|
||||
java::net::PlainSocketImpl::available(void)
|
||||
{
|
||||
#if defined(FIONREAD) || defined(HAVE_SELECT)
|
||||
long num = 0;
|
||||
int r = 0;
|
||||
bool num_set = false;
|
||||
|
||||
#if defined(FIONREAD)
|
||||
r = ::ioctl (fnum, FIONREAD, &num);
|
||||
|
||||
if (r == -1 && errno == ENOTTY)
|
||||
{
|
||||
// If the ioctl doesn't work, we don't care.
|
||||
r = 0;
|
||||
num = 0;
|
||||
}
|
||||
else
|
||||
num_set = true;
|
||||
#elif defined(HAVE_SELECT)
|
||||
if (fnum < 0)
|
||||
{
|
||||
errno = EBADF;
|
||||
r = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (r == -1)
|
||||
{
|
||||
posix_error:
|
||||
throw new java::io::IOException(JvNewStringUTF(strerror(errno)));
|
||||
}
|
||||
|
||||
// If we didn't get anything we can use select.
|
||||
|
||||
#if defined(HAVE_SELECT)
|
||||
if (! num_set)
|
||||
if (! num_set && fnum >= 0 && fnum < FD_SETSIZE)
|
||||
{
|
||||
fd_set rd;
|
||||
FD_ZERO (&rd);
|
||||
FD_SET (fnum, &rd);
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
r = _Jv_select (fnum + 1, &rd, NULL, NULL, &tv);
|
||||
if(r == -1)
|
||||
goto posix_error;
|
||||
num = r == 0 ? 0 : 1;
|
||||
}
|
||||
#endif /* HAVE_SELECT */
|
||||
|
||||
return (jint) num;
|
||||
#else
|
||||
throw new java::io::IOException (JvNewStringUTF ("unimplemented"));
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::setOption (jint optID, java::lang::Object *value)
|
||||
{
|
||||
int val;
|
||||
socklen_t val_len = sizeof (val);
|
||||
|
||||
if (fnum < 0)
|
||||
throw new java::net::SocketException (JvNewStringUTF ("Socket closed"));
|
||||
|
||||
if (_Jv_IsInstanceOf (value, &java::lang::Boolean::class$))
|
||||
{
|
||||
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 if (_Jv_IsInstanceOf (value, &java::lang::Integer::class$))
|
||||
{
|
||||
java::lang::Integer *intobj =
|
||||
static_cast<java::lang::Integer *> (value);
|
||||
val = (int) intobj->intValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new java::lang::IllegalArgumentException (
|
||||
JvNewStringLatin1 ("`value' must be Boolean or Integer"));
|
||||
}
|
||||
|
||||
switch (optID)
|
||||
{
|
||||
case _Jv_TCP_NODELAY_ :
|
||||
#ifdef TCP_NODELAY
|
||||
if (::setsockopt (fnum, IPPROTO_TCP, TCP_NODELAY, (char *) &val,
|
||||
val_len) != 0)
|
||||
goto error;
|
||||
#else
|
||||
throw new java::lang::InternalError
|
||||
(JvNewStringUTF ("TCP_NODELAY not supported"));
|
||||
#endif /* TCP_NODELAY */
|
||||
return;
|
||||
|
||||
case _Jv_SO_KEEPALIVE_ :
|
||||
if (::setsockopt (fnum, SOL_SOCKET, SO_KEEPALIVE, (char *) &val,
|
||||
val_len) != 0)
|
||||
goto error;
|
||||
break;
|
||||
|
||||
case _Jv_SO_BROADCAST_ :
|
||||
throw new java::net::SocketException
|
||||
(JvNewStringUTF ("SO_BROADCAST not valid for TCP"));
|
||||
break;
|
||||
|
||||
case _Jv_SO_OOBINLINE_ :
|
||||
if (::setsockopt (fnum, SOL_SOCKET, SO_OOBINLINE, (char *) &val,
|
||||
val_len) != 0)
|
||||
goto error;
|
||||
break;
|
||||
|
||||
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
|
||||
throw 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
|
||||
throw new java::lang::InternalError (
|
||||
JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
|
||||
#endif
|
||||
return;
|
||||
|
||||
case _Jv_SO_BINDADDR_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("SO_BINDADDR: read only option"));
|
||||
return;
|
||||
|
||||
case _Jv_IP_MULTICAST_IF_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"));
|
||||
return;
|
||||
|
||||
case _Jv_IP_MULTICAST_IF2_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP"));
|
||||
break;
|
||||
|
||||
case _Jv_IP_MULTICAST_LOOP_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP"));
|
||||
break;
|
||||
|
||||
case _Jv_IP_TOS_ :
|
||||
if (::setsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val,
|
||||
val_len) != 0)
|
||||
goto error;
|
||||
break;
|
||||
|
||||
case _Jv_SO_REUSEADDR_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("SO_REUSEADDR: not valid for TCP"));
|
||||
return;
|
||||
|
||||
case _Jv_SO_TIMEOUT_ :
|
||||
timeout = val;
|
||||
return;
|
||||
|
||||
default :
|
||||
errno = ENOPROTOOPT;
|
||||
}
|
||||
|
||||
error:
|
||||
char* strerr = strerror (errno);
|
||||
throw new java::net::SocketException (JvNewStringUTF (strerr));
|
||||
}
|
||||
|
||||
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
|
||||
throw 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 ((jboolean)false);
|
||||
#else
|
||||
throw new java::lang::InternalError
|
||||
(JvNewStringUTF ("SO_LINGER not supported"));
|
||||
#endif
|
||||
break;
|
||||
|
||||
case _Jv_SO_KEEPALIVE_ :
|
||||
if (::getsockopt (fnum, SOL_SOCKET, SO_KEEPALIVE, (char *) &val,
|
||||
&val_len) != 0)
|
||||
goto error;
|
||||
else
|
||||
return new java::lang::Boolean (val != 0);
|
||||
|
||||
case _Jv_SO_BROADCAST_ :
|
||||
if (::getsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &val,
|
||||
&val_len) != 0)
|
||||
goto error;
|
||||
return new java::lang::Boolean ((jboolean)val);
|
||||
|
||||
case _Jv_SO_OOBINLINE_ :
|
||||
if (::getsockopt (fnum, SOL_SOCKET, SO_OOBINLINE, (char *) &val,
|
||||
&val_len) != 0)
|
||||
goto error;
|
||||
return new java::lang::Boolean ((jboolean)val);
|
||||
|
||||
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
|
||||
throw new java::lang::InternalError
|
||||
(JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
|
||||
#endif
|
||||
break;
|
||||
case _Jv_SO_BINDADDR_:
|
||||
// cache the local address
|
||||
if (localAddress == NULL)
|
||||
{
|
||||
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
|
||||
throw new java::net::SocketException
|
||||
(JvNewStringUTF ("invalid family"));
|
||||
localAddress = new java::net::InetAddress (laddr, NULL);
|
||||
}
|
||||
|
||||
return localAddress;
|
||||
break;
|
||||
case _Jv_IP_MULTICAST_IF_ :
|
||||
throw new java::net::SocketException
|
||||
(JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"));
|
||||
break;
|
||||
|
||||
case _Jv_IP_MULTICAST_IF2_ :
|
||||
throw new java::net::SocketException
|
||||
(JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP"));
|
||||
break;
|
||||
|
||||
case _Jv_IP_MULTICAST_LOOP_ :
|
||||
throw new java::net::SocketException
|
||||
(JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP"));
|
||||
break;
|
||||
|
||||
case _Jv_IP_TOS_ :
|
||||
if (::getsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val,
|
||||
&val_len) != 0)
|
||||
goto error;
|
||||
return new java::lang::Integer (val);
|
||||
break;
|
||||
|
||||
case _Jv_SO_REUSEADDR_ :
|
||||
throw new java::net::SocketException
|
||||
(JvNewStringUTF ("SO_REUSEADDR: not valid for TCP"));
|
||||
break;
|
||||
|
||||
case _Jv_SO_TIMEOUT_ :
|
||||
return new java::lang::Integer (timeout);
|
||||
break;
|
||||
|
||||
default :
|
||||
errno = ENOPROTOOPT;
|
||||
}
|
||||
|
||||
error:
|
||||
char* strerr = strerror (errno);
|
||||
throw new java::net::SocketException (JvNewStringUTF (strerr));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::shutdownInput (void)
|
||||
{
|
||||
if (::shutdown (fnum, 0))
|
||||
throw new SocketException (JvNewStringUTF (strerror (errno)));
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::shutdownOutput (void)
|
||||
{
|
||||
if (::shutdown (fnum, 1))
|
||||
throw new SocketException (JvNewStringUTF (strerror (errno)));
|
||||
}
|
|
@ -1,784 +0,0 @@
|
|||
/* Copyright (C) 2003 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
#include <config.h>
|
||||
#include <platform.h>
|
||||
|
||||
#undef STRICT
|
||||
#undef MAX_PRIORITY
|
||||
#undef MIN_PRIORITY
|
||||
|
||||
#include <java/io/IOException.h>
|
||||
#include <java/io/InterruptedIOException.h>
|
||||
#include <java/net/BindException.h>
|
||||
#include <java/net/ConnectException.h>
|
||||
#include <java/net/PlainSocketImpl.h>
|
||||
#include <java/net/InetAddress.h>
|
||||
#include <java/net/InetSocketAddress.h>
|
||||
#include <java/net/SocketException.h>
|
||||
#include <java/net/SocketTimeoutException.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>
|
||||
#include <java/lang/Thread.h>
|
||||
#include <java/lang/NullPointerException.h>
|
||||
#include <java/lang/ArrayIndexOutOfBoundsException.h>
|
||||
#include <java/lang/IllegalArgumentException.h>
|
||||
|
||||
union SockAddr
|
||||
{
|
||||
struct sockaddr_in address;
|
||||
#ifdef HAVE_INET6
|
||||
struct sockaddr_in6 address6;
|
||||
#endif
|
||||
};
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::create (jboolean stream)
|
||||
{
|
||||
int sock = ::socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0);
|
||||
|
||||
if (sock == int(INVALID_SOCKET))
|
||||
{
|
||||
_Jv_ThrowIOException ();
|
||||
}
|
||||
|
||||
_Jv_platform_close_on_exec (sock);
|
||||
|
||||
// We use fnum in place of fd here. From leaving fd null we avoid
|
||||
// the double close problem in FileDescriptor.finalize.
|
||||
fnum = sock;
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::bind (java::net::InetAddress *host, jint lport)
|
||||
{
|
||||
union SockAddr u;
|
||||
struct sockaddr *ptr = (struct sockaddr *) &u.address;
|
||||
jbyteArray haddress = host->addr;
|
||||
jbyte *bytes = elements (haddress);
|
||||
int len = haddress->length;
|
||||
int i = 1;
|
||||
|
||||
if (len == 4)
|
||||
{
|
||||
u.address.sin_family = AF_INET;
|
||||
|
||||
if (host != NULL)
|
||||
memcpy (&u.address.sin_addr, bytes, len);
|
||||
else
|
||||
u.address.sin_addr.s_addr = htonl (INADDR_ANY);
|
||||
|
||||
len = sizeof (struct sockaddr_in);
|
||||
u.address.sin_port = htons (lport);
|
||||
}
|
||||
#ifdef HAVE_INET6
|
||||
else if (len == 16)
|
||||
{
|
||||
u.address6.sin6_family = AF_INET6;
|
||||
memcpy (&u.address6.sin6_addr, bytes, len);
|
||||
len = sizeof (struct sockaddr_in6);
|
||||
u.address6.sin6_port = htons (lport);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
|
||||
|
||||
// Enable SO_REUSEADDR, so that servers can reuse ports left in TIME_WAIT.
|
||||
::setsockopt(fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &i, sizeof(i));
|
||||
|
||||
if (::bind (fnum, ptr, len) != SOCKET_ERROR)
|
||||
{
|
||||
address = host;
|
||||
socklen_t addrlen = sizeof(u);
|
||||
|
||||
if (lport != 0)
|
||||
localport = lport;
|
||||
else if (::getsockname (fnum, (sockaddr*) &u, &addrlen) != SOCKET_ERROR)
|
||||
localport = ntohs (u.address.sin_port);
|
||||
else
|
||||
goto error;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
error:
|
||||
DWORD dwErrorCode = WSAGetLastError ();
|
||||
throw new java::net::BindException (_Jv_WinStrError (dwErrorCode));
|
||||
}
|
||||
|
||||
static void
|
||||
throwConnectException (DWORD dwErrorCode)
|
||||
{
|
||||
throw new java::net::ConnectException (_Jv_WinStrError (dwErrorCode));
|
||||
}
|
||||
|
||||
static void
|
||||
throwConnectException ()
|
||||
{
|
||||
throwConnectException (WSAGetLastError ());
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::connect (java::net::SocketAddress *addr,
|
||||
jint timeout)
|
||||
{
|
||||
java::net::InetSocketAddress *tmp = (java::net::InetSocketAddress*) addr;
|
||||
java::net::InetAddress *host = tmp->getAddress();
|
||||
jint rport = tmp->getPort();
|
||||
|
||||
union SockAddr u;
|
||||
socklen_t addrlen = sizeof(u);
|
||||
jbyteArray haddress = host->addr;
|
||||
jbyte *bytes = elements (haddress);
|
||||
int len = haddress->length;
|
||||
struct sockaddr *ptr = (struct sockaddr *) &u.address;
|
||||
|
||||
if (len == 4)
|
||||
{
|
||||
u.address.sin_family = AF_INET;
|
||||
memcpy (&u.address.sin_addr, bytes, len);
|
||||
len = sizeof (struct sockaddr_in);
|
||||
u.address.sin_port = htons (rport);
|
||||
}
|
||||
#ifdef HAVE_INET6
|
||||
else if (len == 16)
|
||||
{
|
||||
u.address6.sin6_family = AF_INET6;
|
||||
memcpy (&u.address6.sin6_addr, bytes, len);
|
||||
len = sizeof (struct sockaddr_in6);
|
||||
u.address6.sin6_port = htons (rport);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
|
||||
|
||||
if (timeout > 0)
|
||||
{
|
||||
// FIXME: we're creating a fresh WSAEVENT for each connect().
|
||||
WSAEventWrapper aWSAEventWrapper(fnum, FD_CONNECT);
|
||||
WSAEVENT hEvent = aWSAEventWrapper.getEventHandle ();
|
||||
|
||||
if (::connect (fnum, ptr, len) == SOCKET_ERROR)
|
||||
{
|
||||
if (WSAGetLastError () != WSAEWOULDBLOCK)
|
||||
throwConnectException ();
|
||||
|
||||
DWORD dwRet =
|
||||
WSAWaitForMultipleEvents (1, &hEvent, true, timeout, false);
|
||||
// use true, false instead of TRUE, FALSE because the
|
||||
// MS constants got undefined
|
||||
|
||||
if (dwRet == WSA_WAIT_FAILED)
|
||||
throwConnectException ();
|
||||
|
||||
else if (dwRet == WSA_WAIT_TIMEOUT)
|
||||
throw new java::net::SocketTimeoutException
|
||||
(JvNewStringUTF ("connect timed out"));
|
||||
|
||||
// If we get here, we still need to check whether the actual
|
||||
// connect() succeeded. Use any socket-specific error code
|
||||
// instead of the thread-based one.
|
||||
int nErrCode; int nErrLen=sizeof(nErrCode);
|
||||
if (::getsockopt(fnum, SOL_SOCKET, SO_ERROR, (char*) &nErrCode,
|
||||
&nErrLen) == SOCKET_ERROR)
|
||||
{
|
||||
throwConnectException ();
|
||||
}
|
||||
|
||||
if (nErrCode != NO_ERROR)
|
||||
{
|
||||
throwConnectException (nErrCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (::connect (fnum, ptr, len) == SOCKET_ERROR)
|
||||
throwConnectException();
|
||||
}
|
||||
|
||||
address = host;
|
||||
port = rport;
|
||||
|
||||
// A bind may not have been done on this socket; if so, set localport now.
|
||||
if (localport == 0)
|
||||
{
|
||||
if (::getsockname (fnum, (sockaddr*) &u, &addrlen) != SOCKET_ERROR)
|
||||
localport = ntohs (u.address.sin_port);
|
||||
else
|
||||
throwConnectException();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::listen (jint backlog)
|
||||
{
|
||||
if (::listen (fnum, backlog) == SOCKET_ERROR)
|
||||
{
|
||||
_Jv_ThrowIOException ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl *s)
|
||||
{
|
||||
union SockAddr u;
|
||||
socklen_t addrlen = sizeof(u);
|
||||
int new_socket = 0;
|
||||
|
||||
if (timeout > 0)
|
||||
{
|
||||
// FIXME: we're creating a fresh WSAEVENT for each accept().
|
||||
// One possible alternative would be that fnum really points
|
||||
// to an extended structure consisting of the SOCKET, its
|
||||
// associated WSAEVENT, etc.
|
||||
WSAEventWrapper aWSAEventWrapper(fnum, FD_ACCEPT);
|
||||
WSAEVENT hEvent = aWSAEventWrapper.getEventHandle ();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
new_socket = ::accept (fnum, (sockaddr*) &u, &addrlen);
|
||||
|
||||
if (new_socket != int(INVALID_SOCKET))
|
||||
{
|
||||
// This new child socket is nonblocking because the parent
|
||||
// socket became nonblocking via the WSAEventSelect() call,
|
||||
// so we set its mode back to blocking.
|
||||
WSAEventSelect (new_socket, hEvent, 0);
|
||||
// undo the hEvent <-> FD_ACCEPT association inherited
|
||||
// inherited from our parent socket
|
||||
|
||||
unsigned long lSockOpt = 0L;
|
||||
// blocking mode
|
||||
if (ioctlsocket(new_socket, FIONBIO, &lSockOpt) == SOCKET_ERROR)
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (WSAGetLastError () != WSAEWOULDBLOCK)
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
DWORD dwRet =
|
||||
WSAWaitForMultipleEvents (1, &hEvent, true, timeout, false);
|
||||
// use true, false instead of TRUE, FALSE because the
|
||||
// MS constants got undefined
|
||||
|
||||
if (dwRet == WSA_WAIT_FAILED)
|
||||
goto error;
|
||||
else if (dwRet == WSA_WAIT_TIMEOUT)
|
||||
throw new java::net::SocketTimeoutException
|
||||
(JvNewStringUTF ("accept timed out"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
new_socket = ::accept (fnum, (sockaddr*) &u, &addrlen);
|
||||
}
|
||||
|
||||
if (new_socket == int(INVALID_SOCKET))
|
||||
goto error;
|
||||
|
||||
_Jv_platform_close_on_exec (new_socket);
|
||||
|
||||
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
|
||||
throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
|
||||
|
||||
s->fnum = new_socket;
|
||||
s->localport = localport;
|
||||
s->address = new InetAddress (raddr, NULL);
|
||||
s->port = rport;
|
||||
return;
|
||||
|
||||
error:
|
||||
_Jv_ThrowIOException ();
|
||||
}
|
||||
|
||||
// Close(shutdown) the socket.
|
||||
void
|
||||
java::net::PlainSocketImpl::close()
|
||||
{
|
||||
// Avoid races from asynchronous finalization.
|
||||
JvSynchronize sync (this);
|
||||
|
||||
// should we use shutdown here? how would that effect so_linger?
|
||||
int res = ::closesocket (fnum);
|
||||
|
||||
if (res == -1)
|
||||
{
|
||||
// These three errors are not errors according to tests performed
|
||||
// on the reference implementation.
|
||||
DWORD dwErr = WSAGetLastError();
|
||||
if (dwErr != WSAENOTCONN && dwErr != WSAECONNRESET
|
||||
&& dwErr != WSAENOTSOCK)
|
||||
_Jv_ThrowIOException ();
|
||||
}
|
||||
// Safe place to reset the file pointer.
|
||||
fnum = -1;
|
||||
timeout = 0;
|
||||
}
|
||||
|
||||
// Write a byte to the socket.
|
||||
void
|
||||
java::net::PlainSocketImpl::write(jint b)
|
||||
{
|
||||
jbyte d =(jbyte) b;
|
||||
int r = 0;
|
||||
|
||||
while (r != 1)
|
||||
{
|
||||
r = ::send (fnum, (char*) &d, 1, 0);
|
||||
if (r == -1)
|
||||
{
|
||||
DWORD dwErr = WSAGetLastError();
|
||||
if (java::lang::Thread::interrupted())
|
||||
{
|
||||
java::io::InterruptedIOException *iioe
|
||||
= new java::io::InterruptedIOException
|
||||
(_Jv_WinStrError (dwErr));
|
||||
iioe->bytesTransferred = 0;
|
||||
throw iioe;
|
||||
}
|
||||
// Some errors should not cause exceptions.
|
||||
if (dwErr != WSAENOTCONN && dwErr != WSAECONNRESET
|
||||
&& dwErr != WSAENOTSOCK)
|
||||
_Jv_ThrowIOException ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write some bytes to the socket.
|
||||
void
|
||||
java::net::PlainSocketImpl::write(jbyteArray b, jint offset, jint len)
|
||||
{
|
||||
if (! b)
|
||||
throw new java::lang::NullPointerException;
|
||||
if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
|
||||
throw new java::lang::ArrayIndexOutOfBoundsException;
|
||||
|
||||
jbyte *bytes = elements (b) + offset;
|
||||
int written = 0;
|
||||
while (len > 0)
|
||||
{
|
||||
int r = ::send (fnum, (char*) bytes, len, 0);
|
||||
|
||||
if (r == -1)
|
||||
{
|
||||
DWORD dwErr = WSAGetLastError();
|
||||
if (java::lang::Thread::interrupted())
|
||||
{
|
||||
java::io::InterruptedIOException *iioe
|
||||
= new java::io::InterruptedIOException
|
||||
(_Jv_WinStrError (dwErr));
|
||||
iioe->bytesTransferred = written;
|
||||
throw iioe;
|
||||
}
|
||||
// Some errors should not cause exceptions.
|
||||
if (dwErr != WSAENOTCONN && dwErr != WSAECONNRESET
|
||||
&& dwErr != WSAENOTSOCK)
|
||||
_Jv_ThrowIOException ();
|
||||
break;
|
||||
}
|
||||
|
||||
written += r;
|
||||
len -= r;
|
||||
bytes += r;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::sendUrgentData (jint)
|
||||
{
|
||||
throw new SocketException (JvNewStringLatin1 (
|
||||
"PlainSocketImpl: sending of urgent data not supported by this socket"));
|
||||
}
|
||||
|
||||
// read() helper
|
||||
static jint
|
||||
doRead(int fnum, void* buf, int count, int timeout)
|
||||
{
|
||||
int r = 0;
|
||||
DWORD dwErrorCode = 0;
|
||||
// we are forced to declare this here because
|
||||
// a call to Thread::interrupted() blanks out
|
||||
// WSAGetLastError().
|
||||
|
||||
// FIXME: we unconditionally set SO_RCVTIMEO here
|
||||
// because we can't detect whether someone has
|
||||
// gone from a non-zero to zero timeout. What we'd
|
||||
// really need is a member state variable in addition
|
||||
// to timeout
|
||||
int nRet= ::setsockopt(fnum, SOL_SOCKET, SO_RCVTIMEO,
|
||||
(char*)&timeout, sizeof(timeout));
|
||||
if (nRet != NO_ERROR)
|
||||
{
|
||||
dwErrorCode = WSAGetLastError ();
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = ::recv (fnum, (char*) buf, count, 0);
|
||||
|
||||
if (r == 0)
|
||||
return -1;
|
||||
|
||||
dwErrorCode = WSAGetLastError ();
|
||||
// save WSAGetLastError() before calling Thread.interrupted()
|
||||
|
||||
if (java::lang::Thread::interrupted())
|
||||
{
|
||||
java::io::InterruptedIOException *iioe =
|
||||
new java::io::InterruptedIOException
|
||||
(JvNewStringUTF("read interrupted"));
|
||||
iioe->bytesTransferred = r == -1 ? 0 : r;
|
||||
throw iioe;
|
||||
}
|
||||
else if (r == -1)
|
||||
{
|
||||
error:
|
||||
// Some errors cause us to return end of stream...
|
||||
if (dwErrorCode == WSAENOTCONN)
|
||||
return -1;
|
||||
|
||||
// Other errors need to be signalled.
|
||||
if (dwErrorCode == WSAETIMEDOUT)
|
||||
throw new java::net::SocketTimeoutException
|
||||
(JvNewStringUTF ("read timed out") );
|
||||
else
|
||||
_Jv_ThrowIOException (dwErrorCode);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// Read a single byte from the socket.
|
||||
jint
|
||||
java::net::PlainSocketImpl::read(void)
|
||||
{
|
||||
jbyte b;
|
||||
doRead(fnum, &b, 1, timeout);
|
||||
return b & 0xFF;
|
||||
}
|
||||
|
||||
// Read count bytes into the buffer, starting at offset.
|
||||
jint
|
||||
java::net::PlainSocketImpl::read(jbyteArray buffer, jint offset, jint count)
|
||||
{
|
||||
if (! buffer)
|
||||
throw new java::lang::NullPointerException;
|
||||
|
||||
jsize bsize = JvGetArrayLength (buffer);
|
||||
|
||||
if (offset < 0 || count < 0 || offset + count > bsize)
|
||||
throw new java::lang::ArrayIndexOutOfBoundsException;
|
||||
|
||||
jbyte *bytes = elements (buffer) + offset;
|
||||
|
||||
// Read the socket.
|
||||
return doRead(fnum, bytes, count, timeout);
|
||||
}
|
||||
|
||||
// How many bytes are available?
|
||||
jint
|
||||
java::net::PlainSocketImpl::available(void)
|
||||
{
|
||||
unsigned long num = 0;
|
||||
|
||||
if (::ioctlsocket (fnum, FIONREAD, &num) == SOCKET_ERROR)
|
||||
_Jv_ThrowIOException ();
|
||||
|
||||
return (jint) num;
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::setOption (jint optID, java::lang::Object *value)
|
||||
{
|
||||
int val;
|
||||
socklen_t val_len = sizeof (val);
|
||||
|
||||
if (fnum < 0)
|
||||
throw new java::net::SocketException (JvNewStringUTF ("Socket closed"));
|
||||
|
||||
if (_Jv_IsInstanceOf (value, &java::lang::Boolean::class$))
|
||||
{
|
||||
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 if (_Jv_IsInstanceOf (value, &java::lang::Integer::class$))
|
||||
{
|
||||
java::lang::Integer *intobj =
|
||||
static_cast<java::lang::Integer *> (value);
|
||||
val = (int) intobj->intValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new java::lang::IllegalArgumentException (
|
||||
JvNewStringLatin1 ("`value' must be Boolean or Integer"));
|
||||
}
|
||||
|
||||
switch (optID)
|
||||
{
|
||||
case _Jv_TCP_NODELAY_ :
|
||||
if (::setsockopt (fnum, IPPROTO_TCP, TCP_NODELAY, (char *) &val,
|
||||
val_len) == SOCKET_ERROR)
|
||||
goto error;
|
||||
return;
|
||||
|
||||
case _Jv_SO_KEEPALIVE_ :
|
||||
if (::setsockopt (fnum, SOL_SOCKET, SO_KEEPALIVE, (char *) &val,
|
||||
val_len) == SOCKET_ERROR)
|
||||
goto error;
|
||||
break;
|
||||
|
||||
case _Jv_SO_BROADCAST_ :
|
||||
throw new java::net::SocketException
|
||||
(JvNewStringUTF ("SO_BROADCAST not valid for TCP"));
|
||||
break;
|
||||
|
||||
case _Jv_SO_OOBINLINE_ :
|
||||
if (::setsockopt (fnum, SOL_SOCKET, SO_OOBINLINE, (char *) &val,
|
||||
val_len) == SOCKET_ERROR)
|
||||
goto error;
|
||||
break;
|
||||
|
||||
case _Jv_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)) == SOCKET_ERROR)
|
||||
goto error;
|
||||
return;
|
||||
|
||||
case _Jv_SO_SNDBUF_ :
|
||||
case _Jv_SO_RCVBUF_ :
|
||||
int opt;
|
||||
optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
|
||||
if (::setsockopt (fnum, SOL_SOCKET, opt, (char *) &val,
|
||||
val_len) == SOCKET_ERROR)
|
||||
goto error;
|
||||
return;
|
||||
|
||||
case _Jv_SO_BINDADDR_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("SO_BINDADDR: read only option"));
|
||||
return;
|
||||
|
||||
case _Jv_IP_MULTICAST_IF_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"));
|
||||
return;
|
||||
|
||||
case _Jv_IP_MULTICAST_IF2_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP"));
|
||||
break;
|
||||
|
||||
case _Jv_IP_MULTICAST_LOOP_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP"));
|
||||
break;
|
||||
|
||||
case _Jv_IP_TOS_ :
|
||||
if (::setsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val,
|
||||
val_len) == SOCKET_ERROR)
|
||||
goto error;
|
||||
break;
|
||||
|
||||
case _Jv_SO_REUSEADDR_ :
|
||||
throw new java::net::SocketException (
|
||||
JvNewStringUTF ("SO_REUSEADDR: not valid for TCP"));
|
||||
return;
|
||||
|
||||
case _Jv_SO_TIMEOUT_ :
|
||||
timeout = val;
|
||||
return;
|
||||
|
||||
default :
|
||||
WSASetLastError (WSAENOPROTOOPT);
|
||||
}
|
||||
|
||||
error:
|
||||
_Jv_ThrowSocketException ();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
case _Jv_TCP_NODELAY_ :
|
||||
if (::getsockopt (fnum, IPPROTO_TCP, TCP_NODELAY, (char *) &val,
|
||||
&val_len) == SOCKET_ERROR)
|
||||
goto error;
|
||||
else
|
||||
return new java::lang::Boolean (val != 0);
|
||||
break;
|
||||
|
||||
case _Jv_SO_LINGER_ :
|
||||
if (::getsockopt (fnum, SOL_SOCKET, SO_LINGER, (char *) &l_val,
|
||||
&l_val_len) == SOCKET_ERROR)
|
||||
goto error;
|
||||
|
||||
if (l_val.l_onoff)
|
||||
return new java::lang::Integer (l_val.l_linger);
|
||||
else
|
||||
return new java::lang::Boolean ((jboolean)false);
|
||||
break;
|
||||
|
||||
case _Jv_SO_KEEPALIVE_ :
|
||||
if (::getsockopt (fnum, SOL_SOCKET, SO_KEEPALIVE, (char *) &val,
|
||||
&val_len) == SOCKET_ERROR)
|
||||
goto error;
|
||||
else
|
||||
return new java::lang::Boolean (val != 0);
|
||||
|
||||
case _Jv_SO_BROADCAST_ :
|
||||
if (::getsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &val,
|
||||
&val_len) == SOCKET_ERROR)
|
||||
goto error;
|
||||
return new java::lang::Boolean ((jboolean)val);
|
||||
|
||||
case _Jv_SO_OOBINLINE_ :
|
||||
if (::getsockopt (fnum, SOL_SOCKET, SO_OOBINLINE, (char *) &val,
|
||||
&val_len) == SOCKET_ERROR)
|
||||
goto error;
|
||||
return new java::lang::Boolean ((jboolean)val);
|
||||
|
||||
case _Jv_SO_RCVBUF_ :
|
||||
case _Jv_SO_SNDBUF_ :
|
||||
int opt;
|
||||
optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
|
||||
if (::getsockopt (fnum, SOL_SOCKET, opt, (char *) &val,
|
||||
&val_len) == SOCKET_ERROR)
|
||||
goto error;
|
||||
else
|
||||
return new java::lang::Integer (val);
|
||||
break;
|
||||
case _Jv_SO_BINDADDR_:
|
||||
// cache the local address
|
||||
if (localAddress == NULL)
|
||||
{
|
||||
jbyteArray laddr;
|
||||
|
||||
if (::getsockname (fnum, (sockaddr*) &u,
|
||||
&addrlen) == SOCKET_ERROR)
|
||||
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);
|
||||
}
|
||||
|
||||
return localAddress;
|
||||
break;
|
||||
case _Jv_IP_MULTICAST_IF_ :
|
||||
throw new java::net::SocketException
|
||||
(JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"));
|
||||
break;
|
||||
|
||||
case _Jv_IP_MULTICAST_IF2_ :
|
||||
throw new java::net::SocketException
|
||||
(JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP"));
|
||||
break;
|
||||
|
||||
case _Jv_IP_MULTICAST_LOOP_ :
|
||||
throw new java::net::SocketException
|
||||
(JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP"));
|
||||
break;
|
||||
|
||||
case _Jv_IP_TOS_ :
|
||||
if (::getsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val,
|
||||
&val_len) == SOCKET_ERROR)
|
||||
goto error;
|
||||
return new java::lang::Integer (val);
|
||||
break;
|
||||
|
||||
case _Jv_SO_REUSEADDR_ :
|
||||
throw new java::net::SocketException
|
||||
(JvNewStringUTF ("SO_REUSEADDR: not valid for TCP"));
|
||||
break;
|
||||
|
||||
case _Jv_SO_TIMEOUT_ :
|
||||
return new java::lang::Integer (timeout);
|
||||
break;
|
||||
|
||||
default :
|
||||
WSASetLastError (WSAENOPROTOOPT);
|
||||
}
|
||||
|
||||
error:
|
||||
_Jv_ThrowSocketException ();
|
||||
return 0;
|
||||
// we should never get here
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::shutdownInput (void)
|
||||
{
|
||||
if (::shutdown (fnum, 0))
|
||||
_Jv_ThrowSocketException ();
|
||||
}
|
||||
|
||||
void
|
||||
java::net::PlainSocketImpl::shutdownOutput (void)
|
||||
{
|
||||
if (::shutdown (fnum, 1))
|
||||
_Jv_ThrowSocketException ();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue