package net.i2p.client.streaming.impl; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketAddress; import java.net.SocketException; import java.nio.channels.ServerSocketChannel; import net.i2p.I2PException; import net.i2p.client.streaming.I2PSocket; import net.i2p.client.streaming.I2PSocketAddress; /** * Bridge to I2PServerSocket. * * This extends ServerSocket to make porting apps easier. * accept() returns a real Socket (a StandardSocket). * accept() throws IOExceptions like ServerSockets do, rather than returning * null or throwing I2PExceptions. * * StandardServerSockets are always bound. * You may not create an unbound StandardServerSocket. * Create this through the SocketManager. * * @author zzz * @since 0.8.4 */ class StandardServerSocket extends ServerSocket { private final I2PServerSocketFull _socket; /** * Doesn't really throw IOE but super() does */ StandardServerSocket(I2PServerSocketFull socket) throws IOException { _socket = socket; } @Override public Socket accept() throws IOException { try { I2PSocket sock = _socket.accept(); if (sock == null) throw new IOException("No socket"); return new StandardSocket(sock); } catch (I2PException i2pe) { IOException ioe = new IOException("accept fail"); ioe.initCause(i2pe); throw ioe; } } /** * @throws UnsupportedOperationException always */ @Override public void bind(SocketAddress endpoint) { throw new UnsupportedOperationException(); } /** * @throws UnsupportedOperationException always */ @Override public void bind(SocketAddress endpoint, int backlog) { throw new UnsupportedOperationException(); } @Override public void close() throws IOException { if (isClosed()) throw new IOException("Already closed"); _socket.close(); } /** * @return null always, unimplemented */ @Override public ServerSocketChannel getChannel() { //return _socket.getChannel(); return null; } /** * @return null always */ @Override public InetAddress getInetAddress() { return null; } /** * @return -1 always */ @Override public int getLocalPort() { return -1; } /** * Port in returned SocketAddress will be zero. * * @return an I2PSocketAddress as of 0.9.26; prior to that, returned null * @since implemented in 0.9.26 */ @Override public SocketAddress getLocalSocketAddress() { return new I2PSocketAddress(_socket.getManager().getSession().getMyDestination(), 0); } @Override public int getReceiveBufferSize() { ConnectionOptions opts = (ConnectionOptions) ((I2PSocketManagerFull)_socket.getManager()).getDefaultOptions(); if (opts == null) return 64*1024; return opts.getInboundBufferSize(); } /** * @return false always */ @Override public boolean getReuseAddress() { return false; } @Override public int getSoTimeout() { return (int) _socket.getSoTimeout(); } /** * @return true always */ @Override public boolean isBound() { return true; } @Override public boolean isClosed() { return !((I2PSocketManagerFull)_socket.getManager()).getConnectionManager().getAllowIncomingConnections(); } /** * Does nothing. */ @Override public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) { } /** * Does nothing. */ @Override public void setReceiveBufferSize(int size) { } /** * Does nothing. */ @Override public void setReuseAddress(boolean on) { } @Override public void setSoTimeout(int timeout) throws SocketException { _socket.setSoTimeout(timeout); } @Override public String toString() { return _socket.toString(); } }