KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > socks > UDPRelayServer


1 package socks;
2 import socks.server.*;
3 import java.net.*;
4 import java.io.*;
5
6 /**
7  UDP Relay server, used by ProxyServer to perform udp forwarding.
8 */

9 class UDPRelayServer implements Runnable JavaDoc{
10
11
12     DatagramSocket client_sock;
13     DatagramSocket remote_sock;
14
15     Socket controlConnection;
16
17     int relayPort;
18     InetAddress relayIP;
19
20     Thread JavaDoc pipe_thread1,pipe_thread2;
21     Thread JavaDoc master_thread;
22
23     ServerAuthenticator auth;
24
25     long lastReadTime;
26
27     static PrintStream log = null;
28     static Proxy proxy = null;
29     static int datagramSize = 0xFFFF;//64K, a bit more than max udp size
30
static int iddleTimeout = 180000;//3 minutes
31

32
33     /**
34       Constructs UDP relay server to communicate with client
35       on given ip and port.
36       @param clientIP Address of the client from whom datagrams
37       will be recieved and to whom they will be forwarded.
38       @param clientPort Clients port.
39       @param master_thread Thread which will be interrupted, when
40       UDP relay server stoppes for some reason.
41       @param controlConnection Socket which will be closed, before
42       interrupting the master thread, it is introduced due to a bug
43       in windows JVM which does not throw InterruptedIOException in
44       threads which block in I/O operation.
45     */

46     public UDPRelayServer(InetAddress clientIP,int clientPort,
47                           Thread JavaDoc master_thread,
48                           Socket controlConnection,
49                           ServerAuthenticator auth)
50                           throws IOException{
51        this.master_thread = master_thread;
52        this.controlConnection = controlConnection;
53        this.auth = auth;
54
55        client_sock = new Socks5DatagramSocket(true,auth.getUdpEncapsulation(),
56                                               clientIP,clientPort);
57        relayPort = client_sock.getLocalPort();
58        relayIP = client_sock.getLocalAddress();
59
60        if(relayIP.getHostAddress().equals("0.0.0.0"))
61          relayIP = InetAddress.getLocalHost();
62
63        if(proxy == null)
64           remote_sock = new DatagramSocket();
65        else
66           remote_sock = new Socks5DatagramSocket(proxy,0,null);
67     }
68
69
70 //Public methods
71
/////////////////
72

73
74    /**
75     Sets the timeout for UDPRelay server.<br>
76     Zero timeout implies infinity.<br>
77     Default timeout is 3 minutes.
78     */

79
80     static public void setTimeout(int timeout){
81       iddleTimeout = timeout;
82     }
83
84
85    /**
86      Sets the size of the datagrams used in the UDPRelayServer.<br>
87      Default size is 64K, a bit more than maximum possible size of the
88      datagram.
89     */

90     static public void setDatagramSize(int size){
91       datagramSize = size;
92     }
93
94     /**
95       Port to which client should send datagram for association.
96     */

97     public int getRelayPort(){
98        return relayPort;
99     }
100     /**
101      IP address to which client should send datagrams for association.
102     */

103     public InetAddress getRelayIP(){
104        return relayIP;
105     }
106
107     /**
108       Starts udp relay server.
109       Spawns two threads of execution and returns.
110     */

111     public void start() throws IOException{
112        remote_sock.setSoTimeout(iddleTimeout);
113        client_sock.setSoTimeout(iddleTimeout);
114
115        log("Starting UDP relay server on "+relayIP+":"+relayPort);
116        log("Remote socket "+remote_sock.getLocalAddress()+":"+
117                             remote_sock.getLocalPort());
118
119        pipe_thread1 = new Thread JavaDoc(this,"pipe1");
120        pipe_thread2 = new Thread JavaDoc(this,"pipe2");
121
122        lastReadTime = System.currentTimeMillis();
123
124        pipe_thread1.start();
125        pipe_thread2.start();
126     }
127
128     /**
129      Stops Relay server.
130      <p>
131      Does not close control connection, does not interrupt master_thread.
132     */

133     public synchronized void stop(){
134        master_thread = null;
135        controlConnection = null;
136        abort();
137     }
138
139 //Runnable interface
140
////////////////////
141
public void run(){
142        try{
143           if(Thread.currentThread().getName().equals("pipe1"))
144              pipe(remote_sock,client_sock,false);
145           else
146              pipe(client_sock,remote_sock,true);
147        }catch(IOException ioe){
148        }finally{
149           abort();
150           log("UDP Pipe thread "+Thread.currentThread().getName()+" stopped.");
151        }
152
153     }
154
155 //Private methods
156
/////////////////
157
private synchronized void abort(){
158        if(pipe_thread1 == null) return;
159
160        log("Aborting UDP Relay Server");
161
162        remote_sock.close();
163        client_sock.close();
164
165        if(controlConnection != null)
166           try{ controlConnection.close();} catch(IOException ioe){}
167
168        if(master_thread!=null) master_thread.interrupt();
169
170        pipe_thread1.interrupt();
171        pipe_thread2.interrupt();
172
173        pipe_thread1 = null;
174     }
175
176
177     static private void log(String JavaDoc s){
178       if(log != null){
179         log.println(s);
180         log.flush();
181       }
182     }
183
184     private void pipe(DatagramSocket from,DatagramSocket to,boolean out)
185                              throws IOException{
186        byte[] data = new byte[datagramSize];
187        DatagramPacket dp = new DatagramPacket(data,data.length);
188
189        while(true){
190           try{
191             from.receive(dp);
192             lastReadTime = System.currentTimeMillis();
193
194             if(auth.checkRequest(dp,out))
195                to.send(dp);
196
197           }catch(UnknownHostException uhe){
198             log("Dropping datagram for unknown host");
199           }catch(InterruptedIOException iioe){
200             //log("Interrupted: "+iioe);
201
//If we were interrupted by other thread.
202
if(iddleTimeout == 0) return;
203
204             //If last datagram was received, long time ago, return.
205
long timeSinceRead = System.currentTimeMillis() - lastReadTime;
206             if(timeSinceRead >= iddleTimeout -100) //-100 for adjustment
207
return;
208           }
209           dp.setLength(data.length);
210        }
211     }
212 }
213
Popular Tags