1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */

17 package org.apache.coyote.http11;
18
19 import java.io.IOException;
20 import java.io.InterruptedIOException;
21 import java.nio.ByteBuffer;
22 import java.util.ArrayList;
23 import java.util.HashSet;
24 import java.util.List;
25 import java.util.Set;
26 import java.util.regex.Pattern;
27
28 import javax.servlet.http.HttpServletResponse;
29
30 import org.apache.coyote.AbstractProcessor;
31 import org.apache.coyote.ActionCode;
32 import org.apache.coyote.Adapter;
33 import org.apache.coyote.ErrorState;
34 import org.apache.coyote.Request;
35 import org.apache.coyote.RequestInfo;
36 import org.apache.coyote.UpgradeProtocol;
37 import org.apache.coyote.UpgradeToken;
38 import org.apache.coyote.http11.filters.BufferedInputFilter;
39 import org.apache.coyote.http11.filters.ChunkedInputFilter;
40 import org.apache.coyote.http11.filters.ChunkedOutputFilter;
41 import org.apache.coyote.http11.filters.GzipOutputFilter;
42 import org.apache.coyote.http11.filters.IdentityInputFilter;
43 import org.apache.coyote.http11.filters.IdentityOutputFilter;
44 import org.apache.coyote.http11.filters.SavedRequestInputFilter;
45 import org.apache.coyote.http11.filters.VoidInputFilter;
46 import org.apache.coyote.http11.filters.VoidOutputFilter;
47 import org.apache.coyote.http11.upgrade.InternalHttpUpgradeHandler;
48 import org.apache.juli.logging.Log;
49 import org.apache.juli.logging.LogFactory;
50 import org.apache.tomcat.util.ExceptionUtils;
51 import org.apache.tomcat.util.buf.ByteChunk;
52 import org.apache.tomcat.util.buf.MessageBytes;
53 import org.apache.tomcat.util.http.FastHttpDateFormat;
54 import org.apache.tomcat.util.http.MimeHeaders;
55 import org.apache.tomcat.util.http.parser.HttpParser;
56 import org.apache.tomcat.util.http.parser.TokenList;
57 import org.apache.tomcat.util.log.UserDataHelper;
58 import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
59 import org.apache.tomcat.util.net.SSLSupport;
60 import org.apache.tomcat.util.net.SendfileDataBase;
61 import org.apache.tomcat.util.net.SendfileKeepAliveState;
62 import org.apache.tomcat.util.net.SendfileState;
63 import org.apache.tomcat.util.net.SocketWrapperBase;
64 import org.apache.tomcat.util.res.StringManager;
65
66 public class Http11Processor extends AbstractProcessor {
67
68     private static final Log log = LogFactory.getLog(Http11Processor.class);
69
70     /**
71      * The string manager for this package.
72      */

73     private static final StringManager sm = StringManager.getManager(Http11Processor.class);
74
75
76     private final AbstractHttp11Protocol<?> protocol;
77
78
79     /**
80      * Input.
81      */

82     private final Http11InputBuffer inputBuffer;
83
84
85     /**
86      * Output.
87      */

88     private final Http11OutputBuffer outputBuffer;
89
90
91     private final HttpParser httpParser;
92
93
94     /**
95      * Tracks how many internal filters are in the filter library so they
96      * are skipped when looking for pluggable filters.
97      */

98     private int pluggableFilterIndex = Integer.MAX_VALUE;
99
100
101     /**
102      * Keep-alive.
103      */

104     private volatile boolean keepAlive = true;
105
106
107     /**
108      * Flag used to indicate that the socket should be kept open (e.g. for keep
109      * alive or send file.
110      */

111     private boolean openSocket = false;
112
113
114     /**
115      * Flag that indicates if the request headers have been completely read.
116      */

117     private boolean readComplete = true;
118
119     /**
120      * HTTP/1.1 flag.
121      */

122     private boolean http11 = true;
123
124
125     /**
126      * HTTP/0.9 flag.
127      */

128     private boolean http09 = false;
129
130
131     /**
132      * Content delimiter for the request (if false, the connection will
133      * be closed at the end of the request).
134      */

135     private boolean contentDelimitation = true;
136
137
138     /**
139      * Instance of the new protocol to use after the HTTP connection has been
140      * upgraded.
141      */

142     private UpgradeToken upgradeToken = null;
143
144
145     /**
146      * Sendfile data.
147      */

148     private SendfileDataBase sendfileData = null;
149
150
151     public Http11Processor(AbstractHttp11Protocol<?> protocol, Adapter adapter) {
152         super(adapter);
153         this.protocol = protocol;
154
155         httpParser = new HttpParser(protocol.getRelaxedPathChars(),
156                 protocol.getRelaxedQueryChars());
157
158         inputBuffer = new Http11InputBuffer(request, protocol.getMaxHttpHeaderSize(),
159                 protocol.getRejectIllegalHeader(), httpParser);
160         request.setInputBuffer(inputBuffer);
161
162         outputBuffer = new Http11OutputBuffer(response, protocol.getMaxHttpHeaderSize());
163         response.setOutputBuffer(outputBuffer);
164
165         // Create and add the identity filters.
166         inputBuffer.addFilter(new IdentityInputFilter(protocol.getMaxSwallowSize()));
167         outputBuffer.addFilter(new IdentityOutputFilter());
168
169         // Create and add the chunked filters.
170         inputBuffer.addFilter(new ChunkedInputFilter(protocol.getMaxTrailerSize(),
171                 protocol.getAllowedTrailerHeadersInternal(), protocol.getMaxExtensionSize(),
172                 protocol.getMaxSwallowSize()));
173         outputBuffer.addFilter(new ChunkedOutputFilter());
174
175         // Create and add the void filters.
176         inputBuffer.addFilter(new VoidInputFilter());
177         outputBuffer.addFilter(new VoidOutputFilter());
178
179         // Create and add buffered input filter
180         inputBuffer.addFilter(new BufferedInputFilter());
181
182         // Create and add the gzip filters.
183         //inputBuffer.addFilter(new GzipInputFilter());
184         outputBuffer.addFilter(new GzipOutputFilter());
185
186         pluggableFilterIndex = inputBuffer.getFilters().length;
187     }
188
189
190     /**
191      * Determine if we must drop the connection because of the HTTP status
192      * code.  Use the same list of codes as Apache/httpd.
193      */

194     private static boolean statusDropsConnection(int status) {
195         return status == 400 /* SC_BAD_REQUEST */ ||
196                status == 408 /* SC_REQUEST_TIMEOUT */ ||
197                status == 411 /* SC_LENGTH_REQUIRED */ ||
198                status == 413 /* SC_REQUEST_ENTITY_TOO_LARGE */ ||
199                status == 414 /* SC_REQUEST_URI_TOO_LONG */ ||
200                status == 500 /* SC_INTERNAL_SERVER_ERROR */ ||
201                status == 503 /* SC_SERVICE_UNAVAILABLE */ ||
202                status == 501 /* SC_NOT_IMPLEMENTED */;
203     }
204
205
206     /**
207      * Add an input filter to the current request. If the encoding is not
208      * supported, a 501 response will be returned to the client.
209      */

210     private void addInputFilter(InputFilter[] inputFilters, String encodingName) {
211
212         // Parsing trims and converts to lower case.
213
214         if (encodingName.equals("identity")) {
215             // Skip
216         } else if (encodingName.equals("chunked")) {
217             inputBuffer.addActiveFilter
218                 (inputFilters[Constants.CHUNKED_FILTER]);
219             contentDelimitation = true;
220         } else {
221             for (int i = pluggableFilterIndex; i < inputFilters.length; i++) {
222                 if (inputFilters[i].getEncodingName().toString().equals(encodingName)) {
223                     inputBuffer.addActiveFilter(inputFilters[i]);
224                     return;
225                 }
226             }
227             // Unsupported transfer encoding
228             // 501 - Unimplemented
229             response.setStatus(501);
230             setErrorState(ErrorState.CLOSE_CLEAN, null);
231             if (log.isDebugEnabled()) {
232                 log.debug(sm.getString("http11processor.request.prepare") +
233                           " Unsupported transfer encoding [" + encodingName + "]");
234             }
235         }
236     }
237
238
239     @Override
240     public SocketState service(SocketWrapperBase<?> socketWrapper)
241         throws IOException {
242         RequestInfo rp = request.getRequestProcessor();
243         rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
244
245         // Setting up the I/O
246         setSocketWrapper(socketWrapper);
247
248         // Flags
249         keepAlive = true;
250         openSocket = false;
251         readComplete = true;
252         boolean keptAlive = false;
253         SendfileState sendfileState = SendfileState.DONE;
254
255         while (!getErrorState().isError() && keepAlive && !isAsync() && upgradeToken == null &&
256                 sendfileState == SendfileState.DONE && !protocol.isPaused()) {
257
258             // Parsing the request header
259             try {
260                 if (!inputBuffer.parseRequestLine(keptAlive, protocol.getConnectionTimeout(),
261                         protocol.getKeepAliveTimeout())) {
262                     if (inputBuffer.getParsingRequestLinePhase() == -1) {
263                         return SocketState.UPGRADING;
264                     } else if (handleIncompleteRequestLineRead()) {
265                         break;
266                     }
267                 }
268
269                 // Process the Protocol component of the request line
270                 // Need to know if this is an HTTP 0.9 request before trying to
271                 // parse headers.
272                 prepareRequestProtocol();
273
274                 if (protocol.isPaused()) {
275                     // 503 - Service unavailable
276                     response.setStatus(503);
277                     setErrorState(ErrorState.CLOSE_CLEAN, null);
278                 } else {
279                     keptAlive = true;
280                     // Set this every time in case limit has been changed via JMX
281                     request.getMimeHeaders().setLimit(protocol.getMaxHeaderCount());
282                     // Don't parse headers for HTTP/0.9
283                     if (!http09 && !inputBuffer.parseHeaders()) {
284                         // We've read part of the request, don't recycle it
285                         // instead associate it with the socket
286                         openSocket = true;
287                         readComplete = false;
288                         break;
289                     }
290                     if (!protocol.getDisableUploadTimeout()) {
291                         socketWrapper.setReadTimeout(protocol.getConnectionUploadTimeout());
292                     }
293                 }
294             } catch (IOException e) {
295                 if (log.isDebugEnabled()) {
296                     log.debug(sm.getString("http11processor.header.parse"), e);
297                 }
298                 setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e);
299                 break;
300             } catch (Throwable t) {
301                 ExceptionUtils.handleThrowable(t);
302                 UserDataHelper.Mode logMode = userDataHelper.getNextMode();
303                 if (logMode != null) {
304                     String message = sm.getString("http11processor.header.parse");
305                     switch (logMode) {
306                         case INFO_THEN_DEBUG:
307                             message += sm.getString("http11processor.fallToDebug");
308                             //$FALL-THROUGH$
309                         case INFO:
310                             log.info(message, t);
311                             break;
312                         case DEBUG:
313                             log.debug(message, t);
314                     }
315                 }
316                 // 400 - Bad Request
317                 response.setStatus(400);
318                 setErrorState(ErrorState.CLOSE_CLEAN, t);
319             }
320
321             // Has an upgrade been requested?
322             if (isConnectionToken(request.getMimeHeaders(), "upgrade")) {
323                 // Check the protocol
324                 String requestedProtocol = request.getHeader("Upgrade");
325
326                 UpgradeProtocol upgradeProtocol = protocol.getUpgradeProtocol(requestedProtocol);
327                 if (upgradeProtocol != null) {
328                     if (upgradeProtocol.accept(request)) {
329                         response.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS);
330                         response.setHeader("Connection""Upgrade");
331                         response.setHeader("Upgrade", requestedProtocol);
332                         action(ActionCode.CLOSE,  null);
333                         getAdapter().log(request, response, 0);
334
335                         InternalHttpUpgradeHandler upgradeHandler =
336                                 upgradeProtocol.getInternalUpgradeHandler(
337                                         socketWrapper, getAdapter(), cloneRequest(request));
338                         UpgradeToken upgradeToken = new UpgradeToken(upgradeHandler, nullnull);
339                         action(ActionCode.UPGRADE, upgradeToken);
340                         return SocketState.UPGRADING;
341                     }
342                 }
343             }
344
345             if (getErrorState().isIoAllowed()) {
346                 // Setting up filters, and parse some request headers
347                 rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
348                 try {
349                     prepareRequest();
350                 } catch (Throwable t) {
351                     ExceptionUtils.handleThrowable(t);
352                     if (log.isDebugEnabled()) {
353                         log.debug(sm.getString("http11processor.request.prepare"), t);
354                     }
355                     // 500 - Internal Server Error
356                     response.setStatus(500);
357                     setErrorState(ErrorState.CLOSE_CLEAN, t);
358                 }
359             }
360
361             int maxKeepAliveRequests = protocol.getMaxKeepAliveRequests();
362             if (maxKeepAliveRequests == 1) {
363                 keepAlive = false;
364             } else if (maxKeepAliveRequests > 0 &&
365                     socketWrapper.decrementKeepAlive() <= 0) {
366                 keepAlive = false;
367             }
368
369             // Process the request in the adapter
370             if (getErrorState().isIoAllowed()) {
371                 try {
372                     rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
373                     getAdapter().service(request, response);
374                     // Handle when the response was committed before a serious
375                     // error occurred.  Throwing a ServletException should both
376                     // set the status to 500 and set the errorException.
377                     // If we fail here, then the response is likely already
378                     // committed, so we can't try and set headers.
379                     if(keepAlive && !getErrorState().isError() && !isAsync() &&
380                             statusDropsConnection(response.getStatus())) {
381                         setErrorState(ErrorState.CLOSE_CLEAN, null);
382                     }
383                 } catch (InterruptedIOException e) {
384                     setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e);
385                 } catch (HeadersTooLargeException e) {
386                     log.error(sm.getString("http11processor.request.process"), e);
387                     // The response should not have been committed but check it
388                     // anyway to be safe
389                     if (response.isCommitted()) {
390                         setErrorState(ErrorState.CLOSE_NOW, e);
391                     } else {
392                         response.reset();
393                         response.setStatus(500);
394                         setErrorState(ErrorState.CLOSE_CLEAN, e);
395                         response.setHeader("Connection""close"); // TODO: Remove
396                     }
397                 } catch (Throwable t) {
398                     ExceptionUtils.handleThrowable(t);
399                     log.error(sm.getString("http11processor.request.process"), t);
400                     // 500 - Internal Server Error
401                     response.setStatus(500);
402                     setErrorState(ErrorState.CLOSE_CLEAN, t);
403                     getAdapter().log(request, response, 0);
404                 }
405             }
406
407             // Finish the handling of the request
408             rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
409             if (!isAsync()) {
410                 // If this is an async request then the request ends when it has
411                 // been completed. The AsyncContext is responsible for calling
412                 // endRequest() in that case.
413                 endRequest();
414             }
415             rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
416
417             // If there was an error, make sure the request is counted as
418             // and error, and update the statistics counter
419             if (getErrorState().isError()) {
420                 response.setStatus(500);
421             }
422
423             if (!isAsync() || getErrorState().isError()) {
424                 request.updateCounters();
425                 if (getErrorState().isIoAllowed()) {
426                     inputBuffer.nextRequest();
427                     outputBuffer.nextRequest();
428                 }
429             }
430
431             if (!protocol.getDisableUploadTimeout()) {
432                 int connectionTimeout = protocol.getConnectionTimeout();
433                 if(connectionTimeout > 0) {
434                     socketWrapper.setReadTimeout(connectionTimeout);
435                 } else {
436                     socketWrapper.setReadTimeout(0);
437                 }
438             }
439
440             rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
441
442             sendfileState = processSendfile(socketWrapper);
443         }
444
445         rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
446
447         if (getErrorState().isError() || (protocol.isPaused() && !isAsync())) {
448             return SocketState.CLOSED;
449         } else if (isAsync()) {
450             return SocketState.LONG;
451         } else if (isUpgrade()) {
452             return SocketState.UPGRADING;
453         } else {
454             if (sendfileState == SendfileState.PENDING) {
455                 return SocketState.SENDFILE;
456             } else {
457                 if (openSocket) {
458                     if (readComplete) {
459                         return SocketState.OPEN;
460                     } else {
461                         return SocketState.LONG;
462                     }
463                 } else {
464                     return SocketState.CLOSED;
465                 }
466             }
467         }
468     }
469
470
471     @Override
472     protected final void setSocketWrapper(SocketWrapperBase<?> socketWrapper) {
473         super.setSocketWrapper(socketWrapper);
474         inputBuffer.init(socketWrapper);
475         outputBuffer.init(socketWrapper);
476     }
477
478
479     private Request cloneRequest(Request source) throws IOException {
480         Request dest = new Request();
481
482         // Transfer the minimal information required for the copy of the Request
483         // that is passed to the HTTP upgrade process
484
485         dest.decodedURI().duplicate(source.decodedURI());
486         dest.method().duplicate(source.method());
487         dest.getMimeHeaders().duplicate(source.getMimeHeaders());
488         dest.requestURI().duplicate(source.requestURI());
489         dest.queryString().duplicate(source.queryString());
490
491         return dest;
492
493     }
494     private boolean handleIncompleteRequestLineRead() {
495         // Haven't finished reading the request so keep the socket
496         // open
497         openSocket = true;
498         // Check to see if we have read any of the request line yet
499         if (inputBuffer.getParsingRequestLinePhase() > 1) {
500             // Started to read request line.
501             if (protocol.isPaused()) {
502                 // Partially processed the request so need to respond
503                 response.setStatus(503);
504                 setErrorState(ErrorState.CLOSE_CLEAN, null);
505                 return false;
506             } else {
507                 // Need to keep processor associated with socket
508                 readComplete = false;
509             }
510         }
511         return true;
512     }
513
514
515     private void checkExpectationAndResponseStatus() {
516         if (request.hasExpectation() &&
517                 (response.getStatus() < 200 || response.getStatus() > 299)) {
518             // Client sent Expect: 100-continue but received a
519             // non-2xx final response. Disable keep-alive (if enabled)
520             // to ensure that the connection is closed. Some clients may
521             // still send the body, some may send the next request.
522             // No way to differentiate, so close the connection to
523             // force the client to send the next request.
524             inputBuffer.setSwallowInput(false);
525             keepAlive = false;
526         }
527     }
528
529
530     private void prepareRequestProtocol() {
531
532         MessageBytes protocolMB = request.protocol();
533         if (protocolMB.equals(Constants.HTTP_11)) {
534             http09 = false;
535             http11 = true;
536             protocolMB.setString(Constants.HTTP_11);
537         } else if (protocolMB.equals(Constants.HTTP_10)) {
538             http09 = false;
539             http11 = false;
540             keepAlive = false;
541             protocolMB.setString(Constants.HTTP_10);
542         } else if (protocolMB.equals("")) {
543             // HTTP/0.9
544             http09 = true;
545             http11 = false;
546             keepAlive = false;
547         } else {
548             // Unsupported protocol
549             http09 = false;
550             http11 = false;
551             // Send 505; Unsupported HTTP version
552             response.setStatus(505);
553             setErrorState(ErrorState.CLOSE_CLEAN, null);
554             if (log.isDebugEnabled()) {
555                 log.debug(sm.getString("http11processor.request.prepare")+
556                           " Unsupported HTTP version \""+protocolMB+"\"");
557             }
558         }
559     }
560
561
562     /**
563      * After reading the request headers, we have to setup the request filters.
564      */

