package org.limewire.net; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import org.limewire.io.Address; import org.limewire.listener.ListenerSupport; import org.limewire.net.address.AddressConnector; import org.limewire.net.address.AddressResolutionObserver; import org.limewire.net.address.AddressResolver; import org.limewire.nio.NBSocket; import org.limewire.nio.NBSocketFactory; import org.limewire.nio.NIOSocketFactory; import org.limewire.nio.observer.ConnectObserver; import org.limewire.nio.ssl.SSLSocketFactory; import org.limewire.nio.ssl.TLSSocketFactory; /** Factory for creating Sockets. */ public interface SocketsManager extends ListenerSupport<ConnectivityChangeEvent> { /** The different ways a connection can be attempted. */ public static enum ConnectType { PLAIN(new NIOSocketFactory()), TLS(new TLSSocketFactory()), SSL(new SSLSocketFactory()); private final NBSocketFactory factory; ConnectType(NBSocketFactory factory) { this.factory = factory; } NBSocketFactory getFactory() { return factory; } } /** * Creates a new <code>Socket</code>. Does NOT bind or connect the <code>Socket</code>. * <p> * The creation will use the specified connection type. * For example, to make a plain socket, use ConnectType.PLAIN. * To connect with a TLS Socket, use ConnectType.TLS. * * @param type the type of <code>Socket</code> to create * @throws IOException */ public Socket create(ConnectType type) throws IOException; /** * 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. * <p> * The connection will be attempted with the specified connection type. * For example, to make a plain socket, use ConnectType.PLAIN. * To connect with a TLS Socket, use ConnectType.TLS. * * @param socket the socket to connect; if <code>null</code> a new <code>Socket</code> will be created * @param localAddr the Socket address to bind to locally; can be null * @param remoteAddr the host/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 type the type of connection to attempt * @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 Socket connect(NBSocket socket, InetSocketAddress localAddr, InetSocketAddress remoteAddr, int timeout, ConnectType type) throws IOException; /** * 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. * <p> * The connection will be attempted with the specified connection type. * For example, to make a plain socket, use ConnectType.PLAIN. * To connect with a TLS Socket, use ConnectType.TLS. * * @param socket the socket to connect; if <code>null</code> a new <code>Socket</code> will be created * @param localAddr the Socket address to bind to locally; can be null * @param remoteAddr the host/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 type the type of connection to attempt * @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 Socket connect(NBSocket socket, InetSocketAddress localAddr, InetSocketAddress remoteAddr, int timeout, ConnectObserver observer, ConnectType type) throws IOException; /** * 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 addr the host/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 Socket connect(InetSocketAddress addr, int timeout) throws IOException; /** * 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. * <p> * The connection will be attempted with the specified connection type. * For example, to make a plain socket, use ConnectType.PLAIN. * To connect with a TLS Socket, use ConnectType.TLS. * * @param addr the host/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 type the type of connection to attempt * @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 Socket connect(InetSocketAddress addr, int timeout, ConnectType type) throws IOException; /** * Sets up a socket for connecting. * This method may either block or return immediately, depending on if * if observer is null or not. * <p> * 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. * <p> * 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 Socket connect(InetSocketAddress addr, int timeout, ConnectObserver observer) throws IOException; /** * Sets up a socket for connecting. * This method may either block or return immediately, depending on if * if observer is null or not. * <p> * 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. * <p> * If observer is null, this method blocks until a connection can be established. * If no connection can be established, an IOException is thrown. * <p> * The ConnectType determines the kind of connection that is attempted. * For example, ConnectType.PLAIN will create a plaintext socket, whereas * ConnectType.TLS will create a TLS socket. * * @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 * @param type the type of connection to attempt * @return the Socket (connected or unconnected) * @throws IOException see above * @throws <tt>IllegalArgumentException</tt> if the port is invalid */ public Socket connect(InetSocketAddress addr, int timeout, ConnectObserver observer, ConnectType type) throws IOException; /** * Asynchronously connects to <code>address</code> resolving the address if * possible/necessary and notifying <code>observer</code> of the success or * failure. * * @return the observer for fluent access */ public <T extends ConnectObserver> T connect(Address address, T observer); /** * Asynchronously resolves <code>address</code> to other addresses if * possible and notifying <code>observer</code> of the success or * failure. * <p> * If there is no resolver for address, the observer is notified of a address * resolution with the exact same address. * * @return observer for fluent access */ public <T extends AddressResolutionObserver> T resolve(Address address, T 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 boolean removeConnectObserver(ConnectObserver observer); /** Returns the number of Sockets allowed to be created concurrently. */ public int getNumAllowedSockets(); /** Returns the number of Sockets that are waiting for the controller to process them. */ public int getNumWaitingSockets(); /** * Registers an {@link AddressConnector} to handle connects for certain types * of address. * <p> * When {@link #connect(Address, int, ConnectObserver)} is called the sockets * manager will iterate over all registered {@link AddressConnector address connectors} * and see which one can connect to the given address. * <p> * See {@link AddressConnector}. */ public void registerConnector(AddressConnector connector); /** * Registers an {@link AddressResolver} to handle address resolution for * certain types of addresses. * <p> * When {@link #resolve(Address, int, AddressResolutionObserver)} is called the sockets * manager will iterate over all registered {@link AddressResolver address resolvers} * and see which one can resolve the given address. * <p> * See {@link AddressResolver}. */ public void registerResolver(AddressResolver resolver); /** * Returns true if there is a connector that can connect to the address. */ public boolean canConnect(Address address); /** * Returns true if there is a resolver that can resolve the address. */ public boolean canResolve(Address address); }