1 19 20 package org.netbeans; 21 22 import java.io.DataInputStream ; 23 import java.io.DataOutputStream ; 24 import java.io.EOFException ; 25 import java.io.File ; 26 import java.io.FileInputStream ; 27 import java.io.FileOutputStream ; 28 import java.io.IOException ; 29 import java.io.InputStream ; 30 import java.io.InterruptedIOException ; 31 import java.io.OutputStream ; 32 import java.io.PrintStream ; 33 import java.io.PrintWriter ; 34 import java.lang.reflect.InvocationTargetException ; 35 import java.lang.reflect.Method ; 36 import java.net.InetAddress ; 37 import java.net.ServerSocket ; 38 import java.net.Socket ; 39 import java.net.SocketException ; 40 import java.net.UnknownHostException ; 41 import java.security.NoSuchAlgorithmException ; 42 import java.security.SecureRandom ; 43 import java.util.ArrayList ; 44 import java.util.Arrays ; 45 import java.util.Collection ; 46 import java.util.Collections ; 47 import java.util.Iterator ; 48 import java.util.List ; 49 import java.util.Random ; 50 import java.util.logging.Level ; 51 import java.util.logging.Logger ; 52 import org.openide.util.RequestProcessor; 53 import org.openide.util.Task; 54 55 66 public abstract class CLIHandler extends Object { 67 68 private static final int KEY_LENGTH = 10; 69 70 private static final int REPLY_OK = 1; 71 72 private static final int REPLY_EXIT = 2; 73 74 private static final int REPLY_FAIL = 0; 75 76 private static final int REPLY_DELAY = 3; 77 78 79 private static final int REPLY_READ = 10; 80 81 private static final int REPLY_WRITE = 11; 82 83 private static final int REPLY_AVAILABLE = 12; 84 85 private static final int REPLY_ERROR = 13; 86 87 90 public static final int WHEN_BOOT = 1; 91 94 public static final int WHEN_INIT = 2; 95 97 public static final int WHEN_EXTRA = 3; 98 99 101 private static Server server; 102 103 105 private static Logger OUTPUT = Logger.getLogger("org.netbeans.CLIHandler"); 107 private int when; 108 109 113 protected CLIHandler(int when) { 114 this.when = when; 115 } 116 117 124 protected abstract int cli(Args args); 125 126 protected static void showHelp(PrintWriter w, Collection handlers, int when) { 127 Iterator it = handlers.iterator(); 128 while (it.hasNext()) { 129 CLIHandler h = (CLIHandler)it.next(); 130 if (when != -1 && when != h.when) { 131 continue; 132 } 133 134 h.usage(w); 135 } 136 } 137 138 142 protected abstract void usage(PrintWriter w); 143 144 147 private static void enterState(int state, Integer block) { 148 if (OUTPUT.isLoggable(Level.FINEST)) { 149 synchronized (OUTPUT) { 150 OUTPUT.finest("state: " + state + " thread: " + Thread.currentThread()); } 153 } 154 155 if (block == null) return; 156 157 158 synchronized (block) { 159 if (state == block.intValue()) { 160 if (OUTPUT.isLoggable(Level.FINEST)) { 161 OUTPUT.finest(state + " blocked"); } 163 block.notifyAll(); 164 try { 165 block.wait(); 166 } catch (InterruptedException ex) { 167 throw new IllegalStateException (); 168 } 169 } else { 170 if (OUTPUT.isLoggable(Level.FINEST)) { 171 OUTPUT.finest(state + " not blocked"); } 173 } 174 } 175 } 176 177 private static boolean checkHelp(Args args, Collection handlers) { 178 String [] argv = args.getArguments(); 179 for (int i = 0; i < argv.length; i++) { 180 if (argv[i] == null) { 181 continue; 182 } 183 184 if (argv[i].equals("-?") || argv[i].equals("--help") || argv[i].equals ("-help")) { PrintWriter w = new PrintWriter (args.getOutputStream()); 186 showHelp(w, handlers, -1); 187 w.flush(); 188 return true; 189 } 190 } 191 192 return false; 193 } 194 195 198 protected static int notifyHandlers(Args args, Collection handlers, int when, boolean failOnUnknownOptions, boolean consume) { 199 try { 200 int r = 0; 201 Iterator it = handlers.iterator(); 202 while (it.hasNext()) { 203 CLIHandler h = (CLIHandler)it.next(); 204 if (h.when != when) continue; 205 206 r = h.cli(args); 207 if (r != 0) { 209 return r; 210 } 211 } 212 String [] argv = args.getArguments(); 213 if (failOnUnknownOptions) { 214 argv = args.getArguments(); 215 for (int i = 0; i < argv.length; i++) { 216 if (argv[i] != null) { 217 PrintWriter w = new PrintWriter (args.getOutputStream()); 219 w.println("Ignored unknown option: " + argv[i]); 221 226 w.flush(); 227 return 2; 228 } 229 } 230 } 231 return 0; 232 } finally { 233 args.reset(consume); 234 } 235 } 236 237 242 static final class Status { 243 public static final int CANNOT_CONNECT = -255; 244 245 private final File lockFile; 246 private final int port; 247 private int exitCode; 248 private Task parael; 249 252 Status() { 253 this(0); 254 } 255 260 Status(int c) { 261 this(null, 0, c, null); 262 } 263 269 Status(File l, int p, int c, Task parael) { 270 lockFile = l; 271 port = p; 272 exitCode = c; 273 this.parael = parael; 274 } 275 276 private void waitFinished() { 277 if (parael != null) { 278 parael.waitFinished(); 279 } 280 } 281 282 286 public File getLockFile() { 287 waitFinished(); 288 return lockFile; 289 } 290 294 public int getServerPort() { 295 return port; 296 } 297 301 public int getExitCode() { 302 return exitCode; 303 } 304 } 305 306 307 315 static Status initialize( 316 String [] args, 317 InputStream is, 318 OutputStream os, 319 java.io.OutputStream err, 320 MainImpl.BootClassLoader loader, 321 boolean failOnUnknownOptions, 322 boolean cleanLockFile, 323 Runnable runWhenHome 324 ) { 325 return initialize( 326 new Args(args, is, os, err, System.getProperty ("user.dir")), 327 (Integer )null, 328 loader.allCLIs(), 329 failOnUnknownOptions, 330 cleanLockFile, 331 runWhenHome 332 ); 333 } 334 335 339 private static List <Execute> doLater = new ArrayList <Execute> (); 340 static interface Execute { 341 342 public int exec (); 343 } 344 345 347 private static int registerFinishInstallation (Execute run) { 348 boolean runNow; 349 350 synchronized (CLIHandler.class) { 351 if (doLater != null) { 352 doLater.add (run); 353 runNow = false; 354 } else { 355 runNow = true; 356 } 357 } 358 359 if (runNow) { 360 return run.exec (); 361 } 362 363 return 0; 364 } 365 366 372 static int finishInitialization (boolean recreate) { 373 OUTPUT.log(Level.FINER, "finishInitialization {0}", recreate); 374 List toRun; 375 synchronized (CLIHandler.class) { 376 toRun = doLater; 377 doLater = recreate ? new ArrayList <Execute> () : null; 378 if (OUTPUT.isLoggable(Level.FINER)) { 379 OUTPUT.finer("Notify: " + toRun); 380 } 381 if (!recreate) { 382 CLIHandler.class.notifyAll (); 383 } 384 } 385 386 if (toRun != null) { 387 Iterator it = toRun.iterator (); 388 while (it.hasNext ()) { 389 Execute r = (Execute)it.next (); 390 int result = r.exec (); 391 if (result != 0) { 392 return result; 393 } 394 } 395 } 396 return 0; 397 } 398 399 404 private static synchronized boolean waitFinishInstallationIsOver (int timeout) { 405 if (doLater != null) { 406 try { 407 CLIHandler.class.wait (timeout); 408 } catch (InterruptedException ex) { 409 } 411 } 412 return doLater == null; 413 } 414 415 417 public static synchronized void stopServer () { 418 Server s = server; 419 if (s != null) { 420 s.stopServer (); 421 } 422 } 423 424 426 private static InetAddress localHostAddress () throws IOException { 427 java.net.NetworkInterface net = java.net.NetworkInterface.getByName ("lo"); 428 if (net == null || !net.getInetAddresses().hasMoreElements()) { 429 return InetAddress.getLocalHost(); 430 } 431 else { 432 return net.getInetAddresses().nextElement(); 433 } 434 } 435 436 446 static Status initialize( 447 final Args args, final Integer block, 448 final Collection handlers, 449 final boolean failOnUnknownOptions, 450 boolean cleanLockFile, 451 Runnable runWhenHome 452 ) { 453 { 455 int r = notifyHandlers(args, handlers, WHEN_BOOT, false, failOnUnknownOptions); 456 if (r != 0) { 457 return new Status(r); 458 } 459 } 460 461 String home = System.getProperty("netbeans.user"); if (home == null) { 464 home = System.getProperty("user.home"); System.setProperty ("netbeans.user", home); } 467 468 if ("memory".equals(home)) { return new Status(0); 470 } 471 472 if (runWhenHome != null) { 473 runWhenHome.run (); 475 } 476 477 478 File lockFile = new File (home, "lock"); 480 for (int i = 0; i < 5; i++) { 481 try { 483 if (lockFile.exists()) { 484 enterState(5, block); 485 throw new IOException ("EXISTS"); } 487 488 if (i == 0 && checkHelp(args, handlers)) { 489 return new Status(2); 490 } 491 492 lockFile.getParentFile().mkdirs(); 493 lockFile.createNewFile(); 494 lockFile.deleteOnExit(); 495 secureAccess(lockFile); 496 497 enterState(10, block); 498 499 final byte[] arr = new byte[KEY_LENGTH]; 500 new Random ().nextBytes(arr); 501 502 server = new Server(arr, block, handlers, failOnUnknownOptions); 503 504 final DataOutputStream os = new DataOutputStream (new FileOutputStream (lockFile)); 505 int p = server.getLocalPort(); 506 os.writeInt(p); 507 os.flush(); 508 509 enterState(20, block); 510 511 Task parael = new RequestProcessor("Secure CLI Port").post(new Runnable () { public void run() { 513 try { 514 SecureRandom.getInstance("SHA1PRNG").nextBytes(arr); } catch (NoSuchAlgorithmException e) { 516 try { 518 SecureRandom.getInstance("IBMSecureRandom").nextBytes(arr); } catch (NoSuchAlgorithmException e2) { 520 server.stopServer(); 522 } 523 } 524 525 enterState(97, block); 526 527 try { 528 os.write(arr); 529 os.flush(); 530 531 enterState(27,block); 532 byte[] host = InetAddress.getLocalHost().getAddress(); 536 if (block != null && block.intValue() == 667) { 537 throw new java.net.UnknownHostException ("dhcppc0"); } 540 for (int all = 0; all < host.length; all++) { 541 os.write(host[all]); 542 } 543 } catch (UnknownHostException unknownHost) { 544 unknownHost.printStackTrace(); 546 } catch (IOException ex) { 547 ex.printStackTrace(); 548 } 549 try { 550 os.close(); 551 } catch (IOException ex) { 552 } 554 } 555 }); 556 557 int execCode = registerFinishInstallation (new Execute () { 558 public int exec () { 559 return notifyHandlers(args, handlers, WHEN_INIT, failOnUnknownOptions, failOnUnknownOptions); 560 } 561 562 public String toString() { 563 return handlers.toString(); 564 } 565 }); 566 567 enterState(0, block); 568 return new Status(lockFile, server.getLocalPort(), execCode, parael); 569 } catch (IOException ex) { 570 if (!"EXISTS".equals(ex.getMessage())) { ex.printStackTrace(); 572 } 573 byte[] key = null; 575 byte[] serverAddress = null; 576 int port = -1; 577 DataInputStream is = null; 578 try { 579 enterState(21, block); 580 if (OUTPUT.isLoggable(Level.FINER)) { 581 OUTPUT.log(Level.FINER, "Reading lock file {0}", lockFile); } 583 is = new DataInputStream (new FileInputStream (lockFile)); 584 port = is.readInt(); 585 enterState(22, block); 586 key = new byte[KEY_LENGTH]; 587 is.readFully(key); 588 enterState(23, block); 589 byte[] x = new byte[4]; 590 is.readFully(x); 591 enterState(24, block); 592 serverAddress = x; 593 } catch (EOFException eof) { 594 if (port != -1) { 596 try { 597 enterState(94, block); 598 Thread.sleep(2000); 600 } catch (InterruptedException inter) { 601 inter.printStackTrace(); 602 } 603 continue; 604 } 605 } catch (IOException ex2) { 606 enterState(26, block); 608 } finally { 609 if (is != null) { 610 try { 611 is.close(); 612 } catch (IOException ex3) { 613 } 615 } 616 enterState(25, block); 617 } 618 619 if (key != null && port != -1) { 620 try { 621 enterState(28, block); 623 Socket socket = new Socket (localHostAddress (), port); 624 socket.setSoTimeout(5000); 626 DataOutputStream os = new DataOutputStream (socket.getOutputStream()); 627 os.write(key); 628 os.flush(); 629 630 enterState(30, block); 631 632 DataInputStream replyStream = new DataInputStream (socket.getInputStream()); 633 byte[] outputArr = new byte[4096]; 634 635 COMMUNICATION: for (;;) { 636 enterState(32, block); 637 int reply = replyStream.read(); 638 enterState(34, block); 640 641 switch (reply) { 642 case REPLY_FAIL: 643 enterState(36, block); 644 break COMMUNICATION; 645 case REPLY_OK: 646 enterState(38, block); 647 String [] arr = args.getArguments(); 649 os.writeInt(arr.length); 650 for (int a = 0; a < arr.length; a++) { 651 os.writeUTF(arr[a]); 652 } 653 os.writeUTF (args.getCurrentDirectory().toString()); 654 os.flush(); 655 break; 656 case REPLY_EXIT: 657 int exitCode = replyStream.readInt(); 658 if (exitCode == 0) { 659 exitCode = -1; 661 } 662 663 os.close(); 664 replyStream.close(); 665 666 enterState(0, block); 667 return new Status(lockFile, port, exitCode, null); 668 case REPLY_READ: { 669 enterState(42, block); 670 int howMuch = replyStream.readInt(); 671 if (howMuch > outputArr.length) { 672 outputArr = new byte[howMuch]; 673 } 674 int really = args.getInputStream().read(outputArr, 0, howMuch); 675 os.write(really); 676 if (really > 0) { 677 os.write(outputArr, 0, really); 678 } 679 os.flush(); 680 break; 681 } 682 case REPLY_WRITE: { 683 enterState(44, block); 684 int howMuch = replyStream.readInt(); 685 if (howMuch > outputArr.length) { 686 outputArr = new byte[howMuch]; 687 } 688 replyStream.read(outputArr, 0, howMuch); 689 args.getOutputStream().write(outputArr, 0, howMuch); 690 break; 691 } 692 case REPLY_ERROR: { 693 enterState(45, block); 694 int howMuch = replyStream.readInt(); 695 if (howMuch > outputArr.length) { 696 outputArr = new byte[howMuch]; 697 } 698 replyStream.read(outputArr, 0, howMuch); 699 args.getErrorStream().write(outputArr, 0, howMuch); 700 break; 701 } 702 case REPLY_AVAILABLE: 703 enterState(46, block); 704 os.writeInt(args.getInputStream().available()); 705 os.flush(); 706 break; 707 case REPLY_DELAY: 708 enterState(47, block); 709 break; 711 case -1: 712 enterState(48, block); 713 break; 715 default: 716 enterState(49, block); 717 assert false : reply; 718 } 719 } 720 721 } catch (java.net.SocketTimeoutException ex2) { 724 enterState(33, block); 726 } catch (java.net.ConnectException ex2) { 727 enterState(33, block); 729 } catch (IOException ex2) { 730 ex2.printStackTrace(); 732 enterState(33, block); 733 } 734 735 boolean isSameHost = true; 736 if (serverAddress != null) { 737 try { 738 isSameHost = Arrays.equals(InetAddress.getLocalHost().getAddress(), serverAddress); 739 } catch (UnknownHostException ex5) { 740 enterState(999, block); 742 } 743 } 744 745 if (cleanLockFile || isSameHost) { 746 lockFile.delete(); 748 } else { 749 return new Status (Status.CANNOT_CONNECT); 750 } 751 } 752 } 753 754 try { 755 enterState(83, block); 756 Thread.sleep((int)(Math.random() * 1000.00)); 757 enterState(85, block); 758 } catch (InterruptedException ex) { 759 } 761 } 762 763 return new Status(); 765 } 766 767 769 private static void secureAccess(final File file) throws IOException { 770 boolean success = false; 773 774 String vm = System.getProperty("java.version"); if (vm != null && vm.startsWith("1.6")) { try { 777 Method m = File .class.getMethod("setReadable", new Class [] { Boolean.TYPE, Boolean.TYPE }); Object s1 = m.invoke(file, new Object [] {Boolean.FALSE, Boolean.FALSE}); 779 Object s2 = m.invoke(file, new Object [] {Boolean.TRUE, Boolean.TRUE}); 780 success = Boolean.TRUE.equals(s1) && Boolean.TRUE.equals(s2); 781 } catch (InvocationTargetException ex) { 782 ex.printStackTrace(); 783 } catch (IllegalAccessException ex) { 784 ex.printStackTrace(); 785 } catch (NoSuchMethodException ex) { 786 ex.printStackTrace(); 787 } 788 } 789 if (success) { 790 return; 791 } 792 try { 793 File chmod = new File ("/bin/chmod"); if (!chmod.isFile()) { 797 chmod = new File ("/usr/bin/chmod"); } 800 if (chmod.isFile()) { 801 int chmoded = Runtime.getRuntime().exec(new String [] { 802 chmod.getAbsolutePath(), 803 "go-rwx", file.getAbsolutePath() 805 }).waitFor(); 806 if (chmoded != 0) { 807 throw new IOException ("could not run " + chmod + " go-rwx " + file); } 809 } 810 } catch (InterruptedException e) { 811 throw (IOException )new IOException (e.toString()).initCause(e); 812 } 813 } 814 815 818 public static final class Args extends Object { 819 private String [] args; 820 private final String [] argsBackup; 821 private InputStream is; 822 private OutputStream os; 823 private OutputStream err; 824 private File currentDir; 825 private boolean closed; 826 827 Args(String [] args, InputStream is, OutputStream os, java.io.OutputStream err, String currentDir) { 828 argsBackup = args; 829 reset(false); 830 this.is = is; 831 this.os = os; 832 this.err = err; 833 this.currentDir = new File (currentDir); 834 } 835 836 841 void reset(boolean consume) { 842 if (consume) { 843 String [] a = args; 844 if (a == null) { 845 a = argsBackup; 846 } 847 List <String > l = new ArrayList <String >(Arrays.asList(a)); 848 l.removeAll(Collections.singleton(null)); 849 args = l.toArray(new String [l.size()]); 850 } else { 851 args = argsBackup.clone(); 852 } 853 } 854 855 857 final void close() { 858 closed = true; 859 } 860 861 867 public String [] getArguments() { 868 return args; 869 } 870 871 875 public OutputStream getOutputStream() { 876 return os; 877 } 878 879 882 public OutputStream getErrorStream() { 883 return err; 884 } 885 886 public File getCurrentDirectory () { 887 return currentDir; 888 } 889 890 894 public InputStream getInputStream() { 895 return is; 896 } 897 898 904 public boolean isOpen() { 905 return !closed; 906 } 907 908 } 910 912 private static final class Server extends Thread { 913 private byte[] key; 914 private ServerSocket socket; 915 private Integer block; 916 private Collection handlers; 917 private Socket work; 918 private static volatile int counter; 919 private final boolean failOnUnknownOptions; 920 921 private static long lastReply; 922 923 private static long failDelay = 100; 924 925 public Server(byte[] key, Integer block, Collection handlers, boolean failOnUnknownOptions) throws IOException { 926 super("CLI Requests Server"); this.key = key; 928 this.setDaemon(true); 929 this.block = block; 930 this.handlers = handlers; 931 this.failOnUnknownOptions = failOnUnknownOptions; 932 933 socket = new ServerSocket (0, 50, localHostAddress()); 934 start(); 935 } 936 937 public Server(Socket request, byte[] key, Integer block, Collection handlers, boolean failOnUnknownOptions) throws IOException { 938 super("CLI Handler Thread Handler: " + ++counter); this.key = key; 940 this.setDaemon(true); 941 this.block = block; 942 this.handlers = handlers; 943 this.work = request; 944 this.failOnUnknownOptions = failOnUnknownOptions; 945 946 start(); 947 } 948 949 public int getLocalPort() { 950 return socket.getLocalPort(); 951 } 952 953 public void run() { 954 if (work != null) { 955 try { 957 handleConnect(work); 958 } catch (IOException ex) { 959 ex.printStackTrace(); 960 } 961 return; 962 } 963 964 ServerSocket toClose = socket; 965 if (toClose == null) { 966 return; 967 } 968 969 while (socket != null) { 970 try { 971 enterState(65, block); 972 Socket s = socket.accept(); 973 if (socket == null) { 974 enterState(66, block); 975 s.getOutputStream().write(REPLY_FAIL); 976 enterState(67, block); 977 s.close(); 978 continue; 979 } 980 981 new Server(s, key, block, handlers, failOnUnknownOptions); 983 } catch (InterruptedIOException ex) { 984 if (socket != null) { 985 ex.printStackTrace(); 986 } 987 } catch (java.net.SocketException ex) { 990 if (socket != null) { 991 ex.printStackTrace(); 992 } 993 } catch (IOException ex) { 994 ex.printStackTrace(); 995 } 996 } 997 998 try { 999 toClose.close(); 1000 } catch (IOException ex) { 1001 ex.printStackTrace(); 1002 } 1003 } 1004 1005 final void stopServer () { 1006 socket = null; 1007 interrupt(); 1009 } 1010 1011 private void handleConnect(Socket s) throws IOException { 1012 1013 byte[] check = new byte[key.length]; 1014 DataInputStream is = new DataInputStream (s.getInputStream()); 1015 1016 enterState(70, block); 1017 1018 is.readFully(check); 1019 1020 enterState(90, block); 1021 1022 final DataOutputStream os = new DataOutputStream (s.getOutputStream()); 1023 1024 if (Arrays.equals(check, key)) { 1025 while (!waitFinishInstallationIsOver (2000)) { 1026 os.write (REPLY_DELAY); 1027 os.flush (); 1028 } 1029 1030 enterState(93, block); 1031 os.write(REPLY_OK); 1032 os.flush(); 1033 1034 int numberOfArguments = is.readInt(); 1036 String [] args = new String [numberOfArguments]; 1037 for (int i = 0; i < args.length; i++) { 1038 args[i] = is.readUTF(); 1039 } 1040 final String currentDir = is.readUTF (); 1041 1042 final Args arguments = new Args( 1043 args, 1044 new IS(is, os), 1045 new OS(os, REPLY_WRITE), 1046 new OS(os, REPLY_ERROR), 1047 currentDir 1048 ); 1049 1050 class ComputingAndNotifying extends Thread { 1051 public int res; 1052 public boolean finished; 1053 1054 public ComputingAndNotifying () { 1055 super ("Computes values in handlers"); 1056 } 1057 1058 public void run () { 1059 try { 1060 if (checkHelp(arguments, handlers)) { 1061 res = 2; 1062 } else { 1063 res = notifyHandlers (arguments, handlers, WHEN_INIT, failOnUnknownOptions, false); 1064 } 1065 1066 if (res == 0) { 1067 enterState (98, block); 1068 } else { 1069 enterState (99, block); 1070 } 1071 } finally { 1072 synchronized (this) { 1073 finished = true; 1074 notifyAll (); 1075 } 1076 } 1077 } 1078 1079 public synchronized void waitForResultAndNotifyOthers () { 1080 start (); 1082 while (!finished) { 1083 try { 1084 wait (1000); 1085 os.write (REPLY_DELAY); 1086 os.flush (); 1087 } catch (SocketException ex) { 1088 if (isClosedSocket(ex)) { arguments.close(); 1091 interrupt(); 1093 } else { 1094 ex.printStackTrace(); 1095 } 1096 } catch (InterruptedException ex) { 1097 ex.printStackTrace(); 1098 } catch (IOException ex) { 1099 ex.printStackTrace(); 1100 } 1101 } 1102 } 1103 } 1104 ComputingAndNotifying r = new ComputingAndNotifying (); 1105 r.waitForResultAndNotifyOthers (); 1106 try { 1107 os.write(REPLY_EXIT); 1108 os.writeInt(r.res); 1109 } catch (SocketException ex) { 1110 if (isClosedSocket(ex)) { arguments.close(); 1113 r.interrupt(); 1115 } else { 1116 throw ex; 1117 } 1118 } 1119 } else { 1120 enterState(103, block); 1121 long toWait = lastReply + failDelay - System.currentTimeMillis(); 1122 if (toWait > 0) { 1123 try { 1124 Thread.sleep(toWait); 1125 } catch (InterruptedException ex) { 1126 ex.printStackTrace(); 1127 } 1128 failDelay *= 2; 1129 } else { 1130 failDelay = 100; 1131 } 1132 lastReply = System.currentTimeMillis(); 1133 os.write(REPLY_FAIL); 1134 } 1135 1136 1137 enterState(120, block); 1138 1139 os.close(); 1140 is.close(); 1141 } 1142 1143 1147 static final boolean isClosedSocket(SocketException ex) { 1148 if (ex.getMessage().equals("Broken pipe")) { return true; 1150 } 1151 if (ex.getMessage().startsWith("Connection reset by peer")) { return true; 1153 } 1154 1155 return false; 1156 } 1157 1158 private static final class IS extends InputStream { 1159 private DataInputStream is; 1160 private DataOutputStream os; 1161 1162 public IS(DataInputStream is, DataOutputStream os) { 1163 this.is = is; 1164 this.os = os; 1165 } 1166 1167 public int read() throws IOException { 1168 byte[] arr = new byte[1]; 1169 if (read(arr) == 1) { 1170 return arr[0]; 1171 } else { 1172 return -1; 1173 } 1174 } 1175 1176 public void close() throws IOException { 1177 super.close(); 1178 } 1179 1180 public int available() throws IOException { 1181 os.write(REPLY_AVAILABLE); 1183 os.flush(); 1184 return is.readInt(); 1186 } 1187 1188 public int read(byte[] b) throws IOException { 1189 return read(b, 0, b.length); 1190 } 1191 1192 public int read(byte[] b, int off, int len) throws IOException { 1193 os.write(REPLY_READ); 1195 os.writeInt(len); 1196 os.flush(); 1197 int really = is.read (); 1199 if (really > 0) { 1200 return is.read(b, off, really); 1201 } else { 1202 return really; 1203 } 1204 } 1205 1206 } 1208 private static final class OS extends OutputStream { 1209 private DataOutputStream os; 1210 private int type; 1211 1212 public OS(DataOutputStream os, int type) { 1213 this.os = os; 1214 this.type = type; 1215 } 1216 1217 public void write(int b) throws IOException { 1218 byte[] arr = { (byte)b }; 1219 write(arr); 1220 } 1221 1222 public void write(byte[] b) throws IOException { 1223 write(b, 0, b.length); 1224 } 1225 1226 public void close() throws IOException { 1227 super.close(); 1228 } 1229 1230 public void flush() throws IOException { 1231 os.flush(); 1232 } 1233 1234 public void write(byte[] b, int off, int len) throws IOException { 1235 os.write(type); 1236 os.writeInt(len); 1237 os.write(b, off, len); 1238 } 1239 1240 } 1242 } 1244 1245} 1246 | Popular Tags |