KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jgroups > util > Proxy1_4


1 // $Id: Proxy1_4.java,v 1.7 2004/09/23 16:29:56 belaban Exp $
2

3 package org.jgroups.util;
4
5 import EDU.oswego.cs.dl.util.concurrent.Executor;
6 import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
7
8 import javax.net.ssl.SSLServerSocket;
9 import javax.net.ssl.SSLServerSocketFactory;
10 import javax.net.ssl.SSLSocket;
11 import javax.net.ssl.SSLSocketFactory;
12 import java.io.*;
13 import java.net.*;
14 import java.nio.ByteBuffer JavaDoc;
15 import java.nio.channels.SelectionKey JavaDoc;
16 import java.nio.channels.Selector JavaDoc;
17 import java.nio.channels.ServerSocketChannel JavaDoc;
18 import java.nio.channels.SocketChannel JavaDoc;
19 import java.util.*;
20
21
22
23 /**
24  * Redirects incoming TCP connections to other hosts/ports. All redirections are defined in a file as for example
25  * <pre>
26  * 127.0.0.1:8888=www.ibm.com:80
27  * localhost:80=pop.mail.yahoo.com:110
28  * </pre>
29  * The first line forwards all requests to port 8888 on to www.ibm.com at port 80 (it also forwards the HTTP
30  * response back to the sender. The second line essentially provides a POP-3 service on port 8110, using
31  * Yahoo's POP service. This is neat when you're behind a firewall and one of the few services in the outside
32  * world that are not blocked is port 80 (HHTP).<br/>
33  * Note that JDK 1.4 is required for this class. Also, concurrent.jar has to be on the classpath. Note that
34  * you also need to include jsse.jar/jce.jar (same location as rt.jar) if you want SSL sockets.<br>
35  * To create SSLServerSockets you'll need to do the following:
36  * Generate a certificate as follows:
37  * <pre>
38  * keytool -genkey -keystore /home/bela/.keystore -keyalg rsa -alias bela -storepass <passwd> -keypass <passwd>
39  * </pre>
40  *
41  * Start the Proxy as follows:
42  * <pre>
43  * java -Djavax.net.ssl.keyStore=/home/bela/.keystore -Djavax.net.ssl.keyStorePassword=<passwd>
44  * -Djavax.net.ssl.trustStore=/home/bela/.keystore -Djavax.net.ssl.trustStorePassword=<passwd>
45  * org.jgroups.util.Proxy1_4 -file /home/bela/map.properties
46  * </pre>
47  * Start client as follows:
48  * <pre>
49  * java -Djavax.net.ssl.trustStore=/home/bela/.keystore -Djavax.net.ssl.trustStorePassword=<passwd> sslclient
50  * </pre>
51  * <br/>
52  * To import a certificate into the keystore, use the following steps:
53  * <pre>
54  * openssl x509 -in server.crt -out server.crt.der -outform DER
55  * keytool -import -trustcacerts -alias <your alias name> -file server.crt.der
56  * </pre>
57  * This will store the server's certificate in the ${user.home}/.keystore key store.
58  * <br/>
59  * Note that an SSL client or server can be debugged by starting it as follows:
60  * <pre>-Djava.protocol.handler.pkgs=com.sun.net.ssl.internal.www.protocol -Djavax.net.debug=ssl</pre>
61  * <br/>
62  * If you run a web browser, simply enter https://<host>:<port> as URL to connect to an SSLServerSocket
63  * <br/>Note that we cannot use JDK 1.4's selectors for SSL sockets, as
64  * getChannel() on an SSL socket doesn't seem to work.
65  * todo Check whether SSLSocket.getChannel() or SSLServerSocket.getChannel() works
66  * @author Bela Ban
67  */

