📄 ajpprocessor.java
字号:
/*
* 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.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import org.apache.coyote.ActionCode;
import org.apache.coyote.ActionHook;
import org.apache.coyote.Adapter;
import org.apache.coyote.InputBuffer;
import org.apache.coyote.OutputBuffer;
import org.apache.coyote.Request;
import org.apache.coyote.RequestInfo;
import org.apache.coyote.Response;
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.http.HttpMessages;
import org.apache.tomcat.util.http.MimeHeaders;
import org.apache.tomcat.util.net.JIoEndpoint;
import org.apache.tomcat.util.res.StringManager;
/**
* Processes HTTP requests.
*
* @author Remy Maucherat
* @author Henri Gomez
* @author Dan Milstein
* @author Keith Wannamaker
* @author Kevin Seguin
* @author Costin Manolache
* @author Bill Barker
*/
public class AjpProcessor implements ActionHook {
/**
* Logger.
*/
protected static org.apache.juli.logging.Log log
= org.apache.juli.logging.LogFactory.getLog(AjpProcessor.class);
/**
* The string manager for this package.
*/
protected static StringManager sm =
StringManager.getManager(Constants.Package);
// ----------------------------------------------------------- Constructors
public AjpProcessor(int packetSize, JIoEndpoint endpoint) {
this.endpoint = endpoint;
request = new Request();
request.setInputBuffer(new SocketInputBuffer());
response = new Response();
response.setHook(this);
response.setOutputBuffer(new SocketOutputBuffer());
request.setResponse(response);
requestHeaderMessage = new AjpMessage(packetSize);
responseHeaderMessage = new AjpMessage(packetSize);
bodyMessage = new AjpMessage(packetSize);
// Cause loading of HexUtils
int foo = HexUtils.DEC[0];
// Cause loading of HttpMessages
HttpMessages.getMessage(200);
}
// ----------------------------------------------------- Instance Variables
/**
* Associated adapter.
*/
protected Adapter adapter = null;
/**
* Request object.
*/
protected Request request = null;
/**
* Response object.
*/
protected Response response = null;
/**
* Header message. Note that this header is merely the one used during the
* processing of the first message of a "request", so it might not be a request
* header. It will stay unchanged during the processing of the whole request.
*/
protected AjpMessage requestHeaderMessage = null;
/**
* Message used for response header composition.
*/
protected AjpMessage responseHeaderMessage = null;
/**
* Body message.
*/
protected AjpMessage bodyMessage = null;
/**
* Body message.
*/
protected MessageBytes bodyBytes = MessageBytes.newInstance();
/**
* State flag.
*/
protected boolean started = false;
/**
* Error flag.
*/
protected boolean error = false;
/**
* Socket associated with the current connection.
*/
protected Socket socket;
/**
* Input stream.
*/
protected InputStream input;
/**
* Output stream.
*/
protected OutputStream output;
/**
* Host name (used to avoid useless B2C conversion on the host name).
*/
protected char[] hostNameC = new char[0];
/**
* Associated endpoint.
*/
protected JIoEndpoint endpoint;
/**
* The socket timeout used when reading the first block of the request
* header.
*/
protected long readTimeout;
/**
* Temp message bytes used for processing.
*/
protected MessageBytes tmpMB = MessageBytes.newInstance();
/**
* Byte chunk for certs.
*/
protected MessageBytes certificates = MessageBytes.newInstance();
/**
* End of stream flag.
*/
protected boolean endOfStream = false;
/**
* Body empty flag.
*/
protected boolean empty = true;
/**
* First read.
*/
protected boolean first = true;
/**
* Replay read.
*/
protected boolean replay = false;
/**
* Finished response.
*/
protected boolean finished = false;
/**
* Direct buffer used for sending right away a get body message.
*/
protected static final byte[] getBodyMessageArray;
/**
* Direct buffer used for sending right away a pong message.
*/
protected static final byte[] pongMessageArray;
/**
* End message array.
*/
protected static final byte[] endMessageArray;
/**
* Flush message array.
*/
protected static final byte[] flushMessageArray;
// ----------------------------------------------------- Static Initializer
static {
// Set the get body message buffer
AjpMessage getBodyMessage = new AjpMessage(16);
getBodyMessage.reset();
getBodyMessage.appendByte(Constants.JK_AJP13_GET_BODY_CHUNK);
getBodyMessage.appendInt(Constants.MAX_READ_SIZE);
getBodyMessage.end();
getBodyMessageArray = new byte[getBodyMessage.getLen()];
System.arraycopy(getBodyMessage.getBuffer(), 0, getBodyMessageArray,
0, getBodyMessage.getLen());
// Set the read body message buffer
AjpMessage pongMessage = new AjpMessage(16);
pongMessage.reset();
pongMessage.appendByte(Constants.JK_AJP13_CPONG_REPLY);
pongMessage.end();
pongMessageArray = new byte[pongMessage.getLen()];
System.arraycopy(pongMessage.getBuffer(), 0, pongMessageArray,
0, pongMessage.getLen());
// Allocate the end message array
AjpMessage endMessage = new AjpMessage(16);
endMessage.reset();
endMessage.appendByte(Constants.JK_AJP13_END_RESPONSE);
endMessage.appendByte(1);
endMessage.end();
endMessageArray = new byte[endMessage.getLen()];
System.arraycopy(endMessage.getBuffer(), 0, endMessageArray, 0,
endMessage.getLen());
// Allocate the flush message array
AjpMessage flushMessage = new AjpMessage(16);
flushMessage.reset();
flushMessage.appendByte(Constants.JK_AJP13_SEND_BODY_CHUNK);
flushMessage.appendInt(0);
flushMessage.appendByte(0);
flushMessage.end();
flushMessageArray = new byte[flushMessage.getLen()];
System.arraycopy(flushMessage.getBuffer(), 0, flushMessageArray, 0,
flushMessage.getLen());
}
// ------------------------------------------------------------- Properties
/**
* Use Tomcat authentication ?
*/
protected boolean tomcatAuthentication = true;
public boolean getTomcatAuthentication() { return tomcatAuthentication; }
public void setTomcatAuthentication(boolean tomcatAuthentication) { this.tomcatAuthentication = tomcatAuthentication; }
/**
* Required secret.
*/
protected String requiredSecret = null;
public void setRequiredSecret(String requiredSecret) { this.requiredSecret = requiredSecret; }
/**
* The number of milliseconds Tomcat will wait for a subsequent request
* before closing the connection. The default is the same as for
* Apache HTTP Server (15 000 milliseconds).
*/
protected int keepAliveTimeout = -1;
public int getKeepAliveTimeout() { return keepAliveTimeout; }
public void setKeepAliveTimeout(int timeout) { keepAliveTimeout = timeout; }
// --------------------------------------------------------- Public Methods
/** Get the request associated with this processor.
*
* @return The request
*/
public Request getRequest() {
return request;
}
/**
* Process pipelined HTTP requests using the specified input and output
* streams.
*
* @throws IOException error during an I/O operation
*/
public boolean process(Socket socket)
throws IOException {
RequestInfo rp = request.getRequestProcessor();
rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
// Setting up the socket
this.socket = socket;
input = socket.getInputStream();
output = socket.getOutputStream();
int soTimeout = -1;
if (keepAliveTimeout > 0) {
soTimeout = socket.getSoTimeout();
}
// Error flag
error = false;
while (started && !error) {
// Parsing the request header
try {
// Set keep alive timeout if enabled
if (keepAliveTimeout > 0) {
socket.setSoTimeout(keepAliveTimeout);
}
// Get first message of the request
if (!readMessage(requestHeaderMessage)) {
// This means a connection timeout
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
break;
}
// Set back timeout if keep alive timeout is enabled
if (keepAliveTimeout > 0) {
socket.setSoTimeout(soTimeout);
}
// Check message type, process right away and break if
// not regular request processing
int type = requestHeaderMessage.getByte();
if (type == Constants.JK_AJP13_CPING_REQUEST) {
try {
output.write(pongMessageArray);
} catch (IOException e) {
error = true;
}
continue;
} else if(type != Constants.JK_AJP13_FORWARD_REQUEST) {
// Usually the servlet didn't read the previous request body
if(log.isDebugEnabled()) {
log.debug("Unexpected message: "+type);
}
continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -