1 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 ; 15 import java.nio.channels.SelectionKey ; 16 import java.nio.channels.Selector ; 17 import java.nio.channels.ServerSocketChannel ; 18 import java.nio.channels.SocketChannel ; 19 import java.util.*; 20 21 22 23 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 mapping_file=null; final HashMap mappings=new HashMap(); Executor executor; static final int MAX_THREAD_POOL_SIZE=64; static final int BUFSIZE=1024; 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 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 { 97 Map.Entry entry; 98 Selector selector; 99 ServerSocketChannel 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 ex) { 110 log("Failed reading " + mapping_file); 111 throw ex; 112 } 113 } 114 115 log("\nProxy started at " + new java.util.Date ()); 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 selector=Selector.open(); 129 130 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 140 if (key.ssl() || value.ssl()) { 141 SocketAcceptor acceptor=new SocketAcceptor(key, value); 143 executor.execute(acceptor); 144 continue; 145 } 146 147 sock_channel=ServerSocketChannel.open(); 149 sock_channel.configureBlocking(false); 150 sock_channel.socket().bind(key); 151 152 sock_channel.register(selector, SelectionKey.OP_ACCEPT, key); 156 } 157 158 loop(selector); 160 } 161 162 163 164 165 void loop(Selector selector) { 166 Set ready_keys; 167 SelectionKey key; 168 ServerSocketChannel srv_sock; 169 SocketChannel in_sock, out_sock; 170 InetSocketAddress src, dest; 171 172 while (true) { 173 if (verbose) 174 log("[Proxy] ready to accept connection"); 175 176 try { 178 selector.select(); 179 180 ready_keys=selector.selectedKeys(); 182 for (Iterator it=ready_keys.iterator(); it.hasNext();) { 183 key=(SelectionKey ) it.next(); 184 it.remove(); 185 186 if (key.isAcceptable()) { 187 srv_sock=(ServerSocketChannel ) key.channel(); 188 SRC=(InetSocketAddress) key.attachment(); 190 in_sock=srv_sock.accept(); if (verbose) 192 log("Proxy1_4.loop()", "accepted connection from " + toString(in_sock)); 193 dest=(InetSocketAddress) mappings.get(src); 194 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 try { 207 out_sock=SocketChannel.open(dest); 208 handleConnection(in_sock, out_sock); 210 } 211 catch (Exception ex) { 212 in_sock.close(); 213 throw ex; 214 } 215 } 216 } 217 } 218 catch (Exception ex) { 219 log("Proxy1_4.loop()", "exception: " + ex); 220 } 221 } 222 } 223 224 239 void handleConnection(SocketChannel in, SocketChannel out) { 240 try { 241 _handleConnection(in, out); 242 } 243 catch (Exception ex) { 244 log("Proxy1_4.handleConnection()", "exception: " + ex); 245 } 246 } 247 248 void _handleConnection(final SocketChannel in_channel, final SocketChannel out_channel) throws Exception { 249 executor.execute(new Runnable () { 250 public void run() { 251 Selector sel=null; 252 SocketChannel tmp; 253 Set ready_keys; 254 SelectionKey key; 255 ByteBuffer 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 ) it.next(); 268 it.remove(); tmp=(SocketChannel ) key.channel(); 270 if (tmp == null) { 271 log( 272 "Proxy1_4._handleConnection()", 273 "attachment is null, continuing"); 274 continue; 275 } 276 if (key.isReadable()) { if (tmp == in_channel) { 278 if (relay(tmp, out_channel, transfer_buf) == false) 280 return; 281 } 282 if (tmp == out_channel) { 283 if (relay(tmp, in_channel, transfer_buf) == false) 286 return; 287 } 288 } 289 } 290 } 291 } 292 catch (Exception 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 sel, SocketChannel in_channel, SocketChannel out_channel) { 304 try { 305 if (sel !=null) 306 sel.close(); 307 } 308 catch (Exception ex) { 309 } 310 try { 311 if (in_channel !=null) 312 in_channel.close(); 313 } 314 catch (Exception ex) { 315 } 316 try { 317 if (out_channel !=null) 318 out_channel.close(); 319 } 320 catch (Exception ex) { 321 } 322 } 323 324 325 329 boolean relay(SocketChannel from, SocketChannel to, ByteBuffer buf) throws Exception { 330 int num; 331 StringBuffer 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 (); 347 sb.append(new String (buf.array()).trim()); 348 sb.append('\n'); 349 log(sb.toString()); 350 } 351 to.write(buf); 352 buf.flip(); 353 } 354 } 355 356 String toString(SocketChannel ch) { 357 StringBuffer sb=new StringBuffer (); 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 toString(InetSocketAddress addr) { 369 StringBuffer sb=new StringBuffer (); 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 printRelayedData(String from, String to, int num_bytes) { 381 StringBuffer sb=new StringBuffer (); 382 sb.append("\n[PROXY] ").append(from); 383 sb.append(" to ").append(to); 384 sb.append(" (").append(num_bytes).append(" bytes)"); 385 return sb.toString(); 387 } 388 389 390 399 void populateMappings(String filename) throws Exception { 400 FileInputStream in=new FileInputStream(filename); 401 BufferedReader reader; 402 String line; 403 URI key, value; 404 int index; 405 boolean ssl_key, ssl_value; 406 final String 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 ("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 434 void check(URI u) throws Exception { 435 if (u.getScheme() == null) 436 throw new Exception ( 437 "scheme is null in " + u + ", (valid URI is \"http(s)://<host>:<port>\")"); 438 439 if (u.getHost() == null) 440 throw new Exception ( 441 "host is null in " + u + ", (valid URI is \"http(s)://<host>:<port>\")"); 442 443 if (u.getPort() <=0) 444 throw new Exception ( 445 "port is <=0 in " + u + ", (valid URI is \"http(s)://<host>:<port>\")"); 446 447 } 448 449 450 SocketAddress strToAddr(String input) throws Exception { 451 StringTokenizer tok=new StringTokenizer(input, ":"); 452 String host, port; 453 454 host=tok.nextToken(); 455 port=tok.nextToken(); 456 return new InetSocketAddress(host, Integer.parseInt(port)); 457 } 458 459 String printSelectionOps(SelectionKey key) { 460 StringBuffer sb=new StringBuffer (); 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 [] args) { 473 Proxy1_4 p; 474 InetAddress local=null, remote=null; 475 int local_port=0, remote_port=0; 476 String tmp, tmp_addr, tmp_port; 477 boolean verbose=false, debug=false; 478 int index; 479 String 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) { 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) { 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 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 method_name, String msg) { 556 System.out.println('[' + method_name + "]: " + msg); 557 } 558 559 static void log(String 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 ex) { 569 } 570 } 571 if (out !=null) { 572 try { 573 out.close(); 574 } 575 catch (Exception ex) { 576 } 577 } 578 } 579 580 static void close(Socket sock) { 581 if (sock !=null) { 582 try { 583 sock.close(); 584 } 585 catch (Exception ex) { 586 } 587 } 588 } 589 590 static class Relayer implements Runnable { 591 final Socket in_sock; 592 final Socket out_sock; 593 final InputStream in; 594 final OutputStream out; 595 Thread t=null; 596 final java.util.List listeners=new ArrayList(); 597 String name=null; 598 599 interface Listener { 600 void connectionClosed(); 601 } 602 603 public Relayer(Socket in_sock, Socket out_sock, String name) throws Exception { 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 sb; 621 622 try { 623 while(t != null) { 624 if ((num=in.read(buf)) == -1) 625 break; 626 627 if (verbose) { 628 629 631 632 log(printRelayedData(toString(in_sock), toString(out_sock), num)); 636 } 637 if (debug) { 638 sb=new StringBuffer (); 639 sb.append(new String (buf, 0, num).trim()); 640 log(sb.toString()); 641 } 642 643 out.write(buf, 0, num); 644 } 647 648 } 649 catch (Exception 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 (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 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 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 hostname, int port) { 712 super(hostname, port); 713 } 714 715 public MyInetSocketAddress(String 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 toString() { 725 return super.toString() + " [ssl: " + ssl() + ']'; 726 } 727 } 728 729 735 class SocketAcceptor implements Runnable { 736 ServerSocket srv_sock=null; 737 MyInetSocketAddress dest=null; 738 739 740 745 public SocketAcceptor(MyInetSocketAddress sock_addr, MyInetSocketAddress dest) throws Exception { 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 e) { 768 log("Proxy1_4.SSLServerSocketAcceptor.run(): exception=" + e); 769 break; 770 } 771 } 772 } 773 774 775 Socket createSocket(InetSocketAddress addr) throws Exception { 776 return new Socket(addr.getAddress(), addr.getPort()); 777 } 778 779 Socket createSSLSocket(InetSocketAddress addr) throws Exception { 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 { 786 return new ServerSocket(addr.getPort(), 10, addr.getAddress()); 787 } 788 789 ServerSocket createSSLServerSocket(InetSocketAddress addr) throws Exception { 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 809 static class Connection implements Relayer.Listener { 810 Relayer in_to_out=null; 811 Relayer out_to_in=null; 812 813 821 public Connection(Socket in, Socket out) throws Exception { 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 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 |