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();
}
}