68 public class Proxy1_4 {
69     InetAddress local=null, remote=null;
70     int local_port=0, remote_port=0;
71     static boolean verbose=false;
72     static boolean debug=false;
73     String JavaDoc mapping_file=null; // contains a list of src and dest host:port pairs
74
final HashMap mappings=new HashMap(); // keys=MyInetSocketAddr (src), values=MyInetSocketAddr (dest)
75
Executor executor; // maintains a thread pool
76
static final int MAX_THREAD_POOL_SIZE=64; // for processing requests
77
static final int BUFSIZE=1024; // size of data transfer buffer
78

79
80
81     public Proxy1_4(InetAddress local, int local_port, InetAddress remote, int remote_port, boolean verbose, boolean debug) {
82         this.local=local;
83         this.local_port=local_port;
84         this.remote=remote;
85         this.remote_port=remote_port;
86         Proxy1_4.verbose=verbose;
87         Proxy1_4.debug=debug;
88     }
89
90     public Proxy1_4(InetAddress local, int local_port, InetAddress remote, int remote_port,
91                     boolean verbose, boolean debug, String JavaDoc mapping_file) {
92         this(local, local_port, remote, remote_port, verbose, debug);
93         this.mapping_file=mapping_file;
94     }
95
96     public void start() throws Exception JavaDoc {
97         Map.Entry entry;
98         Selector JavaDoc selector;
99         ServerSocketChannel JavaDoc sock_channel;
100         MyInetSocketAddress key, value;
101
102         if (remote !=null && local !=null)
103             mappings.put(new InetSocketAddress(local, local_port), new InetSocketAddress(remote, remote_port));
104         
105         if (mapping_file !=null) {
106             try {
107                 populateMappings(mapping_file);
108             }
109             catch (Exception JavaDoc ex) {
110                 log("Failed reading " + mapping_file);
111                 throw ex;
112             }
113         }
114
115         log("\nProxy started at " + new java.util.Date JavaDoc());
116
117         if (verbose) {
118             log("\nMappings:\n---------");
119             for (Iterator it=mappings.entrySet().iterator(); it.hasNext();) {
120                 entry=(Map.Entry) it.next();
121                 log(toString((InetSocketAddress) entry.getKey()) + " <--> "
122                     + toString((InetSocketAddress) entry.getValue()));
123             }
124             log("\n");
125         }
126
127         // 1. Create a Selector
128
selector=Selector.open();
129
130         // Create a thread pool (Executor)
131
executor=new PooledExecutor(MAX_THREAD_POOL_SIZE);
132
133         for (Iterator it=mappings.keySet().iterator(); it.hasNext();) {
134             key=(MyInetSocketAddress) it.next();
135             value=(MyInetSocketAddress) mappings.get(key);
136
137             // if either source or destination are SSL, we cannot use JDK 1.4
138
// NIO selectors, but have to fall back on separate threads per connection
139

140             if (key.ssl() || value.ssl()) {
141                 // if(2 == 2) {
142
SocketAcceptor acceptor=new SocketAcceptor(key, value);
143                 executor.execute(acceptor);
144                 continue;
145             }
146
147             // 2. Create a ServerSocketChannel
148
sock_channel=ServerSocketChannel.open();
149             sock_channel.configureBlocking(false);
150             sock_channel.socket().bind(key);
151
152             // 3. Register the selector with all server sockets. 'Key' is attachment, so we get it again on
153
// select(). That way we can associate it with the mappings hashmap to find the corresponding
154
// value
155
sock_channel.register(selector, SelectionKey.OP_ACCEPT, key);
156         }
157
158         // 4. Start main loop. won't return until CTRL-C'ed
159
loop(selector);
160     }
161
162
163
164     /** We handle only non-SSL connections */
165     void loop(Selector JavaDoc selector) {
166         Set ready_keys;
167         SelectionKey JavaDoc key;
168         ServerSocketChannel JavaDoc srv_sock;
169         SocketChannel JavaDoc in_sock, out_sock;
170         InetSocketAddress src, dest;
171
172         while (true) {
173             if (verbose)
174                 log("[Proxy] ready to accept connection");
175
176             // 4. Call Selector.select()
177
try {
178                 selector.select();
179
180                 // get set of ready objects
181
ready_keys=selector.selectedKeys();
182                 for (Iterator it=ready_keys.iterator(); it.hasNext();) {
183                     key=(SelectionKey JavaDoc) it.next();
184                     it.remove();
185
186                     if (key.isAcceptable()) {
187                         srv_sock=(ServerSocketChannel JavaDoc) key.channel();
188                         // get server socket and attachment
189
SRC=(InetSocketAddress) key.attachment();
190                         in_sock=srv_sock.accept(); // accept request
191
if (verbose)
192                             log("Proxy1_4.loop()", "accepted connection from " + toString(in_sock));
193                         dest=(InetSocketAddress) mappings.get(src);
194                         // find corresponding dest
195
if (dest == null) {
196                             in_sock.close();
197                             log("Proxy1_4.loop()", "did not find a destination host for " + src);
198                             continue;
199                         }
200                         else {
201                             if (verbose)
202                                 log("Proxy1_4.loop()", "relaying traffic from " + toString(src) + " to " + toString(dest));
203                         }
204
205                         // establish connection to destination host
206
try {
207                             out_sock=SocketChannel.open(dest);
208                             // uses thread pool (Executor) to handle request, closes socks at end
209
handleConnection(in_sock, out_sock);
210                         }
211                         catch (Exception JavaDoc ex) {
212                             in_sock.close();
213                             throw ex;
214                         }
215                     }
216                 }
217             }
218             catch (Exception JavaDoc ex) {
219                 log("Proxy1_4.loop()", "exception: " + ex);
220             }
221         }
222     }
223
224     // void handleConnection(Socket in_sock, Socket out_sock) {
225
// try {
226
// Relayer r=new Relayer(in_sock, out_sock);
227
// executor.execute(r);
228
// r=new Relayer(out_sock, in_sock);
229
// executor.execute(r);
230
// }
231
// catch (Exception ex) {
232
// log("Proxy1_4.handleConnection()", "exception: " + ex);
233
// }
234
// finally {
235
// close(in_sock, out_sock);
236
// }
237
// }
238

239     void handleConnection(SocketChannel JavaDoc in, SocketChannel JavaDoc out) {
240         try {
241             _handleConnection(in, out);
242         }
243         catch (Exception JavaDoc ex) {
244             log("Proxy1_4.handleConnection()", "exception: " + ex);
245         }
246     }
247     
248     void _handleConnection(final SocketChannel JavaDoc in_channel, final SocketChannel JavaDoc out_channel) throws Exception JavaDoc {
249         executor.execute(new Runnable JavaDoc() {
250                 public void run() {
251                     Selector JavaDoc sel=null;
252                     SocketChannel JavaDoc tmp;
253                     Set ready_keys;
254                     SelectionKey JavaDoc key;
255                     ByteBuffer JavaDoc transfer_buf=ByteBuffer.allocate(BUFSIZE);
256
257                     try {
258                         sel=Selector.open();
259                         in_channel.configureBlocking(false);
260                         out_channel.configureBlocking(false);
261                         in_channel.register(sel, SelectionKey.OP_READ);
262                         out_channel.register(sel, SelectionKey.OP_READ);
263                         
264                         while (sel.select() > 0) {
265                             ready_keys=sel.selectedKeys();
266                             for (Iterator it=ready_keys.iterator(); it.hasNext();) {
267                                 key=(SelectionKey JavaDoc) it.next();
268                                 it.remove(); // remove current entry (why ?)
269
tmp=(SocketChannel JavaDoc) key.channel();
270                                 if (tmp == null) {
271                                     log(
272                                         "Proxy1_4._handleConnection()",
273                                         "attachment is null, continuing");
274                                     continue;
275                                 }
276                                 if (key.isReadable()) { // data is available to be read from tmp
277
if (tmp == in_channel) {
278                                         // read all data from in_channel and forward it to out_channel (request)
279
if (relay(tmp, out_channel, transfer_buf) == false)
280                                             return;
281                                     }
282                                     if (tmp == out_channel) {
283                                         // read all data from out_channel and forward it
284
// to in_channel (response)
285
if (relay(tmp, in_channel, transfer_buf) == false)
286                                             return;
287                                     }
288                                 }
289                             }
290                         }
291                     }
292                     catch (Exception JavaDoc ex) {
293                         ex.printStackTrace();
294                         return;
295                     }
296                     finally {
297                         close(sel, in_channel, out_channel);
298                     }
299                 }
300             });
301     }
302     
303     void close(Selector JavaDoc sel, SocketChannel JavaDoc in_channel, SocketChannel JavaDoc out_channel) {
304         try {
305             if (sel !=null)
306                 sel.close();
307         }
308         catch (Exception JavaDoc ex) {
309         }
310         try {
311             if (in_channel !=null)
312                 in_channel.close();
313         }
314         catch (Exception JavaDoc ex) {
315         }
316         try {
317             if (out_channel !=null)
318                 out_channel.close();
319         }
320         catch (Exception JavaDoc ex) {
321         }
322     }
323
324
325     /**
326      * Read all data from <code>from</code> and write it to <code>to</code>.
327      * Returns false if channel was closed
328      */

329     boolean relay(SocketChannel JavaDoc from, SocketChannel JavaDoc to, ByteBuffer JavaDoc buf) throws Exception JavaDoc {
330         int num;
331         StringBuffer JavaDoc sb;
332
333         buf.clear();
334         while (true) {
335             num=from.read(buf);
336             if (num < 0)
337                 return false;
338             else
339                 if (num == 0)
340                     return true;
341             buf.flip();
342             if (verbose) {
343                 log(printRelayedData(toString(from), toString(to), buf.remaining()));
344             }
345             if (debug) {
346                 sb=new StringBuffer JavaDoc();
347                 sb.append(new String JavaDoc(buf.array()).trim());
348                 sb.append('\n');
349                 log(sb.toString());
350             }
351             to.write(buf);
352             buf.flip();
353         }
354     }
355
356     String JavaDoc toString(SocketChannel JavaDoc ch) {
357         StringBuffer JavaDoc sb=new StringBuffer JavaDoc();
358         Socket sock;
359
360         if (ch == null)
361             return null;
362         if ((sock=ch.socket()) == null)
363             return null;
364         sb.append(sock.getInetAddress().getHostName()).append(':').append(sock.getPort());
365         return sb.toString();
366     }
367
368     String JavaDoc toString(InetSocketAddress addr) {
369         StringBuffer JavaDoc sb=new StringBuffer JavaDoc();
370
371         if (addr == null)
372             return null;
373         sb.append(addr.getAddress().getHostName()).append(':').append(addr.getPort());
374         if (addr instanceof MyInetSocketAddress)
375             sb.append(" [ssl=").append(((MyInetSocketAddress) addr).ssl()).append(']');
376         return sb.toString();
377     }
378
379     
380     static String JavaDoc printRelayedData(String JavaDoc from, String JavaDoc to, int num_bytes) {
381         StringBuffer JavaDoc sb=new StringBuffer JavaDoc();
382         sb.append("\n[PROXY] ").append(from);
383         sb.append(" to ").append(to);
384         sb.append(" (").append(num_bytes).append(" bytes)");
385         // log("Proxy1_4.relay()", sb.toString());
386
return sb.toString();
387     }
388     
389
390     /**
391      * Populates <code>mappings</code> hashmap. An example of a definition file is:
392      * <pre>
393      * http://localhost:8888=http://www.yahoo.com:80
394      * https://localhost:2200=https://cvs.sourceforge.net:22
395      * http://localhost:8000=https://www.ibm.com:443
396      * </pre>
397      * Mappings can be http-https, https-http, http-http or https-https
398      */

399     void populateMappings(String JavaDoc filename) throws Exception JavaDoc {
400         FileInputStream in=new FileInputStream(filename);
401         BufferedReader reader;
402         String JavaDoc line;
403         URI key, value;
404         int index;
405         boolean ssl_key, ssl_value;
406         final String JavaDoc HTTPS="https";
407
408         reader=new BufferedReader(new InputStreamReader(in));
409         while ((line=reader.readLine()) !=null) {
410             line=line.trim();
411             if (line.startsWith("//") || line.startsWith("#") || line.length() == 0)
412                 continue;
413             index=line.indexOf('=');
414             if (index == -1)
415                 throw new Exception JavaDoc("Proxy1_4.populateMappings(): detected no '=' character in " + line);
416             key=new URI(line.substring(0, index));
417             ssl_key=key.getScheme().trim().equals(HTTPS);
418
419             value=new URI(line.substring(index + 1));
420             ssl_value=value.getScheme().trim().equals(HTTPS);
421
422             check(key);
423             check(value);
424
425             log("key: " + key + ", value: " + value);
426
427             mappings.put(new MyInetSocketAddress(key.getHost(), key.getPort(), ssl_key),
428                          new MyInetSocketAddress(value.getHost(), value.getPort(), ssl_value));
429         }
430         in.close();
431     }
432
433     /** Checks whether a URI is http(s)://<host>:<port> */
434     void check(URI u) throws Exception JavaDoc {
435         if (u.getScheme() == null)
436             throw new Exception JavaDoc(
437                 "scheme is null in " + u + ", (valid URI is \"http(s)://<host>:<port>\")");
438
439         if (u.getHost() == null)
440             throw new Exception JavaDoc(
441                 "host is null in " + u + ", (valid URI is \"http(s)://<host>:<port>\")");
442
443         if (u.getPort() <=0)
444             throw new Exception JavaDoc(
445                 "port is <=0 in " + u + ", (valid URI is \"http(s)://<host>:<port>\")");
446
447     }
448
449     /** Input is "host:port" */
450     SocketAddress strToAddr(String JavaDoc input) throws Exception JavaDoc {
451         StringTokenizer tok=new StringTokenizer(input, ":");
452         String JavaDoc host, port;
453
454         host=tok.nextToken();
455         port=tok.nextToken();
456         return new InetSocketAddress(host, Integer.parseInt(port));
457     }
458
459     String JavaDoc printSelectionOps(SelectionKey JavaDoc key) {
460         StringBuffer JavaDoc sb=new StringBuffer JavaDoc();
461         if ((key.readyOps() & SelectionKey.OP_ACCEPT) !=0)
462             sb.append("OP_ACCEPT ");
463         if ((key.readyOps() & SelectionKey.OP_CONNECT) !=0)
464             sb.append("OP_CONNECT ");
465         if ((key.readyOps() & SelectionKey.OP_READ) !=0)
466             sb.append("OP_READ ");
467         if ((key.readyOps() & SelectionKey.OP_WRITE) !=0)
468             sb.append("OP_WRITE ");
469         return sb.toString();
470     }
471
472     public static void main(String JavaDoc[] args) {
473         Proxy1_4 p;
474         InetAddress local=null, remote=null;
475         int local_port=0, remote_port=0;
476         String JavaDoc tmp, tmp_addr, tmp_port;
477         boolean verbose=false, debug=false;
478         int index;
479         String JavaDoc mapping_file=null;
480
481         try {
482             for (int i=0; i < args.length; i++) {
483                 tmp=args[i];
484                 if ("-help".equals(tmp)) {
485                     help();
486                     return;
487                 }
488                 if ("-verbose".equals(tmp)) {
489                     verbose=true;
490                     continue;
491                 }
492                 if ("-local".equals(tmp)) {
493                     tmp_addr=args[++i];
494                     index=tmp_addr.indexOf(':');
495                     if (index > -1) { // it is in the format address:port
496
tmp_port=tmp_addr.substring(index + 1);
497                         local_port=Integer.parseInt(tmp_port);
498                         tmp_addr=tmp_addr.substring(0, index);
499                         local=InetAddress.getByName(tmp_addr);
500                     }
501                     else
502                         local=InetAddress.getByName(args[++i]);
503                     continue;
504                 }
505                 if ("-local_port".equals(tmp)) {
506                     local_port=Integer.parseInt(args[++i]);
507                     continue;
508                 }
509                 if ("-remote".equals(tmp)) {
510                     tmp_addr=args[++i];
511                     index=tmp_addr.indexOf(':');
512                     if (index > -1) { // it is in the format address:port
513
tmp_port=tmp_addr.substring(index + 1);
514                         remote_port=Integer.parseInt(tmp_port);
515                         tmp_addr=tmp_addr.substring(0, index);
516                         remote=InetAddress.getByName(tmp_addr);
517                     }
518                     else
519                         remote=InetAddress.getByName(args[++i]);
520                     continue;
521                 }
522                 if ("-remote_port".equals(tmp)) {
523                     remote_port=Integer.parseInt(args[++i]);
524                     continue;
525                 }
526                 if ("-file".equals(tmp)) {
527                     mapping_file=args[++i];
528                     continue;
529                 }
530                 if ("-debug".equals(tmp)) {
531                     debug=true;
532                     continue;
533                 }
534                 help();
535                 return;
536             }
537
538             if (local == null)
539                 local=InetAddress.getLocalHost();
540
541             p=new Proxy1_4(local, local_port, remote, remote_port, verbose, debug, mapping_file);
542             p.start();
543         }
544         catch (Throwable JavaDoc ex) {
545             ex.printStackTrace();
546         }
547     }
548
549     static void help() {
550         System.out.println("Proxy1_4 [-help] [-local <local address>] [-local_port <port>] "
551                            + "[-remote <remote address>] [-remote_port <port>] [-verbose] "
552                            + "[-file <mapping file>] [-debug]");
553     }
554
555     static void log(String JavaDoc method_name, String JavaDoc msg) {
556         System.out.println('[' + method_name + "]: " + msg);
557     }
558
559     static void log(String JavaDoc msg) {
560         System.out.println(msg);
561     }
562
563     static void close(Socket in, Socket out) {
564         if (in !=null) {
565             try {
566                 in.close();
567             }
568             catch (Exception JavaDoc ex) {
569             }
570         }
571         if (out !=null) {
572             try {
573                 out.close();
574             }
575             catch (Exception JavaDoc ex) {
576             }
577         }
578     }
579
580     static void close(Socket sock) {
581         if (sock !=null) {
582             try {
583                 sock.close();
584             }
585             catch (Exception JavaDoc ex) {
586             }
587         }
588     }
589
590     static class Relayer implements Runnable JavaDoc {
591         final Socket in_sock;
592         final Socket out_sock;
593         final InputStream in;
594         final OutputStream out;
595         Thread JavaDoc t=null;
596         final java.util.List JavaDoc listeners=new ArrayList();
597         String JavaDoc name=null;
598
599         interface Listener {
600             void connectionClosed();
601         }
602
603         public Relayer(Socket in_sock, Socket out_sock, String JavaDoc name) throws Exception JavaDoc {
604             this.in_sock=in_sock;
605             this.out_sock=out_sock;
606             this.name=name;
607             in=in_sock.getInputStream();
608             out=out_sock.getOutputStream();
609         }
610
611         public void addListener(Listener l) {
612             if(l != null && !listeners.contains(l))
613                 listeners.add(l);
614         }
615
616
617         public void run() {
618             byte[] buf=new byte[1024];
619             int num;
620             StringBuffer JavaDoc sb;
621
622             try {
623                 while(t != null) {
624                     if ((num=in.read(buf)) == -1)
625                         break;
626
627                     if (verbose) {
628                         
629                         //sb=new StringBuffer();
630

631
632                         //sb.append("forwarding ").append(num).append(" bytes from ").append(toString(in_sock));
633
//sb.append(" to ").append(toString(out_sock));
634
// log("Proxy1_4.Relayer.run()", sb.toString());
635
log(printRelayedData(toString(in_sock), toString(out_sock), num));
636                     }
637                     if (debug) {
638                         sb=new StringBuffer JavaDoc();
639                         sb.append(new String JavaDoc(buf, 0, num).trim());
640                         log(sb.toString());
641                     }
642
643                     out.write(buf, 0, num);
644                     //if(debug)
645
// System.out.println(new String(buf));
646
}
647                 
648             }
649             catch (Exception JavaDoc ex) {
650                 log("Proxy1_4.Relayer.run(): [" + name + "] exception=" + ex + ", in_sock=" +
651                     in_sock + ", out_sock=" + out_sock);
652             }
653             finally {
654                 stop();
655             }
656         }
657
658         public void start() {
659             if(t == null) {
660                 t=new Thread JavaDoc(this, "Proxy1_4.Relayer");
661                 t.setDaemon(true);
662                 t.start();
663             }
664         }
665
666         public void stop() {
667             t=null;
668             close(in_sock);
669             close(out_sock);
670         }
671
672         String JavaDoc toString(Socket s) {
673             if(s == null) return null;
674             return s.getInetAddress().getHostName() + ':' + s.getPort();
675         }
676         
677
678         void notifyListeners() {
679             for(Iterator it=listeners.iterator(); it.hasNext();) {
680                 try {
681                     ((Listener)it.next()).connectionClosed();
682                 }
683                 catch(Throwable JavaDoc ex) {
684                     ;
685                 }
686             }
687         }
688     }
689
690     static class MyInetSocketAddress extends InetSocketAddress {
691         boolean is_ssl=false;
692
693         public MyInetSocketAddress(InetAddress addr, int port) {
694             super(addr, port);
695         }
696
697         public MyInetSocketAddress(InetAddress addr, int port, boolean is_ssl) {
698             super(addr, port);
699             this.is_ssl=is_ssl;
700         }
701
702         public MyInetSocketAddress(int port) {
703             super(port);
704         }
705
706         public MyInetSocketAddress(int port, boolean is_ssl) {
707             super(port);
708             this.is_ssl=is_ssl;
709         }
710
711         public MyInetSocketAddress(String JavaDoc hostname, int port) {
712             super(hostname, port);
713         }
714
715         public MyInetSocketAddress(String JavaDoc hostname, int port, boolean is_ssl) {
716             super(hostname, port);
717             this.is_ssl=is_ssl;
718         }
719
720         public boolean ssl() {
721             return is_ssl;
722         }
723
724         public String JavaDoc toString() {
725             return super.toString() + " [ssl: " + ssl() + ']';
726         }
727     }
728
729     /**
730      * Handles accepts on an SSLServerSocket or ServerSocket. Creates a {@link
731      * Connection} for each successful accept().
732      *
733      * @author bela Dec 19, 2002
734      */

735     class SocketAcceptor implements Runnable JavaDoc {
736         ServerSocket srv_sock=null;
737         MyInetSocketAddress dest=null;
738         
739
740         /**
741          * Create an SSLServerSocket or ServerSocket and continuously call
742          * accept() on it.
743          * @param sock_addr
744          */

745         public SocketAcceptor(MyInetSocketAddress sock_addr, MyInetSocketAddress dest) throws Exception JavaDoc {
746             this.dest=dest;
747             if(sock_addr.ssl()) {
748                 srv_sock=createSSLServerSocket(sock_addr);
749             }
750             else {
751                 srv_sock=createServerSocket(sock_addr);
752             }
753             executor.execute(this);
754         }
755
756         public void run() {
757             Connection conn;
758             Socket s, dest_sock;
759
760             while (srv_sock !=null) {
761                 try {
762                     s=srv_sock.accept();
763                     dest_sock=dest.ssl() ? createSSLSocket(dest) : createSocket(dest);
764                     conn=new Connection(s, dest_sock);
765                     conn.start();
766                 }
767                 catch (Exception JavaDoc e) {
768                     log("Proxy1_4.SSLServerSocketAcceptor.run(): exception=" + e);
769                     break;
770                 }
771             }
772         }
773         
774
775         Socket createSocket(InetSocketAddress addr) throws Exception JavaDoc {
776             return new Socket(addr.getAddress(), addr.getPort());
777         }
778
779         Socket createSSLSocket(InetSocketAddress addr) throws Exception JavaDoc {
780             SSLSocketFactory sslsocketfactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
781             SSLSocket sslsocket = (SSLSocket)sslsocketfactory.createSocket(addr.getAddress(), addr.getPort());
782             return sslsocket;
783         }
784
785         ServerSocket createServerSocket(InetSocketAddress addr) throws Exception JavaDoc {
786             return new ServerSocket(addr.getPort(), 10, addr.getAddress());
787         }
788         
789         ServerSocket createSSLServerSocket(InetSocketAddress addr) throws Exception JavaDoc {
790             SSLServerSocketFactory sslserversocketfactory =
791                 (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
792             SSLServerSocket sslserversocket =
793                 (SSLServerSocket)sslserversocketfactory.createServerSocket(addr.getPort(), 10, addr.getAddress());
794             return sslserversocket;
795         }
796     }
797
798
799
800     /**
801      * Handles an incoming SSLSocket or Socket. Looks up the destination in the
802      * mapping hashmap, key is the incoming socket address. Creates an outgoing
803      * socket (regular or SSL, depending on settings) and relays data between
804      * incoming and outgoing sockets. Closes the connection when either incoming
805      * or outgoing socket is closed, or when stop() is called.
806      *
807      * @author bela Dec 19, 2002
808      */

809     static class Connection implements Relayer.Listener {
810         Relayer in_to_out=null;
811         Relayer out_to_in=null;
812
813         /**
814          * Creates an outgoing (regular or SSL) socket according to the mapping
815          * table. Sets both input and output stream. Caller needs to call
816          * start() after the instance has been created.
817          * @param in The Socket we got as result of accept()
818          * @throws Exception Thrown if either the input or output streams cannot
819          * be created.
820          */

821         public Connection(Socket in, Socket out) throws Exception JavaDoc {
822             in_to_out=new Relayer(in, out, "in-out");
823             in_to_out.addListener(this);
824             out_to_in=new Relayer(out, in, "out-in");
825             out_to_in.addListener(this);
826         }
827
828         /** Starts relaying between incoming and outgoing sockets.
829          * Returns immediately (thread is started).
830          *
831          */

832         public void start() {
833             in_to_out.start();
834             out_to_in.start();
835         }
836
837         public void stop() {
838             if (in_to_out !=null) {
839                 in_to_out.stop();
840             }
841             if (out_to_in !=null) {
842                 out_to_in.stop();
843             }
844         }
845
846         public void connectionClosed() {
847             stop();
848         }
849     }
850
851 }
852
Popular Tags