565     private void prepareRequest() throws IOException {
566
567         contentDelimitation = false;
568
569         if (protocol.isSSLEnabled()) {
570             request.scheme().setString("https");
571         }
572
573         MimeHeaders headers = request.getMimeHeaders();
574
575         // Check connection header
576         MessageBytes connectionValueMB = headers.getValue(Constants.CONNECTION);
577         if (connectionValueMB != null && !connectionValueMB.isNull()) {
578             Set<String> tokens = new HashSet<>();
579             TokenList.parseTokenList(headers.values(Constants.CONNECTION), tokens);
580             if (tokens.contains(Constants.CLOSE)) {
581                 keepAlive = false;
582             } else if (tokens.contains(Constants.KEEP_ALIVE_HEADER_VALUE_TOKEN)) {
583                 keepAlive = true;
584             }
585         }
586
587         if (http11) {
588             MessageBytes expectMB = headers.getValue("expect");
589             if (expectMB != null && !expectMB.isNull()) {
590                 if (expectMB.toString().trim().equalsIgnoreCase("100-continue")) {
591                     inputBuffer.setSwallowInput(false);
592                     request.setExpectation(true);
593                 } else {
594                     response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
595                     setErrorState(ErrorState.CLOSE_CLEAN, null);
596                 }
597             }
598         }
599
600         // Check user-agent header
601         Pattern restrictedUserAgents = protocol.getRestrictedUserAgentsPattern();
602         if (restrictedUserAgents != null && (http11 || keepAlive)) {
603             MessageBytes userAgentValueMB = headers.getValue("user-agent");
604             // Check in the restricted list, and adjust the http11
605             // and keepAlive flags accordingly
606             if(userAgentValueMB != null && !userAgentValueMB.isNull()) {
607                 String userAgentValue = userAgentValueMB.toString();
608                 if (restrictedUserAgents.matcher(userAgentValue).matches()) {
609                     http11 = false;
610                     keepAlive = false;
611                 }
612             }
613         }
614
615
616         // Check host header
617         MessageBytes hostValueMB = null;
618         try {
619             hostValueMB = headers.getUniqueValue("host");
620         } catch (IllegalArgumentException iae) {
621             // Multiple Host headers are not permitted
622             badRequest("http11processor.request.multipleHosts");
623         }
624         if (http11 && hostValueMB == null) {
625             badRequest("http11processor.request.noHostHeader");
626         }
627
628         // Check for an absolute-URI less the query string which has already
629         // been removed during the parsing of the request line
630         ByteChunk uriBC = request.requestURI().getByteChunk();
631         byte[] uriB = uriBC.getBytes();
632         if (uriBC.startsWithIgnoreCase("http", 0)) {
633             int pos = 4;
634             // Check for https
635             if (uriBC.startsWithIgnoreCase("s", pos)) {
636                 pos++;
637             }
638             // Next 3 characters must be "://"
639             if (uriBC.startsWith("://", pos)) {
640                 pos += 3;
641                 int uriBCStart = uriBC.getStart();
642
643                 // '/' does not appear in the authority so use the first
644                 // instance to split the authority and the path segments
645                 int slashPos = uriBC.indexOf('/', pos);
646                 // '@' in the authority delimits the userinfo
647                 int atPos = uriBC.indexOf('@', pos);
648                 if (slashPos > -1 && atPos > slashPos) {
649                     // First '@' is in the path segments so no userinfo
650                     atPos = -1;
651                 }
652
653                 if (slashPos == -1) {
654                     slashPos = uriBC.getLength();
655                     // Set URI as "/". Use 6 as it will always be a '/'.
656                     // 01234567
657                     // http://
658                     // https://
659                     request.requestURI().setBytes(uriB, uriBCStart + 6, 1);
660                 } else {
661                     request.requestURI().setBytes(uriB, uriBCStart + slashPos, uriBC.getLength() - slashPos);
662                 }
663
664                 // Skip any user info
665                 if (atPos != -1) {
666                     // Validate the userinfo
667                     for (; pos < atPos; pos++) {
668                         byte c = uriB[uriBCStart + pos];
669                         if (!HttpParser.isUserInfo(c)) {
670                             // Strictly there needs to be a check for valid %nn
671                             // encoding here but skip it since it will never be
672                             // decoded because the userinfo is ignored
673                             badRequest("http11processor.request.invalidUserInfo");
674                             break;
675                         }
676                     }
677                     // Skip the '@'
678                     pos = atPos + 1;
679                 }
680
681                 if (http11) {
682                     // Missing host header is illegal but handled above
683                     if (hostValueMB != null) {
684                         // Any host in the request line must be consistent with
685                         // the Host header
686                         if (!hostValueMB.getByteChunk().equals(
687                                 uriB, uriBCStart + pos, slashPos - pos)) {
688                             if (protocol.getAllowHostHeaderMismatch()) {
689                                 // The requirements of RFC 2616 are being
690                                 // applied. If the host header and the request
691                                 // line do not agree, the request line takes
692                                 // precedence
693                                 hostValueMB = headers.setValue("host");
694                                 hostValueMB.setBytes(uriB, uriBCStart + pos, slashPos - pos);
695                             } else {
696                                 // The requirements of RFC 7230 are being
697                                 // applied. If the host header and the request
698                                 // line do not agree, trigger a 400 response.
699                                 badRequest("http11processor.request.inconsistentHosts");
700                             }
701                         }
702                     }
703                 } else {
704                     // Not HTTP/1.1 - no Host header so generate one since
705                     // Tomcat internals assume it is set
706                     try {
707                         hostValueMB = headers.setValue("host");
708                         hostValueMB.setBytes(uriB, uriBCStart + pos, slashPos - pos);
709                     } catch (IllegalStateException e) {
710                         // Edge case
711                         // If the request has too many headers it won't be
712                         // possible to create the host header. Ignore this as
713                         // processing won't reach the point where the Tomcat
714                         // internals expect there to be a host header.
715                     }
716                 }
717             } else {
718                 badRequest("http11processor.request.invalidScheme");
719             }
720         }
721
722         // Validate the characters in the URI. %nn decoding will be checked at
723         // the point of decoding.
724         for (int i = uriBC.getStart(); i < uriBC.getEnd(); i++) {
725             if (!httpParser.isAbsolutePathRelaxed(uriB[i])) {
726                 badRequest("http11processor.request.invalidUri");
727                 break;
728             }
729         }
730
731         // Input filter setup
732         InputFilter[] inputFilters = inputBuffer.getFilters();
733
734         // Parse transfer-encoding header
735         if (http11) {
736             MessageBytes transferEncodingValueMB = headers.getValue("transfer-encoding");
737             if (transferEncodingValueMB != null) {
738                 List<String> encodingNames = new ArrayList<>();
739                 if (TokenList.parseTokenList(headers.values("transfer-encoding"), encodingNames)) {
740                     for (String encodingName : encodingNames) {
741                         // "identity" codings are ignored
742                         addInputFilter(inputFilters, encodingName);
743                     }
744                 } else {
745                     // Invalid transfer encoding
746                     badRequest("http11processor.request.invalidTransferEncoding");
747                 }
748             }
749         }
750
751         // Parse content-length header
752         long contentLength = -1;
753         try {
754             contentLength = request.getContentLengthLong();
755         } catch (NumberFormatException e) {
756             badRequest("http11processor.request.nonNumericContentLength");
757         } catch (IllegalArgumentException e) {
758             badRequest("http11processor.request.multipleContentLength");
759         }
760         if (contentLength >= 0) {
761             if (contentDelimitation) {
762                 // contentDelimitation being true at this point indicates that
763                 // chunked encoding is being used but chunked encoding should
764                 // not be used with a content length. RFC 2616, section 4.4,
765                 // bullet 3 states Content-Length must be ignored in this case -
766                 // so remove it.
767                 headers.removeHeader("content-length");
768                 request.setContentLength(-1);
769             } else {
770                 inputBuffer.addActiveFilter(inputFilters[Constants.IDENTITY_FILTER]);
771                 contentDelimitation = true;
772             }
773         }
774
775         // Validate host name and extract port if present
776         parseHost(hostValueMB);
777
778         if (!contentDelimitation) {
779             // If there's no content length
780             // (broken HTTP/1.0 or HTTP/1.1), assume
781             // the client is not broken and didn't send a body
782             inputBuffer.addActiveFilter(inputFilters[Constants.VOID_FILTER]);
783             contentDelimitation = true;
784         }
785
786         if (!getErrorState().isIoAllowed()) {
787             getAdapter().log(request, response, 0);
788         }
789     }
790
791
792     private void badRequest(String errorKey) {
793         response.setStatus(400);
794         setErrorState(ErrorState.CLOSE_CLEAN, null);
795         if (log.isDebugEnabled()) {
796             log.debug(sm.getString(errorKey));
797         }
798     }
799
800
801     /**
802      * When committing the response, we have to validate the set of headers, as
803      * well as setup the response filters.
804      */

805     @Override
806     protected final void prepareResponse() throws IOException {
807
808         boolean entityBody = true;
809         contentDelimitation = false;
810
811         OutputFilter[] outputFilters = outputBuffer.getFilters();
812
813         if (http09 == true) {
814             // HTTP/0.9
815             outputBuffer.addActiveFilter(outputFilters[Constants.IDENTITY_FILTER]);
816             outputBuffer.commit();
817             return;
818         }
819
820         int statusCode = response.getStatus();
821         if (statusCode < 200 || statusCode == 204 || statusCode == 205 ||
822                 statusCode == 304) {
823             // No entity body
824             outputBuffer.addActiveFilter
825                 (outputFilters[Constants.VOID_FILTER]);
826             entityBody = false;
827             contentDelimitation = true;
828             if (statusCode == 205) {
829                 // RFC 7231 requires the server to explicitly signal an empty
830                 // response in this case
831                 response.setContentLength(0);
832             } else {
833                 response.setContentLength(-1);
834             }
835         }
836
837         MessageBytes methodMB = request.method();
838         if (methodMB.equals("HEAD")) {
839             // No entity body
840             outputBuffer.addActiveFilter
841                 (outputFilters[Constants.VOID_FILTER]);
842             contentDelimitation = true;
843         }
844
845         // Sendfile support
846         if (protocol.getUseSendfile()) {
847             prepareSendfile(outputFilters);
848         }
849
850         // Check for compression
851         boolean useCompression = false;
852         if (entityBody && sendfileData == null) {
853             useCompression = protocol.useCompression(request, response);
854         }
855
856         MimeHeaders headers = response.getMimeHeaders();
857         // A SC_NO_CONTENT response may include entity headers
858         if (entityBody || statusCode == HttpServletResponse.SC_NO_CONTENT) {
859             String contentType = response.getContentType();
860             if (contentType != null) {
861                 headers.setValue("Content-Type").setString(contentType);
862             }
863             String contentLanguage = response.getContentLanguage();
864             if (contentLanguage != null) {
865                 headers.setValue("Content-Language")
866                     .setString(contentLanguage);
867             }
868         }
869
870         long contentLength = response.getContentLengthLong();
871         boolean connectionClosePresent = isConnectionToken(headers, Constants.CLOSE);
872         if (http11 && response.getTrailerFields() != null) {
873             // If trailer fields are set, always use chunking
874             outputBuffer.addActiveFilter(outputFilters[Constants.CHUNKED_FILTER]);
875             contentDelimitation = true;
876             headers.addValue(Constants.TRANSFERENCODING).setString(Constants.CHUNKED);
877         } else if (contentLength != -1) {
878             headers.setValue("Content-Length").setLong(contentLength);
879             outputBuffer.addActiveFilter(outputFilters[Constants.IDENTITY_FILTER]);
880             contentDelimitation = true;
881         } else {
882             // If the response code supports an entity body and we're on
883             // HTTP 1.1 then we chunk unless we have a Connection: close header
884             if (http11 && entityBody && !connectionClosePresent) {
885                 outputBuffer.addActiveFilter(outputFilters[Constants.CHUNKED_FILTER]);
886                 contentDelimitation = true;
887                 headers.addValue(Constants.TRANSFERENCODING).setString(Constants.CHUNKED);
888             } else {
889                 outputBuffer.addActiveFilter(outputFilters[Constants.IDENTITY_FILTER]);
890             }
891         }
892
893         if (useCompression) {
894             outputBuffer.addActiveFilter(outputFilters[Constants.GZIP_FILTER]);
895         }
896
897         // Add date header unless application has already set one (e.g. in a
898         // Caching Filter)
899         if (headers.getValue("Date") == null) {
900             headers.addValue("Date").setString(
901                     FastHttpDateFormat.getCurrentDate());
902         }
903
904         // FIXME: Add transfer encoding header
905
906         if ((entityBody) && (!contentDelimitation)) {
907             // Mark as close the connection after the request, and add the
908             // connection: close header
909             keepAlive = false;
910         }
911
912         // This may disabled keep-alive to check before working out the
913         // Connection header.
914         checkExpectationAndResponseStatus();
915
916         // If we know that the request is bad this early, add the
917         // Connection: close header.
918         if (keepAlive && statusDropsConnection(statusCode)) {
919             keepAlive = false;
920         }
921         if (!keepAlive) {
922             // Avoid adding the close header twice
923             if (!connectionClosePresent) {
924                 headers.addValue(Constants.CONNECTION).setString(
925                         Constants.CLOSE);
926             }
927         } else if (!getErrorState().isError()) {
928             if (!http11) {
929                 headers.addValue(Constants.CONNECTION).setString(Constants.KEEP_ALIVE_HEADER_VALUE_TOKEN);
930             }
931
932             if (protocol.getUseKeepAliveResponseHeader()) {
933                 boolean connectionKeepAlivePresent =
934                     isConnectionToken(request.getMimeHeaders(), Constants.KEEP_ALIVE_HEADER_VALUE_TOKEN);
935
936                 if (connectionKeepAlivePresent) {
937                     int keepAliveTimeout = protocol.getKeepAliveTimeout();
938
939                     if (keepAliveTimeout > 0) {
940                         String value = "timeout=" + keepAliveTimeout / 1000L;
941                         headers.setValue(Constants.KEEP_ALIVE_HEADER_NAME).setString(value);
942
943                         if (http11) {
944                             // Append if there is already a Connection header,
945                             // else create the header
946                             MessageBytes connectionHeaderValue = headers.getValue(Constants.CONNECTION);
947                             if (connectionHeaderValue == null) {
948                                 headers.addValue(Constants.CONNECTION).setString(Constants.KEEP_ALIVE_HEADER_VALUE_TOKEN);
949                             } else {
950                                 connectionHeaderValue.setString(
951                                         connectionHeaderValue.getString() + ", " + Constants.KEEP_ALIVE_HEADER_VALUE_TOKEN);
952                             }
953                         }
954                     }
955                 }
956             }
957         }
958
959         // Add server header
960         String server = protocol.getServer();
961         if (server == null) {
962             if (protocol.getServerRemoveAppProvidedValues()) {
963                 headers.removeHeader("server");
964             }
965         } else {
966             // server always overrides anything the app might set
967             headers.setValue("Server").setString(server);
968         }
969
970         // Build the response header
971         try {
972             outputBuffer.sendStatus();
973
974             int size = headers.size();
975             for (int i = 0; i < size; i++) {
976                 outputBuffer.sendHeader(headers.getName(i), headers.getValue(i));
977             }
978             outputBuffer.endHeaders();
979         } catch (Throwable t) {
980             ExceptionUtils.handleThrowable(t);
981             // If something goes wrong, reset the header buffer so the error
982             // response can be written instead.
983             outputBuffer.resetHeaderBuffer();
984             throw t;
985         }
986
987         outputBuffer.commit();
988     }
989
990     private static boolean isConnectionToken(MimeHeaders headers, String token) throws IOException {
991         MessageBytes connection = headers.getValue(Constants.CONNECTION);
992         if (connection == null) {
993             return false;
994         }
995
996         Set<String> tokens = new HashSet<>();
997         TokenList.parseTokenList(headers.values(Constants.CONNECTION), tokens);
998         return tokens.contains(token);
999     }
1000
1001
1002     private void prepareSendfile(OutputFilter[] outputFilters) {
1003         String fileName = (String) request.getAttribute(
1004                 org.apache.coyote.Constants.SENDFILE_FILENAME_ATTR);
1005         if (fileName == null) {
1006             sendfileData = null;
1007         } else {
1008             // No entity body sent here
1009             outputBuffer.addActiveFilter(outputFilters[Constants.VOID_FILTER]);
1010             contentDelimitation = true;
1011             long pos = ((Long) request.getAttribute(
1012                     org.apache.coyote.Constants.SENDFILE_FILE_START_ATTR)).longValue();
1013             long end = ((Long) request.getAttribute(
1014                     org.apache.coyote.Constants.SENDFILE_FILE_END_ATTR)).longValue();
1015             sendfileData = socketWrapper.createSendfileData(fileName, pos, end - pos);
1016         }
1017     }
1018
1019
1020     /*
1021      * Note: populateHost() is not over-ridden.
1022      *       request.serverName() will be set to return the default host name by
1023      *       the Mapper.
1024      */

1025
1026
1027     /**
1028      * {@inheritDoc}
1029      * <p>
1030      * This implementation provides the server port from the local port.
1031      */

1032     @Override
1033     protected void populatePort() {
1034         // Ensure the local port field is populated before using it.
1035         request.action(ActionCode.REQ_LOCALPORT_ATTRIBUTE, request);
1036         request.setServerPort(request.getLocalPort());
1037     }
1038
1039
1040     @Override
1041     protected boolean flushBufferedWrite() throws IOException {
1042         if (outputBuffer.hasDataToWrite()) {
1043             if (outputBuffer.flushBuffer(false)) {
1044                 // The buffer wasn't fully flushed so re-register the
1045                 // socket for write. Note this does not go via the
1046                 // Response since the write registration state at
1047                 // that level should remain unchanged. Once the buffer
1048                 // has been emptied then the code below will call
1049                 // Adaptor.asyncDispatch() which will enable the
1050                 // Response to respond to this event.
1051                 outputBuffer.registerWriteInterest();
1052                 return true;
1053             }
1054         }
1055         return false;
1056     }
1057
1058
1059     @Override
1060     protected SocketState dispatchEndRequest() {
1061         if (!keepAlive || protocol.isPaused()) {
1062             return SocketState.CLOSED;
1063         } else {
1064             endRequest();
1065             inputBuffer.nextRequest();
1066             outputBuffer.nextRequest();
1067             if (socketWrapper.isReadPending()) {
1068                 return SocketState.LONG;
1069             } else {
1070                 return SocketState.OPEN;
1071             }
1072         }
1073     }
1074
1075
1076     @Override
1077     protected Log getLog() {
1078         return log;
1079     }
1080
1081
1082     /*
1083      * No more input will be passed to the application. Remaining input will be
1084      * swallowed or the connection dropped depending on the error and
1085      * expectation status.
1086      */

