📄 ajp13.java
字号:
/*
* Copyright 1999-2004 The Apache Software Foundation
*
* Licensed 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.ajp;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import org.apache.tomcat.util.http.BaseRequest;
import org.apache.tomcat.util.http.HttpMessages;
import org.apache.tomcat.util.http.MimeHeaders;
/**
* Represents a single, persistent connection between the web server and
* the servlet container. Uses the Apache JServ Protocol version 1.3 for
* communication. Because this protocal does not multiplex requests, this
* connection can only be associated with a single request-handling cycle
* at a time.<P>
*
* This class contains knowledge about how an individual packet is laid out
* (via the <CODE>Ajp13Packet</CODE> class), and also about the
* stages of communicaton between the server and the servlet container. It
* translates from Tomcat's internal servlet support methods
* (e.g. doWrite) to the correct packets to send to the web server.
*
* @author Dan Milstein [danmil@shore.net]
* @author Keith Wannamaker [Keith@Wannamaker.org]
* @author Kevin Seguin [seguin@apache.org]
* @author Henri Gomez [hgomez@apache.org]
* @author Costin Manolache
*/
public class Ajp13 {
public static final int MAX_PACKET_SIZE=8192;
public static final int H_SIZE=4; // Size of basic packet header
public static final int MAX_READ_SIZE = MAX_PACKET_SIZE - H_SIZE - 2;
public static final int MAX_SEND_SIZE = MAX_PACKET_SIZE - H_SIZE - 4;
// Error code for Ajp13
public static final int JK_AJP13_BAD_HEADER = -100;
public static final int JK_AJP13_NO_HEADER = -101;
public static final int JK_AJP13_COMM_CLOSED = -102;
public static final int JK_AJP13_COMM_BROKEN = -103;
public static final int JK_AJP13_BAD_BODY = -104;
public static final int JK_AJP13_INCOMPLETE_BODY = -105;
// ============ Instance Properties ====================
OutputStream out;
InputStream in;
// Buffer used of output body and headers
public Ajp13Packet outBuf = new Ajp13Packet( MAX_PACKET_SIZE );
// Buffer used for input body
Ajp13Packet inBuf = new Ajp13Packet( MAX_PACKET_SIZE );
// Buffer used for request head ( and headers )
Ajp13Packet hBuf=new Ajp13Packet( MAX_PACKET_SIZE );
// Holds incoming reads of request body data (*not* header data)
byte []bodyBuff = new byte[MAX_READ_SIZE];
int blen; // Length of current chunk of body data in buffer
int pos; // Current read position within that buffer
boolean end_of_stream; // true if we've received an empty packet
// Required handler - essential request processing
public RequestHandler reqHandler;
// AJP14 - detect protocol,set communication parameters, login
// If no password is set, use only Ajp13 messaging
boolean backwardCompat=true;
boolean logged=false;
String secret=null;
public Ajp13() {
super();
initBuf();
reqHandler=new RequestHandler();
reqHandler.init( this );
}
public Ajp13(RequestHandler reqHandler ) {
super();
initBuf();
this.reqHandler=reqHandler;
reqHandler.init( this );
}
/** Will be overriden
*/
public void initBuf() {
outBuf = new Ajp13Packet( MAX_PACKET_SIZE );
inBuf = new Ajp13Packet( MAX_PACKET_SIZE );
hBuf=new Ajp13Packet( MAX_PACKET_SIZE );
}
public void recycle() {
if (debug > 0) {
logger.log("recycle()");
}
// This is a touch cargo-cultish, but I think wise.
blen = 0;
pos = 0;
end_of_stream = false;
logged=false;
}
/**
* Associate an open socket with this instance.
*/
public void setSocket( Socket socket ) throws IOException {
if (debug > 0) {
logger.log("setSocket()");
}
socket.setSoLinger( true, 100);
out = socket.getOutputStream();
in = socket.getInputStream();
pos = 0;
}
/**
* Backward compat mode, no login needed
*/
public void setBackward(boolean b)
{
backwardCompat=b;
}
public boolean isLogged() {
return logged;
}
void setLogged( boolean b ) {
logged=b;
}
public void setSecret( String s ) {
secret=s;
}
public String getSecret() {
return secret;
}
// -------------------- Handlers registry --------------------
static final int MAX_HANDLERS=32;
static final int RESERVED=16; // reserved names, backward compat
// Note that we don't make distinction between in and out
// messages ( i.e. one id is used only in one direction )
AjpHandler handlers[]=new AjpHandler[MAX_HANDLERS];
String handlerName[]=new String[MAX_HANDLERS];
int currentId=RESERVED;
public int registerMessageType( int id, String name, AjpHandler h,
String sig[] )
{
if( id < 0 ) {
// try to find it by name
for( int i=0; i< handlerName.length; i++ )
if( name.equals( handlerName[i] ) ) return i;
handlerName[currentId]=name;
handlers[currentId]=h;
currentId++;
return currentId;
}
// fixed id
handlerName[id]=name;
handlers[id]=h;
return id;
}
// -------------------- Main dispatch --------------------
/**
* Read a new packet from the web server and decode it. If it's a
* forwarded request, store its properties in the passed-in AjpRequest
* object.
*
* @param req An empty (newly-recycled) request object.
*
* @return 200 in case of a successful read of a forwarded request, 500
* if there were errors in the reading of the request, and -2 if the
* server is asking the container to shut itself down.
*/
public int receiveNextRequest(BaseRequest req) throws IOException {
if (debug > 0) {
logger.log("receiveNextRequest()");
}
// XXX The return values are awful.
int err = 0;
// if we receive an IOException here, it must be because
// the remote just closed the ajp13 connection, and it's not
// an error, we just need to close the AJP13 connection
try {
err = receive(hBuf);
} catch (IOException ioe) {
if(debug >0 ) logger.log( "IOException receiving message ");
return -1; // Indicate it's a disconnection from the remote end
}
if(err < 0) {
if(debug >0 ) logger.log( "Error receiving message ");
return 500;
}
int type = (int)hBuf.getByte();
// System.out.println("XXX " + this );
return handleMessage( type, hBuf, req );
}
/** Override for ajp14, temporary
*/
public int handleMessage( int type, Ajp13Packet hBuf, BaseRequest req )
throws IOException
{
if( type > handlers.length ) {
logger.log( "Invalid handler " + type );
return 500;
}
if( debug > 0 )
logger.log( "Received " + type + " " + handlerName[type]);
// Ajp14, unlogged
if( ! backwardCompat && ! isLogged() ) {
if( type != NegociationHandler.JK_AJP14_LOGINIT_CMD &&
type != NegociationHandler.JK_AJP14_LOGCOMP_CMD ) {
logger.log( "Ajp14 error: not logged " +
type + " " + handlerName[type]);
return 300;
}
// else continue
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -