package com.limegroup.gnutella.util; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import com.limegroup.gnutella.io.ConnectObserver; /** * Factory for creating Sockets. */ public class Sockets { private final static SocketController CONTROLLER = CommonUtils.isWindowsXP() ? new LimitedSocketController(4) : new SimpleSocketController(); /** * Ensure this cannot be constructed. */ private Sockets() {} /** * Connects and returns a socket to the given host, with a timeout. * The timeout only applies to network conditions. More time might be spent * waiting for an available slot to connect with. * * @param host the address of the host to connect to * @param port the port to connect to * @param timeout the desired timeout for connecting, in milliseconds, * or 0 for no timeout. In case of a proxy connection, this timeout * might be exceeded * @return the connected Socket * @throws IOException the connections couldn't be made in the * requested time * @throws <tt>IllegalArgumentException</tt> if the port is invalid */ public static Socket connect(String host, int port, int timeout) throws IOException { return connect(host, port, timeout, null); } /** * Sets up a socket for connecting. * This method may either block or return immediately, depending on if * if observer is null or not. * * If observer is non-null, this returns immediately. This may either return * a connected or unconnected Socket, depending on if a connection was able to * be established immediately. The ConnectObserver will always be notified of * success via handleConnect(Socket), and failure via shutdown(). If the connection * was established immediately, it is possible that handleConnect(Socket) is called * before this method returns. * * If observer is null, this method blocks until a connection can be established. * If no connection can be established, an IOException is thrown. * * @param host the address of the host to connect to * @param port the port to connect to * @param timeout the desired timeout for connecting, in milliseconds, * or 0 for no timeout. In case of a proxy connection, this timeout * might be exceeded * @param observer the ConnectObserver to notify about non-blocking connect events * @return the Socket (connected or unconnected) * @throws IOException see above * @throws <tt>IllegalArgumentException</tt> if the port is invalid */ public static Socket connect(String host, int port, int timeout, ConnectObserver observer) throws IOException { InetAddress address = InetAddress.getByName(host); InetSocketAddress addr = new InetSocketAddress(address, port); return connect(addr, timeout, observer); } /** * Sets up a socket for connecting. * This method may either block or return immediately, depending on if * if observer is null or not. * * If observer is non-null, this returns immediately. This may either return * a connected or unconnected Socket, depending on if a connection was able to * be established immediately. The ConnectObserver will always be notified of * success via handleConnect(Socket), and failure via shutdown(). If the connection * was established immediately, it is possible that handleConnect(Socket) is called * before this method returns. * * If observer is null, this method blocks until a connection can be established. * If no connection can be established, an IOException is thrown. * * @param addr address/port * @param timeout the desired timeout for connecting, in milliseconds, * or 0 for no timeout. In case of a proxy connection, this timeout * might be exceeded * @param observer the ConnectObserver to notify about non-blocking connect events * @return the Socket (connected or unconnected) * @throws IOException see above * @throws <tt>IllegalArgumentException</tt> if the port is invalid */ public static Socket connect(InetSocketAddress addr, int timeout, ConnectObserver observer) throws IOException { if(!NetworkUtils.isValidPort(addr.getPort())) throw new IllegalArgumentException("port out of range: "+addr.getPort()); return CONTROLLER.connect(addr, timeout, observer); } /** * Removes the given ConnectObserver from wanting to make a request. * This returns true if it was able to remove the observer because the request had * not been processed yet. * Otherwise it returns false, and the ConnectObserver should expect some sort of callback * indicating whether or not the connect succeeded. */ public static boolean removeConnectObserver(ConnectObserver observer) { return CONTROLLER.removeConnectObserver(observer); } /** Returns the number of Sockets allowed to be created concurrently. */ public static int getNumAllowedSockets() { return CONTROLLER.getNumAllowedSockets(); } }