package net.sourceforge.jsocks;
import java.net.*;
import java.io.*;
/**
SocksServerSocket allows to accept connections from one particular
host through the SOCKS4 or SOCKS5 proxy.
*/
public class SocksServerSocket extends ServerSocket{
//Data members
protected Proxy proxy;
protected String localHost;
protected InetAddress localIP;
protected int localPort;
boolean doing_direct = false;
InetAddress remoteAddr;
/**
*Creates ServerSocket capable of accepting one connection
*through the firewall, uses given proxy.
*@param host Host from which the connection should be recieved.
*@param port Port number of the primary connection.
*/
public SocksServerSocket(String host, int port) throws SocksException,
UnknownHostException, IOException {
super(0);
remoteAddr = InetAddress.getByName(host);
doDirect();
}
/**
* Creates ServerSocket capable of accepting one connection
* through the firewall, uses default Proxy.
*@param ip Host from which the connection should be recieved.
*@param port Port number of the primary connection.
*/
public SocksServerSocket(InetAddress ip, int port) throws SocksException,
IOException{
this(Proxy.defaultProxy,ip,port);
}
/**
*Creates ServerSocket capable of accepting one connection
*through the firewall, uses given proxy.
*@param ip Host from which the connection should be recieved.
*@param port Port number of the primary connection.
*/
public SocksServerSocket(Proxy p, InetAddress ip, int port)
throws SocksException, IOException {
super(0);
remoteAddr = ip;
doDirect();
}
/**
* Accepts the incoming connection.
*/
public Socket accept() throws IOException{
Socket s;
if(!doing_direct){
if(proxy == null) return null;
ProxyMessage msg = proxy.accept();
s = msg.ip == null? new SocksSocket(msg.host,msg.port,proxy)
: new SocksSocket(msg.ip,msg.port,proxy);
//Set timeout back to 0
proxy.proxySocket.setSoTimeout(0);
}else{ //Direct Connection
//Mimic the proxy behaviour,
//only accept connections from the speciefed host.
while(true){
s = super.accept();
if(s.getInetAddress().equals(remoteAddr)){
//got the connection from the right host
//Close listenning socket.
break;
}else
s.close(); //Drop all connections from other hosts
}
}
proxy = null;
//Return accepted socket
return s;
}
/**
* Closes the connection to proxy if socket have not been accepted, if
* the direct connection is used, closes direct ServerSocket. If the
* client socket have been allready accepted, does nothing.
*/
public void close() throws IOException{
super.close();
if(proxy != null) proxy.endSession();
proxy = null;
}
/**
Get the name of the host proxy is using to listen for incoming
connection.
<P>
Usefull when address is returned by proxy as the hostname.
@return the hostname of the address proxy is using to listen
for incoming connection.
*/
public String getHost(){
return localHost;
}
/**
* Get address assigned by proxy to listen for incomming
* connections, or the local machine address if doing direct
* connection.
*/
public InetAddress getInetAddress(){
if(localIP == null){
try{
localIP = InetAddress.getByName(localHost);
}catch(UnknownHostException e){
return null;
}
}
return localIP;
}
/**
* Get port assigned by proxy to listen for incoming connections, or
the port chosen by local system, if accepting directly.
*/
public int getLocalPort(){
return localPort;
}
/**
Set Timeout.
@param timeout Amount of time in milliseconds, accept should wait for
incoming connection before failing with exception.
Zero timeout implies infinity.
*/
public void setSoTimeout(int timeout) throws SocketException{
super.setSoTimeout(timeout);
if(!doing_direct) proxy.proxySocket.setSoTimeout(timeout);
}
//Private Methods
//////////////////
private void doDirect(){
doing_direct = true;
localPort = super.getLocalPort();
localIP = super.getInetAddress();
localHost = localIP.getHostName();
}
}