comparison src/net/sourceforge/jsocks/UDPRelayServer.java @ 349:205ee2873330

update jsocks to 2011-03-19
author Carl Byington <carl@five-ten-sg.com>
date Fri, 01 Aug 2014 11:23:10 -0700
parents 0ce5cc452d02
children
comparison
equal deleted inserted replaced
348:29076621bab0 349:205ee2873330
4 import java.io.*; 4 import java.io.*;
5 5
6 /** 6 /**
7 UDP Relay server, used by ProxyServer to perform udp forwarding. 7 UDP Relay server, used by ProxyServer to perform udp forwarding.
8 */ 8 */
9 class UDPRelayServer implements Runnable { 9 class UDPRelayServer implements Runnable{
10 10
11 11
12 DatagramSocket client_sock; 12 DatagramSocket client_sock;
13 DatagramSocket remote_sock; 13 DatagramSocket remote_sock;
14 14
15 Socket controlConnection; 15 Socket controlConnection;
16 16
17 int relayPort; 17 int relayPort;
18 InetAddress relayIP; 18 InetAddress relayIP;
19 19
20 Thread pipe_thread1, pipe_thread2; 20 Thread pipe_thread1,pipe_thread2;
21 Thread master_thread; 21 Thread master_thread;
22 22
23 ServerAuthenticator auth; 23 ServerAuthenticator auth;
24 24
25 long lastReadTime; 25 long lastReadTime;
26 26
27 static PrintStream log = null; 27 static PrintStream log = null;
28 static Proxy proxy = null; 28 static CProxy proxy = null;
29 static int datagramSize = 0xFFFF;//64K, a bit more than max udp size 29 static int datagramSize = 0xFFFF;//64K, a bit more than max udp size
30 static int iddleTimeout = 180000;//3 minutes 30 static int iddleTimeout = 180000;//3 minutes
31 31
32 32
33 /** 33 /**
41 @param controlConnection Socket which will be closed, before 41 @param controlConnection Socket which will be closed, before
42 interrupting the master thread, it is introduced due to a bug 42 interrupting the master thread, it is introduced due to a bug
43 in windows JVM which does not throw InterruptedIOException in 43 in windows JVM which does not throw InterruptedIOException in
44 threads which block in I/O operation. 44 threads which block in I/O operation.
45 */ 45 */
46 public UDPRelayServer(InetAddress clientIP, int clientPort, 46 public UDPRelayServer(InetAddress clientIP,int clientPort,
47 Thread master_thread, 47 Thread master_thread,
48 Socket controlConnection, 48 Socket controlConnection,
49 ServerAuthenticator auth) 49 ServerAuthenticator auth)
50 throws IOException { 50 throws IOException{
51 this.master_thread = master_thread; 51 this.master_thread = master_thread;
52 this.controlConnection = controlConnection; 52 this.controlConnection = controlConnection;
53 this.auth = auth; 53 this.auth = auth;
54 client_sock = new Socks5DatagramSocket(true, auth.getUdpEncapsulation(), 54
55 clientIP, clientPort); 55 client_sock = new Socks5DatagramSocket(true,auth.getUdpEncapsulation(),
56 relayPort = client_sock.getLocalPort(); 56 clientIP,clientPort);
57 relayIP = client_sock.getLocalAddress(); 57 relayPort = client_sock.getLocalPort();
58 58 relayIP = client_sock.getLocalAddress();
59 if (relayIP.getHostAddress().equals("0.0.0.0")) 59
60 relayIP = InetAddress.getLocalHost(); 60 if(relayIP.getHostAddress().equals("0.0.0.0"))
61 61 relayIP = InetAddress.getLocalHost();
62 if (proxy == null) 62
63 remote_sock = new DatagramSocket(); 63 if(proxy == null)
64 else 64 remote_sock = new DatagramSocket();
65 remote_sock = new Socks5DatagramSocket(proxy, 0, null); 65 else
66 remote_sock = new Socks5DatagramSocket(proxy,0,null);
66 } 67 }
67 68
68 69
69 //Public methods 70 //Public methods
70 ///////////////// 71 /////////////////
71 72
72 73
73 /** 74 /**
74 Sets the timeout for UDPRelay server.<br> 75 Sets the timeout for UDPRelay server.<br>
75 Zero timeout implies infinity.<br> 76 Zero timeout implies infinity.<br>
76 Default timeout is 3 minutes. 77 Default timeout is 3 minutes.
77 */ 78 */
78 79
79 static public void setTimeout(int timeout) { 80 static public void setTimeout(int timeout){
80 iddleTimeout = timeout; 81 iddleTimeout = timeout;
81 } 82 }
82 83
83 84
84 /** 85 /**
85 Sets the size of the datagrams used in the UDPRelayServer.<br> 86 Sets the size of the datagrams used in the UDPRelayServer.<br>
86 Default size is 64K, a bit more than maximum possible size of the 87 Default size is 64K, a bit more than maximum possible size of the
87 datagram. 88 datagram.
88 */ 89 */
89 static public void setDatagramSize(int size) { 90 static public void setDatagramSize(int size){
90 datagramSize = size; 91 datagramSize = size;
91 } 92 }
92 93
93 /** 94 /**
94 Port to which client should send datagram for association. 95 Port to which client should send datagram for association.
95 */ 96 */
96 public int getRelayPort() { 97 public int getRelayPort(){
97 return relayPort; 98 return relayPort;
98 } 99 }
99 /** 100 /**
100 IP address to which client should send datagrams for association. 101 IP address to which client should send datagrams for association.
101 */ 102 */
102 public InetAddress getRelayIP() { 103 public InetAddress getRelayIP(){
103 return relayIP; 104 return relayIP;
104 } 105 }
105 106
106 /** 107 /**
107 Starts udp relay server. 108 Starts udp relay server.
108 Spawns two threads of execution and returns. 109 Spawns two threads of execution and returns.
109 */ 110 */
110 public void start() throws IOException { 111 public void start() throws IOException{
111 remote_sock.setSoTimeout(iddleTimeout); 112 remote_sock.setSoTimeout(iddleTimeout);
112 client_sock.setSoTimeout(iddleTimeout); 113 client_sock.setSoTimeout(iddleTimeout);
113 log("Starting UDP relay server on " + relayIP + ":" + relayPort); 114
114 log("Remote socket " + remote_sock.getLocalAddress() + ":" + 115 log("Starting UDP relay server on "+relayIP+":"+relayPort);
115 remote_sock.getLocalPort()); 116 log("Remote socket "+remote_sock.getLocalAddress()+":"+
116 pipe_thread1 = new Thread(this, "pipe1"); 117 remote_sock.getLocalPort());
117 pipe_thread2 = new Thread(this, "pipe2"); 118
118 lastReadTime = System.currentTimeMillis(); 119 pipe_thread1 = new Thread(this,"pipe1");
119 pipe_thread1.start(); 120 pipe_thread2 = new Thread(this,"pipe2");
120 pipe_thread2.start(); 121
122 lastReadTime = System.currentTimeMillis();
123
124 pipe_thread1.start();
125 pipe_thread2.start();
121 } 126 }
122 127
123 /** 128 /**
124 Stops Relay server. 129 Stops Relay server.
125 <p> 130 <p>
126 Does not close control connection, does not interrupt master_thread. 131 Does not close control connection, does not interrupt master_thread.
127 */ 132 */
128 133 public synchronized void stop(){
129 public synchronized void stop() { 134 master_thread = null;
130 master_thread = null; 135 controlConnection = null;
131 controlConnection = null; 136 abort();
132 abort();
133 } 137 }
134 138
135 //Runnable interface 139 //Runnable interface
136 //////////////////// 140 ////////////////////
137 public void run() { 141 public void run(){
138 try { 142 try{
139 if (Thread.currentThread().getName().equals("pipe1")) 143 if(Thread.currentThread().getName().equals("pipe1"))
140 pipe(remote_sock, client_sock, false); 144 pipe(remote_sock,client_sock,false);
141 else 145 else
142 pipe(client_sock, remote_sock, true); 146 pipe(client_sock,remote_sock,true);
143 } 147 }catch(IOException ioe){
144 catch (IOException ioe) { 148 }finally{
145 } 149 abort();
146 finally { 150 log("UDP Pipe thread "+Thread.currentThread().getName()+" stopped.");
147 abort(); 151 }
148 log("UDP Pipe thread " + Thread.currentThread().getName() + " stopped."); 152
149 }
150 } 153 }
151 154
152 //Private methods 155 //Private methods
153 ///////////////// 156 /////////////////
154 157 private synchronized void abort(){
155 private synchronized void abort() { 158 if(pipe_thread1 == null) return;
156 if (pipe_thread1 == null) return; 159
157 160 log("Aborting UDP Relay Server");
158 log("Aborting UDP Relay Server"); 161
159 remote_sock.close(); 162 remote_sock.close();
160 client_sock.close(); 163 client_sock.close();
161 164
162 if (controlConnection != null) 165 if(controlConnection != null)
163 try { controlConnection.close();} 166 try{ controlConnection.close();} catch(IOException ioe){}
164 catch (IOException ioe) {} 167
165 168 if(master_thread!=null) master_thread.interrupt();
166 if (master_thread != null) master_thread.interrupt(); 169
167 170 pipe_thread1.interrupt();
168 pipe_thread1.interrupt(); 171 pipe_thread2.interrupt();
169 pipe_thread2.interrupt(); 172
170 pipe_thread1 = null; 173 pipe_thread1 = null;
171 } 174 }
172 175
173 176
174 static private void log(String s) { 177 static private void log(String s){
175 if (log != null) { 178 if(log != null){
176 log.println(s); 179 log.println(s);
177 log.flush(); 180 log.flush();
178 } 181 }
179 } 182 }
180 183
181 private void pipe(DatagramSocket from, DatagramSocket to, boolean out) 184 private void pipe(DatagramSocket from,DatagramSocket to,boolean out)
182 throws IOException { 185 throws IOException{
183 byte[] data = new byte[datagramSize]; 186 byte[] data = new byte[datagramSize];
184 DatagramPacket dp = new DatagramPacket(data, data.length); 187 DatagramPacket dp = new DatagramPacket(data,data.length);
185 188
186 while (true) { 189 while(true){
187 try { 190 try{
188 from.receive(dp); 191 from.receive(dp);
189 lastReadTime = System.currentTimeMillis(); 192 lastReadTime = System.currentTimeMillis();
190 193
191 if (auth.checkRequest(dp, out)) 194 if(auth.checkRequest(dp,out))
192 to.send(dp); 195 to.send(dp);
193 } 196
194 catch (UnknownHostException uhe) { 197 }catch(UnknownHostException uhe){
195 log("Dropping datagram for unknown host"); 198 log("Dropping datagram for unknown host");
196 } 199 }catch(InterruptedIOException iioe){
197 catch (InterruptedIOException iioe) { 200 //log("Interrupted: "+iioe);
198 //log("Interrupted: "+iioe); 201 //If we were interrupted by other thread.
199 //If we were interrupted by other thread. 202 if(iddleTimeout == 0) return;
200 if (iddleTimeout == 0) return; 203
201 204 //If last datagram was received, long time ago, return.
202 //If last datagram was received, long time ago, return. 205 long timeSinceRead = System.currentTimeMillis() - lastReadTime;
203 long timeSinceRead = System.currentTimeMillis() - lastReadTime; 206 if(timeSinceRead >= iddleTimeout -100) //-100 for adjustment
204 207 return;
205 if (timeSinceRead >= iddleTimeout - 100) //-100 for adjustment 208 }
206 return; 209 dp.setLength(data.length);
207 } 210 }
208
209 dp.setLength(data.length);
210 }
211 } 211 }
212 } 212 }