init
This commit is contained in:
964
java/org/apache/coyote/AbstractProcessor.java
Normal file
964
java/org/apache/coyote/AbstractProcessor.java
Normal file
File diff suppressed because it is too large
Load Diff
198
java/org/apache/coyote/AbstractProcessorLight.java
Normal file
198
java/org/apache/coyote/AbstractProcessorLight.java
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
|
||||
import org.apache.tomcat.util.net.DispatchType;
|
||||
import org.apache.tomcat.util.net.SocketEvent;
|
||||
import org.apache.tomcat.util.net.SocketWrapperBase;
|
||||
|
||||
/**
|
||||
* This is a light-weight abstract processor implementation that is intended as
|
||||
* a basis for all Processor implementations from the light-weight upgrade
|
||||
* processors to the HTTP/AJP processors.
|
||||
*/
|
||||
public abstract class AbstractProcessorLight implements Processor {
|
||||
|
||||
private Set<DispatchType> dispatches = new CopyOnWriteArraySet<>();
|
||||
|
||||
|
||||
@Override
|
||||
public SocketState process(SocketWrapperBase<?> socketWrapper, SocketEvent status)
|
||||
throws IOException {
|
||||
|
||||
SocketState state = SocketState.CLOSED;
|
||||
Iterator<DispatchType> dispatches = null;
|
||||
do {
|
||||
if (dispatches != null) {
|
||||
DispatchType nextDispatch = dispatches.next();
|
||||
if (getLog().isDebugEnabled()) {
|
||||
getLog().debug("Processing dispatch type: [" + nextDispatch + "]");
|
||||
}
|
||||
state = dispatch(nextDispatch.getSocketStatus());
|
||||
if (!dispatches.hasNext()) {
|
||||
state = checkForPipelinedData(state, socketWrapper);
|
||||
}
|
||||
} else if (status == SocketEvent.DISCONNECT) {
|
||||
// Do nothing here, just wait for it to get recycled
|
||||
} else if (isAsync() || isUpgrade() || state == SocketState.ASYNC_END) {
|
||||
state = dispatch(status);
|
||||
state = checkForPipelinedData(state, socketWrapper);
|
||||
} else if (status == SocketEvent.OPEN_WRITE) {
|
||||
// Extra write event likely after async, ignore
|
||||
state = SocketState.LONG;
|
||||
} else if (status == SocketEvent.OPEN_READ) {
|
||||
state = service(socketWrapper);
|
||||
} else if (status == SocketEvent.CONNECT_FAIL) {
|
||||
logAccess(socketWrapper);
|
||||
} else {
|
||||
// Default to closing the socket if the SocketEvent passed in
|
||||
// is not consistent with the current state of the Processor
|
||||
state = SocketState.CLOSED;
|
||||
}
|
||||
|
||||
if (getLog().isDebugEnabled()) {
|
||||
getLog().debug("Socket: [" + socketWrapper +
|
||||
"], Status in: [" + status +
|
||||
"], State out: [" + state + "]");
|
||||
}
|
||||
|
||||
if (state != SocketState.CLOSED && isAsync()) {
|
||||
state = asyncPostProcess();
|
||||
if (getLog().isDebugEnabled()) {
|
||||
getLog().debug("Socket: [" + socketWrapper +
|
||||
"], State after async post processing: [" + state + "]");
|
||||
}
|
||||
}
|
||||
|
||||
if (dispatches == null || !dispatches.hasNext()) {
|
||||
// Only returns non-null iterator if there are
|
||||
// dispatches to process.
|
||||
dispatches = getIteratorAndClearDispatches();
|
||||
}
|
||||
} while (state == SocketState.ASYNC_END ||
|
||||
dispatches != null && state != SocketState.CLOSED);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
private SocketState checkForPipelinedData(SocketState inState, SocketWrapperBase<?> socketWrapper)
|
||||
throws IOException {
|
||||
if (inState == SocketState.OPEN) {
|
||||
// There may be pipe-lined data to read. If the data isn't
|
||||
// processed now, execution will exit this loop and call
|
||||
// release() which will recycle the processor (and input
|
||||
// buffer) deleting any pipe-lined data. To avoid this,
|
||||
// process it now.
|
||||
return service(socketWrapper);
|
||||
} else {
|
||||
return inState;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void addDispatch(DispatchType dispatchType) {
|
||||
synchronized (dispatches) {
|
||||
dispatches.add(dispatchType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Iterator<DispatchType> getIteratorAndClearDispatches() {
|
||||
// Note: Logic in AbstractProtocol depends on this method only returning
|
||||
// a non-null value if the iterator is non-empty. i.e. it should never
|
||||
// return an empty iterator.
|
||||
Iterator<DispatchType> result;
|
||||
synchronized (dispatches) {
|
||||
// Synchronized as the generation of the iterator and the clearing
|
||||
// of dispatches needs to be an atomic operation.
|
||||
result = dispatches.iterator();
|
||||
if (result.hasNext()) {
|
||||
dispatches.clear();
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
protected void clearDispatches() {
|
||||
synchronized (dispatches) {
|
||||
dispatches.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add an entry to the access log for a failed connection attempt.
|
||||
*
|
||||
* @param socketWrapper The connection to process
|
||||
*
|
||||
* @throws IOException If an I/O error occurs during the processing of the
|
||||
* request
|
||||
*/
|
||||
protected void logAccess(SocketWrapperBase<?> socketWrapper) throws IOException {
|
||||
// NO-OP by default
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Service a 'standard' HTTP request. This method is called for both new
|
||||
* requests and for requests that have partially read the HTTP request line
|
||||
* or HTTP headers. Once the headers have been fully read this method is not
|
||||
* called again until there is a new HTTP request to process. Note that the
|
||||
* request type may change during processing which may result in one or more
|
||||
* calls to {@link #dispatch(SocketEvent)}. Requests may be pipe-lined.
|
||||
*
|
||||
* @param socketWrapper The connection to process
|
||||
*
|
||||
* @return The state the caller should put the socket in when this method
|
||||
* returns
|
||||
*
|
||||
* @throws IOException If an I/O error occurs during the processing of the
|
||||
* request
|
||||
*/
|
||||
protected abstract SocketState service(SocketWrapperBase<?> socketWrapper) throws IOException;
|
||||
|
||||
/**
|
||||
* Process an in-progress request that is not longer in standard HTTP mode.
|
||||
* Uses currently include Servlet 3.0 Async and HTTP upgrade connections.
|
||||
* Further uses may be added in the future. These will typically start as
|
||||
* HTTP requests.
|
||||
*
|
||||
* @param status The event to process
|
||||
*
|
||||
* @return The state the caller should put the socket in when this method
|
||||
* returns
|
||||
*
|
||||
* @throws IOException If an I/O error occurs during the processing of the
|
||||
* request
|
||||
*/
|
||||
protected abstract SocketState dispatch(SocketEvent status) throws IOException;
|
||||
|
||||
protected abstract SocketState asyncPostProcess();
|
||||
|
||||
protected abstract Log getLog();
|
||||
}
|
||||
1200
java/org/apache/coyote/AbstractProtocol.java
Normal file
1200
java/org/apache/coyote/AbstractProtocol.java
Normal file
File diff suppressed because it is too large
Load Diff
255
java/org/apache/coyote/ActionCode.java
Normal file
255
java/org/apache/coyote/ActionCode.java
Normal file
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.coyote;
|
||||
|
||||
/**
|
||||
* ActionCodes represent callbacks from the servlet container to the coyote
|
||||
* connector. Actions are implemented by ProtocolHandler, using the ActionHook
|
||||
* interface.
|
||||
*
|
||||
* @see ProtocolHandler
|
||||
* @see ActionHook
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
public enum ActionCode {
|
||||
ACK,
|
||||
CLOSE,
|
||||
COMMIT,
|
||||
|
||||
/**
|
||||
* A serious error occurred from which it is not possible to recover safely.
|
||||
* Further attempts to write to the response should be ignored and the
|
||||
* connection needs to be closed as soon as possible. This can also be used
|
||||
* to forcibly close a connection if an error occurs after the response has
|
||||
* been committed.
|
||||
*/
|
||||
CLOSE_NOW,
|
||||
|
||||
/**
|
||||
* A flush() operation originated by the client ( i.e. a flush() on the
|
||||
* servlet output stream or writer, called by a servlet ). Argument is the
|
||||
* Response.
|
||||
*/
|
||||
CLIENT_FLUSH,
|
||||
|
||||
/**
|
||||
* Has the processor been placed into the error state? Note that the
|
||||
* response may not have an appropriate error code set.
|
||||
*/
|
||||
IS_ERROR,
|
||||
|
||||
/**
|
||||
* The processor may have been placed into an error state and some error
|
||||
* states do not permit any further I/O. Is I/O currently allowed?
|
||||
*/
|
||||
IS_IO_ALLOWED,
|
||||
|
||||
/**
|
||||
* Hook called if swallowing request input should be disabled.
|
||||
* Example: Cancel a large file upload.
|
||||
*
|
||||
*/
|
||||
DISABLE_SWALLOW_INPUT,
|
||||
|
||||
/**
|
||||
* Callback for lazy evaluation - extract the remote host name and address.
|
||||
*/
|
||||
REQ_HOST_ATTRIBUTE,
|
||||
|
||||
/**
|
||||
* Callback for lazy evaluation - extract the remote host address.
|
||||
*/
|
||||
REQ_HOST_ADDR_ATTRIBUTE,
|
||||
|
||||
/**
|
||||
* Callback for lazy evaluation - extract the SSL-related attributes
|
||||
* including the client certificate if present.
|
||||
*/
|
||||
REQ_SSL_ATTRIBUTE,
|
||||
|
||||
/**
|
||||
* Force a TLS re-handshake and make the resulting client certificate (if
|
||||
* any) available as a request attribute.
|
||||
*/
|
||||
REQ_SSL_CERTIFICATE,
|
||||
|
||||
/**
|
||||
* Callback for lazy evaluation - socket remote port.
|
||||
*/
|
||||
REQ_REMOTEPORT_ATTRIBUTE,
|
||||
|
||||
/**
|
||||
* Callback for lazy evaluation - socket local port.
|
||||
*/
|
||||
REQ_LOCALPORT_ATTRIBUTE,
|
||||
|
||||
/**
|
||||
* Callback for lazy evaluation - local address.
|
||||
*/
|
||||
REQ_LOCAL_ADDR_ATTRIBUTE,
|
||||
|
||||
/**
|
||||
* Callback for lazy evaluation - local address.
|
||||
*/
|
||||
REQ_LOCAL_NAME_ATTRIBUTE,
|
||||
|
||||
/**
|
||||
* Callback for setting FORM auth body replay
|
||||
*/
|
||||
REQ_SET_BODY_REPLAY,
|
||||
|
||||
/**
|
||||
* Callback for getting the amount of available bytes.
|
||||
*/
|
||||
AVAILABLE,
|
||||
|
||||
/**
|
||||
* Callback for an async request.
|
||||
*/
|
||||
ASYNC_START,
|
||||
|
||||
/**
|
||||
* Callback for an async call to
|
||||
* {@link javax.servlet.AsyncContext#dispatch()}.
|
||||
*/
|
||||
ASYNC_DISPATCH,
|
||||
|
||||
/**
|
||||
* Callback to indicate the the actual dispatch has started and that the
|
||||
* async state needs change.
|
||||
*/
|
||||
ASYNC_DISPATCHED,
|
||||
|
||||
/**
|
||||
* Callback for an async call to
|
||||
* {@link javax.servlet.AsyncContext#start(Runnable)}.
|
||||
*/
|
||||
ASYNC_RUN,
|
||||
|
||||
/**
|
||||
* Callback for an async call to
|
||||
* {@link javax.servlet.AsyncContext#complete()}.
|
||||
*/
|
||||
ASYNC_COMPLETE,
|
||||
|
||||
/**
|
||||
* Callback to trigger the processing of an async timeout.
|
||||
*/
|
||||
ASYNC_TIMEOUT,
|
||||
|
||||
/**
|
||||
* Callback to trigger the error processing.
|
||||
*/
|
||||
ASYNC_ERROR,
|
||||
|
||||
/**
|
||||
* Callback for an async call to
|
||||
* {@link javax.servlet.AsyncContext#setTimeout(long)}
|
||||
*/
|
||||
ASYNC_SETTIMEOUT,
|
||||
|
||||
/**
|
||||
* Callback to determine if async processing is in progress.
|
||||
*/
|
||||
ASYNC_IS_ASYNC,
|
||||
|
||||
/**
|
||||
* Callback to determine if async dispatch is in progress.
|
||||
*/
|
||||
ASYNC_IS_STARTED,
|
||||
|
||||
/**
|
||||
* Call back to determine if async complete is in progress.
|
||||
*/
|
||||
ASYNC_IS_COMPLETING,
|
||||
|
||||
/**
|
||||
* Callback to determine if async dispatch is in progress.
|
||||
*/
|
||||
ASYNC_IS_DISPATCHING,
|
||||
|
||||
/**
|
||||
* Callback to determine if async is timing out.
|
||||
*/
|
||||
ASYNC_IS_TIMINGOUT,
|
||||
|
||||
/**
|
||||
* Callback to determine if async is in error.
|
||||
*/
|
||||
ASYNC_IS_ERROR,
|
||||
|
||||
/**
|
||||
* Callback to trigger post processing. Typically only used during error
|
||||
* handling to trigger essential processing that otherwise would be skipped.
|
||||
*/
|
||||
ASYNC_POST_PROCESS,
|
||||
|
||||
/**
|
||||
* Callback to trigger the HTTP upgrade process.
|
||||
*/
|
||||
UPGRADE,
|
||||
|
||||
/**
|
||||
* Indicator that Servlet is interested in being
|
||||
* notified when data is available to be read.
|
||||
*/
|
||||
NB_READ_INTEREST,
|
||||
|
||||
/**
|
||||
* Used with non-blocking writes to determine if a write is currently
|
||||
* allowed (sets passed parameter to <code>true</code>) or not (sets passed
|
||||
* parameter to <code>false</code>). If a write is not allowed then callback
|
||||
* will be triggered at some future point when write becomes possible again.
|
||||
*/
|
||||
NB_WRITE_INTEREST,
|
||||
|
||||
/**
|
||||
* Indicates if the request body has been fully read.
|
||||
*/
|
||||
REQUEST_BODY_FULLY_READ,
|
||||
|
||||
/**
|
||||
* Indicates that the container needs to trigger a call to onDataAvailable()
|
||||
* for the registered non-blocking read listener.
|
||||
*/
|
||||
DISPATCH_READ,
|
||||
|
||||
/**
|
||||
* Indicates that the container needs to trigger a call to onWritePossible()
|
||||
* for the registered non-blocking write listener.
|
||||
*/
|
||||
DISPATCH_WRITE,
|
||||
|
||||
/**
|
||||
* Execute any non-blocking dispatches that have been registered via
|
||||
* {@link #DISPATCH_READ} or {@link #DISPATCH_WRITE}. Typically required
|
||||
* when the non-blocking listeners are configured on a thread where the
|
||||
* processing wasn't triggered by a read or write event on the socket.
|
||||
*/
|
||||
DISPATCH_EXECUTE,
|
||||
|
||||
/**
|
||||
* Is server push supported and allowed for the current request?
|
||||
*/
|
||||
IS_PUSH_SUPPORTED,
|
||||
|
||||
/**
|
||||
* Push a request on behalf of the client of the current request.
|
||||
*/
|
||||
PUSH_REQUEST
|
||||
}
|
||||
45
java/org/apache/coyote/ActionHook.java
Normal file
45
java/org/apache/coyote/ActionHook.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.coyote;
|
||||
|
||||
|
||||
/**
|
||||
* Action hook. Actions represent the callback mechanism used by
|
||||
* coyote servlet containers to request operations on the coyote connectors.
|
||||
* Some standard actions are defined in ActionCode, however custom
|
||||
* actions are permitted.
|
||||
*
|
||||
* The param object can be used to pass and return informations related with the
|
||||
* action.
|
||||
*
|
||||
*
|
||||
* This interface is typically implemented by ProtocolHandlers, and the param
|
||||
* is usually a Request or Response object.
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
public interface ActionHook {
|
||||
|
||||
/**
|
||||
* Send an action to the connector.
|
||||
*
|
||||
* @param actionCode Type of the action
|
||||
* @param param Action parameter
|
||||
*/
|
||||
public void action(ActionCode actionCode, Object param);
|
||||
}
|
||||
91
java/org/apache/coyote/Adapter.java
Normal file
91
java/org/apache/coyote/Adapter.java
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote;
|
||||
|
||||
import org.apache.tomcat.util.net.SocketEvent;
|
||||
|
||||
/**
|
||||
* Adapter. This represents the entry point in a coyote-based servlet container.
|
||||
*
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
* @see ProtocolHandler
|
||||
*/
|
||||
public interface Adapter {
|
||||
|
||||
/**
|
||||
* Call the service method, and notify all listeners
|
||||
*
|
||||
* @param req The request object
|
||||
* @param res The response object
|
||||
*
|
||||
* @exception Exception if an error happens during handling of
|
||||
* the request. Common errors are:
|
||||
* <ul><li>IOException if an input/output error occurs and we are
|
||||
* processing an included servlet (otherwise it is swallowed and
|
||||
* handled by the top level error handler mechanism)
|
||||
* <li>ServletException if a servlet throws an exception and
|
||||
* we are processing an included servlet (otherwise it is swallowed
|
||||
* and handled by the top level error handler mechanism)
|
||||
* </ul>
|
||||
* Tomcat should be able to handle and log any other exception ( including
|
||||
* runtime exceptions )
|
||||
*/
|
||||
public void service(Request req, Response res) throws Exception;
|
||||
|
||||
/**
|
||||
* Prepare the given request/response for processing. This method requires
|
||||
* that the request object has been populated with the information available
|
||||
* from the HTTP headers.
|
||||
*
|
||||
* @param req The request object
|
||||
* @param res The response object
|
||||
*
|
||||
* @return <code>true</code> if processing can continue, otherwise
|
||||
* <code>false</code> in which case an appropriate error will have
|
||||
* been set on the response
|
||||
*
|
||||
* @throws Exception If the processing fails unexpectedly
|
||||
*/
|
||||
public boolean prepare(Request req, Response res) throws Exception;
|
||||
|
||||
public boolean asyncDispatch(Request req,Response res, SocketEvent status)
|
||||
throws Exception;
|
||||
|
||||
public void log(Request req, Response res, long time);
|
||||
|
||||
/**
|
||||
* Assert that request and response have been recycled. If they have not
|
||||
* then log a warning and force a recycle. This method is called as a safety
|
||||
* check when a processor is being recycled and may be returned to a pool
|
||||
* for reuse.
|
||||
*
|
||||
* @param req
|
||||
* Request
|
||||
* @param res
|
||||
* Response
|
||||
*/
|
||||
public void checkRecycled(Request req, Response res);
|
||||
|
||||
/**
|
||||
* Provide the name of the domain to use to register MBeans for components
|
||||
* associated with the connector.
|
||||
*
|
||||
* @return The MBean domain name
|
||||
*/
|
||||
public String getDomain();
|
||||
}
|
||||
36
java/org/apache/coyote/AsyncContextCallback.java
Normal file
36
java/org/apache/coyote/AsyncContextCallback.java
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote;
|
||||
|
||||
/**
|
||||
* Provides a mechanism for the Coyote connectors to communicate with the
|
||||
* {@link javax.servlet.AsyncContext}. It is implemented in this manner so that
|
||||
* the org.apache.coyote package does not have a dependency on the
|
||||
* org.apache.catalina package.
|
||||
*/
|
||||
public interface AsyncContextCallback {
|
||||
public void fireOnComplete();
|
||||
|
||||
/**
|
||||
* Reports if the web application associated with this async request is
|
||||
* available.
|
||||
*
|
||||
* @return {@code true} if the associated web application is available,
|
||||
* otherwise {@code false}
|
||||
*/
|
||||
public boolean isAvailable();
|
||||
}
|
||||
494
java/org/apache/coyote/AsyncStateMachine.java
Normal file
494
java/org/apache/coyote/AsyncStateMachine.java
Normal file
@@ -0,0 +1,494 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
import org.apache.tomcat.util.security.PrivilegedGetTccl;
|
||||
import org.apache.tomcat.util.security.PrivilegedSetTccl;
|
||||
|
||||
/**
|
||||
* Manages the state transitions for async requests.
|
||||
*
|
||||
* <pre>
|
||||
* The internal states that are used are:
|
||||
* DISPATCHED - Standard request. Not in Async mode.
|
||||
* STARTING - ServletRequest.startAsync() has been called from
|
||||
* Servlet.service() but service() has not exited.
|
||||
* STARTED - ServletRequest.startAsync() has been called from
|
||||
* Servlet.service() and service() has exited.
|
||||
* READ_WRITE_OP - Performing an asynchronous read or write.
|
||||
* MUST_COMPLETE - ServletRequest.startAsync() followed by complete() have
|
||||
* been called during a single Servlet.service() method. The
|
||||
* complete() will be processed as soon as Servlet.service()
|
||||
* exits.
|
||||
* COMPLETE_PENDING - ServletRequest.startAsync() has been called from
|
||||
* Servlet.service() but, before service() exited, complete()
|
||||
* was called from another thread. The complete() will
|
||||
* be processed as soon as Servlet.service() exits.
|
||||
* COMPLETING - The call to complete() was made once the request was in
|
||||
* the STARTED state.
|
||||
* TIMING_OUT - The async request has timed out and is waiting for a call
|
||||
* to complete() or dispatch(). If that isn't made, the error
|
||||
* state will be entered.
|
||||
* MUST_DISPATCH - ServletRequest.startAsync() followed by dispatch() have
|
||||
* been called during a single Servlet.service() method. The
|
||||
* dispatch() will be processed as soon as Servlet.service()
|
||||
* exits.
|
||||
* DISPATCH_PENDING - ServletRequest.startAsync() has been called from
|
||||
* Servlet.service() but, before service() exited, dispatch()
|
||||
* was called from another thread. The dispatch() will
|
||||
* be processed as soon as Servlet.service() exits.
|
||||
* DISPATCHING - The dispatch is being processed.
|
||||
* MUST_ERROR - ServletRequest.startAsync() has been called from
|
||||
* Servlet.service() but, before service() exited, an I/O
|
||||
* error occured on another thread. The container will
|
||||
* perform the necessary error handling when
|
||||
* Servlet.service() exits.
|
||||
* ERROR - Something went wrong.
|
||||
*
|
||||
*
|
||||
* The valid state transitions are:
|
||||
*
|
||||
* post() dispatched()
|
||||
* |-------»------------------»---------| |-------«-----------------------«-----|
|
||||
* | | | |
|
||||
* | | | post() |
|
||||
* | post() \|/ \|/ dispatched() |
|
||||
* | |-----»----------------»DISPATCHED«-------------«-------------| |
|
||||
* | | | /|\ | | |
|
||||
* | | startAsync()| |--|timeout() | |
|
||||
* ^ | | | |
|
||||
* | | complete() | dispatch() ^ |
|
||||
* | | |--«---------------«-- | ---«--MUST_ERROR--»-----| | |
|
||||
* | | | | /|\ | | |
|
||||
* | ^ | | | | | |
|
||||
* | | | | /-----|error() | | |
|
||||
* | | | | / | ^ |
|
||||
* | | \|/ ST-complete() \|/ / ST-dispatch() \|/ | |
|
||||
* | MUST_COMPLETE«--------«--------STARTING--------»---------»MUST_DISPATCH |
|
||||
* | / | \ |
|
||||
* | / | \ |
|
||||
* | OT-complete() / | \ OT-dispatch() |
|
||||
* | COMPLETE_PENDING«------«------/ | \-------»---------»DISPATCH_PENDING |
|
||||
* | | | | |
|
||||
* | post()| timeout() post()| post() post()| timeout() |
|
||||
* | | |--| | |--| | |--| |
|
||||
* | \|/ \|/ | complete() \|/\|/ | dispatch() \|/ \|/ | |
|
||||
* |--«-----COMPLETING«--------«----------STARTED--------»---------»DISPATCHING----|
|
||||
* /|\ /|\ /|\ | /|\ \ /|\ /|\ /|\
|
||||
* | | | | \ \asyncOperation() | | |
|
||||
* | | | timeout()| \ \ | | |
|
||||
* | | | | \ \ | | |
|
||||
* | | | | \ \ | | |
|
||||
* | | | | \ \ | | |
|
||||
* | | | | \ \ | | |
|
||||
* | | | | post()\ \ dispatch()| | |
|
||||
* | | | complete() | \ \|/ | | |
|
||||
* | | |---«------------«-- | --«---READ_WRITE----»----| | |
|
||||
* | | | | |
|
||||
* | | complete() \|/ dispatch() | |
|
||||
* | |------------«-------TIMING_OUT--------»----------------| |
|
||||
* | |
|
||||
* | complete() dispatch() |
|
||||
* |---------------«-----------ERROR--------------»-----------------|
|
||||
*
|
||||
*
|
||||
* Notes: * For clarity, the transitions to ERROR which are valid from every state apart from
|
||||
* STARTING are not shown.
|
||||
* * All transitions may happen on either the Servlet.service() thread (ST) or on any
|
||||
* other thread (OT) unless explicitly marked.
|
||||
* </pre>
|
||||
*/
|
||||
public class AsyncStateMachine {
|
||||
|
||||
/**
|
||||
* The string manager for this package.
|
||||
*/
|
||||
private static final StringManager sm = StringManager.getManager(AsyncStateMachine.class);
|
||||
|
||||
private enum AsyncState {
|
||||
DISPATCHED (false, false, false, false),
|
||||
STARTING (true, true, false, false),
|
||||
STARTED (true, true, false, false),
|
||||
MUST_COMPLETE (true, true, true, false),
|
||||
COMPLETE_PENDING(true, true, false, false),
|
||||
COMPLETING (true, false, true, false),
|
||||
TIMING_OUT (true, true, false, false),
|
||||
MUST_DISPATCH (true, true, false, true),
|
||||
DISPATCH_PENDING(true, true, false, false),
|
||||
DISPATCHING (true, false, false, true),
|
||||
READ_WRITE_OP (true, true, false, false),
|
||||
MUST_ERROR (true, true, false, false),
|
||||
ERROR (true, true, false, false);
|
||||
|
||||
private final boolean isAsync;
|
||||
private final boolean isStarted;
|
||||
private final boolean isCompleting;
|
||||
private final boolean isDispatching;
|
||||
|
||||
private AsyncState(boolean isAsync, boolean isStarted, boolean isCompleting,
|
||||
boolean isDispatching) {
|
||||
this.isAsync = isAsync;
|
||||
this.isStarted = isStarted;
|
||||
this.isCompleting = isCompleting;
|
||||
this.isDispatching = isDispatching;
|
||||
}
|
||||
|
||||
public boolean isAsync() {
|
||||
return isAsync;
|
||||
}
|
||||
|
||||
public boolean isStarted() {
|
||||
return isStarted;
|
||||
}
|
||||
|
||||
public boolean isDispatching() {
|
||||
return isDispatching;
|
||||
}
|
||||
|
||||
public boolean isCompleting() {
|
||||
return isCompleting;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private volatile AsyncState state = AsyncState.DISPATCHED;
|
||||
private volatile long lastAsyncStart = 0;
|
||||
/*
|
||||
* Tracks the current generation of async processing for this state machine.
|
||||
* The generation is incremented every time async processing is started. The
|
||||
* primary purpose of this is to enable Tomcat to detect and prevent
|
||||
* attempts to process an event for a previous generation with the current
|
||||
* generation as processing such an event usually ends badly:
|
||||
* e.g. CVE-2018-8037.
|
||||
*/
|
||||
private final AtomicLong generation = new AtomicLong(0);
|
||||
// Need this to fire listener on complete
|
||||
private AsyncContextCallback asyncCtxt = null;
|
||||
private final AbstractProcessor processor;
|
||||
|
||||
|
||||
public AsyncStateMachine(AbstractProcessor processor) {
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
|
||||
public boolean isAsync() {
|
||||
return state.isAsync();
|
||||
}
|
||||
|
||||
public boolean isAsyncDispatching() {
|
||||
return state.isDispatching();
|
||||
}
|
||||
|
||||
public boolean isAsyncStarted() {
|
||||
return state.isStarted();
|
||||
}
|
||||
|
||||
public boolean isAsyncTimingOut() {
|
||||
return state == AsyncState.TIMING_OUT;
|
||||
}
|
||||
|
||||
public boolean isAsyncError() {
|
||||
return state == AsyncState.ERROR;
|
||||
}
|
||||
|
||||
public boolean isCompleting() {
|
||||
return state.isCompleting();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the time that this connection last transitioned to async
|
||||
* processing.
|
||||
*
|
||||
* @return The time (as returned by {@link System#currentTimeMillis()}) that
|
||||
* this connection last transitioned to async
|
||||
*/
|
||||
public long getLastAsyncStart() {
|
||||
return lastAsyncStart;
|
||||
}
|
||||
|
||||
long getCurrentGeneration() {
|
||||
return generation.get();
|
||||
}
|
||||
|
||||
public synchronized void asyncStart(AsyncContextCallback asyncCtxt) {
|
||||
if (state == AsyncState.DISPATCHED) {
|
||||
generation.incrementAndGet();
|
||||
state = AsyncState.STARTING;
|
||||
this.asyncCtxt = asyncCtxt;
|
||||
lastAsyncStart = System.currentTimeMillis();
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
sm.getString("asyncStateMachine.invalidAsyncState",
|
||||
"asyncStart()", state));
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void asyncOperation() {
|
||||
if (state==AsyncState.STARTED) {
|
||||
state = AsyncState.READ_WRITE_OP;
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
sm.getString("asyncStateMachine.invalidAsyncState",
|
||||
"asyncOperation()", state));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Async has been processed. Whether or not to enter a long poll depends on
|
||||
* current state. For example, as per SRV.2.3.3.3 can now process calls to
|
||||
* complete() or dispatch().
|
||||
*/
|
||||
public synchronized SocketState asyncPostProcess() {
|
||||
if (state == AsyncState.COMPLETE_PENDING) {
|
||||
clearNonBlockingListeners();
|
||||
state = AsyncState.COMPLETING;
|
||||
return SocketState.ASYNC_END;
|
||||
} else if (state == AsyncState.DISPATCH_PENDING) {
|
||||
clearNonBlockingListeners();
|
||||
state = AsyncState.DISPATCHING;
|
||||
return SocketState.ASYNC_END;
|
||||
} else if (state == AsyncState.STARTING || state == AsyncState.READ_WRITE_OP) {
|
||||
state = AsyncState.STARTED;
|
||||
return SocketState.LONG;
|
||||
} else if (state == AsyncState.MUST_COMPLETE || state == AsyncState.COMPLETING) {
|
||||
asyncCtxt.fireOnComplete();
|
||||
state = AsyncState.DISPATCHED;
|
||||
return SocketState.ASYNC_END;
|
||||
} else if (state == AsyncState.MUST_DISPATCH) {
|
||||
state = AsyncState.DISPATCHING;
|
||||
return SocketState.ASYNC_END;
|
||||
} else if (state == AsyncState.DISPATCHING) {
|
||||
state = AsyncState.DISPATCHED;
|
||||
return SocketState.ASYNC_END;
|
||||
} else if (state == AsyncState.STARTED) {
|
||||
// This can occur if an async listener does a dispatch to an async
|
||||
// servlet during onTimeout
|
||||
return SocketState.LONG;
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
sm.getString("asyncStateMachine.invalidAsyncState",
|
||||
"asyncPostProcess()", state));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public synchronized boolean asyncComplete() {
|
||||
if (!ContainerThreadMarker.isContainerThread() && state == AsyncState.STARTING) {
|
||||
state = AsyncState.COMPLETE_PENDING;
|
||||
return false;
|
||||
}
|
||||
|
||||
clearNonBlockingListeners();
|
||||
boolean triggerDispatch = false;
|
||||
if (state == AsyncState.STARTING || state == AsyncState.MUST_ERROR) {
|
||||
// Processing is on a container thread so no need to transfer
|
||||
// processing to a new container thread
|
||||
state = AsyncState.MUST_COMPLETE;
|
||||
} else if (state == AsyncState.STARTED) {
|
||||
state = AsyncState.COMPLETING;
|
||||
// A dispatch to a container thread is always required.
|
||||
// If on a non-container thread, need to get back onto a container
|
||||
// thread to complete the processing.
|
||||
// If on a container thread the current request/response are not the
|
||||
// request/response associated with the AsyncContext so need a new
|
||||
// container thread to process the different request/response.
|
||||
triggerDispatch = true;
|
||||
} else if (state == AsyncState.READ_WRITE_OP || state == AsyncState.TIMING_OUT ||
|
||||
state == AsyncState.ERROR) {
|
||||
// Read/write operations can happen on or off a container thread but
|
||||
// while in this state the call to listener that triggers the
|
||||
// read/write will be in progress on a container thread.
|
||||
// Processing of timeouts and errors can happen on or off a
|
||||
// container thread (on is much more likely) but while in this state
|
||||
// the call that triggers the timeout will be in progress on a
|
||||
// container thread.
|
||||
// The socket will be added to the poller when the container thread
|
||||
// exits the AbstractConnectionHandler.process() method so don't do
|
||||
// a dispatch here which would add it to the poller a second time.
|
||||
state = AsyncState.COMPLETING;
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
sm.getString("asyncStateMachine.invalidAsyncState",
|
||||
"asyncComplete()", state));
|
||||
}
|
||||
return triggerDispatch;
|
||||
}
|
||||
|
||||
|
||||
public synchronized boolean asyncTimeout() {
|
||||
if (state == AsyncState.STARTED) {
|
||||
state = AsyncState.TIMING_OUT;
|
||||
return true;
|
||||
} else if (state == AsyncState.COMPLETING ||
|
||||
state == AsyncState.DISPATCHING ||
|
||||
state == AsyncState.DISPATCHED) {
|
||||
// NOOP - App called complete() or dispatch() between the the
|
||||
// timeout firing and execution reaching this point
|
||||
return false;
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
sm.getString("asyncStateMachine.invalidAsyncState",
|
||||
"asyncTimeout()", state));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public synchronized boolean asyncDispatch() {
|
||||
if (!ContainerThreadMarker.isContainerThread() && state == AsyncState.STARTING) {
|
||||
state = AsyncState.DISPATCH_PENDING;
|
||||
return false;
|
||||
}
|
||||
|
||||
clearNonBlockingListeners();
|
||||
boolean triggerDispatch = false;
|
||||
if (state == AsyncState.STARTING || state == AsyncState.MUST_ERROR) {
|
||||
// Processing is on a container thread so no need to transfer
|
||||
// processing to a new container thread
|
||||
state = AsyncState.MUST_DISPATCH;
|
||||
} else if (state == AsyncState.STARTED) {
|
||||
state = AsyncState.DISPATCHING;
|
||||
// A dispatch to a container thread is always required.
|
||||
// If on a non-container thread, need to get back onto a container
|
||||
// thread to complete the processing.
|
||||
// If on a container thread the current request/response are not the
|
||||
// request/response associated with the AsyncContext so need a new
|
||||
// container thread to process the different request/response.
|
||||
triggerDispatch = true;
|
||||
} else if (state == AsyncState.READ_WRITE_OP || state == AsyncState.TIMING_OUT ||
|
||||
state == AsyncState.ERROR) {
|
||||
// Read/write operations can happen on or off a container thread but
|
||||
// while in this state the call to listener that triggers the
|
||||
// read/write will be in progress on a container thread.
|
||||
// Processing of timeouts and errors can happen on or off a
|
||||
// container thread (on is much more likely) but while in this state
|
||||
// the call that triggers the timeout will be in progress on a
|
||||
// container thread.
|
||||
// The socket will be added to the poller when the container thread
|
||||
// exits the AbstractConnectionHandler.process() method so don't do
|
||||
// a dispatch here which would add it to the poller a second time.
|
||||
state = AsyncState.DISPATCHING;
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
sm.getString("asyncStateMachine.invalidAsyncState",
|
||||
"asyncDispatch()", state));
|
||||
}
|
||||
return triggerDispatch;
|
||||
}
|
||||
|
||||
|
||||
public synchronized void asyncDispatched() {
|
||||
if (state == AsyncState.DISPATCHING ||
|
||||
state == AsyncState.MUST_DISPATCH) {
|
||||
state = AsyncState.DISPATCHED;
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
sm.getString("asyncStateMachine.invalidAsyncState",
|
||||
"asyncDispatched()", state));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public synchronized boolean asyncError() {
|
||||
clearNonBlockingListeners();
|
||||
if (state == AsyncState.STARTING) {
|
||||
state = AsyncState.MUST_ERROR;
|
||||
} else {
|
||||
state = AsyncState.ERROR;
|
||||
}
|
||||
return !ContainerThreadMarker.isContainerThread();
|
||||
}
|
||||
|
||||
|
||||
public synchronized void asyncRun(Runnable runnable) {
|
||||
if (state == AsyncState.STARTING || state == AsyncState.STARTED ||
|
||||
state == AsyncState.READ_WRITE_OP) {
|
||||
// Execute the runnable using a container thread from the
|
||||
// Connector's thread pool. Use a wrapper to prevent a memory leak
|
||||
ClassLoader oldCL;
|
||||
if (Constants.IS_SECURITY_ENABLED) {
|
||||
PrivilegedAction<ClassLoader> pa = new PrivilegedGetTccl();
|
||||
oldCL = AccessController.doPrivileged(pa);
|
||||
} else {
|
||||
oldCL = Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
try {
|
||||
if (Constants.IS_SECURITY_ENABLED) {
|
||||
PrivilegedAction<Void> pa = new PrivilegedSetTccl(
|
||||
this.getClass().getClassLoader());
|
||||
AccessController.doPrivileged(pa);
|
||||
} else {
|
||||
Thread.currentThread().setContextClassLoader(
|
||||
this.getClass().getClassLoader());
|
||||
}
|
||||
|
||||
processor.getExecutor().execute(runnable);
|
||||
} finally {
|
||||
if (Constants.IS_SECURITY_ENABLED) {
|
||||
PrivilegedAction<Void> pa = new PrivilegedSetTccl(
|
||||
oldCL);
|
||||
AccessController.doPrivileged(pa);
|
||||
} else {
|
||||
Thread.currentThread().setContextClassLoader(oldCL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
sm.getString("asyncStateMachine.invalidAsyncState",
|
||||
"asyncRun()", state));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
synchronized boolean isAvailable() {
|
||||
if (asyncCtxt == null) {
|
||||
// Async processing has probably been completed in another thread.
|
||||
// Trigger a timeout to make sure the Processor is cleaned up.
|
||||
return false;
|
||||
}
|
||||
return asyncCtxt.isAvailable();
|
||||
}
|
||||
|
||||
|
||||
public synchronized void recycle() {
|
||||
// Use lastAsyncStart to determine if this instance has been used since
|
||||
// it was last recycled. If it hasn't there is no need to recycle again
|
||||
// which saves the relatively expensive call to notifyAll()
|
||||
if (lastAsyncStart == 0) {
|
||||
return;
|
||||
}
|
||||
// Ensure in case of error that any non-container threads that have been
|
||||
// paused are unpaused.
|
||||
notifyAll();
|
||||
asyncCtxt = null;
|
||||
state = AsyncState.DISPATCHED;
|
||||
lastAsyncStart = 0;
|
||||
}
|
||||
|
||||
|
||||
private void clearNonBlockingListeners() {
|
||||
processor.getRequest().listener = null;
|
||||
processor.getRequest().getResponse().listener = null;
|
||||
}
|
||||
}
|
||||
51
java/org/apache/coyote/CloseNowException.java
Normal file
51
java/org/apache/coyote/CloseNowException.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This exception is thrown to signal to the Tomcat internals that an error has
|
||||
* occurred that requires the connection to be closed. For multiplexed protocols
|
||||
* such as HTTP/2, this means the channel must be closed but the connection can
|
||||
* continue. For non-multiplexed protocols, the connection must be closed. It
|
||||
* corresponds to {@link ErrorState#CLOSE_NOW}.
|
||||
*/
|
||||
public class CloseNowException extends IOException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
public CloseNowException() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
public CloseNowException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
|
||||
public CloseNowException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
public CloseNowException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
351
java/org/apache/coyote/CompressionConfig.java
Normal file
351
java/org/apache/coyote/CompressionConfig.java
Normal file
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.buf.MessageBytes;
|
||||
import org.apache.tomcat.util.http.MimeHeaders;
|
||||
import org.apache.tomcat.util.http.ResponseUtil;
|
||||
import org.apache.tomcat.util.http.parser.AcceptEncoding;
|
||||
import org.apache.tomcat.util.http.parser.TokenList;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
public class CompressionConfig {
|
||||
|
||||
private static final Log log = LogFactory.getLog(CompressionConfig.class);
|
||||
private static final StringManager sm = StringManager.getManager(CompressionConfig.class);
|
||||
|
||||
private int compressionLevel = 0;
|
||||
private Pattern noCompressionUserAgents = null;
|
||||
private String compressibleMimeType = "text/html,text/xml,text/plain,text/css," +
|
||||
"text/javascript,application/javascript,application/json,application/xml";
|
||||
private String[] compressibleMimeTypes = null;
|
||||
private int compressionMinSize = 2048;
|
||||
private boolean noCompressionStrongETag = true;
|
||||
|
||||
|
||||
/**
|
||||
* Set compression level.
|
||||
*
|
||||
* @param compression One of <code>on</code>, <code>force</code>,
|
||||
* <code>off</code> or the minimum compression size in
|
||||
* bytes which implies <code>on</code>
|
||||
*/
|
||||
public void setCompression(String compression) {
|
||||
if (compression.equals("on")) {
|
||||
this.compressionLevel = 1;
|
||||
} else if (compression.equals("force")) {
|
||||
this.compressionLevel = 2;
|
||||
} else if (compression.equals("off")) {
|
||||
this.compressionLevel = 0;
|
||||
} else {
|
||||
try {
|
||||
// Try to parse compression as an int, which would give the
|
||||
// minimum compression size
|
||||
setCompressionMinSize(Integer.parseInt(compression));
|
||||
this.compressionLevel = 1;
|
||||
} catch (Exception e) {
|
||||
this.compressionLevel = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return compression level.
|
||||
*
|
||||
* @return The current compression level in string form (off/on/force)
|
||||
*/
|
||||
public String getCompression() {
|
||||
switch (compressionLevel) {
|
||||
case 0:
|
||||
return "off";
|
||||
case 1:
|
||||
return "on";
|
||||
case 2:
|
||||
return "force";
|
||||
}
|
||||
return "off";
|
||||
}
|
||||
|
||||
|
||||
public int getCompressionLevel() {
|
||||
return compressionLevel;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtain the String form of the regular expression that defines the user
|
||||
* agents to not use gzip with.
|
||||
*
|
||||
* @return The regular expression as a String
|
||||
*/
|
||||
public String getNoCompressionUserAgents() {
|
||||
if (noCompressionUserAgents == null) {
|
||||
return null;
|
||||
} else {
|
||||
return noCompressionUserAgents.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Pattern getNoCompressionUserAgentsPattern() {
|
||||
return noCompressionUserAgents;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set no compression user agent pattern. Regular expression as supported
|
||||
* by {@link Pattern}. e.g.: <code>gorilla|desesplorer|tigrus</code>.
|
||||
*
|
||||
* @param noCompressionUserAgents The regular expression for user agent
|
||||
* strings for which compression should not
|
||||
* be applied
|
||||
*/
|
||||
public void setNoCompressionUserAgents(String noCompressionUserAgents) {
|
||||
if (noCompressionUserAgents == null || noCompressionUserAgents.length() == 0) {
|
||||
this.noCompressionUserAgents = null;
|
||||
} else {
|
||||
this.noCompressionUserAgents =
|
||||
Pattern.compile(noCompressionUserAgents);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getCompressibleMimeType() {
|
||||
return compressibleMimeType;
|
||||
}
|
||||
|
||||
|
||||
public void setCompressibleMimeType(String valueS) {
|
||||
compressibleMimeType = valueS;
|
||||
compressibleMimeTypes = null;
|
||||
}
|
||||
|
||||
|
||||
public String[] getCompressibleMimeTypes() {
|
||||
String[] result = compressibleMimeTypes;
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
List<String> values = new ArrayList<>();
|
||||
StringTokenizer tokens = new StringTokenizer(compressibleMimeType, ",");
|
||||
while (tokens.hasMoreTokens()) {
|
||||
String token = tokens.nextToken().trim();
|
||||
if (token.length() > 0) {
|
||||
values.add(token);
|
||||
}
|
||||
}
|
||||
result = values.toArray(new String[values.size()]);
|
||||
compressibleMimeTypes = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public int getCompressionMinSize() {
|
||||
return compressionMinSize;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set Minimum size to trigger compression.
|
||||
*
|
||||
* @param compressionMinSize The minimum content length required for
|
||||
* compression in bytes
|
||||
*/
|
||||
public void setCompressionMinSize(int compressionMinSize) {
|
||||
this.compressionMinSize = compressionMinSize;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if compression is disabled if the resource has a strong ETag.
|
||||
*
|
||||
* @return {@code true} if compression is disabled, otherwise {@code false}
|
||||
*
|
||||
* @deprecated Will be removed in Tomcat 10 where it will be hard-coded to
|
||||
* {@code true}
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean getNoCompressionStrongETag() {
|
||||
return noCompressionStrongETag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set whether compression is disabled for resources with a strong ETag.
|
||||
*
|
||||
* @param noCompressionStrongETag {@code true} if compression is disabled,
|
||||
* otherwise {@code false}
|
||||
*
|
||||
* @deprecated Will be removed in Tomcat 10 where it will be hard-coded to
|
||||
* {@code true}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setNoCompressionStrongETag(boolean noCompressionStrongETag) {
|
||||
this.noCompressionStrongETag = noCompressionStrongETag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines if compression should be enabled for the given response and if
|
||||
* it is, sets any necessary headers to mark it as such.
|
||||
*
|
||||
* @param request The request that triggered the response
|
||||
* @param response The response to consider compressing
|
||||
*
|
||||
* @return {@code true} if compression was enabled for the given response,
|
||||
* otherwise {@code false}
|
||||
*/
|
||||
public boolean useCompression(Request request, Response response) {
|
||||
// Check if compression is enabled
|
||||
if (compressionLevel == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MimeHeaders responseHeaders = response.getMimeHeaders();
|
||||
|
||||
// Check if content is not already compressed
|
||||
MessageBytes contentEncodingMB = responseHeaders.getValue("Content-Encoding");
|
||||
if (contentEncodingMB != null) {
|
||||
// Content-Encoding values are ordered but order is not important
|
||||
// for this check so use a Set rather than a List
|
||||
Set<String> tokens = new HashSet<>();
|
||||
try {
|
||||
TokenList.parseTokenList(responseHeaders.values("Content-Encoding"), tokens);
|
||||
} catch (IOException e) {
|
||||
// Because we are using StringReader, any exception here is a
|
||||
// Tomcat bug.
|
||||
log.warn(sm.getString("compressionConfig.ContentEncodingParseFail"), e);
|
||||
return false;
|
||||
}
|
||||
if (tokens.contains("gzip") || tokens.contains("br")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If force mode, the length and MIME type checks are skipped
|
||||
if (compressionLevel != 2) {
|
||||
// Check if the response is of sufficient length to trigger the compression
|
||||
long contentLength = response.getContentLengthLong();
|
||||
if (contentLength != -1 && contentLength < compressionMinSize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for compatible MIME-TYPE
|
||||
String[] compressibleMimeTypes = getCompressibleMimeTypes();
|
||||
if (compressibleMimeTypes != null &&
|
||||
!startsWithStringArray(compressibleMimeTypes, response.getContentType())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the resource has a strong ETag
|
||||
if (noCompressionStrongETag) {
|
||||
String eTag = responseHeaders.getHeader("ETag");
|
||||
if (eTag != null && !eTag.trim().startsWith("W/")) {
|
||||
// Has an ETag that doesn't start with "W/..." so it must be a
|
||||
// strong ETag
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If processing reaches this far, the response might be compressed.
|
||||
// Therefore, set the Vary header to keep proxies happy
|
||||
ResponseUtil.addVaryFieldName(responseHeaders, "accept-encoding");
|
||||
|
||||
// Check if user-agent supports gzip encoding
|
||||
// Only interested in whether gzip encoding is supported. Other
|
||||
// encodings and weights can be ignored.
|
||||
Enumeration<String> headerValues = request.getMimeHeaders().values("accept-encoding");
|
||||
boolean foundGzip = false;
|
||||
while (!foundGzip && headerValues.hasMoreElements()) {
|
||||
List<AcceptEncoding> acceptEncodings = null;
|
||||
try {
|
||||
acceptEncodings = AcceptEncoding.parse(new StringReader(headerValues.nextElement()));
|
||||
} catch (IOException ioe) {
|
||||
// If there is a problem reading the header, disable compression
|
||||
return false;
|
||||
}
|
||||
|
||||
for (AcceptEncoding acceptEncoding : acceptEncodings) {
|
||||
if ("gzip".equalsIgnoreCase(acceptEncoding.getEncoding())) {
|
||||
foundGzip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundGzip) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If force mode, the browser checks are skipped
|
||||
if (compressionLevel != 2) {
|
||||
// Check for incompatible Browser
|
||||
Pattern noCompressionUserAgents = this.noCompressionUserAgents;
|
||||
if (noCompressionUserAgents != null) {
|
||||
MessageBytes userAgentValueMB = request.getMimeHeaders().getValue("user-agent");
|
||||
if(userAgentValueMB != null) {
|
||||
String userAgentValue = userAgentValueMB.toString();
|
||||
if (noCompressionUserAgents.matcher(userAgentValue).matches()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All checks have passed. Compression is enabled.
|
||||
|
||||
// Compressed content length is unknown so mark it as such.
|
||||
response.setContentLength(-1);
|
||||
// Configure the content encoding for compressed content
|
||||
responseHeaders.setValue("Content-Encoding").setString("gzip");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if any entry in the string array starts with the specified value
|
||||
*
|
||||
* @param sArray the StringArray
|
||||
* @param value string
|
||||
*/
|
||||
private static boolean startsWithStringArray(String sArray[], String value) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < sArray.length; i++) {
|
||||
if (value.startsWith(sArray[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
114
java/org/apache/coyote/Constants.java
Normal file
114
java/org/apache/coyote/Constants.java
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Constants.
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
public final class Constants {
|
||||
|
||||
/**
|
||||
* @deprecated This will be removed in Tomcat 9.0.x onwards.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String DEFAULT_CHARACTER_ENCODING="ISO-8859-1";
|
||||
|
||||
public static final Charset DEFAULT_URI_CHARSET = StandardCharsets.ISO_8859_1;
|
||||
public static final Charset DEFAULT_BODY_CHARSET = StandardCharsets.ISO_8859_1;
|
||||
|
||||
public static final int MAX_NOTES = 32;
|
||||
|
||||
|
||||
// Request states
|
||||
public static final int STAGE_NEW = 0;
|
||||
public static final int STAGE_PARSE = 1;
|
||||
public static final int STAGE_PREPARE = 2;
|
||||
public static final int STAGE_SERVICE = 3;
|
||||
public static final int STAGE_ENDINPUT = 4;
|
||||
public static final int STAGE_ENDOUTPUT = 5;
|
||||
public static final int STAGE_KEEPALIVE = 6;
|
||||
public static final int STAGE_ENDED = 7;
|
||||
|
||||
// Default protocol settings
|
||||
public static final int DEFAULT_CONNECTION_LINGER = -1;
|
||||
public static final boolean DEFAULT_TCP_NO_DELAY = true;
|
||||
|
||||
/**
|
||||
* Has security been turned on?
|
||||
*/
|
||||
public static final boolean IS_SECURITY_ENABLED = (System.getSecurityManager() != null);
|
||||
|
||||
|
||||
/**
|
||||
* If true, custom HTTP status messages will be used in headers.
|
||||
* @deprecated This option will be removed in Tomcat 9. Reason phrase will
|
||||
* not be sent.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final boolean USE_CUSTOM_STATUS_MSG_IN_HEADER =
|
||||
Boolean.getBoolean("org.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER");
|
||||
|
||||
/**
|
||||
* The request attribute that is set to the value of {@code Boolean.TRUE}
|
||||
* if connector processing this request supports use of sendfile.
|
||||
*/
|
||||
public static final String SENDFILE_SUPPORTED_ATTR = "org.apache.tomcat.sendfile.support";
|
||||
|
||||
|
||||
/**
|
||||
* The request attribute that can be used by a servlet to pass
|
||||
* to the connector the name of the file that is to be served
|
||||
* by sendfile. The value should be {@code java.lang.String}
|
||||
* that is {@code File.getCanonicalPath()} of the file to be served.
|
||||
*/
|
||||
public static final String SENDFILE_FILENAME_ATTR = "org.apache.tomcat.sendfile.filename";
|
||||
|
||||
|
||||
/**
|
||||
* The request attribute that can be used by a servlet to pass
|
||||
* to the connector the start offset of the part of a file
|
||||
* that is to be served by sendfile. The value should be
|
||||
* {@code java.lang.Long}. To serve complete file
|
||||
* the value should be {@code Long.valueOf(0)}.
|
||||
*/
|
||||
public static final String SENDFILE_FILE_START_ATTR = "org.apache.tomcat.sendfile.start";
|
||||
|
||||
|
||||
/**
|
||||
* The request attribute that can be used by a servlet to pass
|
||||
* to the connector the end offset (not including) of the part
|
||||
* of a file that is to be served by sendfile. The value should be
|
||||
* {@code java.lang.Long}. To serve complete file
|
||||
* the value should be equal to the length of the file.
|
||||
*/
|
||||
public static final String SENDFILE_FILE_END_ATTR = "org.apache.tomcat.sendfile.end";
|
||||
|
||||
|
||||
/**
|
||||
* The request attribute set by the RemoteIpFilter, RemoteIpValve (and may
|
||||
* be set by other similar components) that identifies for the connector the
|
||||
* remote IP address claimed to be associated with this request when a
|
||||
* request is received via one or more proxies. It is typically provided via
|
||||
* the X-Forwarded-For HTTP header.
|
||||
*/
|
||||
public static final String REMOTE_ADDR_ATTRIBUTE = "org.apache.tomcat.remoteAddr";
|
||||
}
|
||||
38
java/org/apache/coyote/ContainerThreadMarker.java
Normal file
38
java/org/apache/coyote/ContainerThreadMarker.java
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote;
|
||||
|
||||
/**
|
||||
* Used to mark threads that have been allocated by the container to process
|
||||
* data from an incoming connection. Application created threads are not
|
||||
* container threads and neither are threads taken from the container thread
|
||||
* pool to execute AsyncContext.start(Runnable).
|
||||
*/
|
||||
public class ContainerThreadMarker {
|
||||
|
||||
public static boolean isContainerThread() {
|
||||
return org.apache.tomcat.util.net.ContainerThreadMarker.isContainerThread();
|
||||
}
|
||||
|
||||
public static void set() {
|
||||
org.apache.tomcat.util.net.ContainerThreadMarker.set();
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
org.apache.tomcat.util.net.ContainerThreadMarker.clear();
|
||||
}
|
||||
}
|
||||
93
java/org/apache/coyote/ErrorState.java
Normal file
93
java/org/apache/coyote/ErrorState.java
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote;
|
||||
|
||||
public enum ErrorState {
|
||||
|
||||
/**
|
||||
* Not in an error state.
|
||||
*/
|
||||
NONE(false, 0, true, true),
|
||||
|
||||
/**
|
||||
* The current request/response is in an error state and while it is safe to
|
||||
* complete the current response it is not safe to continue to use the
|
||||
* existing connection which must be closed once the response has been
|
||||
* completed. For multiplexed protocols, the channel must be closed when the
|
||||
* current request/response completes but the connection may continue.
|
||||
*/
|
||||
CLOSE_CLEAN(true, 1, true, true),
|
||||
|
||||
/**
|
||||
* The current request/response is in an error state and it is not safe to
|
||||
* continue to use them. For multiplexed protocols (such as HTTP/2) the
|
||||
* stream/channel must be closed immediately but the connection may
|
||||
* continue. For non-multiplexed protocols (AJP, HTTP/1.x) the current
|
||||
* connection must be closed.
|
||||
*/
|
||||
CLOSE_NOW(true, 2, false, true),
|
||||
|
||||
/**
|
||||
* An error has been detected that impacts the underlying network
|
||||
* connection. It is not safe to continue using the network connection which
|
||||
* must be closed immediately. For multiplexed protocols (such as HTTP/2)
|
||||
* this impacts all multiplexed channels.
|
||||
*/
|
||||
CLOSE_CONNECTION_NOW(true, 3, false, false);
|
||||
|
||||
private final boolean error;
|
||||
private final int severity;
|
||||
private final boolean ioAllowed;
|
||||
private final boolean connectionIoAllowed;
|
||||
|
||||
private ErrorState(boolean error, int severity, boolean ioAllowed,
|
||||
boolean connectionIoAllowed) {
|
||||
this.error = error;
|
||||
this.severity = severity;
|
||||
this.ioAllowed = ioAllowed;
|
||||
this.connectionIoAllowed = connectionIoAllowed;
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare this ErrorState with the provided ErrorState and return the most
|
||||
* severe.
|
||||
*
|
||||
* @param input The error state to compare to this one
|
||||
*
|
||||
* @return The most severe error state from the the provided error state and
|
||||
* this one
|
||||
*/
|
||||
public ErrorState getMostSevere(ErrorState input) {
|
||||
if (input.severity > this.severity) {
|
||||
return input;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isIoAllowed() {
|
||||
return ioAllowed;
|
||||
}
|
||||
|
||||
public boolean isConnectionIoAllowed() {
|
||||
return connectionIoAllowed;
|
||||
}
|
||||
}
|
||||
64
java/org/apache/coyote/InputBuffer.java
Normal file
64
java/org/apache/coyote/InputBuffer.java
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.tomcat.util.buf.ByteChunk;
|
||||
import org.apache.tomcat.util.net.ApplicationBufferHandler;
|
||||
|
||||
/**
|
||||
* This class is only for internal use in the protocol implementation. All
|
||||
* reading from Tomcat (or adapter) should be done using Request.doRead().
|
||||
*/
|
||||
public interface InputBuffer {
|
||||
|
||||
/**
|
||||
* Read from the input stream into the given buffer.
|
||||
* IMPORTANT: the current model assumes that the protocol will 'own' the
|
||||
* buffer and return a pointer to it in ByteChunk (i.e. the param will
|
||||
* have chunk.getBytes()==null before call, and the result after the call).
|
||||
*
|
||||
* @param chunk The buffer to read data into.
|
||||
*
|
||||
* @return The number of bytes that have been added to the buffer or -1 for
|
||||
* end of stream
|
||||
*
|
||||
* @throws IOException If an I/O error occurs reading from the input stream
|
||||
*
|
||||
* @deprecated Unused. Will be removed in Tomcat 9. Use
|
||||
* {@link #doRead(ApplicationBufferHandler)}
|
||||
*/
|
||||
@Deprecated
|
||||
public int doRead(ByteChunk chunk) throws IOException;
|
||||
|
||||
/**
|
||||
* Read from the input stream into the ByteBuffer provided by the
|
||||
* ApplicationBufferHandler.
|
||||
* IMPORTANT: the current model assumes that the protocol will 'own' the
|
||||
* ByteBuffer and return a pointer to it.
|
||||
*
|
||||
* @param handler ApplicationBufferHandler that provides the buffer to read
|
||||
* data into.
|
||||
*
|
||||
* @return The number of bytes that have been added to the buffer or -1 for
|
||||
* end of stream
|
||||
*
|
||||
* @throws IOException If an I/O error occurs reading from the input stream
|
||||
*/
|
||||
public int doRead(ApplicationBufferHandler handler) throws IOException;
|
||||
}
|
||||
67
java/org/apache/coyote/LocalStrings.properties
Normal file
67
java/org/apache/coyote/LocalStrings.properties
Normal file
@@ -0,0 +1,67 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
abstractConnectionHandler.connectionsGet=Found processor [{0}] for socket [{1}]
|
||||
abstractConnectionHandler.error=Error reading request, ignored
|
||||
abstractConnectionHandler.ioexception.debug=IOExceptions are normal, ignored
|
||||
abstractConnectionHandler.negotiatedProcessor.fail=Failed to create Processor for negotiated protocol [{0}]
|
||||
abstractConnectionHandler.oome=Failed to complete processing of a request
|
||||
abstractConnectionHandler.process=Processing socket [{0}] with status [{1}]
|
||||
abstractConnectionHandler.processorCreate=Created new processor [{0}]
|
||||
abstractConnectionHandler.processorPop=Popped processor [{0}] from cache
|
||||
abstractConnectionHandler.protocolexception.debug=ProtocolExceptions are normal, ignored
|
||||
abstractConnectionHandler.socketexception.debug=SocketExceptions are normal, ignored
|
||||
abstractConnectionHandler.upgradeCreate=Created upgrade processor [{0}] for socket wrapper [{1}]
|
||||
|
||||
abstractProcessor.fallToDebug=\n\
|
||||
\ Note: further occurrences of request parsing errors will be logged at DEBUG level.
|
||||
abstractProcessor.hostInvalid=The host [{0}] is not valid
|
||||
abstractProcessor.httpupgrade.notsupported=HTTP upgrade is not supported by this protocol
|
||||
abstractProcessor.pushrequest.notsupported=Server push requests are not supported by this protocol
|
||||
abstractProcessor.socket.ssl=Exception getting SSL attributes
|
||||
|
||||
abstractProtocol.mbeanDeregistrationFailed=Failed to deregister MBean named [{0}] from MBean server [{1}]
|
||||
abstractProtocol.processorRegisterError=Error registering request processor
|
||||
abstractProtocol.processorUnregisterError=Error unregistering request processor
|
||||
abstractProcotol.waitingProcerssor.add=Added processor [{0}] to waiting processors
|
||||
abstractProcotol.waitingProcerssor.remove=Removed processor [{0}] from waiting processors
|
||||
|
||||
abstractProtocolHandler.destroy=Destroying ProtocolHandler [{0}]
|
||||
abstractProtocolHandler.destroyError=Failed to destroy end point associated with ProtocolHandler [{0}]
|
||||
abstractProtocolHandler.getAttribute=Get attribute [{0}] with value [{1}]
|
||||
abstractProtocolHandler.init=Initializing ProtocolHandler [{0}]
|
||||
abstractProtocolHandler.pause=Pausing ProtocolHandler [{0}]
|
||||
abstractProtocolHandler.pauseError=Failed to pause end point associated with ProtocolHandler [{0}]
|
||||
abstractProtocolHandler.resume=Resuming ProtocolHandler [{0}]
|
||||
abstractProtocolHandler.resumeError=Failed to resume end point associated with ProtocolHandler [{0}]
|
||||
abstractProtocolHandler.setAttribute=Set attribute [{0}] with value [{1}]
|
||||
abstractProtocolHandler.start=Starting ProtocolHandler [{0}]
|
||||
abstractProtocolHandler.startError=Failed to start end point associated with ProtocolHandler [{0}]
|
||||
abstractProtocolHandler.stop=Stopping ProtocolHandler [{0}]
|
||||
abstractProtocolHandler.stopError=Failed to stop end point associated with ProtocolHandler [{0}]
|
||||
|
||||
asyncStateMachine.invalidAsyncState=Calling [{0}] is not valid for a request with Async state [{1}]
|
||||
|
||||
compressionConfig.ContentEncodingParseFail=Failed to parse Content-Encoding header when checking to see if compression was already in use
|
||||
|
||||
request.notAsync=It is only valid to switch to non-blocking IO within async processing or HTTP upgrade processing
|
||||
request.nullReadListener=The listener passed to setReadListener() may not be null
|
||||
request.readListenerSet=The non-blocking read listener has already been set
|
||||
|
||||
response.encoding.invalid=The encoding [{0}] is not recognised by the JRE
|
||||
response.notAsync=It is only valid to switch to non-blocking IO within async processing or HTTP upgrade processing
|
||||
response.notNonBlocking=It is invalid to call isReady() when the response has not been put into non-blocking mode
|
||||
response.nullWriteListener=The listener passed to setWriteListener() may not be null
|
||||
response.writeListenerSet=The non-blocking write listener has already been set
|
||||
28
java/org/apache/coyote/LocalStrings_de.properties
Normal file
28
java/org/apache/coyote/LocalStrings_de.properties
Normal file
@@ -0,0 +1,28 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
abstractConnectionHandler.oome=Verarbeitung der Anfrage fehlgeschlagen
|
||||
abstractConnectionHandler.processorPop=Prozessor [{0}] wurde aus dem Cache genommen.
|
||||
abstractConnectionHandler.socketexception.debug=SocketExceptions sind normal, werden ignoriert
|
||||
|
||||
abstractProcessor.fallToDebug=Info: Weitere Vorkommen von Fehlern beim Parsen der Anfragen werden mit DEBUG Level ausgegeben
|
||||
abstractProcessor.hostInvalid=Der Host [{0}] ist nicht gültig.
|
||||
abstractProcessor.httpupgrade.notsupported=HTTP-Upgrade wird von diesem Protokol nicht unterstützt
|
||||
|
||||
abstractProtocolHandler.init=Initialisiere ProtocolHandler[{0}]
|
||||
|
||||
asyncStateMachine.invalidAsyncState=Der Aufruf von [{0}] ist nicht erlaubt, während der Request im Async-Status [{1}] ist
|
||||
|
||||
response.writeListenerSet=Der Nicht-blockierende Schreib-Listener wurde bereits gesetzt
|
||||
28
java/org/apache/coyote/LocalStrings_es.properties
Normal file
28
java/org/apache/coyote/LocalStrings_es.properties
Normal file
@@ -0,0 +1,28 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
abstractConnectionHandler.error=Error leyendo requerimiento, ignorado
|
||||
abstractConnectionHandler.processorPop=Sacando procesador [{0}] de la cache
|
||||
|
||||
abstractProcessor.fallToDebug=Nota: futuras ocurrencias de la solicitud the parseo de errores será logueada con nivel DEBUG.
|
||||
abstractProcessor.hostInvalid=El host [{0}] no es válido\n
|
||||
abstractProcessor.httpupgrade.notsupported=La actualización HTTP no esta soportada por esta protocol
|
||||
abstractProcessor.socket.ssl=Excepción obteniendo atributos SSL
|
||||
|
||||
abstractProtocolHandler.init=Inicializando el manejador de protocolo [{0}]\n
|
||||
|
||||
asyncStateMachine.invalidAsyncState=Llamando [{0}] no es una solicitud válida en el estado [{1}]\n
|
||||
|
||||
response.writeListenerSet=El escuchador de escritura no bloqueable ya ha sido establecido
|
||||
57
java/org/apache/coyote/LocalStrings_fr.properties
Normal file
57
java/org/apache/coyote/LocalStrings_fr.properties
Normal file
@@ -0,0 +1,57 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
abstractConnectionHandler.connectionsGet=Trouvé le processeur [{0}] pour le socket [{1}]
|
||||
abstractConnectionHandler.error=Erreur de lecture de la requête, ignorée
|
||||
abstractConnectionHandler.ioexception.debug=Les IOException sont normales et sont ignorées
|
||||
abstractConnectionHandler.negotiatedProcessor.fail=Impossible de créer un processeur pour le protocole négocié [{0}]
|
||||
abstractConnectionHandler.oome=Echec de la fin de traitement d'une requête
|
||||
abstractConnectionHandler.process=Traitement du socket [{0}] avec le statut [{1}]
|
||||
abstractConnectionHandler.processorPop=Retrait du processeur [{0}] du cache
|
||||
abstractConnectionHandler.protocolexception.debug=Les ProtocolExceptions sont normales et sont ignorées
|
||||
abstractConnectionHandler.socketexception.debug=Les SocketException sont normales et sont ignorées
|
||||
abstractConnectionHandler.upgradeCreate=Création du processeur pour l''upgrade [{0}] du wrapper du socket [{1}]
|
||||
|
||||
abstractProcessor.fallToDebug=\ Note : les occurrences suivantes d'erreur d'analyse de la requête seront enregistrées au niveau DEBUG
|
||||
abstractProcessor.hostInvalid=L''hôte [{0}] n''est pas valide
|
||||
abstractProcessor.httpupgrade.notsupported=La promotion (upgrade) HTTP n'est pas supporté par ce protocole
|
||||
abstractProcessor.pushrequest.notsupported=Le requêtes push du serveur ne sont pas supportées par ce protocole
|
||||
abstractProcessor.socket.ssl=Exception lors de l'obtention des attributs SSL
|
||||
|
||||
abstractProtocol.mbeanDeregistrationFailed=Erreur lors du désenregistrement du mbean [{0}] dans le serveur [{1}]
|
||||
abstractProtocol.processorRegisterError=Erreur lors de l'enregistrement du processeur de requêtes
|
||||
abstractProtocol.processorUnregisterError=Erreur lors du désenregistrement du processeur de requêtes
|
||||
|
||||
abstractProtocolHandler.destroy=Destruction du gestionnaire de protocole [{0}]
|
||||
abstractProtocolHandler.init=Initialisation du gestionnaire de protocole [{0}]
|
||||
abstractProtocolHandler.pause=Le gestionnaire de protocole [{0}] est mis en pause
|
||||
abstractProtocolHandler.resume=Reprise du gestionnaire de protocole [{0}]
|
||||
abstractProtocolHandler.setAttribute=Fixe l''attribut [{0}] avec la valeur [{1}]
|
||||
abstractProtocolHandler.start=Démarrage du gestionnaire de protocole [{0}]
|
||||
abstractProtocolHandler.stop=Arrêt du gestionnaire de protocole [{0}]
|
||||
|
||||
asyncStateMachine.invalidAsyncState=L''appel à [{0}] n''est pas valide pour une requête dans l''état Async [{1}]
|
||||
|
||||
compressionConfig.ContentEncodingParseFail=Echec du traitement de l'en-tête Content-Encoding en vérifiant si la compression était déjà utilisée
|
||||
|
||||
request.notAsync=Il n'est possible de passer en mode d'entrée-sorties non bloquantes que lors de traitements asynchrones ou après mise à niveau depuis HTTP
|
||||
request.nullReadListener=L'écouteur passé à setReadListener() ne peut pas être null
|
||||
request.readListenerSet=L'écouteur des lectures non bloquantes a déjà été défini
|
||||
|
||||
response.encoding.invalid=L''encodage [{0}] n''est pas reconnu par le JRE
|
||||
response.notAsync=Il n'est possible de passer en mode d'entrée-sorties non bloquantes que lors de traitements asynchrones ou après mise à niveau depuis HTTP
|
||||
response.notNonBlocking=Il n'est pas permis d'appeler isReady() quand la réponse n'a pas été mise en mode non-bloquant
|
||||
response.nullWriteListener=L'écouteur passé à setWriteListener() ne peut pas être null
|
||||
response.writeListenerSet=La cible des notifications en écriture ("write listener") non-bloquantes a déjà été spécifiée
|
||||
52
java/org/apache/coyote/LocalStrings_ja.properties
Normal file
52
java/org/apache/coyote/LocalStrings_ja.properties
Normal file
@@ -0,0 +1,52 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
abstractConnectionHandler.connectionsGet=ソケット[{1}]のプロセッサ[{0}]が見つかりました。
|
||||
abstractConnectionHandler.error=リクエストの読み取り中にエラーが発生しました。無視します。
|
||||
abstractConnectionHandler.ioexception.debug=IOExceptionは正常で無視されます。
|
||||
abstractConnectionHandler.negotiatedProcessor.fail=ネゴシエートされたプロトコル[{0}]のプロセッサの作成に失敗しました。
|
||||
abstractConnectionHandler.process=ステータス[{1}]のソケット[{0}]を処理しています。
|
||||
abstractConnectionHandler.processorPop=キャッシュからプロセッサー [{0}] を取得しました。
|
||||
abstractConnectionHandler.protocolexception.debug=ProtocolExceptionsは正常です。無視します。
|
||||
abstractConnectionHandler.socketexception.debug=SocketExceptionsは正常です。無視します。
|
||||
abstractConnectionHandler.upgradeCreate=SocketWrapper [{1}]のアップグレードプロセッサ[{0}]が作成されました。
|
||||
|
||||
abstractProcessor.fallToDebug=注:リクエスト構文解析エラーのさらなる発生はDEBUGレベルでログに記録されます。
|
||||
abstractProcessor.hostInvalid=ホスト名 [{0}] は不正なホスト名です。
|
||||
abstractProcessor.httpupgrade.notsupported=このプロトコルは HTTP アップグレードに対応していません。
|
||||
abstractProcessor.pushrequest.notsupported=このプロトコルはサーバープッシュの要求に対応していません。
|
||||
abstractProcessor.socket.ssl=SSL属性を取得する例外
|
||||
|
||||
abstractProtocol.mbeanDeregistrationFailed=MBeanサーバー[{1}]から[{0}]という名前のMBeanの登録を解除できませんでした。
|
||||
|
||||
abstractProtocolHandler.destroy=ProtocolHandler [{0}] を破棄します。
|
||||
abstractProtocolHandler.init=プロトコルハンドラ [{0}] を初期化します。
|
||||
abstractProtocolHandler.pause=ProtocolHandler [{0}] を一時停止します。
|
||||
abstractProtocolHandler.resume=プロトコルハンドラー [{0}] を再開します。
|
||||
abstractProtocolHandler.setAttribute=属性[{0}]に値[{1}]を設定する
|
||||
abstractProtocolHandler.start=プロトコルハンドラー [{0}] を開始しました。
|
||||
abstractProtocolHandler.stop=ProtocolHandler [{0}]の停止中
|
||||
|
||||
asyncStateMachine.invalidAsyncState=非同期状態[{1}]のリクエストに対して[{0}]を呼び出すことはできません
|
||||
|
||||
request.notAsync=非同期処理またはHTTPアップグレード処理内のノンブロッキングIOに切り替えることは有効です。
|
||||
request.nullReadListener=setReadListener() には null を指定できません。
|
||||
request.readListenerSet=ノンブロッキングリードリスナーは既に設定されています。
|
||||
|
||||
response.encoding.invalid=JRE は文字エンコーディング [{0}] を認識しません。
|
||||
response.notAsync=非同期処理、あるいは、HTTP アップグレード処理の途中でのみノンブロッキング IO へ切り替えることができます。
|
||||
response.notNonBlocking=ノンブロッキングモードにしなかったレスポンスの isReady() を呼び出すことはできません。
|
||||
response.nullWriteListener=setWriteListener() には null を指定できません。
|
||||
response.writeListenerSet=ノンブロッキング書き込みリスナーが設定済みです
|
||||
58
java/org/apache/coyote/LocalStrings_ko.properties
Normal file
58
java/org/apache/coyote/LocalStrings_ko.properties
Normal file
@@ -0,0 +1,58 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
abstractConnectionHandler.connectionsGet=소켓 [{1}]을(를) 위한 프로세서 [{0}]을(를) 발견했습니다.
|
||||
abstractConnectionHandler.error=요청을 읽는 중 오류 발생. 무시합니다.
|
||||
abstractConnectionHandler.ioexception.debug=IOException들은 정상적이므로, 무시합니다.
|
||||
abstractConnectionHandler.negotiatedProcessor.fail=Negotiate된 프로토콜 [{0}]을(를) 위한 프로세서를 생성하지 못했습니다.
|
||||
abstractConnectionHandler.oome=요청 처리를 완료하지 못했습니다.
|
||||
abstractConnectionHandler.process=상태가 [{1}]인 소켓 [{0}]을(를) 처리합니다.
|
||||
abstractConnectionHandler.processorPop=캐시로부터 프로세서 [{0}]을(를) 추출했습니다.
|
||||
abstractConnectionHandler.protocolexception.debug=ProtocolException들은 정상적이므로, 무시합니다.
|
||||
abstractConnectionHandler.socketexception.debug=SocketException들은 정상적인 상태이므로 무시되었습니다.
|
||||
abstractConnectionHandler.upgradeCreate=소켓 wrapper [{1}]을(를) 위한 업그레이드 프로세서 [{0}]을(를) 생성했습니다.
|
||||
|
||||
abstractProcessor.fallToDebug=\n\
|
||||
비고: 요청에 대한 파싱 오류들이 더 발생하는 경우 DEBUG 레벨 로그로 기록될 것입니다.
|
||||
abstractProcessor.hostInvalid=호스트 [{0}]은(는) 유효하지 않습니다.
|
||||
abstractProcessor.httpupgrade.notsupported=HTTP 업그레이드는 이 프로토콜에 의해 지원되지 않습니다.
|
||||
abstractProcessor.pushrequest.notsupported=이 프로토콜은 서버 push 요청들을 지원하지 않습니다.
|
||||
abstractProcessor.socket.ssl=SSL 속성들을 얻으려는 중 예외 발생
|
||||
|
||||
abstractProtocol.mbeanDeregistrationFailed=MBean 서버 [{1}](으)로부터, [{0}](이)라는 이름의 MBean의 등록을 제거하지 못했습니다.
|
||||
abstractProtocol.processorRegisterError=RequestProcessor 구성요소를 등록하는 중 오류 발생
|
||||
abstractProtocol.processorUnregisterError=RequestProcessor 구성요소를 등록 해제하는 중 오류 발생
|
||||
|
||||
abstractProtocolHandler.destroy=프로토콜 핸들러 [{0}]을(를) 소멸시킵니다.
|
||||
abstractProtocolHandler.init=프로토콜 핸들러 [{0}]을(를) 초기화합니다.
|
||||
abstractProtocolHandler.pause=프로토콜 핸들러 [{0}]을(를) 일시 정지 중
|
||||
abstractProtocolHandler.resume=프로토콜 핸들러 [{0}]을(를) 재개합니다.
|
||||
abstractProtocolHandler.setAttribute=속성 [{0}]에 값 [{1}]을(를) 설정
|
||||
abstractProtocolHandler.start=프로토콜 핸들러 [{0}]을(를) 시작합니다.
|
||||
abstractProtocolHandler.stop=프로토콜 핸들러 [{0}]을(를) 중지시킵니다.
|
||||
|
||||
asyncStateMachine.invalidAsyncState=비동기 상태가 [{1}]인 요청에 대하여, [{0}]을(를) 호출하는 것은 유효하지 않습니다.
|
||||
|
||||
compressionConfig.ContentEncodingParseFail=압축이 이미 사용되는지 여부를 점검하는 중, Content-Encoding 헤더를 파싱하지 못했습니다.
|
||||
|
||||
request.notAsync=오직 비동기 처리 또는 HTTP 업그레이드 처리 시에만, Non-blocking IO로의 전환이 유효합니다.
|
||||
request.nullReadListener=setReadListener()에 전달된 리스너는 널일 수 없습니다.
|
||||
request.readListenerSet=Non-blocking 읽기 리스너가 이미 설정되어 있습니다.
|
||||
|
||||
response.encoding.invalid=인코딩 [{0}]은(는) JRE에 의해 인식되지 않습니다.
|
||||
response.notAsync=오직 비동기 처리 중 또는 HTTP 업그레이드 처리 중일 때에만, non-blocking IO로 전환하려는 것이 유효합니다.
|
||||
response.notNonBlocking=응답이 non-blocking 모드 내에 있지 않을 때, isReady()를 호출하는 것은 유효하지 않습니다.
|
||||
response.nullWriteListener=setWriteListener()에 전달되는 리스너가 널이이서는 안됩니다.
|
||||
response.writeListenerSet=Non-blocking 쓰기 리스너가 이미 설정되었습니다.
|
||||
37
java/org/apache/coyote/LocalStrings_zh_CN.properties
Normal file
37
java/org/apache/coyote/LocalStrings_zh_CN.properties
Normal file
@@ -0,0 +1,37 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
abstractConnectionHandler.ioexception.debug=正常的 IOException,忽略
|
||||
abstractConnectionHandler.processorPop=从缓存中弹出的处理器[{0}]
|
||||
abstractConnectionHandler.socketexception.debug=(:SocketException是正常的,忽略
|
||||
abstractConnectionHandler.upgradeCreate=为套接字包装程序[{1}]创建了升级处理器[{0}]
|
||||
|
||||
abstractProcessor.fallToDebug=注意:更多的请求解析错误将以DEBUG级别日志进行记录。
|
||||
abstractProcessor.hostInvalid=[{0}] 是无效主机
|
||||
abstractProcessor.httpupgrade.notsupported=此协议不支持HTTP升级(upgrade)。
|
||||
abstractProcessor.socket.ssl=获取SSL属性异常
|
||||
|
||||
abstractProtocol.processorRegisterError=注册请求处理器错误
|
||||
abstractProtocol.processorUnregisterError=注销请求处理器错误
|
||||
|
||||
abstractProtocolHandler.destroy=正在摧毁协议处理器 [{0}]
|
||||
abstractProtocolHandler.init=初始化协议处理器 [{0}]
|
||||
abstractProtocolHandler.start=开始协议处理句柄[{0}]
|
||||
abstractProtocolHandler.stop=正在停止ProtocolHandler [{0}]
|
||||
|
||||
asyncStateMachine.invalidAsyncState=调用[{0}]对于具有异步状态[{1}]的请求无效
|
||||
|
||||
response.notNonBlocking=当响应尚未进入非阻塞模式时,调用 isReady() 无效
|
||||
response.writeListenerSet=非阻塞的写监听已经被设置.
|
||||
71
java/org/apache/coyote/OutputBuffer.java
Normal file
71
java/org/apache/coyote/OutputBuffer.java
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.apache.tomcat.util.buf.ByteChunk;
|
||||
|
||||
/**
|
||||
* Output buffer.
|
||||
*
|
||||
* This class is used internally by the protocol implementation. All writes from
|
||||
* higher level code should happen via Response.doWrite().
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
public interface OutputBuffer {
|
||||
|
||||
/**
|
||||
* Write the given data to the response. The caller owns the chunks.
|
||||
*
|
||||
* @param chunk data to write
|
||||
*
|
||||
* @return The number of bytes written which may be less than available in
|
||||
* the input chunk
|
||||
*
|
||||
* @throws IOException an underlying I/O error occurred
|
||||
*
|
||||
* @deprecated Unused. Will be removed in Tomcat 9. Use
|
||||
* {@link #doWrite(ByteBuffer)}
|
||||
*/
|
||||
@Deprecated
|
||||
public int doWrite(ByteChunk chunk) throws IOException;
|
||||
|
||||
|
||||
/**
|
||||
* Write the given data to the response. The caller owns the chunks.
|
||||
*
|
||||
* @param chunk data to write
|
||||
*
|
||||
* @return The number of bytes written which may be less than available in
|
||||
* the input chunk
|
||||
*
|
||||
* @throws IOException an underlying I/O error occurred
|
||||
*/
|
||||
public int doWrite(ByteBuffer chunk) throws IOException;
|
||||
|
||||
|
||||
/**
|
||||
* Bytes written to the underlying socket. This includes the effects of
|
||||
* chunking, compression, etc.
|
||||
*
|
||||
* @return Bytes written for the current request
|
||||
*/
|
||||
public long getBytesWritten();
|
||||
}
|
||||
128
java/org/apache/coyote/Processor.java
Normal file
128
java/org/apache/coyote/Processor.java
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
|
||||
import org.apache.tomcat.util.net.SSLSupport;
|
||||
import org.apache.tomcat.util.net.SocketEvent;
|
||||
import org.apache.tomcat.util.net.SocketWrapperBase;
|
||||
|
||||
/**
|
||||
* Common interface for processors of all protocols.
|
||||
*/
|
||||
public interface Processor {
|
||||
|
||||
/**
|
||||
* Process a connection. This is called whenever an event occurs (e.g. more
|
||||
* data arrives) that allows processing to continue for a connection that is
|
||||
* not currently being processed.
|
||||
*
|
||||
* @param socketWrapper The connection to process
|
||||
* @param status The status of the connection that triggered this additional
|
||||
* processing
|
||||
*
|
||||
* @return The state the caller should put the socket in when this method
|
||||
* returns
|
||||
*
|
||||
* @throws IOException If an I/O error occurs during the processing of the
|
||||
* request
|
||||
*/
|
||||
SocketState process(SocketWrapperBase<?> socketWrapper, SocketEvent status) throws IOException;
|
||||
|
||||
/**
|
||||
* Generate an upgrade token.
|
||||
*
|
||||
* @return An upgrade token encapsulating the information required to
|
||||
* process the upgrade request
|
||||
*
|
||||
* @throws IllegalStateException if this is called on a Processor that does
|
||||
* not support upgrading
|
||||
*/
|
||||
UpgradeToken getUpgradeToken();
|
||||
|
||||
/**
|
||||
* @return {@code true} if the Processor is currently processing an upgrade
|
||||
* request, otherwise {@code false}
|
||||
*/
|
||||
boolean isUpgrade();
|
||||
boolean isAsync();
|
||||
|
||||
/**
|
||||
* Check this processor to see if the timeout has expired and process a
|
||||
* timeout if that is that case.
|
||||
* <p>
|
||||
* Note: The name of this method originated with the Servlet 3.0
|
||||
* asynchronous processing but evolved over time to represent a timeout that
|
||||
* is triggered independently of the socket read/write timeouts.
|
||||
*
|
||||
* @param now The time (as returned by {@link System#currentTimeMillis()} to
|
||||
* use as the current time to determine whether the timeout has
|
||||
* expired. If negative, the timeout will always be treated as ifq
|
||||
* it has expired.
|
||||
*/
|
||||
void timeoutAsync(long now);
|
||||
|
||||
/**
|
||||
* @return The request associated with this processor.
|
||||
*/
|
||||
Request getRequest();
|
||||
|
||||
/**
|
||||
* Recycle the processor, ready for the next request which may be on the
|
||||
* same connection or a different connection.
|
||||
*/
|
||||
void recycle();
|
||||
|
||||
/**
|
||||
* Set the SSL information for this HTTP connection.
|
||||
*
|
||||
* @param sslSupport The SSL support object to use for this connection
|
||||
*/
|
||||
void setSslSupport(SSLSupport sslSupport);
|
||||
|
||||
/**
|
||||
* Allows retrieving additional input during the upgrade process.
|
||||
*
|
||||
* @return leftover bytes
|
||||
*
|
||||
* @throws IllegalStateException if this is called on a Processor that does
|
||||
* not support upgrading
|
||||
*/
|
||||
ByteBuffer getLeftoverInput();
|
||||
|
||||
/**
|
||||
* Informs the processor that the underlying I/O layer has stopped accepting
|
||||
* new connections. This is primarily intended to enable processors that
|
||||
* use multiplexed connections to prevent further 'streams' being added to
|
||||
* an existing multiplexed connection.
|
||||
*/
|
||||
void pause();
|
||||
|
||||
/**
|
||||
* Check to see if the async generation (each cycle of async increments the
|
||||
* generation of the AsyncStateMachine) is the same as the generation when
|
||||
* the most recent async timeout was triggered. This is intended to be used
|
||||
* to avoid unnecessary processing.
|
||||
*
|
||||
* @return {@code true} If the async generation has not changed since the
|
||||
* async timeout was triggered
|
||||
*/
|
||||
boolean checkAsyncTimeoutGeneration();
|
||||
}
|
||||
42
java/org/apache/coyote/ProtocolException.java
Normal file
42
java/org/apache/coyote/ProtocolException.java
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote;
|
||||
|
||||
/**
|
||||
* Used when we need to indicate failure but the (Servlet) API doesn't declare
|
||||
* any appropriate exceptions.
|
||||
*/
|
||||
public class ProtocolException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ProtocolException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ProtocolException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ProtocolException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ProtocolException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
139
java/org/apache/coyote/ProtocolHandler.java
Normal file
139
java/org/apache/coyote/ProtocolHandler.java
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.apache.tomcat.util.net.SSLHostConfig;
|
||||
|
||||
/**
|
||||
* Abstract the protocol implementation, including threading, etc.
|
||||
*
|
||||
* This is the main interface to be implemented by a coyote protocol.
|
||||
* Adapter is the main interface to be implemented by a coyote servlet
|
||||
* container.
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
* @author Costin Manolache
|
||||
* @see Adapter
|
||||
*/
|
||||
public interface ProtocolHandler {
|
||||
|
||||
/**
|
||||
* Return the adapter associated with the protocol handler.
|
||||
* @return the adapter
|
||||
*/
|
||||
public Adapter getAdapter();
|
||||
|
||||
|
||||
/**
|
||||
* The adapter, used to call the connector.
|
||||
*
|
||||
* @param adapter The adapter to associate
|
||||
*/
|
||||
public void setAdapter(Adapter adapter);
|
||||
|
||||
|
||||
/**
|
||||
* The executor, provide access to the underlying thread pool.
|
||||
*
|
||||
* @return The executor used to process requests
|
||||
*/
|
||||
public Executor getExecutor();
|
||||
|
||||
|
||||
/**
|
||||
* Initialise the protocol.
|
||||
*
|
||||
* @throws Exception If the protocol handler fails to initialise
|
||||
*/
|
||||
public void init() throws Exception;
|
||||
|
||||
|
||||
/**
|
||||
* Start the protocol.
|
||||
*
|
||||
* @throws Exception If the protocol handler fails to start
|
||||
*/
|
||||
public void start() throws Exception;
|
||||
|
||||
|
||||
/**
|
||||
* Pause the protocol (optional).
|
||||
*
|
||||
* @throws Exception If the protocol handler fails to pause
|
||||
*/
|
||||
public void pause() throws Exception;
|
||||
|
||||
|
||||
/**
|
||||
* Resume the protocol (optional).
|
||||
*
|
||||
* @throws Exception If the protocol handler fails to resume
|
||||
*/
|
||||
public void resume() throws Exception;
|
||||
|
||||
|
||||
/**
|
||||
* Stop the protocol.
|
||||
*
|
||||
* @throws Exception If the protocol handler fails to stop
|
||||
*/
|
||||
public void stop() throws Exception;
|
||||
|
||||
|
||||
/**
|
||||
* Destroy the protocol (optional).
|
||||
*
|
||||
* @throws Exception If the protocol handler fails to destroy
|
||||
*/
|
||||
public void destroy() throws Exception;
|
||||
|
||||
|
||||
/**
|
||||
* Close the server socket (to prevent further connections) if the server
|
||||
* socket was bound on {@link #start()} (rather than on {@link #init()}
|
||||
* but do not perform any further shutdown.
|
||||
*/
|
||||
public void closeServerSocketGraceful();
|
||||
|
||||
|
||||
/**
|
||||
* Requires APR/native library
|
||||
*
|
||||
* @return <code>true</code> if this Protocol Handler requires the
|
||||
* APR/native library, otherwise <code>false</code>
|
||||
*/
|
||||
public boolean isAprRequired();
|
||||
|
||||
|
||||
/**
|
||||
* Does this ProtocolHandler support sendfile?
|
||||
*
|
||||
* @return <code>true</code> if this Protocol Handler supports sendfile,
|
||||
* otherwise <code>false</code>
|
||||
*/
|
||||
public boolean isSendfileSupported();
|
||||
|
||||
|
||||
public void addSslHostConfig(SSLHostConfig sslHostConfig);
|
||||
public SSLHostConfig[] findSslHostConfigs();
|
||||
|
||||
|
||||
public void addUpgradeProtocol(UpgradeProtocol upgradeProtocol);
|
||||
public UpgradeProtocol[] findUpgradeProtocols();
|
||||
}
|
||||
727
java/org/apache/coyote/Request.java
Normal file
727
java/org/apache/coyote/Request.java
Normal file
File diff suppressed because it is too large
Load Diff
153
java/org/apache/coyote/RequestGroupInfo.java
Normal file
153
java/org/apache/coyote/RequestGroupInfo.java
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/** This can be moved to top level ( eventually with a better name ).
|
||||
* It is currently used only as a JMX artifact, to aggregate the data
|
||||
* collected from each RequestProcessor thread.
|
||||
*/
|
||||
public class RequestGroupInfo {
|
||||
private final ArrayList<RequestInfo> processors = new ArrayList<>();
|
||||
private long deadMaxTime = 0;
|
||||
private long deadProcessingTime = 0;
|
||||
private int deadRequestCount = 0;
|
||||
private int deadErrorCount = 0;
|
||||
private long deadBytesReceived = 0;
|
||||
private long deadBytesSent = 0;
|
||||
|
||||
public synchronized void addRequestProcessor( RequestInfo rp ) {
|
||||
processors.add( rp );
|
||||
}
|
||||
|
||||
public synchronized void removeRequestProcessor( RequestInfo rp ) {
|
||||
if( rp != null ) {
|
||||
if( deadMaxTime < rp.getMaxTime() )
|
||||
deadMaxTime = rp.getMaxTime();
|
||||
deadProcessingTime += rp.getProcessingTime();
|
||||
deadRequestCount += rp.getRequestCount();
|
||||
deadErrorCount += rp.getErrorCount();
|
||||
deadBytesReceived += rp.getBytesReceived();
|
||||
deadBytesSent += rp.getBytesSent();
|
||||
|
||||
processors.remove( rp );
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized long getMaxTime() {
|
||||
long maxTime = deadMaxTime;
|
||||
for (RequestInfo rp : processors) {
|
||||
if (maxTime < rp.getMaxTime()) {
|
||||
maxTime=rp.getMaxTime();
|
||||
}
|
||||
}
|
||||
return maxTime;
|
||||
}
|
||||
|
||||
// Used to reset the times
|
||||
public synchronized void setMaxTime(long maxTime) {
|
||||
deadMaxTime = maxTime;
|
||||
for (RequestInfo rp : processors) {
|
||||
rp.setMaxTime(maxTime);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized long getProcessingTime() {
|
||||
long time = deadProcessingTime;
|
||||
for (RequestInfo rp : processors) {
|
||||
time += rp.getProcessingTime();
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
public synchronized void setProcessingTime(long totalTime) {
|
||||
deadProcessingTime = totalTime;
|
||||
for (RequestInfo rp : processors) {
|
||||
rp.setProcessingTime( totalTime );
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized int getRequestCount() {
|
||||
int requestCount = deadRequestCount;
|
||||
for (RequestInfo rp : processors) {
|
||||
requestCount += rp.getRequestCount();
|
||||
}
|
||||
return requestCount;
|
||||
}
|
||||
|
||||
public synchronized void setRequestCount(int requestCount) {
|
||||
deadRequestCount = requestCount;
|
||||
for (RequestInfo rp : processors) {
|
||||
rp.setRequestCount( requestCount );
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized int getErrorCount() {
|
||||
int requestCount = deadErrorCount;
|
||||
for (RequestInfo rp : processors) {
|
||||
requestCount += rp.getErrorCount();
|
||||
}
|
||||
return requestCount;
|
||||
}
|
||||
|
||||
public synchronized void setErrorCount(int errorCount) {
|
||||
deadErrorCount = errorCount;
|
||||
for (RequestInfo rp : processors) {
|
||||
rp.setErrorCount( errorCount);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized long getBytesReceived() {
|
||||
long bytes = deadBytesReceived;
|
||||
for (RequestInfo rp : processors) {
|
||||
bytes += rp.getBytesReceived();
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public synchronized void setBytesReceived(long bytesReceived) {
|
||||
deadBytesReceived = bytesReceived;
|
||||
for (RequestInfo rp : processors) {
|
||||
rp.setBytesReceived( bytesReceived );
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized long getBytesSent() {
|
||||
long bytes=deadBytesSent;
|
||||
for (RequestInfo rp : processors) {
|
||||
bytes += rp.getBytesSent();
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public synchronized void setBytesSent(long bytesSent) {
|
||||
deadBytesSent = bytesSent;
|
||||
for (RequestInfo rp : processors) {
|
||||
rp.setBytesSent( bytesSent );
|
||||
}
|
||||
}
|
||||
|
||||
public void resetCounters() {
|
||||
this.setBytesReceived(0);
|
||||
this.setBytesSent(0);
|
||||
this.setRequestCount(0);
|
||||
this.setProcessingTime(0);
|
||||
this.setMaxTime(0);
|
||||
this.setErrorCount(0);
|
||||
}
|
||||
}
|
||||
264
java/org/apache/coyote/RequestInfo.java
Normal file
264
java/org/apache/coyote/RequestInfo.java
Normal file
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.coyote;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
|
||||
|
||||
/**
|
||||
* Structure holding the Request and Response objects. It also holds statistical
|
||||
* informations about request processing and provide management informations
|
||||
* about the requests being processed.
|
||||
*
|
||||
* Each thread uses a Request/Response pair that is recycled on each request.
|
||||
* This object provides a place to collect global low-level statistics - without
|
||||
* having to deal with synchronization ( since each thread will have it's own
|
||||
* RequestProcessorMX ).
|
||||
*
|
||||
* @author Costin Manolache
|
||||
*/
|
||||
public class RequestInfo {
|
||||
private RequestGroupInfo global=null;
|
||||
|
||||
// ----------------------------------------------------------- Constructors
|
||||
|
||||
public RequestInfo( Request req) {
|
||||
this.req=req;
|
||||
}
|
||||
|
||||
public RequestGroupInfo getGlobalProcessor() {
|
||||
return global;
|
||||
}
|
||||
|
||||
public void setGlobalProcessor(RequestGroupInfo global) {
|
||||
if( global != null) {
|
||||
this.global=global;
|
||||
global.addRequestProcessor( this );
|
||||
} else {
|
||||
if (this.global != null) {
|
||||
this.global.removeRequestProcessor( this );
|
||||
this.global = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------- Instance Variables
|
||||
private final Request req;
|
||||
private int stage = Constants.STAGE_NEW;
|
||||
private String workerThreadName;
|
||||
private ObjectName rpName;
|
||||
|
||||
// -------------------- Information about the current request -----------
|
||||
// This is useful for long-running requests only
|
||||
|
||||
public String getMethod() {
|
||||
return req.method().toString();
|
||||
}
|
||||
|
||||
public String getCurrentUri() {
|
||||
return req.requestURI().toString();
|
||||
}
|
||||
|
||||
public String getCurrentQueryString() {
|
||||
return req.queryString().toString();
|
||||
}
|
||||
|
||||
public String getProtocol() {
|
||||
return req.protocol().toString();
|
||||
}
|
||||
|
||||
public String getVirtualHost() {
|
||||
return req.serverName().toString();
|
||||
}
|
||||
|
||||
public int getServerPort() {
|
||||
return req.getServerPort();
|
||||
}
|
||||
|
||||
public String getRemoteAddr() {
|
||||
req.action(ActionCode.REQ_HOST_ADDR_ATTRIBUTE, null);
|
||||
return req.remoteAddr().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the remote address for this connection as reported by an
|
||||
* intermediate proxy (if any).
|
||||
*
|
||||
* @return The remote address for the this connection
|
||||
*/
|
||||
public String getRemoteAddrForwarded() {
|
||||
String remoteAddrProxy = (String) req.getAttribute(Constants.REMOTE_ADDR_ATTRIBUTE);
|
||||
if (remoteAddrProxy == null) {
|
||||
return getRemoteAddr();
|
||||
}
|
||||
return remoteAddrProxy;
|
||||
}
|
||||
|
||||
public int getContentLength() {
|
||||
return req.getContentLength();
|
||||
}
|
||||
|
||||
public long getRequestBytesReceived() {
|
||||
return req.getBytesRead();
|
||||
}
|
||||
|
||||
public long getRequestBytesSent() {
|
||||
return req.getResponse().getContentWritten();
|
||||
}
|
||||
|
||||
public long getRequestProcessingTime() {
|
||||
// Not perfect, but good enough to avoid returning strange values due to
|
||||
// concurrent updates.
|
||||
long startTime = req.getStartTime();
|
||||
if (getStage() == org.apache.coyote.Constants.STAGE_ENDED || startTime < 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return System.currentTimeMillis() - startTime;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------- Statistical data --------------------
|
||||
// Collected at the end of each request.
|
||||
private long bytesSent;
|
||||
private long bytesReceived;
|
||||
|
||||
// Total time = divide by requestCount to get average.
|
||||
private long processingTime;
|
||||
// The longest response time for a request
|
||||
private long maxTime;
|
||||
// URI of the request that took maxTime
|
||||
private String maxRequestUri;
|
||||
|
||||
private int requestCount;
|
||||
// number of response codes >= 400
|
||||
private int errorCount;
|
||||
|
||||
//the time of the last request
|
||||
private long lastRequestProcessingTime = 0;
|
||||
|
||||
|
||||
/** Called by the processor before recycling the request. It'll collect
|
||||
* statistic information.
|
||||
*/
|
||||
void updateCounters() {
|
||||
bytesReceived+=req.getBytesRead();
|
||||
bytesSent+=req.getResponse().getContentWritten();
|
||||
|
||||
requestCount++;
|
||||
if( req.getResponse().getStatus() >=400 )
|
||||
errorCount++;
|
||||
long t0=req.getStartTime();
|
||||
long t1=System.currentTimeMillis();
|
||||
long time=t1-t0;
|
||||
this.lastRequestProcessingTime = time;
|
||||
processingTime+=time;
|
||||
if( maxTime < time ) {
|
||||
maxTime=time;
|
||||
maxRequestUri=req.requestURI().toString();
|
||||
}
|
||||
}
|
||||
|
||||
public int getStage() {
|
||||
return stage;
|
||||
}
|
||||
|
||||
public void setStage(int stage) {
|
||||
this.stage = stage;
|
||||
}
|
||||
|
||||
public long getBytesSent() {
|
||||
return bytesSent;
|
||||
}
|
||||
|
||||
public void setBytesSent(long bytesSent) {
|
||||
this.bytesSent = bytesSent;
|
||||
}
|
||||
|
||||
public long getBytesReceived() {
|
||||
return bytesReceived;
|
||||
}
|
||||
|
||||
public void setBytesReceived(long bytesReceived) {
|
||||
this.bytesReceived = bytesReceived;
|
||||
}
|
||||
|
||||
public long getProcessingTime() {
|
||||
return processingTime;
|
||||
}
|
||||
|
||||
public void setProcessingTime(long processingTime) {
|
||||
this.processingTime = processingTime;
|
||||
}
|
||||
|
||||
public long getMaxTime() {
|
||||
return maxTime;
|
||||
}
|
||||
|
||||
public void setMaxTime(long maxTime) {
|
||||
this.maxTime = maxTime;
|
||||
}
|
||||
|
||||
public String getMaxRequestUri() {
|
||||
return maxRequestUri;
|
||||
}
|
||||
|
||||
public void setMaxRequestUri(String maxRequestUri) {
|
||||
this.maxRequestUri = maxRequestUri;
|
||||
}
|
||||
|
||||
public int getRequestCount() {
|
||||
return requestCount;
|
||||
}
|
||||
|
||||
public void setRequestCount(int requestCount) {
|
||||
this.requestCount = requestCount;
|
||||
}
|
||||
|
||||
public int getErrorCount() {
|
||||
return errorCount;
|
||||
}
|
||||
|
||||
public void setErrorCount(int errorCount) {
|
||||
this.errorCount = errorCount;
|
||||
}
|
||||
|
||||
public String getWorkerThreadName() {
|
||||
return workerThreadName;
|
||||
}
|
||||
|
||||
public ObjectName getRpName() {
|
||||
return rpName;
|
||||
}
|
||||
|
||||
public long getLastRequestProcessingTime() {
|
||||
return lastRequestProcessingTime;
|
||||
}
|
||||
|
||||
public void setWorkerThreadName(String workerThreadName) {
|
||||
this.workerThreadName = workerThreadName;
|
||||
}
|
||||
|
||||
public void setRpName(ObjectName rpName) {
|
||||
this.rpName = rpName;
|
||||
}
|
||||
|
||||
public void setLastRequestProcessingTime(long lastRequestProcessingTime) {
|
||||
this.lastRequestProcessingTime = lastRequestProcessingTime;
|
||||
}
|
||||
}
|
||||
763
java/org/apache/coyote/Response.java
Normal file
763
java/org/apache/coyote/Response.java
Normal file
File diff suppressed because it is too large
Load Diff
93
java/org/apache/coyote/UpgradeProtocol.java
Normal file
93
java/org/apache/coyote/UpgradeProtocol.java
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote;
|
||||
|
||||
import org.apache.coyote.http11.upgrade.InternalHttpUpgradeHandler;
|
||||
import org.apache.tomcat.util.net.SocketWrapperBase;
|
||||
|
||||
public interface UpgradeProtocol {
|
||||
|
||||
/**
|
||||
* @param isSSLEnabled Is this for a connector that is configured to support
|
||||
* TLS. Some protocols (e.g. HTTP/2) only support HTTP
|
||||
* upgrade over non-secure connections.
|
||||
* @return The name that clients will use to request an upgrade to this
|
||||
* protocol via an HTTP/1.1 upgrade request or <code>null</code> if
|
||||
* upgrade via an HTTP/1.1 upgrade request is not supported.
|
||||
*/
|
||||
public String getHttpUpgradeName(boolean isSSLEnabled);
|
||||
|
||||
/**
|
||||
* @return The byte sequence as listed in the IANA registry for this
|
||||
* protocol or <code>null</code> if upgrade via ALPN is not
|
||||
* supported.
|
||||
*/
|
||||
public byte[] getAlpnIdentifier();
|
||||
|
||||
/**
|
||||
* @return The name of the protocol as listed in the IANA registry if and
|
||||
* only if {@link #getAlpnIdentifier()} returns the UTF-8 encoding
|
||||
* of this name. If {@link #getAlpnIdentifier()} returns some other
|
||||
* byte sequence, then this method returns the empty string. If
|
||||
* upgrade via ALPN is not supported then <code>null</code> is
|
||||
* returned.
|
||||
*/
|
||||
/*
|
||||
* Implementation note: If Tomcat ever supports ALPN for a protocol where
|
||||
* the identifier is not the UTF-8 encoding of the name
|
||||
* then some refactoring is going to be required.
|
||||
*
|
||||
* Implementation note: Tomcat assumes that the UTF-8 encoding of this name
|
||||
* will not exceed 255 bytes. Tomcat's behaviour if
|
||||
* longer names are used is undefined.
|
||||
*/
|
||||
public String getAlpnName();
|
||||
|
||||
/**
|
||||
* @param socketWrapper The socketWrapper for the connection that requires
|
||||
* a processor
|
||||
* @param adapter The Adapter instance that provides access to the standard
|
||||
* Engine/Host/Context/Wrapper processing chain
|
||||
*
|
||||
* @return A processor instance for processing a connection using this
|
||||
* protocol.
|
||||
*/
|
||||
public Processor getProcessor(SocketWrapperBase<?> socketWrapper, Adapter adapter);
|
||||
|
||||
|
||||
/**
|
||||
* @param adapter The Adapter to use to configure the new upgrade handler
|
||||
* @param request A copy (may be incomplete) of the request that triggered
|
||||
* the upgrade
|
||||
*
|
||||
* @return An instance of the HTTP upgrade handler for this protocol
|
||||
*/
|
||||
public InternalHttpUpgradeHandler getInternalUpgradeHandler(Adapter adapter, Request request);
|
||||
|
||||
|
||||
/**
|
||||
* Allows the implementation to examine the request and accept or reject it
|
||||
* based on what it finds.
|
||||
*
|
||||
* @param request The request that included an upgrade header for this
|
||||
* protocol
|
||||
*
|
||||
* @return <code>true</code> if the request is accepted, otherwise
|
||||
* <code>false</code>
|
||||
*/
|
||||
public boolean accept(Request request);
|
||||
}
|
||||
53
java/org/apache/coyote/UpgradeToken.java
Normal file
53
java/org/apache/coyote/UpgradeToken.java
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.coyote;
|
||||
|
||||
import javax.servlet.http.HttpUpgradeHandler;
|
||||
|
||||
import org.apache.tomcat.ContextBind;
|
||||
import org.apache.tomcat.InstanceManager;
|
||||
|
||||
/**
|
||||
* Token used during the upgrade process.
|
||||
*/
|
||||
public final class UpgradeToken {
|
||||
|
||||
private final ContextBind contextBind;
|
||||
private final HttpUpgradeHandler httpUpgradeHandler;
|
||||
private final InstanceManager instanceManager;
|
||||
|
||||
public UpgradeToken(HttpUpgradeHandler httpUpgradeHandler,
|
||||
ContextBind contextBind, InstanceManager instanceManager) {
|
||||
this.contextBind = contextBind;
|
||||
this.httpUpgradeHandler = httpUpgradeHandler;
|
||||
this.instanceManager = instanceManager;
|
||||
}
|
||||
|
||||
public final ContextBind getContextBind() {
|
||||
return contextBind;
|
||||
}
|
||||
|
||||
public final HttpUpgradeHandler getHttpUpgradeHandler() {
|
||||
return httpUpgradeHandler;
|
||||
}
|
||||
|
||||
public final InstanceManager getInstanceManager() {
|
||||
return instanceManager;
|
||||
}
|
||||
|
||||
}
|
||||
279
java/org/apache/coyote/ajp/AbstractAjpProtocol.java
Normal file
279
java/org/apache/coyote/ajp/AbstractAjpProtocol.java
Normal file
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote.ajp;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.coyote.AbstractProtocol;
|
||||
import org.apache.coyote.Processor;
|
||||
import org.apache.coyote.UpgradeProtocol;
|
||||
import org.apache.coyote.UpgradeToken;
|
||||
import org.apache.tomcat.util.net.AbstractEndpoint;
|
||||
import org.apache.tomcat.util.net.SSLHostConfig;
|
||||
import org.apache.tomcat.util.net.SocketWrapperBase;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
/**
|
||||
* The is the base implementation for the AJP protocol handlers. Implementations
|
||||
* typically extend this base class rather than implement {@link
|
||||
* org.apache.coyote.ProtocolHandler}. All of the implementations that ship with
|
||||
* Tomcat are implemented this way.
|
||||
*
|
||||
* @param <S> The type of socket used by the implementation
|
||||
*/
|
||||
public abstract class AbstractAjpProtocol<S> extends AbstractProtocol<S> {
|
||||
|
||||
/**
|
||||
* The string manager for this package.
|
||||
*/
|
||||
protected static final StringManager sm = StringManager.getManager(AbstractAjpProtocol.class);
|
||||
|
||||
|
||||
public AbstractAjpProtocol(AbstractEndpoint<S> endpoint) {
|
||||
super(endpoint);
|
||||
setConnectionTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT);
|
||||
// AJP does not use Send File
|
||||
getEndpoint().setUseSendfile(false);
|
||||
// AJP listens on loopback by default
|
||||
getEndpoint().setAddress(InetAddress.getLoopbackAddress());
|
||||
ConnectionHandler<S> cHandler = new ConnectionHandler<>(this);
|
||||
setHandler(cHandler);
|
||||
getEndpoint().setHandler(cHandler);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getProtocolName() {
|
||||
return "Ajp";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* Overridden to make getter accessible to other classes in this package.
|
||||
*/
|
||||
@Override
|
||||
protected AbstractEndpoint<S> getEndpoint() {
|
||||
return super.getEndpoint();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* AJP does not support protocol negotiation so this always returns null.
|
||||
*/
|
||||
@Override
|
||||
protected UpgradeProtocol getNegotiatedProtocol(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* AJP does not support protocol upgrade so this always returns null.
|
||||
*/
|
||||
@Override
|
||||
protected UpgradeProtocol getUpgradeProtocol(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// ------------------------------------------------- AJP specific properties
|
||||
// ------------------------------------------ managed in the ProtocolHandler
|
||||
|
||||
protected boolean ajpFlush = true;
|
||||
public boolean getAjpFlush() { return ajpFlush; }
|
||||
/**
|
||||
* Configure whether to aend an AJP flush packet when flushing. A flush
|
||||
* packet is a zero byte AJP13 SEND_BODY_CHUNK packet. mod_jk and
|
||||
* mod_proxy_ajp interpret this as a request to flush data to the client.
|
||||
* AJP always does flush at the and of the response, so if it is not
|
||||
* important, that the packets get streamed up to the client, do not use
|
||||
* extra flush packets. For compatibility and to stay on the safe side,
|
||||
* flush packets are enabled by default.
|
||||
*
|
||||
* @param ajpFlush The new flush setting
|
||||
*/
|
||||
public void setAjpFlush(boolean ajpFlush) {
|
||||
this.ajpFlush = ajpFlush;
|
||||
}
|
||||
|
||||
|
||||
private boolean tomcatAuthentication = true;
|
||||
/**
|
||||
* Should authentication be done in the native web server layer,
|
||||
* or in the Servlet container ?
|
||||
*
|
||||
* @return {@code true} if authentication should be performed by Tomcat,
|
||||
* otherwise {@code false}
|
||||
*/
|
||||
public boolean getTomcatAuthentication() { return tomcatAuthentication; }
|
||||
public void setTomcatAuthentication(boolean tomcatAuthentication) {
|
||||
this.tomcatAuthentication = tomcatAuthentication;
|
||||
}
|
||||
|
||||
|
||||
private boolean tomcatAuthorization = false;
|
||||
/**
|
||||
* Should authentication be done in the native web server layer and
|
||||
* authorization in the Servlet container?
|
||||
*
|
||||
* @return {@code true} if authorization should be performed by Tomcat,
|
||||
* otherwise {@code false}
|
||||
*/
|
||||
public boolean getTomcatAuthorization() { return tomcatAuthorization; }
|
||||
public void setTomcatAuthorization(boolean tomcatAuthorization) {
|
||||
this.tomcatAuthorization = tomcatAuthorization;
|
||||
}
|
||||
|
||||
|
||||
private String secret = null;
|
||||
/**
|
||||
* Set the secret that must be included with every request.
|
||||
*
|
||||
* @param secret The required secret
|
||||
*/
|
||||
public void setSecret(String secret) {
|
||||
this.secret = secret;
|
||||
}
|
||||
protected String getSecret() {
|
||||
return secret;
|
||||
}
|
||||
/**
|
||||
* Set the required secret that must be included with every request.
|
||||
*
|
||||
* @param requiredSecret The required secret
|
||||
*
|
||||
* @deprecated Replaced by {@link #setSecret(String)}.
|
||||
* Will be removed in Tomcat 11 onwards
|
||||
*/
|
||||
@Deprecated
|
||||
public void setRequiredSecret(String requiredSecret) {
|
||||
setSecret(requiredSecret);
|
||||
}
|
||||
/**
|
||||
* @return The current secret
|
||||
*
|
||||
* @deprecated Replaced by {@link #getSecret()}.
|
||||
* Will be removed in Tomcat 11 onwards
|
||||
*/
|
||||
@Deprecated
|
||||
protected String getRequiredSecret() {
|
||||
return getSecret();
|
||||
}
|
||||
|
||||
|
||||
private boolean secretRequired = true;
|
||||
public void setSecretRequired(boolean secretRequired) {
|
||||
this.secretRequired = secretRequired;
|
||||
}
|
||||
public boolean getSecretRequired() {
|
||||
return secretRequired;
|
||||
}
|
||||
|
||||
|
||||
private Pattern allowedRequestAttributesPattern;
|
||||
public void setAllowedRequestAttributesPattern(String allowedRequestAttributesPattern) {
|
||||
this.allowedRequestAttributesPattern = Pattern.compile(allowedRequestAttributesPattern);
|
||||
}
|
||||
public String getAllowedRequestAttributesPattern() {
|
||||
return allowedRequestAttributesPattern.pattern();
|
||||
}
|
||||
protected Pattern getAllowedRequestAttributesPatternInternal() {
|
||||
return allowedRequestAttributesPattern;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* AJP packet size.
|
||||
*/
|
||||
private int packetSize = Constants.MAX_PACKET_SIZE;
|
||||
public int getPacketSize() { return packetSize; }
|
||||
public void setPacketSize(int packetSize) {
|
||||
if(packetSize < Constants.MAX_PACKET_SIZE) {
|
||||
this.packetSize = Constants.MAX_PACKET_SIZE;
|
||||
} else {
|
||||
this.packetSize = packetSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------- SSL is not supported in AJP
|
||||
|
||||
@Override
|
||||
public void addSslHostConfig(SSLHostConfig sslHostConfig) {
|
||||
getLog().warn(sm.getString("ajpprotocol.noSSL", sslHostConfig.getHostName()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SSLHostConfig[] findSslHostConfigs() {
|
||||
return new SSLHostConfig[0];
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addUpgradeProtocol(UpgradeProtocol upgradeProtocol) {
|
||||
getLog().warn(sm.getString("ajpprotocol.noUpgrade", upgradeProtocol.getClass().getName()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UpgradeProtocol[] findUpgradeProtocols() {
|
||||
return new UpgradeProtocol[0];
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected Processor createProcessor() {
|
||||
AjpProcessor processor = new AjpProcessor(getPacketSize(), getEndpoint());
|
||||
processor.setAdapter(getAdapter());
|
||||
processor.setAjpFlush(getAjpFlush());
|
||||
processor.setTomcatAuthentication(getTomcatAuthentication());
|
||||
processor.setTomcatAuthorization(getTomcatAuthorization());
|
||||
processor.setSecret(secret);
|
||||
processor.setKeepAliveTimeout(getKeepAliveTimeout());
|
||||
processor.setClientCertProvider(getClientCertProvider());
|
||||
processor.setSendReasonPhrase(getSendReasonPhrase());
|
||||
processor.setAllowedRequestAttributesPattern(getAllowedRequestAttributesPatternInternal());
|
||||
return processor;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Processor createUpgradeProcessor(SocketWrapperBase<?> socket,
|
||||
UpgradeToken upgradeToken) {
|
||||
throw new IllegalStateException(sm.getString("ajpprotocol.noUpgradeHandler",
|
||||
upgradeToken.getHttpUpgradeHandler().getClass().getName()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void start() throws Exception {
|
||||
if (getSecretRequired()) {
|
||||
String secret = getSecret();
|
||||
if (secret == null || secret.length() == 0) {
|
||||
throw new IllegalArgumentException(sm.getString("ajpprotocol.nosecret"));
|
||||
}
|
||||
}
|
||||
super.start();
|
||||
}
|
||||
}
|
||||
62
java/org/apache/coyote/ajp/AjpAprProtocol.java
Normal file
62
java/org/apache/coyote/ajp/AjpAprProtocol.java
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote.ajp;
|
||||
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.net.AprEndpoint;
|
||||
|
||||
|
||||
/**
|
||||
* This the APR/native based protocol handler implementation for AJP.
|
||||
*/
|
||||
public class AjpAprProtocol extends AbstractAjpProtocol<Long> {
|
||||
|
||||
private static final Log log = LogFactory.getLog(AjpAprProtocol.class);
|
||||
|
||||
@Override
|
||||
protected Log getLog() { return log; }
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isAprRequired() {
|
||||
// Override since this protocol implementation requires the APR/native
|
||||
// library
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------ Constructor
|
||||
|
||||
public AjpAprProtocol() {
|
||||
super(new AprEndpoint());
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------- Public Methods
|
||||
|
||||
public int getPollTime() { return ((AprEndpoint)getEndpoint()).getPollTime(); }
|
||||
public void setPollTime(int pollTime) { ((AprEndpoint)getEndpoint()).setPollTime(pollTime); }
|
||||
|
||||
|
||||
// ----------------------------------------------------- JMX related methods
|
||||
|
||||
@Override
|
||||
protected String getNamePrefix() {
|
||||
return "ajp-apr";
|
||||
}
|
||||
}
|
||||
426
java/org/apache/coyote/ajp/AjpMessage.java
Normal file
426
java/org/apache/coyote/ajp/AjpMessage.java
Normal file
@@ -0,0 +1,426 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.coyote.ajp;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.buf.ByteChunk;
|
||||
import org.apache.tomcat.util.buf.HexUtils;
|
||||
import org.apache.tomcat.util.buf.MessageBytes;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
/**
|
||||
* A single packet for communication between the web server and the
|
||||
* container. Designed to be reused many times with no creation of
|
||||
* garbage. Understands the format of data types for these packets.
|
||||
* Can be used (somewhat confusingly) for both incoming and outgoing
|
||||
* packets.
|
||||
*
|
||||
* @author Henri Gomez
|
||||
* @author Dan Milstein
|
||||
* @author Keith Wannamaker
|
||||
* @author Kevin Seguin
|
||||
* @author Costin Manolache
|
||||
*/
|
||||
public class AjpMessage {
|
||||
|
||||
|
||||
private static final Log log = LogFactory.getLog(AjpMessage.class);
|
||||
|
||||
/**
|
||||
* The string manager for this package.
|
||||
*/
|
||||
protected static final StringManager sm = StringManager.getManager(AjpMessage.class);
|
||||
|
||||
|
||||
// ------------------------------------------------------------ Constructor
|
||||
|
||||
|
||||
public AjpMessage(int packetSize) {
|
||||
buf = new byte[packetSize];
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------- Instance Variables
|
||||
|
||||
|
||||
/**
|
||||
* Fixed size buffer.
|
||||
*/
|
||||
protected final byte buf[];
|
||||
|
||||
|
||||
/**
|
||||
* The current read or write position in the buffer.
|
||||
*/
|
||||
protected int pos;
|
||||
|
||||
|
||||
/**
|
||||
* This actually means different things depending on whether the
|
||||
* packet is read or write. For read, it's the length of the
|
||||
* payload (excluding the header). For write, it's the length of
|
||||
* the packet as a whole (counting the header). Oh, well.
|
||||
*/
|
||||
protected int len;
|
||||
|
||||
|
||||
// --------------------------------------------------------- Public Methods
|
||||
|
||||
|
||||
/**
|
||||
* Prepare this packet for accumulating a message from the container to
|
||||
* the web server. Set the write position to just after the header
|
||||
* (but leave the length unwritten, because it is as yet unknown).
|
||||
*/
|
||||
public void reset() {
|
||||
len = 4;
|
||||
pos = 4;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* For a packet to be sent to the web server, finish the process of
|
||||
* accumulating data and write the length of the data payload into
|
||||
* the header.
|
||||
*/
|
||||
public void end() {
|
||||
len = pos;
|
||||
int dLen = len - 4;
|
||||
|
||||
buf[0] = (byte) 0x41;
|
||||
buf[1] = (byte) 0x42;
|
||||
buf[2] = (byte) ((dLen>>>8) & 0xFF);
|
||||
buf[3] = (byte) (dLen & 0xFF);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the underlying byte buffer.
|
||||
*
|
||||
* @return The buffer
|
||||
*/
|
||||
public byte[] getBuffer() {
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the current message length.
|
||||
*
|
||||
* @return For read, it's the length of the payload (excluding the header).
|
||||
* For write, it's the length of the packet as a whole (counting the
|
||||
* header).
|
||||
*/
|
||||
public int getLen() {
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a short integer (2 bytes) to the message.
|
||||
*
|
||||
* @param val The integer to append
|
||||
*/
|
||||
public void appendInt(int val) {
|
||||
buf[pos++] = (byte) ((val >>> 8) & 0xFF);
|
||||
buf[pos++] = (byte) (val & 0xFF);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Append a byte (1 byte) to the message.
|
||||
*
|
||||
* @param val The byte value to append
|
||||
*/
|
||||
public void appendByte(int val) {
|
||||
buf[pos++] = (byte) val;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write a MessageBytes out at the current write position. A null
|
||||
* MessageBytes is encoded as a string with length 0.
|
||||
*
|
||||
* @param mb The data to write
|
||||
*/
|
||||
public void appendBytes(MessageBytes mb) {
|
||||
if (mb == null) {
|
||||
log.error(sm.getString("ajpmessage.null"),
|
||||
new NullPointerException());
|
||||
appendInt(0);
|
||||
appendByte(0);
|
||||
return;
|
||||
}
|
||||
if (mb.getType() != MessageBytes.T_BYTES) {
|
||||
mb.toBytes();
|
||||
ByteChunk bc = mb.getByteChunk();
|
||||
// Need to filter out CTLs excluding TAB. ISO-8859-1 and UTF-8
|
||||
// values will be OK. Strings using other encodings may be
|
||||
// corrupted.
|
||||
byte[] buffer = bc.getBuffer();
|
||||
for (int i = bc.getOffset(); i < bc.getLength(); i++) {
|
||||
// byte values are signed i.e. -128 to 127
|
||||
// The values are used unsigned. 0 to 31 are CTLs so they are
|
||||
// filtered (apart from TAB which is 9). 127 is a control (DEL).
|
||||
// The values 128 to 255 are all OK. Converting those to signed
|
||||
// gives -128 to -1.
|
||||
if ((buffer[i] > -1 && buffer[i] <= 31 && buffer[i] != 9) ||
|
||||
buffer[i] == 127) {
|
||||
buffer[i] = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
appendByteChunk(mb.getByteChunk());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write a ByteChunk out at the current write position. A null ByteChunk is
|
||||
* encoded as a string with length 0.
|
||||
*
|
||||
* @param bc The data to write
|
||||
*/
|
||||
public void appendByteChunk(ByteChunk bc) {
|
||||
if (bc == null) {
|
||||
log.error(sm.getString("ajpmessage.null"),
|
||||
new NullPointerException());
|
||||
appendInt(0);
|
||||
appendByte(0);
|
||||
return;
|
||||
}
|
||||
appendBytes(bc.getBytes(), bc.getStart(), bc.getLength());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy a chunk of bytes into the packet, starting at the current
|
||||
* write position. The chunk of bytes is encoded with the length
|
||||
* in two bytes first, then the data itself, and finally a
|
||||
* terminating \0 (which is <B>not</B> included in the encoded
|
||||
* length).
|
||||
*
|
||||
* @param b The array from which to copy bytes.
|
||||
* @param off The offset into the array at which to start copying
|
||||
* @param numBytes The number of bytes to copy.
|
||||
*/
|
||||
public void appendBytes(byte[] b, int off, int numBytes) {
|
||||
if (checkOverflow(numBytes)) {
|
||||
return;
|
||||
}
|
||||
appendInt(numBytes);
|
||||
System.arraycopy(b, off, buf, pos, numBytes);
|
||||
pos += numBytes;
|
||||
appendByte(0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy a chunk of bytes into the packet, starting at the current
|
||||
* write position. The chunk of bytes is encoded with the length
|
||||
* in two bytes first, then the data itself, and finally a
|
||||
* terminating \0 (which is <B>not</B> included in the encoded
|
||||
* length).
|
||||
*
|
||||
* @param b The ByteBuffer from which to copy bytes.
|
||||
*/
|
||||
public void appendBytes(ByteBuffer b) {
|
||||
int numBytes = b.remaining();
|
||||
if (checkOverflow(numBytes)) {
|
||||
return;
|
||||
}
|
||||
appendInt(numBytes);
|
||||
b.get(buf, pos, numBytes);
|
||||
pos += numBytes;
|
||||
appendByte(0);
|
||||
}
|
||||
|
||||
|
||||
private boolean checkOverflow(int numBytes) {
|
||||
if (pos + numBytes + 3 > buf.length) {
|
||||
log.error(sm.getString("ajpmessage.overflow", "" + numBytes, "" + pos),
|
||||
new ArrayIndexOutOfBoundsException());
|
||||
if (log.isDebugEnabled()) {
|
||||
dump("Overflow/coBytes");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read an integer from packet, and advance the read position past
|
||||
* it. Integers are encoded as two unsigned bytes with the
|
||||
* high-order byte first, and, as far as I can tell, in
|
||||
* little-endian order within each byte.
|
||||
*
|
||||
* @return The integer value read from the message
|
||||
*/
|
||||
public int getInt() {
|
||||
int b1 = buf[pos++] & 0xFF;
|
||||
int b2 = buf[pos++] & 0xFF;
|
||||
validatePos(pos);
|
||||
return (b1<<8) + b2;
|
||||
}
|
||||
|
||||
|
||||
public int peekInt() {
|
||||
validatePos(pos + 2);
|
||||
int b1 = buf[pos] & 0xFF;
|
||||
int b2 = buf[pos+1] & 0xFF;
|
||||
return (b1<<8) + b2;
|
||||
}
|
||||
|
||||
|
||||
public byte getByte() {
|
||||
byte res = buf[pos++];
|
||||
validatePos(pos);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
public void getBytes(MessageBytes mb) {
|
||||
doGetBytes(mb, true);
|
||||
}
|
||||
|
||||
public void getBodyBytes(MessageBytes mb) {
|
||||
doGetBytes(mb, false);
|
||||
}
|
||||
|
||||
private void doGetBytes(MessageBytes mb, boolean terminated) {
|
||||
int length = getInt();
|
||||
if ((length == 0xFFFF) || (length == -1)) {
|
||||
mb.recycle();
|
||||
return;
|
||||
}
|
||||
if (terminated) {
|
||||
validatePos(pos + length + 1);
|
||||
} else {
|
||||
validatePos(pos + length);
|
||||
}
|
||||
mb.setBytes(buf, pos, length);
|
||||
mb.getCharChunk().recycle(); // not valid anymore
|
||||
pos += length;
|
||||
if (terminated) {
|
||||
pos++; // Skip the terminating \0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read a 32 bits integer from packet, and advance the read position past
|
||||
* it. Integers are encoded as four unsigned bytes with the
|
||||
* high-order byte first, and, as far as I can tell, in
|
||||
* little-endian order within each byte.
|
||||
*
|
||||
* @return The long value read from the message
|
||||
*/
|
||||
public int getLongInt() {
|
||||
int b1 = buf[pos++] & 0xFF; // No swap, Java order
|
||||
b1 <<= 8;
|
||||
b1 |= (buf[pos++] & 0xFF);
|
||||
b1 <<= 8;
|
||||
b1 |= (buf[pos++] & 0xFF);
|
||||
b1 <<=8;
|
||||
b1 |= (buf[pos++] & 0xFF);
|
||||
validatePos(pos);
|
||||
return b1;
|
||||
}
|
||||
|
||||
|
||||
public int processHeader(boolean toContainer) {
|
||||
pos = 0;
|
||||
int mark = getInt();
|
||||
len = getInt();
|
||||
// Verify message signature
|
||||
if ((toContainer && mark != 0x1234) ||
|
||||
(!toContainer && mark != 0x4142)) {
|
||||
log.error(sm.getString("ajpmessage.invalid", "" + mark));
|
||||
if (log.isDebugEnabled()) {
|
||||
dump("In");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Received " + len + " " + buf[0]);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
private void dump(String prefix) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(prefix + ": " + HexUtils.toHexString(buf) + " " + pos +"/" + (len + 4));
|
||||
}
|
||||
int max = pos;
|
||||
if (len + 4 > pos)
|
||||
max = len+4;
|
||||
if (max > 1000)
|
||||
max = 1000;
|
||||
if (log.isDebugEnabled()) {
|
||||
for (int j = 0; j < max; j += 16) {
|
||||
log.debug(hexLine(buf, j, len));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void validatePos(int posToTest) {
|
||||
if (posToTest > len + 4) {
|
||||
// Trying to read data beyond the end of the AJP message
|
||||
throw new ArrayIndexOutOfBoundsException(sm.getString(
|
||||
"ajpMessage.invalidPos", Integer.valueOf(posToTest)));
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------ Protected Methods
|
||||
|
||||
|
||||
protected static String hexLine(byte buf[], int start, int len) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = start; i < start + 16 ; i++) {
|
||||
if (i < len + 4) {
|
||||
sb.append(hex(buf[i]) + " ");
|
||||
} else {
|
||||
sb.append(" ");
|
||||
}
|
||||
}
|
||||
sb.append(" | ");
|
||||
for (int i = start; i < start + 16 && i < len + 4; i++) {
|
||||
if (!Character.isISOControl((char) buf[i])) {
|
||||
sb.append(Character.valueOf((char) buf[i]));
|
||||
} else {
|
||||
sb.append(".");
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
protected static String hex(int x) {
|
||||
String h = Integer.toHexString(x);
|
||||
if (h.length() == 1) {
|
||||
h = "0" + h;
|
||||
}
|
||||
return h.substring(h.length() - 2);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
49
java/org/apache/coyote/ajp/AjpNio2Protocol.java
Normal file
49
java/org/apache/coyote/ajp/AjpNio2Protocol.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote.ajp;
|
||||
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.net.Nio2Channel;
|
||||
import org.apache.tomcat.util.net.Nio2Endpoint;
|
||||
|
||||
|
||||
/**
|
||||
* This the NIO2 based protocol handler implementation for AJP.
|
||||
*/
|
||||
public class AjpNio2Protocol extends AbstractAjpProtocol<Nio2Channel> {
|
||||
|
||||
private static final Log log = LogFactory.getLog(AjpNio2Protocol.class);
|
||||
|
||||
@Override
|
||||
protected Log getLog() { return log; }
|
||||
|
||||
|
||||
// ------------------------------------------------------------ Constructor
|
||||
|
||||
public AjpNio2Protocol() {
|
||||
super(new Nio2Endpoint());
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------- JMX related methods
|
||||
|
||||
@Override
|
||||
protected String getNamePrefix() {
|
||||
return "ajp-nio2";
|
||||
}
|
||||
}
|
||||
48
java/org/apache/coyote/ajp/AjpNioProtocol.java
Normal file
48
java/org/apache/coyote/ajp/AjpNioProtocol.java
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote.ajp;
|
||||
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.net.NioChannel;
|
||||
import org.apache.tomcat.util.net.NioEndpoint;
|
||||
|
||||
/**
|
||||
* This the NIO based protocol handler implementation for AJP.
|
||||
*/
|
||||
public class AjpNioProtocol extends AbstractAjpProtocol<NioChannel> {
|
||||
|
||||
private static final Log log = LogFactory.getLog(AjpNioProtocol.class);
|
||||
|
||||
@Override
|
||||
protected Log getLog() { return log; }
|
||||
|
||||
|
||||
// ------------------------------------------------------------ Constructor
|
||||
|
||||
public AjpNioProtocol() {
|
||||
super(new NioEndpoint());
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------- JMX related methods
|
||||
|
||||
@Override
|
||||
protected String getNamePrefix() {
|
||||
return "ajp-nio";
|
||||
}
|
||||
}
|
||||
1511
java/org/apache/coyote/ajp/AjpProcessor.java
Normal file
1511
java/org/apache/coyote/ajp/AjpProcessor.java
Normal file
File diff suppressed because it is too large
Load Diff
37
java/org/apache/coyote/ajp/AjpProtocol.java
Normal file
37
java/org/apache/coyote/ajp/AjpProtocol.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote.ajp;
|
||||
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
/**
|
||||
* @deprecated This class will be removed in Tomcat 9.
|
||||
*/
|
||||
@Deprecated
|
||||
public class AjpProtocol extends AjpNioProtocol {
|
||||
|
||||
private static final Log log = LogFactory.getLog(AjpProtocol.class);
|
||||
private static final StringManager sm = StringManager.getManager(AjpProtocol.class);
|
||||
|
||||
|
||||
public AjpProtocol() {
|
||||
super();
|
||||
log.warn(sm.getString("ajpprotocol.noBio"));
|
||||
}
|
||||
}
|
||||
240
java/org/apache/coyote/ajp/Constants.java
Normal file
240
java/org/apache/coyote/ajp/Constants.java
Normal file
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote.ajp;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
* Constants.
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
public final class Constants {
|
||||
|
||||
public static final int DEFAULT_CONNECTION_TIMEOUT = -1;
|
||||
|
||||
// Prefix codes for message types from server to container
|
||||
public static final byte JK_AJP13_FORWARD_REQUEST = 2;
|
||||
public static final byte JK_AJP13_SHUTDOWN = 7; // XXX Unused
|
||||
public static final byte JK_AJP13_PING_REQUEST = 8; // XXX Unused
|
||||
public static final byte JK_AJP13_CPING_REQUEST = 10;
|
||||
|
||||
// Prefix codes for message types from container to server
|
||||
public static final byte JK_AJP13_SEND_BODY_CHUNK = 3;
|
||||
public static final byte JK_AJP13_SEND_HEADERS = 4;
|
||||
public static final byte JK_AJP13_END_RESPONSE = 5;
|
||||
public static final byte JK_AJP13_GET_BODY_CHUNK = 6;
|
||||
public static final byte JK_AJP13_CPONG_REPLY = 9;
|
||||
|
||||
// Integer codes for common response header strings
|
||||
public static final int SC_RESP_CONTENT_TYPE = 0xA001;
|
||||
public static final int SC_RESP_CONTENT_LANGUAGE = 0xA002;
|
||||
public static final int SC_RESP_CONTENT_LENGTH = 0xA003;
|
||||
public static final int SC_RESP_DATE = 0xA004;
|
||||
public static final int SC_RESP_LAST_MODIFIED = 0xA005;
|
||||
public static final int SC_RESP_LOCATION = 0xA006;
|
||||
public static final int SC_RESP_SET_COOKIE = 0xA007;
|
||||
public static final int SC_RESP_SET_COOKIE2 = 0xA008;
|
||||
public static final int SC_RESP_SERVLET_ENGINE = 0xA009;
|
||||
public static final int SC_RESP_STATUS = 0xA00A;
|
||||
public static final int SC_RESP_WWW_AUTHENTICATE = 0xA00B;
|
||||
public static final int SC_RESP_AJP13_MAX = 11;
|
||||
|
||||
// Integer codes for common (optional) request attribute names
|
||||
public static final byte SC_A_CONTEXT = 1; // XXX Unused
|
||||
public static final byte SC_A_SERVLET_PATH = 2; // XXX Unused
|
||||
public static final byte SC_A_REMOTE_USER = 3;
|
||||
public static final byte SC_A_AUTH_TYPE = 4;
|
||||
public static final byte SC_A_QUERY_STRING = 5;
|
||||
public static final byte SC_A_JVM_ROUTE = 6;
|
||||
public static final byte SC_A_SSL_CERT = 7;
|
||||
public static final byte SC_A_SSL_CIPHER = 8;
|
||||
public static final byte SC_A_SSL_SESSION = 9;
|
||||
public static final byte SC_A_SSL_KEY_SIZE = 11;
|
||||
public static final byte SC_A_SECRET = 12;
|
||||
public static final byte SC_A_STORED_METHOD = 13;
|
||||
|
||||
// Used for attributes which are not in the list above
|
||||
public static final byte SC_A_REQ_ATTRIBUTE = 10;
|
||||
|
||||
/**
|
||||
* AJP private request attributes
|
||||
*/
|
||||
public static final String SC_A_REQ_LOCAL_ADDR = "AJP_LOCAL_ADDR";
|
||||
public static final String SC_A_REQ_REMOTE_PORT = "AJP_REMOTE_PORT";
|
||||
public static final String SC_A_SSL_PROTOCOL = "AJP_SSL_PROTOCOL";
|
||||
|
||||
// Terminates list of attributes
|
||||
public static final byte SC_A_ARE_DONE = (byte)0xFF;
|
||||
|
||||
// Ajp13 specific - needs refactoring for the new model
|
||||
|
||||
/**
|
||||
* Default maximum total byte size for an AJP packet
|
||||
*/
|
||||
public static final int MAX_PACKET_SIZE = 8192;
|
||||
/**
|
||||
* Size of basic packet header
|
||||
*/
|
||||
public static final int H_SIZE = 4;
|
||||
|
||||
/**
|
||||
* Size of the header metadata
|
||||
*/
|
||||
public static final int READ_HEAD_LEN = 6;
|
||||
public static final int SEND_HEAD_LEN = 8;
|
||||
|
||||
/**
|
||||
* Default maximum size of data that can be sent in one packet
|
||||
*/
|
||||
public static final int MAX_READ_SIZE = MAX_PACKET_SIZE - READ_HEAD_LEN;
|
||||
public static final int MAX_SEND_SIZE = MAX_PACKET_SIZE - SEND_HEAD_LEN;
|
||||
|
||||
// Translates integer codes to names of HTTP methods
|
||||
private static final String [] methodTransArray = {
|
||||
"OPTIONS",
|
||||
"GET",
|
||||
"HEAD",
|
||||
"POST",
|
||||
"PUT",
|
||||
"DELETE",
|
||||
"TRACE",
|
||||
"PROPFIND",
|
||||
"PROPPATCH",
|
||||
"MKCOL",
|
||||
"COPY",
|
||||
"MOVE",
|
||||
"LOCK",
|
||||
"UNLOCK",
|
||||
"ACL",
|
||||
"REPORT",
|
||||
"VERSION-CONTROL",
|
||||
"CHECKIN",
|
||||
"CHECKOUT",
|
||||
"UNCHECKOUT",
|
||||
"SEARCH",
|
||||
"MKWORKSPACE",
|
||||
"UPDATE",
|
||||
"LABEL",
|
||||
"MERGE",
|
||||
"BASELINE-CONTROL",
|
||||
"MKACTIVITY"
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts an AJP coded HTTP method to the method name.
|
||||
* @param code the coded value
|
||||
* @return the string value of the method
|
||||
*/
|
||||
public static final String getMethodForCode(final int code) {
|
||||
return methodTransArray[code];
|
||||
}
|
||||
|
||||
public static final int SC_M_JK_STORED = (byte) 0xFF;
|
||||
|
||||
// id's for common request headers
|
||||
public static final int SC_REQ_ACCEPT = 1;
|
||||
public static final int SC_REQ_ACCEPT_CHARSET = 2;
|
||||
public static final int SC_REQ_ACCEPT_ENCODING = 3;
|
||||
public static final int SC_REQ_ACCEPT_LANGUAGE = 4;
|
||||
public static final int SC_REQ_AUTHORIZATION = 5;
|
||||
public static final int SC_REQ_CONNECTION = 6;
|
||||
public static final int SC_REQ_CONTENT_TYPE = 7;
|
||||
public static final int SC_REQ_CONTENT_LENGTH = 8;
|
||||
public static final int SC_REQ_COOKIE = 9;
|
||||
public static final int SC_REQ_COOKIE2 = 10;
|
||||
public static final int SC_REQ_HOST = 11;
|
||||
public static final int SC_REQ_PRAGMA = 12;
|
||||
public static final int SC_REQ_REFERER = 13;
|
||||
public static final int SC_REQ_USER_AGENT = 14;
|
||||
|
||||
// Translates integer codes to request header names
|
||||
private static final String [] headerTransArray = {
|
||||
"accept",
|
||||
"accept-charset",
|
||||
"accept-encoding",
|
||||
"accept-language",
|
||||
"authorization",
|
||||
"connection",
|
||||
"content-type",
|
||||
"content-length",
|
||||
"cookie",
|
||||
"cookie2",
|
||||
"host",
|
||||
"pragma",
|
||||
"referer",
|
||||
"user-agent"
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts an AJP coded HTTP request header to the header name.
|
||||
* @param code the coded value
|
||||
* @return the string value of the header name
|
||||
*/
|
||||
public static final String getHeaderForCode(final int code) {
|
||||
return headerTransArray[code];
|
||||
}
|
||||
|
||||
// Translates integer codes to response header names
|
||||
private static final String [] responseTransArray = {
|
||||
"Content-Type",
|
||||
"Content-Language",
|
||||
"Content-Length",
|
||||
"Date",
|
||||
"Last-Modified",
|
||||
"Location",
|
||||
"Set-Cookie",
|
||||
"Set-Cookie2",
|
||||
"Servlet-Engine",
|
||||
"Status",
|
||||
"WWW-Authenticate"
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts an AJP coded response header name to the HTTP response header name.
|
||||
* @param code the coded value
|
||||
* @return the string value of the header
|
||||
*/
|
||||
public static final String getResponseHeaderForCode(final int code) {
|
||||
return responseTransArray[code];
|
||||
}
|
||||
|
||||
private static final Hashtable<String,Integer> responseTransHash =
|
||||
new Hashtable<>(20);
|
||||
|
||||
static {
|
||||
try {
|
||||
int i;
|
||||
for (i = 0; i < SC_RESP_AJP13_MAX; i++) {
|
||||
responseTransHash.put(getResponseHeaderForCode(i),
|
||||
Integer.valueOf(0xA001 + i));
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
public static final int getResponseAjpIndex(String header)
|
||||
{
|
||||
Integer i = responseTransHash.get(header);
|
||||
if (i == null)
|
||||
return 0;
|
||||
else
|
||||
return i.intValue();
|
||||
}
|
||||
}
|
||||
37
java/org/apache/coyote/ajp/LocalStrings.properties
Normal file
37
java/org/apache/coyote/ajp/LocalStrings.properties
Normal file
@@ -0,0 +1,37 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
ajpMessage.invalidPos=Requested read of bytes at position [{0}] which is beyond the end of the AJP message
|
||||
|
||||
ajpmessage.invalid=Invalid message received with signature [{0}]
|
||||
ajpmessage.invalidLength=Invalid message received with length [{0}]
|
||||
ajpmessage.null=Cannot append null value
|
||||
ajpmessage.overflow=Overflow error for buffer adding [{0}] bytes at position [{1}]
|
||||
|
||||
ajpnioprotocol.releaseEnd=Done iterating through our connections to release a socket channel [{0}] released [{1}]
|
||||
ajpnioprotocol.releaseStart=Iterating through our connections to release a socket channel [{0}]
|
||||
|
||||
ajpprocessor.certs.fail=Certificate conversion failed
|
||||
ajpprocessor.header.error=Header message parsing failed
|
||||
ajpprocessor.header.tooLong=Header message of length [{0}] received but the packetSize is only [{1}]
|
||||
ajpprocessor.readtimeout=Timeout attempting to read data from the socket
|
||||
ajpprocessor.request.prepare=Error preparing request
|
||||
ajpprocessor.request.process=Error processing request
|
||||
|
||||
ajpprotocol.noBio=The AJP BIO connector has been removed in Tomcat 8.5.x onwards. The AJP BIO connector configuration has been automatically switched to use the AJP NIO connector instead.
|
||||
ajpprotocol.noSSL=SSL is not supported with AJP. The SSL host configuration for [{0}] was ignored
|
||||
ajpprotocol.nosecret=The AJP Connector is configured with secretRequired="true" but the secret attribute is either null or "". This combination is not valid.
|
||||
ajpprotocol.noUpgrade=Upgrade is not supported with AJP. The UpgradeProtocol configuration for [{0}] was ignored
|
||||
ajpprotocol.noUpgradeHandler=Upgrade is not supported with AJP. The HttpUpgradeHandler [{0}] can not be processed
|
||||
18
java/org/apache/coyote/ajp/LocalStrings_de.properties
Normal file
18
java/org/apache/coyote/ajp/LocalStrings_de.properties
Normal file
@@ -0,0 +1,18 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
ajpmessage.overflow=Überlauffehler im Puffer beim Hinzufügen von [{0}] Bytes an Position [{1}]
|
||||
|
||||
ajpprotocol.noUpgrade=Upgrade wird von AJP nicht unterstützt. Die Konfiguration UpgradeProtocol für [{0}] wurde ignoriert
|
||||
25
java/org/apache/coyote/ajp/LocalStrings_es.properties
Normal file
25
java/org/apache/coyote/ajp/LocalStrings_es.properties
Normal file
@@ -0,0 +1,25 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
ajpmessage.invalid=Mensaje inválido recibido con firma [{0}]
|
||||
ajpmessage.null=No puedo añadir valor nulo
|
||||
ajpmessage.overflow=Error de desbordamiento en búfer al añadir [{0}] bytes en posición [{1}]
|
||||
|
||||
ajpprocessor.certs.fail=Fallo en conversión de Certificado
|
||||
ajpprocessor.header.error=Fallo en análisis de mensaje de cabecera
|
||||
ajpprocessor.request.prepare=Error preparando requerimiento
|
||||
ajpprocessor.request.process=Error procesando requerimiento
|
||||
|
||||
ajpprotocol.noUpgrade=Actualización (upgrade) no esta soportada para AJP. Se ha ignorado la configuración UpgradeProtocol para [{0}]
|
||||
32
java/org/apache/coyote/ajp/LocalStrings_fr.properties
Normal file
32
java/org/apache/coyote/ajp/LocalStrings_fr.properties
Normal file
@@ -0,0 +1,32 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
ajpMessage.invalidPos=Une lecture d''octets à la position [{0}] a été demandée ce qui est au-delà de la fin du message AJP
|
||||
|
||||
ajpmessage.invalid=Message invalide reçu avec la signature [{0}]
|
||||
ajpmessage.invalidLength=Message invalide reçu avec une longueur [{0}]
|
||||
ajpmessage.null=Impossible d'ajouter une valeur nulle.
|
||||
ajpmessage.overflow=Débordement du tampon en ajoutant [{0}] octets à la position [{1}]
|
||||
|
||||
ajpprocessor.certs.fail=La conversion du certificat a échouée
|
||||
ajpprocessor.header.error=Erreur de traitement du message d'en-tête
|
||||
ajpprocessor.header.tooLong=Un en-tête de message de taille [{0}] a été reçu mais la packtSize est de seulement [{1}]
|
||||
ajpprocessor.readtimeout=Timeout lors de la lecture de données sur le socket
|
||||
ajpprocessor.request.prepare=Erreur lors de la préparation de la requête
|
||||
ajpprocessor.request.process=Erreur de traitement de la requête
|
||||
|
||||
ajpprotocol.noSSL=SSL n''est pas supporté par AJP, la configuration de l''hôte SSL pour [{0}] a été ignorée
|
||||
ajpprotocol.noUpgrade=L''upgrade n''est pas supporté par AJP. La configuration UpgradeProtocol pour [{0}] a été ignorée
|
||||
ajpprotocol.noUpgradeHandler=AJP ne supporte pas la mise à niveau (upgrade) de HTTP/1.1, le HttpUpgradeHandler [{0}] ne peut pas être utilisé
|
||||
32
java/org/apache/coyote/ajp/LocalStrings_ja.properties
Normal file
32
java/org/apache/coyote/ajp/LocalStrings_ja.properties
Normal file
@@ -0,0 +1,32 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
ajpMessage.invalidPos=AJP メッセージの終端より先の位置 [{0}] のバイト読み取りを要求されました。
|
||||
|
||||
ajpmessage.invalid=署名[{0}]で無効なメッセージが受信されました。
|
||||
ajpmessage.invalidLength=長さ[{0}]の無効なメッセージが受信されました
|
||||
ajpmessage.null=null 値は追加できません。
|
||||
ajpmessage.overflow=バッファーの位置 [{1}] へ [{0}] バイトのデータを追加しようとして、オーバーフローエラーが発生しました。
|
||||
|
||||
ajpprocessor.certs.fail=証明書変換に失敗しました。
|
||||
ajpprocessor.header.error=ヘッダーメッセージの解析に失敗しました
|
||||
ajpprocessor.header.tooLong=受信したヘッダーに指定されたメッセージ長は [{0}] ですがpacketSize は [{1}] しかありません。
|
||||
ajpprocessor.readtimeout=ソケットからのデータの読み取りをタイムアウトにします。
|
||||
ajpprocessor.request.prepare=リクエスト準備中エラー
|
||||
ajpprocessor.request.process=リクエスト処理エラー
|
||||
|
||||
ajpprotocol.noSSL=AJP は SSL に対応していません。SSL ホスト構成 [{0}] を無視します。
|
||||
ajpprotocol.noUpgrade=AJP はプロトコルアップグレードに対応していないため、[{0}] の設定を無視しました。
|
||||
ajpprotocol.noUpgradeHandler=アップグレードはAJPではサポートされていません。 HttpUpgradeHandler [{0}]を処理できません。
|
||||
32
java/org/apache/coyote/ajp/LocalStrings_ko.properties
Normal file
32
java/org/apache/coyote/ajp/LocalStrings_ko.properties
Normal file
@@ -0,0 +1,32 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
ajpMessage.invalidPos=위치 [{0}](으)로부터 바이트들을 읽기를 요청 받았는데, 이는 해당 AJP 메시지의 끝 위치를 넘어섰습니다.
|
||||
|
||||
ajpmessage.invalid=서명 [{0}]와(과) 함께, 유효하지 않은 메시지를 받았습니다.
|
||||
ajpmessage.invalidLength=길이가 [{0}]인 유효하지 않은 메시지를 받았습니다.
|
||||
ajpmessage.null=널 값을 추가할 수 없습니다.
|
||||
ajpmessage.overflow=버퍼에 [{0}] 바이트들을 위치 [{1}]에 추가하는 동안 오버플로우 오류 발생
|
||||
|
||||
ajpprocessor.certs.fail=인증서를 변환시키지 못했습니다.
|
||||
ajpprocessor.header.error=헤더 메시지를 파싱하지 못했습니다.
|
||||
ajpprocessor.header.tooLong=길이가 [{0}]인 헤더 메시지를 받았지만, 패킷 크기는 단지 [{1}]입니다.
|
||||
ajpprocessor.readtimeout=소켓으로부터 데이터를 읽으려는 시도가 제한 시간 초과되었습니다.
|
||||
ajpprocessor.request.prepare=요청을 준비하는 중 오류 발생
|
||||
ajpprocessor.request.process=요청 처리 중 오류 발생
|
||||
|
||||
ajpprotocol.noSSL=AJP와 함께 SSL은 지원되지 않습니다. [{0}]을(를) 위한 SSL 호스트 설정은 무시되었습니다.
|
||||
ajpprotocol.noUpgrade=AJP에서 프로토콜 업그레이드는 지원되지 않습니다. [{0}]을(를) 위한 UpgradeProtocol 설정은 무시됩니다.
|
||||
ajpprotocol.noUpgradeHandler=AJP를 사용할 때, 업그레이드는 지원되지 않습니다. HttpUpgradeHandler [{0}]은(는) 처리될 수 없습니다.
|
||||
23
java/org/apache/coyote/ajp/LocalStrings_zh_CN.properties
Normal file
23
java/org/apache/coyote/ajp/LocalStrings_zh_CN.properties
Normal file
@@ -0,0 +1,23 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
ajpmessage.null=不能赋空值
|
||||
ajpmessage.overflow=在缓冲区[{1}]位置添加[{0}]字节时发生溢出错误
|
||||
|
||||
ajpprocessor.certs.fail=):证书转换失败
|
||||
ajpprocessor.header.error=头部信息解析失败
|
||||
ajpprocessor.readtimeout=从Socket读取数据超时
|
||||
|
||||
ajpprotocol.noUpgrade=AJP 不支持升级。[{0}] 的升级协议配置被忽略。
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote.http11;
|
||||
|
||||
import org.apache.tomcat.util.net.AbstractJsseEndpoint;
|
||||
import org.apache.tomcat.util.net.openssl.OpenSSLImplementation;
|
||||
|
||||
public abstract class AbstractHttp11JsseProtocol<S>
|
||||
extends AbstractHttp11Protocol<S> {
|
||||
|
||||
public AbstractHttp11JsseProtocol(AbstractJsseEndpoint<S> endpoint) {
|
||||
super(endpoint);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected AbstractJsseEndpoint<S> getEndpoint() {
|
||||
// Over-ridden to add cast
|
||||
return (AbstractJsseEndpoint<S>) super.getEndpoint();
|
||||
}
|
||||
|
||||
|
||||
protected String getSslImplementationShortName() {
|
||||
if (OpenSSLImplementation.class.getName().equals(getSslImplementationName())) {
|
||||
return "openssl";
|
||||
}
|
||||
return "jsse";
|
||||
}
|
||||
|
||||
public String getSslImplementationName() { return getEndpoint().getSslImplementationName(); }
|
||||
public void setSslImplementationName(String s) { getEndpoint().setSslImplementationName(s); }
|
||||
|
||||
|
||||
public int getSniParseLimit() { return getEndpoint().getSniParseLimit(); }
|
||||
public void setSniParseLimit(int sniParseLimit) {
|
||||
getEndpoint().setSniParseLimit(sniParseLimit);
|
||||
}
|
||||
}
|
||||
1011
java/org/apache/coyote/http11/AbstractHttp11Protocol.java
Normal file
1011
java/org/apache/coyote/http11/AbstractHttp11Protocol.java
Normal file
File diff suppressed because it is too large
Load Diff
179
java/org/apache/coyote/http11/Constants.java
Normal file
179
java/org/apache/coyote/http11/Constants.java
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote.http11;
|
||||
|
||||
import org.apache.tomcat.util.buf.ByteChunk;
|
||||
|
||||
/**
|
||||
* Constants.
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
public final class Constants {
|
||||
|
||||
public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
|
||||
|
||||
|
||||
/**
|
||||
* CRLF.
|
||||
*/
|
||||
public static final String CRLF = "\r\n";
|
||||
|
||||
|
||||
/**
|
||||
* CR.
|
||||
*/
|
||||
public static final byte CR = (byte) '\r';
|
||||
|
||||
|
||||
/**
|
||||
* LF.
|
||||
*/
|
||||
public static final byte LF = (byte) '\n';
|
||||
|
||||
|
||||
/**
|
||||
* SP.
|
||||
*/
|
||||
public static final byte SP = (byte) ' ';
|
||||
|
||||
|
||||
/**
|
||||
* HT.
|
||||
*/
|
||||
public static final byte HT = (byte) '\t';
|
||||
|
||||
|
||||
/**
|
||||
* COLON.
|
||||
*/
|
||||
public static final byte COLON = (byte) ':';
|
||||
|
||||
|
||||
/**
|
||||
* SEMI_COLON.
|
||||
*/
|
||||
public static final byte SEMI_COLON = (byte) ';';
|
||||
|
||||
|
||||
/**
|
||||
* 'A'.
|
||||
*/
|
||||
public static final byte A = (byte) 'A';
|
||||
|
||||
|
||||
/**
|
||||
* 'a'.
|
||||
*/
|
||||
public static final byte a = (byte) 'a';
|
||||
|
||||
|
||||
/**
|
||||
* 'Z'.
|
||||
*/
|
||||
public static final byte Z = (byte) 'Z';
|
||||
|
||||
|
||||
/**
|
||||
* '?'.
|
||||
*/
|
||||
public static final byte QUESTION = (byte) '?';
|
||||
|
||||
|
||||
/**
|
||||
* Lower case offset.
|
||||
*/
|
||||
public static final byte LC_OFFSET = A - a;
|
||||
|
||||
|
||||
/* Various constant "strings" */
|
||||
public static final String CONNECTION = "Connection";
|
||||
public static final String CLOSE = "close";
|
||||
/**
|
||||
* @deprecated Unused. Will be removed in Tomcat 10.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final byte[] CLOSE_BYTES = ByteChunk.convertToBytes(CLOSE);
|
||||
/**
|
||||
* @deprecated Unused. Will be removed in Tomcat 10.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String KEEPALIVE = "keep-alive";
|
||||
public static final String KEEP_ALIVE_HEADER_VALUE_TOKEN = "keep-alive";
|
||||
/**
|
||||
* @deprecated Unused. Will be removed in Tomcat 10.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final byte[] KEEPALIVE_BYTES = ByteChunk.convertToBytes(KEEPALIVE);
|
||||
public static final String CHUNKED = "chunked";
|
||||
/**
|
||||
* @deprecated This option will be removed in Tomcat 9. Reason phrase will
|
||||
* not be sent.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final byte[] ACK_BYTES_REASON =
|
||||
ByteChunk.convertToBytes("HTTP/1.1 100 Continue" + CRLF + CRLF);
|
||||
public static final byte[] ACK_BYTES = ByteChunk.convertToBytes("HTTP/1.1 100 " + CRLF + CRLF);
|
||||
public static final String TRANSFERENCODING = "Transfer-Encoding";
|
||||
public static final String KEEP_ALIVE_HEADER_NAME = "Keep-Alive";
|
||||
public static final byte[] _200_BYTES = ByteChunk.convertToBytes("200");
|
||||
public static final byte[] _400_BYTES = ByteChunk.convertToBytes("400");
|
||||
public static final byte[] _404_BYTES = ByteChunk.convertToBytes("404");
|
||||
|
||||
|
||||
/**
|
||||
* Identity filters (input and output).
|
||||
*/
|
||||
public static final int IDENTITY_FILTER = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Chunked filters (input and output).
|
||||
*/
|
||||
public static final int CHUNKED_FILTER = 1;
|
||||
|
||||
|
||||
/**
|
||||
* Void filters (input and output).
|
||||
*/
|
||||
public static final int VOID_FILTER = 2;
|
||||
|
||||
|
||||
/**
|
||||
* GZIP filter (output).
|
||||
*/
|
||||
public static final int GZIP_FILTER = 3;
|
||||
|
||||
|
||||
/**
|
||||
* Buffered filter (input)
|
||||
*/
|
||||
public static final int BUFFERED_FILTER = 3;
|
||||
|
||||
|
||||
/**
|
||||
* HTTP/1.0.
|
||||
*/
|
||||
public static final String HTTP_10 = "HTTP/1.0";
|
||||
|
||||
|
||||
/**
|
||||
* HTTP/1.1.
|
||||
*/
|
||||
public static final String HTTP_11 = "HTTP/1.1";
|
||||
public static final byte[] HTTP_11_BYTES = ByteChunk.convertToBytes(HTTP_11);
|
||||
}
|
||||
42
java/org/apache/coyote/http11/HeadersTooLargeException.java
Normal file
42
java/org/apache/coyote/http11/HeadersTooLargeException.java
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.coyote.http11;
|
||||
|
||||
/**
|
||||
* Exception used to mark the specific error condition of the HTTP headers
|
||||
* exceeding the maximum permitted size.
|
||||
*/
|
||||
public class HeadersTooLargeException extends IllegalStateException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public HeadersTooLargeException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public HeadersTooLargeException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public HeadersTooLargeException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public HeadersTooLargeException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user