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.nio.channels.SelectionKey ; 24 import java.util.StringTokenizer ; 25 import java.util.regex.Pattern ; 26 import java.util.regex.PatternSyntaxException ; 27 28 import org.apache.coyote.ActionCode; 29 import org.apache.coyote.ActionHook; 30 import org.apache.coyote.Adapter; 31 import org.apache.coyote.Request; 32 import org.apache.coyote.RequestInfo; 33 import org.apache.coyote.Response; 34 import org.apache.coyote.http11.filters.BufferedInputFilter; 35 import org.apache.coyote.http11.filters.ChunkedInputFilter; 36 import org.apache.coyote.http11.filters.ChunkedOutputFilter; 37 import org.apache.coyote.http11.filters.GzipOutputFilter; 38 import org.apache.coyote.http11.filters.IdentityInputFilter; 39 import org.apache.coyote.http11.filters.IdentityOutputFilter; 40 import org.apache.coyote.http11.filters.SavedRequestInputFilter; 41 import org.apache.coyote.http11.filters.VoidInputFilter; 42 import org.apache.coyote.http11.filters.VoidOutputFilter; 43 import org.apache.tomcat.util.buf.Ascii; 44 import org.apache.tomcat.util.buf.ByteChunk; 45 import org.apache.tomcat.util.buf.HexUtils; 46 import org.apache.tomcat.util.buf.MessageBytes; 47 import org.apache.tomcat.util.http.FastHttpDateFormat; 48 import org.apache.tomcat.util.http.MimeHeaders; 49 import org.apache.tomcat.util.net.NioChannel; 50 import org.apache.tomcat.util.net.NioEndpoint; 51 import org.apache.tomcat.util.net.SSLSupport; 52 import org.apache.tomcat.util.net.SocketStatus; 53 import org.apache.tomcat.util.net.NioEndpoint.Handler.SocketState; 54 import org.apache.tomcat.util.res.StringManager; 55 56 57 63 public class Http11NioProcessor implements ActionHook { 64 65 66 69 protected static org.apache.commons.logging.Log log 70 = org.apache.commons.logging.LogFactory.getLog(Http11NioProcessor.class); 71 72 75 protected static StringManager sm = 76 StringManager.getManager(Constants.Package); 77 78 81 protected SSLSupport sslSupport; 82 83 85 86 public Http11NioProcessor(int rxBufSize, int txBufSize, int maxHttpHeaderSize, NioEndpoint endpoint) { 87 88 this.endpoint = endpoint; 89 90 request = new Request(); 91 int readTimeout = endpoint.getFirstReadTimeout(); 92 if (readTimeout == 0) { 93 readTimeout = 100; 94 } else if (readTimeout < 0) { 95 readTimeout = timeout; 96 } 98 inputBuffer = new InternalNioInputBuffer(request, maxHttpHeaderSize,readTimeout); 99 request.setInputBuffer(inputBuffer); 100 101 response = new Response(); 102 response.setHook(this); 103 outputBuffer = new InternalNioOutputBuffer(response, maxHttpHeaderSize,readTimeout); 104 response.setOutputBuffer(outputBuffer); 105 request.setResponse(response); 106 107 ssl = endpoint.isSSLEnabled(); 108 109 initializeFilters(); 110 111 int foo = HexUtils.DEC[0]; 113 114 FastHttpDateFormat.getCurrentDate(); 116 117 } 118 119 120 122 123 126 protected Adapter adapter = null; 127 128 129 132 protected Request request = null; 133 134 135 138 protected Response response = null; 139 140 141 144 protected InternalNioInputBuffer inputBuffer = null; 145 146 147 150 protected InternalNioOutputBuffer outputBuffer = null; 151 152 153 156 protected boolean error = false; 157 158 159 162 protected boolean keepAlive = true; 163 164 165 168 protected boolean http11 = true; 169 170 171 174 protected boolean http09 = false; 175 176 177 178 181 protected boolean comet = false; 182 183 189 protected boolean cometClose = false; 190 191 195 protected boolean contentDelimitation = true; 196 197 198 201 protected boolean expectation = false; 202 203 204 207 protected Pattern [] restrictedUserAgents = null; 208 209 210 213 protected int maxKeepAliveRequests = -1; 214 215 216 219 protected boolean ssl = false; 220 221 222 225 protected NioChannel socket = null; 226 227 228 231 protected String remoteAddr = null; 232 233 234 237 protected String remoteHost = null; 238 239 240 243 protected String localName = null; 244 245 246 247 250 protected int localPort = -1; 251 252 253 256 protected int remotePort = -1; 257 258 259 262 protected String localAddr = null; 263 264 265 268 protected int timeout = 300000; 269 270 271 274 protected boolean disableUploadTimeout = false; 275 276 277 280 protected int compressionLevel = 0; 281 282 283 286 protected int compressionMinSize = 2048; 287 288 289 292 protected int socketBuffer = -1; 293 294 295 298 protected int maxSavePostSize = 4 * 1024; 299 300 301 304 protected Pattern noCompressionUserAgents[] = null; 305 306 309 protected String [] compressableMimeTypes = 310 { "text/html", "text/xml", "text/plain" }; 311 312 313 316 protected char[] hostNameC = new char[0]; 317 318 319 322 protected NioEndpoint endpoint; 323 324 325 328 protected String server = null; 329 330 331 333 334 337 public String getCompression() { 338 switch (compressionLevel) { 339 case 0: 340 return "off"; 341 case 1: 342 return "on"; 343 case 2: 344 return "force"; 345 } 346 return "off"; 347 } 348 349 350 353 public void setCompression(String compression) { 354 if (compression.equals("on")) { 355 this.compressionLevel = 1; 356 } else if (compression.equals("force")) { 357 this.compressionLevel = 2; 358 } else if (compression.equals("off")) { 359 this.compressionLevel = 0; 360 } else { 361 try { 362 compressionMinSize = Integer.parseInt(compression); 365 this.compressionLevel = 1; 366 } catch (Exception e) { 367 this.compressionLevel = 0; 368 } 369 } 370 } 371 372 375 public void setCompressionMinSize(int compressionMinSize) { 376 this.compressionMinSize = compressionMinSize; 377 } 378 379 380 387 public void addNoCompressionUserAgent(String userAgent) { 388 try { 389 Pattern nRule = Pattern.compile(userAgent); 390 noCompressionUserAgents = 391 addREArray(noCompressionUserAgents, nRule); 392 } catch (PatternSyntaxException pse) { 393 log.error(sm.getString("http11processor.regexp.error", userAgent), pse); 394 } 395 } 396 397 398 403 public void setNoCompressionUserAgents(Pattern [] noCompressionUserAgents) { 404 this.noCompressionUserAgents = noCompressionUserAgents; 405 } 406 407 408 414 public void setNoCompressionUserAgents(String noCompressionUserAgents) { 415 if (noCompressionUserAgents != null) { 416 StringTokenizer st = new StringTokenizer (noCompressionUserAgents, ","); 417 418 while (st.hasMoreTokens()) { 419 addNoCompressionUserAgent(st.nextToken().trim()); 420 } 421 } 422 } 423 424 431 public void addCompressableMimeType(String mimeType) { 432 compressableMimeTypes = 433 addStringArray(compressableMimeTypes, mimeType); 434 } 435 436 437 442 public void setCompressableMimeTypes(String [] compressableMimeTypes) { 443 this.compressableMimeTypes = compressableMimeTypes; 444 } 445 446 447 453 public void setCompressableMimeTypes(String compressableMimeTypes) { 454 if (compressableMimeTypes != null) { 455 StringTokenizer st = new StringTokenizer (compressableMimeTypes, ","); 456 457 while (st.hasMoreTokens()) { 458 addCompressableMimeType(st.nextToken().trim()); 459 } 460 } 461 } 462 463 464 467 public String [] findCompressableMimeTypes() { 468 return (compressableMimeTypes); 469 } 470 471 472 473 475 476 481 protected void addFilter(String className) { 482 try { 483 Class clazz = Class.forName(className); 484 Object obj = clazz.newInstance(); 485 if (obj instanceof InputFilter) { 486 inputBuffer.addFilter((InputFilter) obj); 487 } else if (obj instanceof OutputFilter) { 488 outputBuffer.addFilter((OutputFilter) obj); 489 } else { 490 log.warn(sm.getString("http11processor.filter.unknown", className)); 491 } 492 } catch (Exception e) { 493 log.error(sm.getString("http11processor.filter.error", className), e); 494 } 495 } 496 497 498 504 private String [] addStringArray(String sArray[], String value) { 505 String [] result = null; 506 if (sArray == null) { 507 result = new String [1]; 508 result[0] = value; 509 } 510 else { 511 result = new String [sArray.length + 1]; 512 for (int i = 0; i < sArray.length; i++) 513 result[i] = sArray[i]; 514 result[sArray.length] = value; 515 } 516 return result; 517 } 518 519 520 526 private Pattern [] addREArray(Pattern rArray[], Pattern value) { 527 Pattern [] result = null; 528 if (rArray == null) { 529 result = new Pattern [1]; 530 result[0] = value; 531 } 532 else { 533 result = new Pattern [rArray.length + 1]; 534 for (int i = 0; i < rArray.length; i++) 535 result[i] = rArray[i]; 536 result[rArray.length] = value; 537 } 538 return result; 539 } 540 541 542 548 private boolean inStringArray(String sArray[], String value) { 549 for (int i = 0; i < sArray.length; i++) { 550 if (sArray[i].equals(value)) { 551 return true; 552 } 553 } 554 return false; 555 } 556 557 558 564 private boolean startsWithStringArray(String sArray[], String value) { 565 if (value == null) 566 return false; 567 for (int i = 0; i < sArray.length; i++) { 568 if (value.startsWith(sArray[i])) { 569 return true; 570 } 571 } 572 return false; 573 } 574 575 576 583 public void addRestrictedUserAgent(String userAgent) { 584 try { 585 Pattern nRule = Pattern.compile(userAgent); 586 restrictedUserAgents = addREArray(restrictedUserAgents, nRule); 587 } catch (PatternSyntaxException pse) { 588 log.error(sm.getString("http11processor.regexp.error", userAgent), pse); 589 } 590 } 591 592 593 598 public void setRestrictedUserAgents(Pattern [] restrictedUserAgents) { 599 this.restrictedUserAgents = restrictedUserAgents; 600 } 601 602 603 609 public void setRestrictedUserAgents(String restrictedUserAgents) { 610 if (restrictedUserAgents != null) { 611 StringTokenizer st = 612 new StringTokenizer (restrictedUserAgents, ","); 613 while (st.hasMoreTokens()) { 614 addRestrictedUserAgent(st.nextToken().trim()); 615 } 616 } 617 } 618 619 620 623 public String [] findRestrictedUserAgents() { 624 String [] sarr = new String [restrictedUserAgents.length]; 625 626 for (int i = 0; i < restrictedUserAgents.length; i++) 627 sarr[i] = restrictedUserAgents[i].toString(); 628 629 return (sarr); 630 } 631 632 633 638 public void setMaxKeepAliveRequests(int mkar) { 639 maxKeepAliveRequests = mkar; 640 } 641 642 643 646 public int getMaxKeepAliveRequests() { 647 return maxKeepAliveRequests; 648 } 649 650 651 654 public void setMaxSavePostSize(int msps) { 655 maxSavePostSize = msps; 656 } 657 658 659 662 public int getMaxSavePostSize() { 663 return maxSavePostSize; 664 } 665 666 667 670 public void setDisableUploadTimeout(boolean isDisabled) { 671 disableUploadTimeout = isDisabled; 672 } 673 674 677 public boolean getDisableUploadTimeout() { 678 return disableUploadTimeout; 679 } 680 681 684 public void setSocketBuffer(int socketBuffer) { 685 this.socketBuffer = socketBuffer; 686 outputBuffer.setSocketBuffer(socketBuffer); 687 } 688 689 692 public int getSocketBuffer() { 693 return socketBuffer; 694 } 695 696 699 public void setTimeout( int timeouts ) { 700 timeout = timeouts ; 701 } 702 703 706 public int getTimeout() { 707 return timeout; 708 } 709 710 711 714 public void setServer( String server ) { 715 if (server==null || server.equals("")) { 716 this.server = null; 717 } else { 718 this.server = server; 719 } 720 } 721 722 725 public String getServer() { 726 return server; 727 } 728 729 730 734 public Request getRequest() { 735 return request; 736 } 737 738 744 public SocketState event(SocketStatus status) 745 throws IOException { 746 747 RequestInfo rp = request.getRequestProcessor(); 748 749 try { 750 rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE); 751 error = !adapter.event(request, response, status); 752 SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector()); 753 if ( key != null ) { 754 NioEndpoint.KeyAttachment attach = (NioEndpoint.KeyAttachment) key.attachment(); 755 if ( attach!=null ) { 756 attach.setComet(comet); 757 Integer comettimeout = (Integer )request.getAttribute("org.apache.tomcat.comet.timeout"); 758 if ( comettimeout != null ) attach.setTimeout(comettimeout.longValue()); 759 } 760 } 761 762 } catch (InterruptedIOException e) { 763 error = true; 764 } catch (Throwable t) { 765 log.error(sm.getString("http11processor.request.process"), t); 766 response.setStatus(500); 768 error = true; 769 } 770 771 rp.setStage(org.apache.coyote.Constants.STAGE_ENDED); 772 773 if (error) { 774 recycle(); 775 return SocketState.CLOSED; 776 } else if (!comet) { 777 socket.getPoller().add(socket); 778 recycle(); 779 return SocketState.OPEN; 780 } else { 781 socket.getPoller().add(socket); 782 return SocketState.LONG; 783 } 784 } 785 786 792 public SocketState process(NioChannel socket) 793 throws IOException { 794 RequestInfo rp = request.getRequestProcessor(); 795 rp.setStage(org.apache.coyote.Constants.STAGE_PARSE); 796 797 remoteAddr = null; 799 remoteHost = null; 800 localAddr = null; 801 localName = null; 802 remotePort = -1; 803 localPort = -1; 804 805 this.socket = socket; 807 inputBuffer.setSocket(socket); 808 outputBuffer.setSocket(socket); 809 inputBuffer.setSelectorPool(endpoint.getSelectorPool()); 810 outputBuffer.setSelectorPool(endpoint.getSelectorPool()); 811 812 error = false; 814 keepAlive = true; 815 816 int keepAliveLeft = maxKeepAliveRequests; 817 long soTimeout = endpoint.getSoTimeout(); 818 819 int limit = 0; 820 if (endpoint.getFirstReadTimeout() > 0 || endpoint.getFirstReadTimeout() < -1) { 821 limit = endpoint.getMaxThreads() / 2; 822 } 823 824 boolean keptAlive = false; 825 boolean openSocket = false; 826 boolean recycle = true; 827 while (!error && keepAlive && !comet) { 828 829 try { 831 if( !disableUploadTimeout && keptAlive && soTimeout > 0 ) { 832 socket.getIOChannel().socket().setSoTimeout((int)soTimeout); 833 inputBuffer.readTimeout = soTimeout; 834 } 835 if (!inputBuffer.parseRequestLine(keptAlive && (endpoint.getCurrentThreadsBusy() > limit))) { 836 openSocket = true; 840 socket.getPoller().add(socket); 842 break; 843 } 844 keptAlive = true; 845 if ( !inputBuffer.parseHeaders() ) { 846 openSocket = true; 847 socket.getPoller().add(socket); 848 recycle = false; 849 break; 850 } 851 request.setStartTime(System.currentTimeMillis()); 852 if (!disableUploadTimeout) { socket.getIOChannel().socket().setSoTimeout((int)timeout); 854 inputBuffer.readTimeout = soTimeout; 855 } 856 } catch (IOException e) { 857 error = true; 858 break; 859 } catch (Throwable t) { 860 if (log.isDebugEnabled()) { 861 log.debug(sm.getString("http11processor.header.parse"), t); 862 } 863 response.setStatus(400); 865 error = true; 866 } 867 868 rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE); 870 try { 871 prepareRequest(); 872 } catch (Throwable t) { 873 if (log.isDebugEnabled()) { 874 log.debug(sm.getString("http11processor.request.prepare"), t); 875 } 876 response.setStatus(400); 878 error = true; 879 } 880 881 if (maxKeepAliveRequests > 0 && --keepAliveLeft == 0) 882 keepAlive = false; 883 884 if (!error) { 886 try { 887 rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE); 888 adapter.service(request, response); 889 if(keepAlive && !error) { error = response.getErrorException() != null || 896 statusDropsConnection(response.getStatus()); 897 } 898 SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector()); 900 if (key != null) { 901 NioEndpoint.KeyAttachment attach = (NioEndpoint.KeyAttachment) key.attachment(); 902 if (attach != null) { 903 attach.setComet(comet); 904 Integer comettimeout = (Integer ) request.getAttribute("org.apache.tomcat.comet.timeout"); 905 if (comettimeout != null) attach.setTimeout(comettimeout.longValue()); 906 } 907 } 908 } catch (InterruptedIOException e) { 909 error = true; 910 } catch (Throwable t) { 911 log.error(sm.getString("http11processor.request.process"), t); 912 response.setStatus(500); 914 error = true; 915 } 916 } 917 918 if (!comet) { 920 endRequest(); 921 } 922 923 if (error) { 926 response.setStatus(500); 927 } 928 request.updateCounters(); 929 930 rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE); 931 932 } 933 934 rp.setStage(org.apache.coyote.Constants.STAGE_ENDED); 935 936 if (comet) { 937 if (error) { 938 recycle(); 939 return SocketState.CLOSED; 940 } else { 941 return SocketState.LONG; 942 } 943 } else { 944 if ( recycle ) recycle(); 945 return (openSocket) ? SocketState.OPEN : SocketState.CLOSED; 946 } 947 948 } 949 950 951 public void endRequest() { 952 953 try { 955 inputBuffer.endRequest(); 956 } catch (IOException e) { 957 error = true; 958 } catch (Throwable t) { 959 log.error(sm.getString("http11processor.request.finish"), t); 960 response.setStatus(500); 962 error = true; 963 } 964 try { 965 outputBuffer.endRequest(); 966 } catch (IOException e) { 967 error = true; 968 } catch (Throwable t) { 969 log.error(sm.getString("http11processor.response.finish"), t); 970 error = true; 971 } 972 973 inputBuffer.nextRequest(); 975 outputBuffer.nextRequest(); 976 977 } 978 979 980 public void recycle() { 981 inputBuffer.recycle(); 982 outputBuffer.recycle(); 983 this.socket = null; 984 this.cometClose = false; 985 this.comet = false; 986 } 987 988 989 991 992 998 public void action(ActionCode actionCode, Object param) { 999 1000 if (actionCode == ActionCode.ACTION_COMMIT) { 1001 1003 if (response.isCommitted()) 1004 return; 1005 1006 1008 try { 1009 prepareResponse(); 1010 outputBuffer.commit(); 1011 } catch (IOException e) { 1012 error = true; 1014 } 1015 1016 } else if (actionCode == ActionCode.ACTION_ACK) { 1017 1018 1020 1023 if ((response.isCommitted()) || !expectation) 1024 return; 1025 1026 inputBuffer.setSwallowInput(true); 1027 try { 1028 outputBuffer.sendAck(); 1029 } catch (IOException e) { 1030 error = true; 1032 } 1033 1034 } else if (actionCode == ActionCode.ACTION_CLIENT_FLUSH) { 1035 1036 try { 1037 outputBuffer.flush(); 1038 } catch (IOException e) { 1039 error = true; 1041 response.setErrorException(e); 1042 } 1043 1044 } else if (actionCode == ActionCode.ACTION_CLOSE) { 1045 1047 1050 comet = false; 1051 cometClose = true; 1052 SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector()); 1053 if ( key != null ) { 1054 NioEndpoint.KeyAttachment attach = (NioEndpoint.KeyAttachment) key.attachment(); 1055 if ( attach!=null && attach.getComet()) { 1056 request.getAttributes().remove("org.apache.tomcat.comet.timeout"); 1059 attach.setError(true); 1060 attach.setComet(false); 1061 } 1062 } 1063 1064 try { 1065 outputBuffer.endRequest(); 1066 } catch (IOException e) { 1067 error = true; 1069 } 1070 1071 } else if (actionCode == ActionCode.ACTION_RESET) { 1072 1073 1075 1077 outputBuffer.reset(); 1078 1079 } else if (actionCode == ActionCode.ACTION_CUSTOM) { 1080 1081 1083 } else if (actionCode == ActionCode.ACTION_REQ_HOST_ADDR_ATTRIBUTE) { 1084 1085 if ((remoteAddr == null) && (socket != null)) { 1087 InetAddress inetAddr = socket.getIOChannel().socket().getInetAddress(); 1088 if (inetAddr != null) { 1089 remoteAddr = inetAddr.getHostAddress(); 1090 } 1091 } 1092 request.remoteAddr().setString(remoteAddr); 1093 1094 } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_NAME_ATTRIBUTE) { 1095 1096 if ((localName == null) && (socket != null)) { 1098 InetAddress inetAddr = socket.getIOChannel().socket().getLocalAddress(); 1099 if (inetAddr != null) { 1100 localName = inetAddr.getHostName(); 1101 } 1102 } 1103 request.localName().setString(localName); 1104 1105 } else if (actionCode == ActionCode.ACTION_REQ_HOST_ATTRIBUTE) { 1106 1107 if ((remoteHost == null) && (socket != null)) { 1109 InetAddress inetAddr = socket.getIOChannel().socket().getInetAddress(); 1110 if (inetAddr != null) { 1111 remoteHost = inetAddr.getHostName(); 1112 } 1113 if(remoteHost == null) { 1114 if(remoteAddr != null) { 1115 remoteHost = remoteAddr; 1116 } else { request.remoteHost().recycle(); 1118 } 1119 } 1120 } 1121 request.remoteHost().setString(remoteHost); 1122 1123 } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_ADDR_ATTRIBUTE) { 1124 1125 if (localAddr == null) 1126 localAddr = socket.getIOChannel().socket().getLocalAddress().getHostAddress(); 1127 1128 request.localAddr().setString(localAddr); 1129 1130 } else if (actionCode == ActionCode.ACTION_REQ_REMOTEPORT_ATTRIBUTE) { 1131 1132 if ((remotePort == -1 ) && (socket !=null)) { 1133 remotePort = socket.getIOChannel().socket().getPort(); 1134 } 1135 request.setRemotePort(remotePort); 1136 1137 } else if (actionCode == ActionCode.ACTION_REQ_LOCALPORT_ATTRIBUTE) { 1138 1139 if ((localPort == -1 ) && (socket !=null)) { 1140 localPort = socket.getIOChannel().socket().getLocalPort(); 1141 } 1142 request.setLocalPort(localPort); 1143 1144 } else if (actionCode == ActionCode.ACTION_REQ_SSL_ATTRIBUTE ) { 1145 1146 try { 1147 if (sslSupport != null) { 1148 Object sslO = sslSupport.getCipherSuite(); 1149 if (sslO != null) 1150 request.setAttribute 1151 (SSLSupport.CIPHER_SUITE_KEY, sslO); 1152 sslO = sslSupport.getPeerCertificateChain(false); 1153 if (sslO != null) 1154 request.setAttribute 1155 (SSLSupport.CERTIFICATE_KEY, sslO); 1156 sslO = sslSupport.getKeySize(); 1157 if (sslO != null) 1158 request.setAttribute 1159 (SSLSupport.KEY_SIZE_KEY, sslO); 1160 sslO = sslSupport.getSessionId(); 1161 if (sslO != null) 1162 request.setAttribute 1163 (SSLSupport.SESSION_ID_KEY, sslO); 1164 } 1165 } catch (Exception e) { 1166 log.warn(sm.getString("http11processor.socket.ssl"), e); 1167 } 1168 1169 } else if (actionCode == ActionCode.ACTION_REQ_SSL_CERTIFICATE) { 1170 1171 if( sslSupport != null) { 1172 1176 InputFilter[] inputFilters = inputBuffer.getFilters(); 1177 ((BufferedInputFilter) inputFilters[Constants.BUFFERED_FILTER]) 1178 .setLimit(maxSavePostSize); 1179 inputBuffer.addActiveFilter 1180 (inputFilters[Constants.BUFFERED_FILTER]); 1181 try { 1182 Object sslO = sslSupport.getPeerCertificateChain(true); 1183 if( sslO != null) { 1184 request.setAttribute 1185 (SSLSupport.CERTIFICATE_KEY, sslO); 1186 } 1187 } catch (Exception e) { 1188 log.warn(sm.getString("http11processor.socket.ssl"), e); 1189 } 1190 } 1191 1192 } else if (actionCode == ActionCode.ACTION_REQ_SET_BODY_REPLAY) { 1193 ByteChunk body = (ByteChunk) param; 1194 1195 InputFilter savedBody = new SavedRequestInputFilter(body); 1196 savedBody.setRequest(request); 1197 1198 InternalNioInputBuffer internalBuffer = (InternalNioInputBuffer) 1199 request.getInputBuffer(); 1200 internalBuffer.addActiveFilter(savedBody); 1201 1202 } else if (actionCode == ActionCode.ACTION_COMET_BEGIN) { 1203 comet = true; 1204 } else if (actionCode == ActionCode.ACTION_COMET_END) { 1205 comet = false; 1206 } 1207 1208 } 1209 1210 1211 1213 1214 1219 public void setAdapter(Adapter adapter) { 1220 this.adapter = adapter; 1221 } 1222 1223 public void setSslSupport(SSLSupport sslSupport) { 1224 this.sslSupport = sslSupport; 1225 } 1226 1227 1232 public Adapter getAdapter() { 1233 return adapter; 1234 } 1235 1236 public SSLSupport getSslSupport() { 1237 return sslSupport; 1238 } 1239 1240 1242 1243 1246 protected void prepareRequest() { 1247 1248 http11 = true; 1249 http09 = false; 1250 contentDelimitation = false; 1251 expectation = false; 1252 if (ssl) { 1253 request.scheme().setString("https"); 1254 } 1255 MessageBytes protocolMB = request.protocol(); 1256 if (protocolMB.equals(Constants.HTTP_11)) { 1257 http11 = true; 1258 protocolMB.setString(Constants.HTTP_11); 1259 } else if (protocolMB.equals(Constants.HTTP_10)) { 1260 http11 = false; 1261 keepAlive = false; 1262 protocolMB.setString(Constants.HTTP_10); 1263 } else if (protocolMB.equals("")) { 1264 http09 = true; 1266 http11 = false; 1267 keepAlive = false; 1268 } else { 1269 http11 = false; 1271 error = true; 1272 response.setStatus(505); 1274 } 1275 1276 MessageBytes methodMB = request.method(); 1277 if (methodMB.equals(Constants.GET)) { 1278 methodMB.setString(Constants.GET); 1279 } else if (methodMB.equals(Constants.POST)) { 1280 methodMB.setString(Constants.POST); 1281 } 1282 1283 MimeHeaders headers = request.getMimeHeaders(); 1284 1285 MessageBytes connectionValueMB = headers.getValue("connection"); 1287 if (connectionValueMB != null) { 1288 ByteChunk connectionValueBC = connectionValueMB.getByteChunk(); 1289 if (findBytes(connectionValueBC, Constants.CLOSE_BYTES) != -1) { 1290 keepAlive = false; 1291 } else if (findBytes(connectionValueBC, 1292 Constants.KEEPALIVE_BYTES) != -1) { 1293 keepAlive = true; 1294 } 1295 } 1296 1297 MessageBytes expectMB = null; 1298 if (http11) 1299 expectMB = headers.getValue("expect"); 1300 if ((expectMB != null) 1301 && (expectMB.indexOfIgnoreCase("100-continue", 0) != -1)) { 1302 inputBuffer.setSwallowInput(false); 1303 expectation = true; 1304 } 1305 1306 if ((restrictedUserAgents != null) && ((http11) || (keepAlive))) { 1308 MessageBytes userAgentValueMB = headers.getValue("user-agent"); 1309 if(userAgentValueMB != null) { 1312 String userAgentValue = userAgentValueMB.toString(); 1313 for (int i = 0; i < restrictedUserAgents.length; i++) { 1314 if (restrictedUserAgents[i].matcher(userAgentValue).matches()) { 1315 http11 = false; 1316 keepAlive = false; 1317 break; 1318 } 1319 } 1320 } 1321 } 1322 1323 ByteChunk uriBC = request.requestURI().getByteChunk(); 1325 if (uriBC.startsWithIgnoreCase("http", 0)) { 1326 1327 int pos = uriBC.indexOf("://", 0, 3, 4); 1328 int uriBCStart = uriBC.getStart(); 1329 int slashPos = -1; 1330 if (pos != -1) { 1331 byte[] uriB = uriBC.getBytes(); 1332 slashPos = uriBC.indexOf('/', pos + 3); 1333 if (slashPos == -1) { 1334 slashPos = uriBC.getLength(); 1335 request.requestURI().setBytes 1337 (uriB, uriBCStart + pos + 1, 1); 1338 } else { 1339 request.requestURI().setBytes 1340 (uriB, uriBCStart + slashPos, 1341 uriBC.getLength() - slashPos); 1342 } 1343 MessageBytes hostMB = headers.setValue("host"); 1344 hostMB.setBytes(uriB, uriBCStart + pos + 3, 1345 slashPos - pos - 3); 1346 } 1347 1348 } 1349 1350 InputFilter[] inputFilters = inputBuffer.getFilters(); 1352 1353 MessageBytes transferEncodingValueMB = null; 1355 if (http11) 1356 transferEncodingValueMB = headers.getValue("transfer-encoding"); 1357 if (transferEncodingValueMB != null) { 1358 String transferEncodingValue = transferEncodingValueMB.toString(); 1359 int startPos = 0; 1361 int commaPos = transferEncodingValue.indexOf(','); 1362 String encodingName = null; 1363 while (commaPos != -1) { 1364 encodingName = transferEncodingValue.substring 1365 (startPos, commaPos).toLowerCase().trim(); 1366 if (!addInputFilter(inputFilters, encodingName)) { 1367 error = true; 1369 response.setStatus(501); 1371 } 1372 startPos = commaPos + 1; 1373 commaPos = transferEncodingValue.indexOf(',', startPos); 1374 } 1375 encodingName = transferEncodingValue.substring(startPos) 1376 .toLowerCase().trim(); 1377 if (!addInputFilter(inputFilters, encodingName)) { 1378 error = true; 1380 response.setStatus(501); 1382 } 1383 } 1384 1385 long contentLength = request.getContentLengthLong(); 1387 if (contentLength >= 0 && !contentDelimitation) { 1388 inputBuffer.addActiveFilter 1389 (inputFilters[Constants.IDENTITY_FILTER]); 1390 contentDelimitation = true; 1391 } 1392 1393 MessageBytes valueMB = headers.getValue("host"); 1394 1395 if (http11 && (valueMB == null)) { 1397 error = true; 1398 response.setStatus(400); 1400 } 1401 1402 parseHost(valueMB); 1403 1404 if (!contentDelimitation) { 1405 inputBuffer.addActiveFilter 1409 (inputFilters[Constants.VOID_FILTER]); 1410 contentDelimitation = true; 1411 } 1412 1413 request.setAttribute("org.apache.tomcat.comet.support", Boolean.TRUE); 1415 request.setAttribute("org.apache.tomcat.comet.timeout.support", Boolean.TRUE); 1417 1418 } 1419 1420 1421 1424 public void parseHost(MessageBytes valueMB) { 1425 1426 if (valueMB == null || valueMB.isNull()) { 1427 request.setServerPort(endpoint.getPort()); 1431 return; 1432 } 1433 1434 ByteChunk valueBC = valueMB.getByteChunk(); 1435 byte[] valueB = valueBC.getBytes(); 1436 int valueL = valueBC.getLength(); 1437 int valueS = valueBC.getStart(); 1438 int colonPos = -1; 1439 if (hostNameC.length < valueL) { 1440 hostNameC = new char[valueL]; 1441 } 1442 1443 boolean ipv6 = (valueB[valueS] == '['); 1444 boolean bracketClosed = false; 1445 for (int i = 0; i < valueL; i++) { 1446 char b = (char) valueB[i + valueS]; 1447 hostNameC[i] = b; 1448 if (b == ']') { 1449 bracketClosed = true; 1450 } else if (b == ':') { 1451 if (!ipv6 || bracketClosed) { 1452 colonPos = i; 1453 break; 1454 } 1455 } 1456 } 1457 1458 if (colonPos < 0) { 1459 if (!ssl) { 1460 request.setServerPort(80); 1462 } else { 1463 request.setServerPort(443); 1465 } 1466 request.serverName().setChars(hostNameC, 0, valueL); 1467 } else { 1468 1469 request.serverName().setChars(hostNameC, 0, colonPos); 1470 1471 int port = 0; 1472 int mult = 1; 1473 for (int i = valueL - 1; i > colonPos; i--) { 1474 int charValue = HexUtils.DEC[(int) valueB[i + valueS]]; 1475 if (charValue == -1) { 1476 error = true; 1478 response.setStatus(400); 1480 break; 1481 } 1482 port = port + (charValue * mult); 1483 mult = 10 * mult; 1484 } 1485 request.setServerPort(port); 1486 1487 } 1488 1489 } 1490 1491 1492 1495 private boolean isCompressable() { 1496 1497 1500 1504 MessageBytes acceptEncodingMB = 1506 request.getMimeHeaders().getValue("accept-encoding"); 1507 1508 if ((acceptEncodingMB == null) 1509 || (acceptEncodingMB.indexOf("gzip") == -1)) 1510 return false; 1511 1512 MessageBytes contentEncodingMB = 1514 response.getMimeHeaders().getValue("Content-Encoding"); 1515 1516 if ((contentEncodingMB != null) 1517 && (contentEncodingMB.indexOf("gzip") != -1)) 1518 return false; 1519 1520 if (compressionLevel == 2) 1522 return true; 1523 1524 if (noCompressionUserAgents != null) { 1526 MessageBytes userAgentValueMB = 1527 request.getMimeHeaders().getValue("user-agent"); 1528 if(userAgentValueMB != null) { 1529 String userAgentValue = userAgentValueMB.toString(); 1530 1531 for (int i = 0; i < noCompressionUserAgents.length; i++) 1533 if (noCompressionUserAgents[i].matcher(userAgentValue).matches()) 1534 return false; 1535 } 1536 } 1537 1538 long contentLength = response.getContentLengthLong(); 1540 if ((contentLength == -1) 1541 || (contentLength > compressionMinSize)) { 1542 if (compressableMimeTypes != null) { 1544 return (startsWithStringArray(compressableMimeTypes, 1545 response.getContentType())); 1546 } 1547 } 1548 1549 return false; 1550 } 1551 1552 1553 1557 protected void prepareResponse() throws IOException { 1558 1559 boolean entityBody = true; 1560 contentDelimitation = false; 1561 1562 OutputFilter[] outputFilters = outputBuffer.getFilters(); 1563 1564 if (http09 == true) { 1565 outputBuffer.addActiveFilter 1567 (outputFilters[Constants.IDENTITY_FILTER]); 1568 return; 1569 } 1570 1571 int statusCode = response.getStatus(); 1572 if ((statusCode == 204) || (statusCode == 205) 1573 || (statusCode == 304)) { 1574 outputBuffer.addActiveFilter 1576 (outputFilters[Constants.VOID_FILTER]); 1577 entityBody = false; 1578 contentDelimitation = true; 1579 } 1580 1581 MessageBytes methodMB = request.method(); 1582 if (methodMB.equals("HEAD")) { 1583 outputBuffer.addActiveFilter 1585 (outputFilters[Constants.VOID_FILTER]); 1586 contentDelimitation = true; 1587 } 1588 1589 1590 boolean useCompression = false; 1592 if (entityBody && (compressionLevel > 0)) { 1593 useCompression = isCompressable(); 1594 if (useCompression) { 1596 response.setContentLength(-1); 1597 } 1598 } 1599 1600 MimeHeaders headers = response.getMimeHeaders(); 1601 if (!entityBody) { 1602 response.setContentLength(-1); 1603 } else { 1604 String contentType = response.getContentType(); 1605 if (contentType != null) { 1606 headers.setValue("Content-Type").setString(contentType); 1607 } 1608 String contentLanguage = response.getContentLanguage(); 1609 if (contentLanguage != null) { 1610 headers.setValue("Content-Language") 1611 .setString(contentLanguage); 1612 } 1613 } 1614 1615 long contentLength = response.getContentLengthLong(); 1616 if (contentLength != -1) { 1617 headers.setValue("Content-Length").setLong(contentLength); 1618 outputBuffer.addActiveFilter 1619 (outputFilters[Constants.IDENTITY_FILTER]); 1620 contentDelimitation = true; 1621 } else { 1622 if (entityBody && http11 && keepAlive) { 1623 outputBuffer.addActiveFilter 1624 (outputFilters[Constants.CHUNKED_FILTER]); 1625 contentDelimitation = true; 1626 headers.addValue(Constants.TRANSFERENCODING).setString(Constants.CHUNKED); 1627 } else { 1628 outputBuffer.addActiveFilter 1629 (outputFilters[Constants.IDENTITY_FILTER]); 1630 } 1631 } 1632 1633 if (useCompression) { 1634 outputBuffer.addActiveFilter(outputFilters[Constants.GZIP_FILTER]); 1635 headers.setValue("Content-Encoding").setString("gzip"); 1636 headers.setValue("Vary").setString("Accept-Encoding"); 1638 } 1639 1640 headers.setValue("Date").setString(FastHttpDateFormat.getCurrentDate()); 1642 1643 1645 if ((entityBody) && (!contentDelimitation)) { 1646 keepAlive = false; 1649 } 1650 1651 keepAlive = keepAlive && !statusDropsConnection(statusCode); 1654 if (!keepAlive) { 1655 headers.addValue(Constants.CONNECTION).setString(Constants.CLOSE); 1656 } else if (!http11 && !error) { 1657 headers.addValue(Constants.CONNECTION).setString(Constants.KEEPALIVE); 1658 } 1659 1660 outputBuffer.sendStatus(); 1662 1663 if (server != null) { 1665 headers.setValue("Server").setString(server); 1666 } else { 1667 outputBuffer.write(Constants.SERVER_BYTES); 1668 } 1669 1670 int size = headers.size(); 1671 for (int i = 0; i < size; i++) { 1672 outputBuffer.sendHeader(headers.getName(i), headers.getValue(i)); 1673 } 1674 outputBuffer.endHeaders(); 1675 1676 } 1677 1678 1679 1682 protected void initializeFilters() { 1683 1684 inputBuffer.addFilter(new IdentityInputFilter()); 1686 outputBuffer.addFilter(new IdentityOutputFilter()); 1687 1688 inputBuffer.addFilter(new ChunkedInputFilter()); 1690 outputBuffer.addFilter(new ChunkedOutputFilter()); 1691 1692 inputBuffer.addFilter(new VoidInputFilter()); 1694 outputBuffer.addFilter(new VoidOutputFilter()); 1695 1696 inputBuffer.addFilter(new BufferedInputFilter()); 1698 1699 outputBuffer.addFilter(new GzipOutputFilter()); 1702 1703 } 1704 1705 1706 1712 protected boolean addInputFilter(InputFilter[] inputFilters, 1713 String encodingName) { 1714 if (encodingName.equals("identity")) { 1715 } else if (encodingName.equals("chunked")) { 1717 inputBuffer.addActiveFilter 1718 (inputFilters[Constants.CHUNKED_FILTER]); 1719 contentDelimitation = true; 1720 } else { 1721 for (int i = 2; i < inputFilters.length; i++) { 1722 if (inputFilters[i].getEncodingName() 1723 .toString().equals(encodingName)) { 1724 inputBuffer.addActiveFilter(inputFilters[i]); 1725 return true; 1726 } 1727 } 1728 return false; 1729 } 1730 return true; 1731 } 1732 1733 1734 1738 protected int findBytes(ByteChunk bc, byte[] b) { 1739 1740 byte first = b[0]; 1741 byte[] buff = bc.getBuffer(); 1742 int start = bc.getStart(); 1743 int end = bc.getEnd(); 1744 1745 int srcEnd = b.length; 1747 1748 for (int i = start; i <= (end - srcEnd); i++) { 1749 if (Ascii.toLower(buff[i]) != first) continue; 1750 int myPos = i+1; 1752 for (int srcPos = 1; srcPos < srcEnd; ) { 1753 if (Ascii.toLower(buff[myPos++]) != b[srcPos++]) 1754 break; 1755 if (srcPos == srcEnd) return i - start; } 1757 } 1758 return -1; 1759 1760 } 1761 1762 1766 protected boolean statusDropsConnection(int status) { 1767 return status == 400 || 1768 status == 408 || 1769 status == 411 || 1770 status == 413 || 1771 status == 414 || 1772 status == 500 || 1773 status == 503 || 1774 status == 501 ; 1775 } 1776 1777} 1778 | Popular Tags |