1087     private void endRequest() {
1088         if (getErrorState().isError()) {
1089             // If we know we are closing the connection, don't drain
1090             // input. This way uploading a 100GB file doesn't tie up the
1091             // thread if the servlet has rejected it.
1092             inputBuffer.setSwallowInput(false);
1093         } else {
1094             // Need to check this again here in case the response was
1095             // committed before the error that requires the connection
1096             // to be closed occurred.
1097             checkExpectationAndResponseStatus();
1098         }
1099
1100         // Finish the handling of the request
1101         if (getErrorState().isIoAllowed()) {
1102             try {
1103                 inputBuffer.endRequest();
1104             } catch (IOException e) {
1105                 setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e);
1106             } catch (Throwable t) {
1107                 ExceptionUtils.handleThrowable(t);
1108                 // 500 - Internal Server Error
1109                 // Can't add a 500 to the access log since that has already been
1110                 // written in the Adapter.service method.
1111                 response.setStatus(500);
1112                 setErrorState(ErrorState.CLOSE_NOW, t);
1113                 log.error(sm.getString("http11processor.request.finish"), t);
1114             }
1115         }
1116         if (getErrorState().isIoAllowed()) {
1117             try {
1118                 action(ActionCode.COMMIT, null);
1119                 outputBuffer.end();
1120             } catch (IOException e) {
1121                 setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e);
1122             } catch (Throwable t) {
1123                 ExceptionUtils.handleThrowable(t);
1124                 setErrorState(ErrorState.CLOSE_NOW, t);
1125                 log.error(sm.getString("http11processor.response.finish"), t);
1126             }
1127         }
1128     }
1129
1130
1131     @Override
1132     protected final void finishResponse() throws IOException {
1133         outputBuffer.end();
1134     }
1135
1136
1137     @Override
1138     protected final void ack() {
1139         // Acknowledge request
1140         // Send a 100 status back if it makes sense (response not committed
1141         // yet, and client specified an expectation for 100-continue)
1142         if (!response.isCommitted() && request.hasExpectation()) {
1143             inputBuffer.setSwallowInput(true);
1144             try {
1145                 outputBuffer.sendAck();
1146             } catch (IOException e) {
1147                 setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e);
1148             }
1149         }
1150     }
1151
1152
1153     @Override
1154     protected final void flush() throws IOException {
1155         outputBuffer.flush();
1156     }
1157
1158
1159     @Override
1160     protected final int available(boolean doRead) {
1161         return inputBuffer.available(doRead);
1162     }
1163
1164
1165     @Override
1166     protected final void setRequestBody(ByteChunk body) {
1167         InputFilter savedBody = new SavedRequestInputFilter(body);
1168         Http11InputBuffer internalBuffer = (Http11InputBuffer) request.getInputBuffer();
1169         internalBuffer.addActiveFilter(savedBody);
1170     }
1171
1172
1173     @Override
1174     protected final void setSwallowResponse() {
1175         outputBuffer.responseFinished = true;
1176     }
1177
1178
1179     @Override
1180     protected final void disableSwallowRequest() {
1181         inputBuffer.setSwallowInput(false);
1182     }
1183
1184
1185     @Override
1186     protected final void sslReHandShake() throws IOException {
1187         if (sslSupport != null) {
1188             // Consume and buffer the request body, so that it does not
1189             // interfere with the client's handshake messages
1190             InputFilter[] inputFilters = inputBuffer.getFilters();
1191             ((BufferedInputFilter) inputFilters[Constants.BUFFERED_FILTER]).setLimit(
1192                     protocol.getMaxSavePostSize());
1193             inputBuffer.addActiveFilter(inputFilters[Constants.BUFFERED_FILTER]);
1194
1195             /*
1196              * Outside the try/catch because we want I/O errors during
1197              * renegotiation to be thrown for the caller to handle since they
1198              * will be fatal to the connection.
1199              */

1200             socketWrapper.doClientAuth(sslSupport);
1201             try {
1202                 /*
1203                  * Errors processing the cert chain do not affect the client
1204                  * connection so they can be logged and swallowed here.
1205                  */

1206                 Object sslO = sslSupport.getPeerCertificateChain();
1207                 if (sslO != null) {
1208                     request.setAttribute(SSLSupport.CERTIFICATE_KEY, sslO);
1209                 }
1210             } catch (IOException ioe) {
1211                 log.warn(sm.getString("http11processor.socket.ssl"), ioe);
1212             }
1213         }
1214     }
1215
1216
1217     @Override
1218     protected final boolean isRequestBodyFullyRead() {
1219         return inputBuffer.isFinished();
1220     }
1221
1222
1223     @Override
1224     protected final void registerReadInterest() {
1225         socketWrapper.registerReadInterest();
1226     }
1227
1228
1229     @Override
1230     protected final boolean isReadyForWrite() {
1231         return outputBuffer.isReady();
1232     }
1233
1234
1235     @Override
1236     public UpgradeToken getUpgradeToken() {
1237         return upgradeToken;
1238     }
1239
1240
1241     @Override
1242     protected final void doHttpUpgrade(UpgradeToken upgradeToken) {
1243         this.upgradeToken = upgradeToken;
1244         // Stop further HTTP output
1245         outputBuffer.responseFinished = true;
1246     }
1247
1248
1249     @Override
1250     public ByteBuffer getLeftoverInput() {
1251         return inputBuffer.getLeftover();
1252     }
1253
1254
1255     @Override
1256     public boolean isUpgrade() {
1257         return upgradeToken != null;
1258     }
1259
1260
1261     @Override
1262     protected boolean isTrailerFieldsReady() {
1263         if (inputBuffer.isChunking()) {
1264             return inputBuffer.isFinished();
1265         } else {
1266             return true;
1267         }
1268     }
1269
1270
1271     @Override
1272     protected boolean isTrailerFieldsSupported() {
1273         // Request must be HTTP/1.1 to support trailer fields
1274         if (!http11) {
1275             return false;
1276         }
1277
1278         // If the response is not yet committed, chunked encoding can be used
1279         // and the trailer fields sent
1280         if (!response.isCommitted()) {
1281             return true;
1282         }
1283
1284         // Response has been committed - need to see if chunked is being used
1285         return outputBuffer.isChunking();
1286     }
1287
1288
1289     /**
1290      * Trigger sendfile processing if required.
1291      *
1292      * @return The state of send file processing
1293      */

