This commit is contained in:
2024-11-30 19:03:49 +08:00
commit 1e6763c160
3806 changed files with 737676 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View 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();
}

File diff suppressed because it is too large Load Diff

View 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
}

View 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);
}

View 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();
}

View 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();
}

View 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;
}
}

View 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);
}
}

View 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;
}
}

View 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";
}

View 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();
}
}

View 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;
}
}

View 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;
}

View 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

View 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

View 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

View 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

View 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=ノンブロッキング書き込みリスナーが設定済みです

View 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 쓰기 리스너가 이미 설정되었습니다.

View 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=非阻塞的写监听已经被设置.

View 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();
}

View 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();
}

View 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);
}
}

View 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();
}

File diff suppressed because it is too large Load Diff

View 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);
}
}

View 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;
}
}

File diff suppressed because it is too large Load Diff

View 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);
}

View 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;
}
}

View 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();
}
}

View 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";
}
}

View 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);
}
}

View 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";
}
}

View 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";
}
}

File diff suppressed because it is too large Load Diff

View 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"));
}
}

View 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();
}
}

View 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

View 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

View 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}]

View 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é

View 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}]を処理できません。

View 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}]은(는) 처리될 수 없습니다.

View 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}] 的升级协议配置被忽略。

View 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.
*/
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);
}
}

File diff suppressed because it is too large Load Diff

View 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);
}

View 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