aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/sourceforge/jsocks/SocksServerSocket.java
blob: 739251d489d24195ccb930de68ded4c9ef516e09 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
href='#n89'>89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
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();
   }

}