| 1 17 18 package org.apache.coyote.http11; 19 20 import java.io.IOException ; 21 import java.io.InterruptedIOException ; 22 import java.net.InetAddress ; 23 import java.net.Socket ; 24 import java.security.AccessController ; 25 import java.security.PrivilegedAction ; 26 import java.util.StringTokenizer ; 27 import java.util.regex.Pattern ; 28 import java.util.regex.PatternSyntaxException ; 29 30 import org.apache.coyote.ActionCode; 31 import org.apache.coyote.ActionHook; 32 import org.apache.coyote.Adapter; 33 import org.apache.coyote.Request; 34 import org.apache.coyote.RequestInfo; 35 import org.apache.coyote.Response; 36 import org.apache.coyote.http11.filters.BufferedInputFilter; 37 import org.apache.coyote.http11.filters.ChunkedInputFilter; 38 import org.apache.coyote.http11.filters.ChunkedOutputFilter; 39 import org.apache.coyote.http11.filters.GzipOutputFilter; 40 import org.apache.coyote.http11.filters.IdentityInputFilter; 41 import org.apache.coyote.http11.filters.IdentityOutputFilter; 42 import org.apache.coyote.http11.filters.SavedRequestInputFilter; 43 import org.apache.coyote.http11.filters.VoidInputFilter; 44 import org.apache.coyote.http11.filters.VoidOutputFilter; 45 import org.apache.tomcat.util.buf.Ascii; 46 import org.apache.tomcat.util.buf.ByteChunk; 47 import org.apache.tomcat.util.buf.HexUtils; 48 import org.apache.tomcat.util.buf.MessageBytes; 49 import org.apache.tomcat.util.http.FastHttpDateFormat; 50 import org.apache.tomcat.util.http.MimeHeaders; 51 import org.apache.tomcat.util.net.JIoEndpoint; 52 import org.apache.tomcat.util.net.SSLSupport; 53 import org.apache.tomcat.util.res.StringManager; 54 55 56 61 public class Http11Processor implements ActionHook { 62 63 64 67 protected static org.apache.commons.logging.Log log 68 = org.apache.commons.logging.LogFactory.getLog(Http11Processor.class); 69 70 73 protected static StringManager sm = 74 StringManager.getManager(Constants.Package); 75 76 77 79 80 public Http11Processor(int headerBufferSize, JIoEndpoint endpoint) { 81 82 this.endpoint = endpoint; 83 84 request = new Request(); 85 inputBuffer = new InternalInputBuffer(request, headerBufferSize); 86 request.setInputBuffer(inputBuffer); 87 88 response = new Response(); 89 response.setHook(this); 90 outputBuffer = new InternalOutputBuffer(response, headerBufferSize); 91 response.setOutputBuffer(outputBuffer); 92 request.setResponse(response); 93 94 initializeFilters(); 95 96 int foo = HexUtils.DEC[0]; 98 99 } 100 101 102 104 105 108 protected Adapter adapter = null; 109 110 111 114 protected Request request = null; 115 116 117 120 protected Response response = null; 121 122 123 126 protected InternalInputBuffer inputBuffer = null; 127 128 129 132 protected InternalOutputBuffer outputBuffer = null; 133 134 135 138 protected boolean started = false; 139 140 141 144 protected boolean error = false; 145 146 147 150 protected boolean keepAlive = true; 151 152 153 156 protected boolean http11 = true; 157 158 159 162 protected boolean http09 = false; 163 164 165 169 protected boolean contentDelimitation = true; 170 171 172 175 protected boolean expectation = false; 176 177 178 181 protected Pattern [] restrictedUserAgents = null; 182 183 184 187 protected int maxKeepAliveRequests = -1; 188 189 190 193 protected SSLSupport sslSupport; 194 195 196 199 protected Socket socket; 200 201 202 205 protected String remoteAddr = null; 206 207 208 211 protected String remoteHost = null; 212 213 214 217 protected String localName = null; 218 219 220 221 224 protected int localPort = -1; 225 226 227 230 protected int remotePort = -1; 231 232 233 236 protected String localAddr = null; 237 238 239 242 protected int timeout = 300000; 243 244 245 248 protected boolean disableUploadTimeout = false; 249 250 251 254 protected int compressionLevel = 0; 255 256 257 260 protected int compressionMinSize = 2048; 261 262 263 266 protected int socketBuffer = -1; 267 268 269 272 protected int maxSavePostSize = 4 * 1024; 273 274 275 278 protected Pattern noCompressionUserAgents[] = null; 279 280 283 protected String [] compressableMimeTypes = 284 { "text/html", "text/xml", "text/plain" }; 285 286 287 290 protected char[] hostNameC = new char[0]; 291 292 293 296 protected JIoEndpoint endpoint; 297 298 299 302 protected String server = null; 303 304 305 307 308 311 public String getCompression() { 312 switch (compressionLevel) { 313 case 0: 314 return "off"; 315 case 1: 316 return "on"; 317 case 2: 318 return "force"; 319 } 320 return "off"; 321 } 322 323 324 327 public void setCompression(String compression) { 328 if (compression.equals("on")) { 329 this.compressionLevel = 1; 330 } else if (compression.equals("force")) { 331 this.compressionLevel = 2; 332 } else if (compression.equals("off")) { 333 this.compressionLevel = 0; 334 } else { 335 try { 336 compressionMinSize = Integer.parseInt(compression); 339 this.compressionLevel = 1; 340 } catch (Exception e) { 341 this.compressionLevel = 0; 342 } 343 } 344 } 345 346 349 public void setCompressionMinSize(int compressionMinSize) { 350 this.compressionMinSize = compressionMinSize; 351 } 352 353 354 361 public void addNoCompressionUserAgent(String userAgent) { 362 try { 363 Pattern nRule = Pattern.compile(userAgent); 364 noCompressionUserAgents = 365 addREArray(noCompressionUserAgents, nRule); 366 } catch (PatternSyntaxException pse) { 367 log.error(sm.getString("http11processor.regexp.error", userAgent), pse); 368 } 369 } 370 371 372 377 public void setNoCompressionUserAgents(Pattern [] noCompressionUserAgents) { 378 this.noCompressionUserAgents = noCompressionUserAgents; 379 } 380 381 382 388 public void setNoCompressionUserAgents(String noCompressionUserAgents) { 389 if (noCompressionUserAgents != null) { 390 StringTokenizer st = new StringTokenizer (noCompressionUserAgents, ","); 391 392 while (st.hasMoreTokens()) { 393 addNoCompressionUserAgent(st.nextToken().trim()); 394 } 395 } 396 } 397 398 405 public void addCompressableMimeType(String mimeType) { 406 compressableMimeTypes = 407 addStringArray(compressableMimeTypes, mimeType); 408 } 409 410 411 416 public void setCompressableMimeTypes(String [] compressableMimeTypes) { 417 this.compressableMimeTypes = compressableMimeTypes; 418 } 419 420 421 427 public void setCompressableMimeTypes(String compressableMimeTypes) { 428 if (compressableMimeTypes != null) { 429 StringTokenizer st = new StringTokenizer (compressableMimeTypes, ","); 430 431 while (st.hasMoreTokens()) { 432 addCompressableMimeType(st.nextToken().trim()); 433 } 434 } 435 } 436 437 438 441 public String [] findCompressableMimeTypes() { 442 return (compressableMimeTypes); 443 } 444 445 446 447 449 450 455 protected void addFilter(String className) { 456 try { 457 Class clazz = Class.forName(className); 458 Object obj = clazz.newInstance(); 459 if (obj instanceof InputFilter) { 460 inputBuffer.addFilter((InputFilter) obj); 461 } else if (obj instanceof OutputFilter) { 462 outputBuffer.addFilter((OutputFilter) obj); 463 } else { 464 log.warn(sm.getString("http11processor.filter.unknown", className)); 465 } 466 } catch (Exception e) { 467 log.error(sm.getString("http11processor.filter.error", className), e); 468 } 469 } 470 471 472 478 private String [] addStringArray(String sArray[], String value) { 479 String [] result = null; 480 if (sArray == null) { 481 result = new String [1]; 482 result[0] = value; 483 } 484 else { 485 result = new String [sArray.length + 1]; 486 for (int i = 0; i < sArray.length; i++) 487 result[i] = sArray[i]; 488 result[sArray.length] = value; 489 } 490 return result; 491 } 492 493 494 500 private Pattern [] addREArray(Pattern rArray[], Pattern value) { 501 Pattern [] result = null; 502 if (rArray == null) { 503 result = new Pattern [1]; 504 result[0] = value; 505 } 506 else { 507 result = new Pattern [rArray.length + 1]; 508 for (int i = 0; i < rArray.length; i++) 509 result[i] = rArray[i]; 510 result[rArray.length] = value; 511 } 512 return result; 513 } 514 515 516 522 private boolean inStringArray(String sArray[], String value) { 523 for (int i = 0; i < sArray.length; i++) { 524 if (sArray[i].equals(value)) { 525 return true; 526 } 527 } 528 return false; 529 } 530 531 532 538 private boolean startsWithStringArray(String sArray[], String value) { 539 if (value == null) 540 return false; 541 for (int i = 0; i < sArray.length; i++) { 542 if (value.startsWith(sArray[i])) { 543 return true; 544 } 545 } 546 return false; 547 } 548 549 550 557 public void addRestrictedUserAgent(String userAgent) { 558 try { 559 Pattern nRule = Pattern.compile(userAgent); 560 restrictedUserAgents = addREArray(restrictedUserAgents, nRule); 561 } catch (PatternSyntaxException pse) { 562 log.error(sm.getString("http11processor.regexp.error", userAgent), pse); 563 } 564 } 565 566 567 572 public void setRestrictedUserAgents(Pattern [] restrictedUserAgents) { 573 this.restrictedUserAgents = restrictedUserAgents; 574 } 575 576 577 583 public void setRestrictedUserAgents(String restrictedUserAgents) { 584 if (restrictedUserAgents != null) { 585 StringTokenizer st = 586 new StringTokenizer (restrictedUserAgents, ","); 587 while (st.hasMoreTokens()) { 588 addRestrictedUserAgent(st.nextToken().trim()); 589 } 590 } 591 } 592 593 594 597 public String [] findRestrictedUserAgents() { 598 String [] sarr = new String [restrictedUserAgents.length]; 599 600 for (int i = 0; i < restrictedUserAgents.length; i++) 601 sarr[i] = restrictedUserAgents[i].toString(); 602 603 return (sarr); 604 } 605 606 607 612 public void setMaxKeepAliveRequests(int mkar) { 613 maxKeepAliveRequests = mkar; 614 } 615 616 617 620 public int getMaxKeepAliveRequests() { 621 return maxKeepAliveRequests; 622 } 623 624 625 628 public void setMaxSavePostSize(int msps) { 629 maxSavePostSize = msps; 630 } 631 632 633 636 public int getMaxSavePostSize() { 637 return maxSavePostSize; 638 } 639 640 641 644 public void setSSLSupport(SSLSupport sslSupport) { 645 this.sslSupport = sslSupport; 646 } 647 648 649 652 public void setDisableUploadTimeout(boolean isDisabled) { 653 disableUploadTimeout = isDisabled; 654 } 655 656 659 public boolean getDisableUploadTimeout() { 660 return disableUploadTimeout; 661 } 662 663 666 public void setSocketBuffer(int socketBuffer) { 667 this.socketBuffer = socketBuffer; 668 outputBuffer.setSocketBuffer(socketBuffer); 669 } 670 671 674 public int getSocketBuffer() { 675 return socketBuffer; 676 } 677 678 681 public void setTimeout( int timeouts ) { 682 timeout = timeouts ; 683 } 684 685 688 public int getTimeout() { 689 return timeout; 690 } 691 692 693 696 public void setServer( String server ) { 697 if (server==null || server.equals("")) { 698 this.server = null; 699 } else { 700 this.server = server; 701 } 702 } 703 704 707 public String getServer() { 708 return server; 709 } 710 711 712 716 public Request getRequest() { 717 return request; 718 } 719 720 729 public void process(Socket socket) 730 throws IOException { 731 RequestInfo rp = request.getRequestProcessor(); 732 rp.setStage(org.apache.coyote.Constants.STAGE_PARSE); 733 734 remoteAddr = null; 736 remoteHost = null; 737 localAddr = null; 738 localName = null; 739 remotePort = -1; 740 localPort = -1; 741 742 this.socket = socket; 744 inputBuffer.setInputStream(socket.getInputStream()); 745 outputBuffer.setOutputStream(socket.getOutputStream()); 746 747 error = false; 749 keepAlive = true; 750 751 int keepAliveLeft = maxKeepAliveRequests; 752 int soTimeout = socket.getSoTimeout(); 753 int oldSoTimeout = soTimeout; 754 755 int threadRatio = (endpoint.getCurrentThreadsBusy() * 100) 756 / endpoint.getMaxThreads(); 757 if (threadRatio > 75) { 758 keepAliveLeft = 1; 759 } 760 761 if (soTimeout != oldSoTimeout) { 762 try { 763 socket.setSoTimeout(soTimeout); 764 } catch (Throwable t) { 765 log.debug(sm.getString("http11processor.socket.timeout"), t); 766 error = true; 767 } 768 } 769 770 boolean keptAlive = false; 771 772 while (started && !error && keepAlive) { 773 774 try { 776 if( !disableUploadTimeout && keptAlive && soTimeout > 0 ) { 777 socket.setSoTimeout(soTimeout); 778 } 779 inputBuffer.parseRequestLine(); 780 request.setStartTime(System.currentTimeMillis()); 781 keptAlive = true; 782 if (!disableUploadTimeout) { 783 socket.setSoTimeout(timeout); 784 } 785 inputBuffer.parseHeaders(); 786 } catch (IOException e) { 787 error = true; 788 break; 789 } catch (Throwable t) { 790 if (log.isDebugEnabled()) { 791 log.debug(sm.getString("http11processor.header.parse"), t); 792 } 793 response.setStatus(400); 795 error = true; 796 } 797 798 rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE); 800 try { 801 prepareRequest(); 802 } catch (Throwable t) { 803 if (log.isDebugEnabled()) { 804 log.debug(sm.getString("http11processor.request.prepare"), t); 805 } 806 response.setStatus(400); 808 error = true; 809 } 810 811 if (maxKeepAliveRequests > 0 && --keepAliveLeft == 0) 812 keepAlive = false; 813 814 if (!error) { 816 try { 817 rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE); 818 adapter.service(request, response); 819 if(keepAlive && !error) { error = response.getErrorException() != null || 826 statusDropsConnection(response.getStatus()); 827 } 828 829 } catch (InterruptedIOException e) { 830 error = true; 831 } catch (Throwable t) { 832 log.error(sm.getString("http11processor.request.process"), t); 833 response.setStatus(500); 835 error = true; 836 } 837 } 838 839 try { 841 rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT); 842 inputBuffer.endRequest(); 843 } catch (IOException e) { 844 error = true; 845 } catch (Throwable t) { 846 log.error(sm.getString("http11processor.request.finish"), t); 847 response.setStatus(500); 849 error = true; 850 } 851 try { 852 rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT); 853 outputBuffer.endRequest(); 854 } catch (IOException e) { 855 error = true; 856 } catch (Throwable t) { 857 log.error(sm.getString("http11processor.response.finish"), t); 858 error = true; 859 } 860 861 if (error) { 864 response.setStatus(500); 865 } 866 request.updateCounters(); 867 868 rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE); 869 870 inputBuffer.nextRequest(); 875 outputBuffer.nextRequest(); 876 877 } 878 879 rp.setStage(org.apache.coyote.Constants.STAGE_ENDED); 880 881 inputBuffer.recycle(); 883 outputBuffer.recycle(); 884 885 sslSupport = null; 887 } 888 889 890 892 893 899 public void action(ActionCode actionCode, Object param) { 900 901 if (actionCode == ActionCode.ACTION_COMMIT) { 902 904 if (response.isCommitted()) 905 return; 906 907 prepareResponse(); 909 try { 910 outputBuffer.commit(); 911 } catch (IOException e) { 912 error = true; 914 } 915 916 } else if (actionCode == ActionCode.ACTION_ACK) { 917 918 920 923 if ((response.isCommitted()) || !expectation) 924 return; 925 926 inputBuffer.setSwallowInput(true); 927 try { 928 outputBuffer.sendAck(); 929 } catch (IOException e) { 930 error = true; 932 } 933 934 } else if (actionCode == ActionCode.ACTION_CLIENT_FLUSH) { 935 936 try { 937 outputBuffer.flush(); 938 } catch (IOException e) { 939 error = true; 941 response.setErrorException(e); 942 } 943 944 } else if (actionCode == ActionCode.ACTION_CLOSE) { 945 947 950 try { 951 outputBuffer.endRequest(); 952 &
|