1294     private SendfileState processSendfile(SocketWrapperBase<?> socketWrapper) {
1295         openSocket = keepAlive;
1296         // Done is equivalent to sendfile not being used
1297         SendfileState result = SendfileState.DONE;
1298         // Do sendfile as needed: add socket to sendfile and end
1299         if (sendfileData != null && !getErrorState().isError()) {
1300             if (keepAlive) {
1301                 if (available(false) == 0) {
1302                     sendfileData.keepAliveState = SendfileKeepAliveState.OPEN;
1303                 } else {
1304                     sendfileData.keepAliveState = SendfileKeepAliveState.PIPELINED;
1305                 }
1306             } else {
1307                 sendfileData.keepAliveState = SendfileKeepAliveState.NONE;
1308             }
1309             result = socketWrapper.processSendfile(sendfileData);
1310             switch (result) {
1311             case ERROR:
1312                 // Write failed
1313                 if (log.isDebugEnabled()) {
1314                     log.debug(sm.getString("http11processor.sendfile.error"));
1315                 }
1316                 setErrorState(ErrorState.CLOSE_CONNECTION_NOW, null);
1317                 //$FALL-THROUGH$
1318             default:
1319                 sendfileData = null;
1320             }
1321         }
1322         return result;
1323     }
1324
1325
1326     @Override
1327     public final void recycle() {
1328         getAdapter().checkRecycled(request, response);
1329         super.recycle();
1330         inputBuffer.recycle();
1331         outputBuffer.recycle();
1332         upgradeToken = null;
1333         socketWrapper = null;
1334         sendfileData = null;
1335         sslSupport = null;
1336     }
1337
1338
1339     @Override
1340     public void pause() {
1341         // NOOP for HTTP
1342     }
1343 }
1344