239 lines
5.9 KiB
Java
239 lines
5.9 KiB
Java
package com.runjva.sourceforge.jsocks.protocol;
|
|
|
|
import java.io.IOException;
|
|
import java.net.InetAddress;
|
|
import java.net.ServerSocket;
|
|
import java.net.Socket;
|
|
import java.net.SocketException;
|
|
import java.net.UnknownHostException;
|
|
|
|
/**
|
|
* SocksServerSocket allows to accept connections from one particular host
|
|
* through the SOCKS4 or SOCKS5 proxy.
|
|
*/
|
|
public class SocksServerSocket extends ServerSocket {
|
|
// Data members
|
|
protected SocksProxyBase 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 default 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 {
|
|
this(SocksProxyBase.defaultProxy, host, port);
|
|
}
|
|
|
|
/**
|
|
*Creates ServerSocket capable of accepting one connection through the
|
|
* firewall, uses given proxy.
|
|
*
|
|
* @param p
|
|
* Proxy object to use.
|
|
*@param host
|
|
* Host from which the connection should be recieved.
|
|
*@param port
|
|
* Port number of the primary connection.
|
|
*/
|
|
public SocksServerSocket(SocksProxyBase p, String host, int port)
|
|
throws SocksException, UnknownHostException, IOException {
|
|
|
|
super(0);
|
|
if (p == null) {
|
|
throw new SocksException(SocksProxyBase.SOCKS_NO_PROXY);
|
|
}
|
|
// proxy=p;
|
|
proxy = p.copy();
|
|
if (proxy.isDirect(host)) {
|
|
remoteAddr = InetAddress.getByName(host);
|
|
proxy = null;
|
|
doDirect();
|
|
} else {
|
|
processReply(proxy.bind(host, port));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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(SocksProxyBase.defaultProxy, ip, port);
|
|
}
|
|
|
|
/**
|
|
*Creates ServerSocket capable of accepting one connection through the
|
|
* firewall, uses given proxy.
|
|
*
|
|
* @param p
|
|
* Proxy object to use.
|
|
*@param ip
|
|
* Host from which the connection should be recieved.
|
|
*@param port
|
|
* Port number of the primary connection.
|
|
*/
|
|
public SocksServerSocket(SocksProxyBase p, InetAddress ip, int port)
|
|
throws SocksException, IOException {
|
|
super(0);
|
|
|
|
if (p == null) {
|
|
throw new SocksException(SocksProxyBase.SOCKS_NO_PROXY);
|
|
}
|
|
this.proxy = p.copy();
|
|
|
|
if (proxy.isDirect(ip)) {
|
|
remoteAddr = ip;
|
|
doDirect();
|
|
} else {
|
|
processReply(proxy.bind(ip, port));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Accepts the incoming connection.
|
|
*/
|
|
public Socket accept() throws IOException {
|
|
Socket s;
|
|
|
|
if (!doing_direct) {
|
|
if (proxy == null) {
|
|
return null;
|
|
}
|
|
|
|
final 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);
|
|
if (ProxyServer.vpnService != null)
|
|
ProxyServer.vpnService.protect(proxy.proxySocket);
|
|
|
|
} 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 (final 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 processReply(ProxyMessage reply) throws SocksException {
|
|
localPort = reply.port;
|
|
/*
|
|
* If the server have assigned same host as it was contacted on it might
|
|
* return an address of all zeros
|
|
*/
|
|
if (reply.host.equals("0.0.0.0")) {
|
|
localIP = proxy.proxyIP;
|
|
localHost = localIP.getHostName();
|
|
} else {
|
|
localHost = reply.host;
|
|
localIP = reply.ip;
|
|
}
|
|
}
|
|
|
|
private void doDirect() {
|
|
doing_direct = true;
|
|
localPort = super.getLocalPort();
|
|
localIP = super.getInetAddress();
|
|
localHost = localIP.getHostName();
|
|
}
|
|
|
|
}
|