+++ /dev/null
-/*
- * @(#)FCGIGlobalDefs.java
- *
- *
- * FastCGi compatibility package Interface
- *
- *
- * Copyright (c) 1996 Open Market, Inc.
- *
- * See the file "LICENSE.TERMS" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * $Id: FCGIGlobalDefs.java,v 1.2 1998/12/12 04:42:16 roberts Exp $
- */
-
-/* This class contains FCGI global definitions corresponding to
- * the #defs in the C version.
- */
-import java.io.PrintStream;
-
-public abstract class FCGIGlobalDefs {
-
- public static final int def_FCGIMaxLen = 0xffff;
- /*
- * Define Length of FCGI message bodies in bytes
- */
- public static final int def_FCGIHeaderLen = 8;
- public static final int def_FCGIEndReqBodyLen = 8;
- public static final int def_FCGIBeginReqBodyLen = 8;
- public static final int def_FCGIUnknownBodyTypeBodyLen = 8;
- /*
- * Header defines
- */
- public static int def_FCGIVersion1 = 1;
- /* FCGI Record Types */
- public static final int def_FCGIBeginRequest = 1;
- public static final int def_FCGIAbortRequest = 2;
- public static final int def_FCGIEndRequest = 3;
- public static final int def_FCGIParams = 4;
- public static final int def_FCGIStdin = 5;
- public static final int def_FCGIStdout = 6;
- public static final int def_FCGIStderr = 7;
- public static final int def_FCGIData = 8;
- public static final int def_FCGIGetValues = 9;
- public static final int def_FCGIGetValuesResult = 10;
- public static final int def_FCGIUnknownType = 11;
- public static final int def_FCGIMaxType = def_FCGIUnknownType;
- /* Request ID Values */
- public static final int def_FCGINullRequestID = 0;
- /*
- * Begin Request defines
- */
- /* Mask flags */
- public static int def_FCGIKeepConn = 1;
- /* Roles */
- public static final int def_FCGIResponder = 1;
- public static final int def_FCGIAuthorizer = 2;
- public static final int def_FCGIFilter = 3;
- /*
- * End Request defines
- */
- /* Protocol status */
- public static final int def_FCGIRequestComplete = 0;
- public static final int def_FCGICantMpxConn = 1;
- public static final int def_FCGIOverload = 2;
- public static final int def_FCGIUnknownRole = 3;
- /*
- * Get Values, Get Values Results defines
- */
- public static final String def_FCGIMaxConns = "FCGI_MAX_CONNS";
- public static final String def_FCGIMaxReqs = "FCGI_MAX_REQS";
- public static final String def_FCGIMpxsConns = "FCGI_MPXS_CONNS";
- /*
- * Return codes for Process* functions
- */
- public static final int def_FCGIStreamRecord = 0;
- public static final int def_FCGISkip = 1;
- public static final int def_FCGIBeginRecord = 2;
- public static final int def_FCGIMgmtRecord = 3;
- /*
- * Error Codes
- */
- public static final int def_FCGIUnsupportedVersion = -2;
- public static final int def_FCGIProtocolError = -3;
- public static final int def_FCGIParamsError = -4;
- public static final int def_FCGICallSeqError = -5;
-}
+++ /dev/null
-/*
- * @(#)FCGIInputStream.java
- *
- * FastCGi compatibility package Interface
- *
- *
- * Copyright (c) 1996 Open Market, Inc.
- *
- * See the file "LICENSE.TERMS" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * $Id: FCGIInputStream.java,v 1.2 1998/12/12 04:42:17 roberts Exp $
- */
-
-import java.io.*;
-import FCGIRequest;
-import FCGIGlobalDefs;
-
-/**
- * This stream manages buffered reads of FCGI messages.
- */
-public class FCGIInputStream extends InputStream {
-
- /* Stream vars */
-
- public int rdNext;
- public int stop;
- public boolean isClosed;
-
- /* require methods to set, get and clear */
- private int errno;
- private Exception errex;
-
- /* data vars */
-
- public byte buff[];
- public int buffLen;
- public int buffStop;
- public int type;
- public int contentLen;
- public int paddingLen;
- public boolean skip;
- public boolean eorStop;
- public FCGIRequest request;
-
- public InputStream in;
-
-
- /**
- * Creates a new input stream to manage fcgi prototcol stuff
- * @param in the input stream bufLen length of buffer streamType
- */
- public FCGIInputStream(FileInputStream inStream, int bufLen,
- int streamType,
- FCGIRequest inReq) {
-
- in = inStream;
- buffLen = Math.min(bufLen,FCGIGlobalDefs.def_FCGIMaxLen);
- buff = new byte[buffLen];
- type = streamType;
- stop = rdNext = buffStop = 0;
- isClosed = false;
- contentLen = 0;
- paddingLen = 0;
- skip = false;
- eorStop = false;
- request = inReq;
-
- }
- /**
- * Reads a byte of data. This method will block if no input is
- * available.
- * @return the byte read, or -1 if the end of the
- * stream is reached.
- * @exception IOException If an I/O error has occurred.
- */
- public int read() throws IOException {
- if (rdNext != stop) {
- return buff[rdNext++];
- }
- if (isClosed){
- return -1;
- }
- fill();
- if (rdNext != stop){
- return buff[rdNext++];
- }
- return -1;
- }
- /**
- * Reads into an array of bytes. This method will
- * block until some input is available.
- * @param b the buffer into which the data is read
- * @return the actual number of bytes read, -1 is
- * returned when the end of the stream is reached.
- * @exception IOException If an I/O error has occurred.
- */
- public int read(byte b[]) throws IOException {
- return read(b, 0, b.length);
- }
-
- /**
- * Reads into an array of bytes.
- * Blocks until some input is available.
- * @param b the buffer into which the data is read
- * @param off the start offset of the data
- * @param len the maximum number of bytes read
- * @return the actual number of bytes read, -1 is
- * returned when the end of the stream is reached.
- * @exception IOException If an I/O error has occurred.
- */
- public int read(byte b[], int off, int len) throws IOException {
- int m, bytesMoved;
-
- if (len <= 0){
- return 0;
- }
- /*
- *Fast path: len bytes already available.
- */
-
- if (len <= stop - rdNext){
- System.arraycopy(buff, rdNext, b, off, len);
- rdNext += len;
- return len;
- }
- /*
- *General case: stream is closed or fill needs to be called
- */
- bytesMoved = 0;
- for(;;){
- if (rdNext != stop){
- m = Math.min(len - bytesMoved, stop - rdNext);
- System.arraycopy(buff, rdNext, b, off, m);
- bytesMoved += m;
- rdNext += m;
- if (bytesMoved == len)
- return bytesMoved;
- off += m;
- }
- if (isClosed){
- return bytesMoved;
- }
- fill();
-
- }
- }
- /**
- * Reads into an array of bytes. This method will
- * block until some input is available.
- * @param b the buffer into which the data is read
- * @param off the start offset of the data
- * @param len the maximum number of bytes read
- * @return the actual number of bytes read, -1 is
- * returned when the end of the stream is reached.
- * @exception IOException If an I/O error has occurred.
- */
- public void fill() throws IOException {
- byte[] headerBuf = new byte[FCGIGlobalDefs.def_FCGIHeaderLen];
- int headerLen = 0;
- int status = 0;
- int count = 0;
- for(;;) {
- /*
- * If buffer is empty, do a read
- */
- if (rdNext == buffStop) {
- try {
- count = in.read(buff, 0, buffLen);
- } catch (IOException e) {
- setException(e);
- return;
- }
- if (count == 0) {
- setFCGIError(FCGIGlobalDefs.def_FCGIProtocolError);
- return;
- }
- rdNext = 0;
- buffStop = count; // 1 more than we read
- }
- /* Now buf is not empty: If the current record contains more content
- * bytes, deliver all that are present in buff to callers buffer
- * unless he asked for less than we have, in which case give him less
- */
- if (contentLen > 0) {
- count = Math.min(contentLen, buffStop - rdNext);
- contentLen -= count;
- if (!skip) {
- stop = rdNext + count;
- return;
- }
- else {
- rdNext += count;
- if (contentLen > 0) {
- continue;
- }
- else {
- skip = false;
- }
- }
- }
- /* Content has been consumed by client.
- * If record was padded, skip over padding
- */
- if (paddingLen > 0) {
- count = Math.min(paddingLen, buffStop - rdNext);
- paddingLen -= count;
- rdNext += count;
- if (paddingLen > 0) {
- continue; // more padding to read
- }
- }
- /* All done with current record, including the padding.
- * If we are in a recursive call from Process Header, deliver EOF
- */
- if (eorStop){
- stop = rdNext;
- isClosed = true;
- return;
- }
- /*
- * Fill header with bytes from input buffer - get the whole header.
- */
- count = Math.min(headerBuf.length - headerLen, buffStop - rdNext);
- System.arraycopy(buff,rdNext, headerBuf, headerLen, count);
- headerLen += count;
- rdNext += count;
- if (headerLen < headerBuf.length) {
- continue;
- }
- headerLen = 0;
- /*
- * Interperet the header. eorStop prevents ProcessHeader from
- * reading past the end of record when using stream to read content
- */
- eorStop = true;
- stop = rdNext;
- status = 0;
- status = new FCGIMessage(this).processHeader(headerBuf);
- eorStop = false;
- isClosed = false;
- switch (status){
- case FCGIGlobalDefs.def_FCGIStreamRecord:
- if (contentLen == 0) {
- stop = rdNext;
- isClosed = true;
- return;
- }
- break;
- case FCGIGlobalDefs.def_FCGISkip:
- skip = true;
- break;
- case FCGIGlobalDefs.def_FCGIBeginRecord:
- /*
- * If this header marked the beginning of a new
- * request, return role info to caller
- */
- return;
- case FCGIGlobalDefs.def_FCGIMgmtRecord:
- break;
- default:
- /*
- * ASSERT
- */
- setFCGIError(status);
- return;
-
- }
- }
- }
-
- /**
- * Skips n bytes of input.
- * @param n the number of bytes to be skipped
- * @return the actual number of bytes skipped.
- * @exception IOException If an I/O error has occurred.
- */
- public long skip(long n) throws IOException {
- byte data[] = new byte[(int)n];
- return in.read(data);
- }
-
- /*
- * An FCGI error has occurred. Save the error code in the stream
- * for diagnostic purposes and set the stream state so that
- * reads return EOF
- */
- public void setFCGIError(int errnum) {
- /*
- * Preserve only the first error.
- */
- if(errno == 0) {
- errno = errnum;
- }
- isClosed = true;
- }
- /*
- * An Exception has occurred. Save the Exception in the stream
- * for diagnostic purposes and set the stream state so that
- * reads return EOF
- */
- public void setException(Exception errexpt) {
- /*
- * Preserve only the first error.
- */
- if(errex == null) {
- errex = errexpt;
- }
- isClosed = true;
- }
-
- /*
- * Clear the stream error code and end-of-file indication.
- */
- public void clearFCGIError() {
- errno = 0;
- /*
- * isClosed = false;
- * XXX: should clear isClosed but work is needed to make it safe
- * to do so.
- */
- }
- /*
- * Clear the stream error code and end-of-file indication.
- */
- public void clearException() {
- errex = null;
- /*
- * isClosed = false;
- * XXX: should clear isClosed but work is needed to make it safe
- * to do so.
- */
- }
-
- /*
- * accessor method since var is private
- */
- public int getFCGIError() {
- return errno;
- }
- /*
- * accessor method since var is private
- */
- public Exception getException() {
- return errex;
- }
- /*
- * Re-initializes the stream to read data of the specified type.
- */
- public void setReaderType(int streamType) {
-
- type = streamType;
- eorStop = false;
- skip = false;
- contentLen = 0;
- paddingLen = 0;
- stop = rdNext;
- isClosed = false;
- }
-
- /*
- * Close the stream. This method does not really exist for BufferedInputStream in java,
- * but is implemented here for compatibility with the FCGI structures being used. It
- * doent really throw any IOExceptions either, but that's there for compatiblity with
- * the InputStreamInterface.
- */
- public void close() throws IOException{
- isClosed = true;
- stop = rdNext;
- }
-
- /*
- * Returns the number of bytes that can be read without blocking.
- */
-
- public int available() throws IOException {
- return stop - rdNext + in.available();
- }
-
-}
+++ /dev/null
-/*
- * @(#)FCGIInterface.java
- *
- *
- * FastCGi compatibility package Interface
- *
- *
- * Copyright (c) 1996 Open Market, Inc.
- *
- * See the file "LICENSE.TERMS" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * $Id: FCGIInterface.java,v 1.3 1998/12/12 04:42:18 roberts Exp $
- */
-
-import java.net.*;
-import java.io.*;
-import java.util.Properties;
-import FCGIGlobalDefs;
-import FCGIRequest;
-import FCGIInputStream;
-import FCGIOutputStream;
-import FCGIMessage;
-
-/*
- * This is the FastCGI interface that the application calls to communicate with the
- * FastCGI web server. This version is single threaded, and handles one request at
- * a time, which is why we can have a static variable for it.
- */
-public class FCGIInterface {
-
- /*
- * Class variables
- */
- public static FCGIRequest request = null;
- public static boolean acceptCalled = false;
- public static boolean isFCGI = true;
- public static Properties startupProps;
- public static ServerSocket srvSocket;
-
- /*
- * Accepts a new request from the HTTP server and creates
- * a conventional execution environment for the request.
- * If the application was invoked as a FastCGI server,
- * the first call to FCGIaccept indicates that the application
- * has completed its initialization and is ready to accept
- * a request. Subsequent calls to FCGI_accept indicate that
- * the application has completed its processing of the
- * current request and is ready to accept a new request.
- * If the application was invoked as a CGI program, the first
- * call to FCGIaccept is essentially a no-op and the second
- * call returns EOF (-1) as does an error. Application should exit.
- *
- * If the application was invoked as a FastCGI server,
- * and this is not the first call to this procedure,
- * FCGIaccept first flushes any buffered output to the HTTP server.
- *
- * On every call, FCGIaccept accepts the new request and
- * reads the FCGI_PARAMS stream into System.props. It also creates
- * streams that understand FastCGI protocol and take input from
- * the HTTP server send output and error output to the HTTP server,
- * and assigns these new streams to System.in, System.out and
- * System.err respectively.
- *
- * For now, we will just return an int to the caller, which is why
- * this method catches, but doen't throw Exceptions.
- *
- */
- public int FCGIaccept() {
- int acceptResult = 0;
-
- /*
- * If first call, mark it and if fcgi save original system properties,
- * If not first call, and we are cgi, we should be gone.
- */
- if (!acceptCalled){
- isFCGI = System.getProperties().containsKey("FCGI_PORT");
- acceptCalled = true;
- if (isFCGI) {
- /*
- * save original system properties (nonrequest)
- * and get a server socket
- */
- System.out.close();
- System.err.close();
- startupProps = new Properties(System.getProperties());
- String str =
- new String(System.getProperty("FCGI_PORT"));
- if (str.length() <= 0) {
- return -1;
- }
- int portNum = Integer.parseInt(str);
-
- try {
- srvSocket = new ServerSocket(portNum);
- } catch (IOException e) {
- request.socket = null;
- srvSocket = null;
- request = null;
- return -1;
- }
- }
- }
- else {
- if (!isFCGI){
- return -1;
- }
- }
- /*
- * If we are cgi, just leave everything as is, otherwise set up env
- */
- if (isFCGI){
- try {
- acceptResult = FCGIAccept();
- } catch (IOException e) {
- return -1;
- }
- if (acceptResult < 0){
- return -1;
- }
-
- /*
- * redirect stdin, stdout and stderr to fcgi socket
- */
- System.setIn(new BufferedInputStream(request.inStream, 8192));
- System.setOut(new PrintStream(new BufferedOutputStream(
- request.outStream, 8192)));
- System.setErr(new PrintStream(new BufferedOutputStream(
- request.errStream, 512)));
- System.setProperties(request.params);
- }
- return 0;
- }
-
- /*
- * Accepts a new request from the HTTP server.
- * Finishes the request accepted by the previous call
- * to FCGI_Accept. Sets up the FCGI environment and reads
- * saved and per request environmental varaibles into
- * the request object. (This is redundant on System.props
- * as long as we can handle only one request object.)
- */
- int FCGIAccept() throws IOException{
-
- boolean isNewConnection;
- boolean errCloseEx = false;
- boolean outCloseEx = false;
-
- if (request != null) {
- /*
- * Complete the previous request
- */
- System.err.close();
- System.out.close();
- boolean prevRequestfailed = (errCloseEx || outCloseEx ||
- request.inStream.getFCGIError() != 0 ||
- request.inStream.getException() != null);
- if (prevRequestfailed || !request.keepConnection ) {
- request.socket.close();
- request.socket = null;
- }
- if (prevRequestfailed) {
- request = null;
- return -1;
- }
- }
- else {
- /*
- * Get a Request and initialize some variables
- */
- request = new FCGIRequest();
- request.socket = null;
- request.inStream = null;
- }
- isNewConnection = false;
-
- /*
- * if connection isnt open accept a new connection (blocking)
- */
- for(;;) {
- if (request.socket == null){
- try {
- request.socket = srvSocket.accept();
- } catch (IOException e) {
- request.socket = null;
- request = null;
- return -1;
- }
- isNewConnection = true;
- }
-
- /* Try reading from new connection. If the read fails and
- * it was an old connection the web server probably closed it;
- * try making a new connection before giving up
- */
- request.isBeginProcessed = false;
- request.inStream =
- new FCGIInputStream((FileInputStream)request.
- socket.getInputStream(),
- 8192, 0, request);
- request.inStream.fill();
- if (request.isBeginProcessed) {
- break;
- }
- request.socket.close();
-
- request.socket = null;
- if (isNewConnection) {
- return -1;
- }
- }
- /*
- * Set up the objects for the new request
- */
- request.params = new Properties(startupProps);
- switch(request.role) {
- case FCGIGlobalDefs.def_FCGIResponder:
- request.params.put("ROLE","RESPONDER");
- break;
- case FCGIGlobalDefs.def_FCGIAuthorizer:
- request.params.put("ROLE", "AUTHORIZER");
- break;
- case FCGIGlobalDefs.def_FCGIFilter:
- request.params.put("ROLE", "FILTER");
- break;
- default:
- return -1;
- }
- request.inStream.setReaderType(FCGIGlobalDefs.def_FCGIParams);
- /*
- * read the rest of request parameters
- */
- if (new FCGIMessage(request.inStream).readParams(request.params) < 0) {
- return -1;
- }
- request.inStream.setReaderType(FCGIGlobalDefs.def_FCGIStdin);
- request.outStream
- = new FCGIOutputStream((FileOutputStream)request.socket.
- getOutputStream(), 8192,
- FCGIGlobalDefs.def_FCGIStdout,request);
- request.errStream
- = new FCGIOutputStream((FileOutputStream)request.socket.
- getOutputStream(), 512,
- FCGIGlobalDefs.def_FCGIStderr,request);
- request.numWriters = 2;
- return 0;
- }
-}
+++ /dev/null
-/*
- * @(#)FCGIMessage.java
- *
- *
- * FastCGi compatibility package Interface
- *
- *
- * Copyright (c) 1996 Open Market, Inc.
- *
- * See the file "LICENSE.TERMS" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * $Id: FCGIMessage.java,v 1.3 1998/12/12 04:42:19 roberts Exp $
- */
-
-import java.io.*;
-import java.util.Properties;
-
-/* This class handles reading and building the fastcgi messages.
- * For reading incoming mesages, we pass the input
- * stream as a param to the constructor rather than to each method.
- * Methods that build messages use and return internal buffers, so they
- * dont need a stream.
- */
-
-public class FCGIMessage {
-
- /*
- * Instance variables
- */
- /*
- * FCGI Message Records
- * The logical structures of the FCGI Message Records.
- * Fields are originally 1 unsigned byte in message
- * unless otherwise noted.
- */
- /*
- * FCGI Header
- */
- private int h_version;
- private int h_type;
- private int h_requestID; // 2 bytes
- private int h_contentLength; // 2 bytes
- private int h_paddingLength;
- /*
- * FCGI BeginRequest body.
- */
- private int br_role; // 2 bytes
- private int br_flags;
-
- private FCGIInputStream in;
-
- /*
- * constructor - Java would do this implicitly.
- */
- public FCGIMessage(){
- super();
- }
- /*
- * constructor - get the stream.
- */
- public FCGIMessage(FCGIInputStream instream){
- in = instream;
- }
-
- /*
- * Message Reading Methods
- */
-
- /*
- * Interpret the FCGI Message Header. Processes FCGI
- * BeginRequest and Management messages. Param hdr is the header.
- * The calling routine has to keep track of the stream reading
- * management or use FCGIInputStream.fill() which does just that.
- */
- public int processHeader(byte[] hdr) throws IOException{
- processHeaderBytes(hdr);
- if (h_version != FCGIGlobalDefs.def_FCGIVersion1) {
- return(FCGIGlobalDefs.def_FCGIUnsupportedVersion);
- }
- in.contentLen = h_contentLength;
- in.paddingLen = h_paddingLength;
- if (h_type == FCGIGlobalDefs.def_FCGIBeginRequest) {
- return processBeginRecord(h_requestID);
- }
- if (h_requestID == FCGIGlobalDefs.def_FCGINullRequestID) {
- return processManagementRecord(h_type);
- }
- if (h_requestID != in.request.requestID) {
- return(FCGIGlobalDefs.def_FCGISkip);
- }
- if (h_type != in.type) {
- return(FCGIGlobalDefs.def_FCGIProtocolError);
- }
- return(FCGIGlobalDefs.def_FCGIStreamRecord);
- }
-
- /* Put the unsigned bytes in the incoming FCGI header into
- * integer form for Java, concatinating bytes when needed.
- * Because Java has no unsigned byte type, we have to be careful
- * about signed numeric promotion to int.
- */
- private void processHeaderBytes(byte[] hdrBuf){
- h_version = hdrBuf[0] & 0xFF;
- h_type = hdrBuf[1] & 0xFF;
- h_requestID = ((hdrBuf[2] & 0xFF) << 8) | (hdrBuf[3] & 0xFF);
- h_contentLength = ((hdrBuf[4] & 0xFF) << 8) | (hdrBuf[5] & 0xFF);
- h_paddingLength = hdrBuf[6] & 0xFF;
- }
-
- /*
- * Reads FCGI Begin Request Record.
- */
- public int processBeginRecord(int requestID) throws IOException {
- byte beginReqBody[];
- byte endReqMsg[];
- if (requestID == 0 || in.contentLen
- != FCGIGlobalDefs.def_FCGIEndReqBodyLen) {
- return FCGIGlobalDefs.def_FCGIProtocolError;
- }
- /*
- * If the webserver is multiplexing the connection,
- * this library can't deal with it, so repond with
- * FCGIEndReq message with protocolStatus FCGICantMpxConn
- */
- if (in.request.isBeginProcessed) {
- endReqMsg = new byte[FCGIGlobalDefs.def_FCGIHeaderLen
- + FCGIGlobalDefs.def_FCGIEndReqBodyLen];
- System.arraycopy(makeHeader(
- FCGIGlobalDefs.def_FCGIEndRequest,
- requestID,
- FCGIGlobalDefs.def_FCGIEndReqBodyLen,
- 0), 0, endReqMsg, 0,
- FCGIGlobalDefs.def_FCGIHeaderLen);
- System.arraycopy(makeEndrequestBody(0,
- FCGIGlobalDefs.def_FCGICantMpxConn), 0,
- endReqMsg,
- FCGIGlobalDefs.def_FCGIHeaderLen,
- FCGIGlobalDefs.def_FCGIEndReqBodyLen);
- /*
- * since isBeginProcessed is first set below,this
- * can't be out first call, so request.out is properly set
- */
- try {
- in.request.outStream.write(endReqMsg, 0,
- FCGIGlobalDefs.def_FCGIHeaderLen
- + FCGIGlobalDefs.def_FCGIEndReqBodyLen);
- } catch (IOException e){
- in.request.outStream.setException(e);
- return -1;
- }
- }
- /*
- * Accept this new request. Read the record body
- */
- in.request.requestID = requestID;
- beginReqBody =
- new byte[FCGIGlobalDefs.def_FCGIBeginReqBodyLen];
- if (in.read(beginReqBody, 0,
- FCGIGlobalDefs.def_FCGIBeginReqBodyLen) !=
- FCGIGlobalDefs.def_FCGIBeginReqBodyLen) {
- return FCGIGlobalDefs.def_FCGIProtocolError;
- }
- br_flags = beginReqBody[2] & 0xFF;
- in.request.keepConnection
- = (br_flags & FCGIGlobalDefs.def_FCGIKeepConn) != 0;
- br_role = ((beginReqBody[0] & 0xFF) << 8) | (beginReqBody[1] & 0xFF);
- in.request.role = br_role;
- in.request.isBeginProcessed = true;
- return FCGIGlobalDefs.def_FCGIBeginRecord;
- }
-
- /*
- * Reads and Responds to a Management Message. The only type of
- * management message this library understands is FCGIGetValues.
- * The only variables that this library's FCGIGetValues understands
- * are def_FCGIMaxConns, def_FCGIMaxReqs, and def_FCGIMpxsConns.
- * Ignore the other management variables, and repsond to other
- * management messages with FCGIUnknownType.
- */
- public int processManagementRecord(int type) throws IOException {
-
- byte[] response = new byte[64];
- int wrndx = response[FCGIGlobalDefs.def_FCGIHeaderLen];
- int value, len, plen;
- if (type == FCGIGlobalDefs.def_FCGIGetValues) {
- Properties tmpProps = new Properties();
- readParams(tmpProps);
-
- if (in.getFCGIError() != 0 || in.contentLen != 0) {
- return FCGIGlobalDefs.def_FCGIProtocolError;
- }
- if (tmpProps.containsKey(
- FCGIGlobalDefs.def_FCGIMaxConns)) {
- makeNameVal(
- FCGIGlobalDefs.def_FCGIMaxConns, "1",
- response, wrndx);
- }
- else {
- if (tmpProps.containsKey(
- FCGIGlobalDefs.def_FCGIMaxReqs)) {
- makeNameVal(
- FCGIGlobalDefs.def_FCGIMaxReqs, "1",
- response, wrndx);
- }
- else {
- if (tmpProps.containsKey(
- FCGIGlobalDefs.def_FCGIMaxConns)) {
- makeNameVal(
- FCGIGlobalDefs.def_FCGIMpxsConns, "0",
- response, wrndx);
- }
- }
- }
- plen = 64 - wrndx;
- len = wrndx - FCGIGlobalDefs.def_FCGIHeaderLen;
- System.arraycopy(makeHeader(
- FCGIGlobalDefs.def_FCGIGetValuesResult,
- FCGIGlobalDefs.def_FCGINullRequestID,
- len, plen), 0,
- response, 0,
- FCGIGlobalDefs.def_FCGIHeaderLen);
- }
- else {
- plen = len =
- FCGIGlobalDefs.def_FCGIUnknownBodyTypeBodyLen;
- System.arraycopy(makeHeader(
- FCGIGlobalDefs.def_FCGIUnknownType,
- FCGIGlobalDefs.def_FCGINullRequestID,
- len, 0), 0,
- response, 0,
- FCGIGlobalDefs.def_FCGIHeaderLen);
- System.arraycopy(makeUnknownTypeBodyBody(h_type), 0,
- response,
- FCGIGlobalDefs.def_FCGIHeaderLen,
- FCGIGlobalDefs.def_FCGIUnknownBodyTypeBodyLen);
- }
- /*
- * No guarantee that we have a request yet, so
- * dont use fcgi output stream to reference socket, instead
- * use the FileInputStream that refrences it. Also
- * nowhere to save exception, since this is not FCGI stream.
- */
-
- try {
- in.request.socket.getOutputStream().write(response, 0,
- FCGIGlobalDefs.def_FCGIHeaderLen +
- FCGIGlobalDefs.def_FCGIUnknownBodyTypeBodyLen);
-
- } catch (IOException e){
- return -1;
- }
- return FCGIGlobalDefs.def_FCGIMgmtRecord;
- }
-
- /*
- * Makes a name/value with name = string of some length, and
- * value a 1 byte integer. Pretty specific to what we are doing
- * above.
- */
- void makeNameVal(String name, String value, byte[] dest, int pos) {
- int nameLen = name.length();
- if (nameLen < 0x80) {
- dest[pos++] = (byte)nameLen;
- }else {
- dest[pos++] = (byte)(((nameLen >> 24) | 0x80) & 0xff);
- dest[pos++] = (byte)((nameLen >> 16) & 0xff);
- dest[pos++] = (byte)((nameLen >> 8) & 0xff);
- dest[pos++] = (byte)nameLen;
- }
- int valLen = value.length();
- if (valLen < 0x80) {
- dest[pos++] = (byte)valLen;
- }else {
- dest[pos++] = (byte)(((valLen >> 24) | 0x80) & 0xff);
- dest[pos++] = (byte)((valLen >> 16) & 0xff);
- dest[pos++] = (byte)((valLen >> 8) & 0xff);
- dest[pos++] = (byte)valLen;
- }
- name.getBytes(0, nameLen, dest, pos);
- pos += nameLen;
- value.getBytes(0, valLen, dest, pos);
- pos += valLen;
- }
-
- /*
- * Read FCGI name-value pairs from a stream until EOF. Put them
- * into a Properties object, storing both as strings.
- */
- public int readParams(Properties props) throws IOException{
- int nameLen, valueLen;
- byte lenBuff[] = new byte[3];
- int i = 1;
-
- while ((nameLen = in.read()) != -1) {
- i++;
- if ((nameLen & 0x80) != 0) {
- if ((in.read( lenBuff, 0, 3)) != 3) {
- in.setFCGIError(
- FCGIGlobalDefs.def_FCGIParamsError);
- return -1;
- }
- nameLen = ((nameLen & 0x7f) << 24)
- | ((lenBuff[0] & 0xFF) << 16)
- | ((lenBuff[1] & 0xFF) << 8)
- | (lenBuff[2] & 0xFF);
- }
-
- if ((valueLen = in.read()) == -1) {
- in.setFCGIError(
- FCGIGlobalDefs.def_FCGIParamsError);
- return -1;
- }
- if ((valueLen & 0x80) != 0) {
- if ((in.read( lenBuff, 0, 3)) != 3) {
- in.setFCGIError(
- FCGIGlobalDefs.def_FCGIParamsError);
- return -1;
- }
- valueLen = ((valueLen & 0x7f) << 24)
- | ((lenBuff[0] & 0xFF) << 16)
- | ((lenBuff[1] & 0xFF) << 8)
- | (lenBuff[2] & 0xFF);
- }
-
- /*
- * nameLen and valueLen are now valid; read the name
- * and the value from the stream and construct a standard
- * environmental entity
- */
- byte[] name = new byte[nameLen];
- byte[] value = new byte[valueLen];
- if (in.read(name ,0, nameLen) != nameLen) {
- in.setFCGIError(
- FCGIGlobalDefs.def_FCGIParamsError);
- return -1;
- }
-
- if(in.read(value, 0, valueLen) != valueLen) {
- in.setFCGIError(
- FCGIGlobalDefs.def_FCGIParamsError);
- return -1;
- }
- String strName = new String(name, 0, 0, name.length);
- String strValue = new String(value, 0, 0, value.length);
- props.put(strName, strValue);
- }
- return 0;
-
-
- }
- /*
- * Message Building Methods
- */
-
- /*
- * Build an FCGI Message Header -
- */
- public byte[] makeHeader(int type,
- int requestId,
- int contentLength,
- int paddingLength) {
- byte[] header = new byte[FCGIGlobalDefs.def_FCGIHeaderLen];
- header[0] = (byte)FCGIGlobalDefs.def_FCGIVersion1;
- header[1] = (byte)type;
- header[2] = (byte)((requestId >> 8) & 0xff);
- header[3] = (byte)((requestId ) & 0xff);
- header[4] = (byte)((contentLength >> 8) & 0xff);
- header[5] = (byte)((contentLength ) & 0xff);
- header[6] = (byte)paddingLength;
- header[7] = 0; //reserved byte
- return header;
- }
- /*
- * Build an FCGI Message End Request Body
- */
- public byte[] makeEndrequestBody(int appStatus,int protocolStatus){
- byte body[] = new byte[FCGIGlobalDefs.def_FCGIEndReqBodyLen];
- body[0] = (byte)((appStatus >> 24) & 0xff);
- body[1] = (byte)((appStatus >> 16) & 0xff);
- body[2] = (byte)((appStatus >> 8) & 0xff);
- body[3] = (byte)((appStatus ) & 0xff);
- body[4] = (byte)protocolStatus;
- for (int i = 5; i < 8; i++) {
- body[i] = 0;
- }
- return body;
- }
- /*
- * Build an FCGI Message UnknownTypeBodyBody
- */
- public byte[] makeUnknownTypeBodyBody(int type){
- byte body[] =
- new byte[FCGIGlobalDefs.def_FCGIUnknownBodyTypeBodyLen];
- body[0] = (byte)type;
- for (int i = 1;
- i < FCGIGlobalDefs.def_FCGIUnknownBodyTypeBodyLen; i++) {
- body[i] = 0;
- }
- return body;
- }
-
-} //end class
+++ /dev/null
-/*
- * @(#)FCGIOutputStream.java
- *
- * FastCGi compatibility package Interface
- *
- * Copyright (c) 1996 Open Market, Inc.
- *
- * See the file "LICENSE.TERMS" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * $Id: FCGIOutputStream.java,v 1.2 1998/12/12 04:42:21 roberts Exp $
- */
-
-import java.io.*;
-import FCGIRequest;
-import FCGIGlobalDefs;
-import FCGIMessage;
-import FCGIInputStream;
-
-/**
- * This stream understands FCGI prototcol.
- */
-
-public class FCGIOutputStream extends OutputStream {
-
- /* Stream vars */
-
- public int wrNext;
- public int stop;
- public boolean isClosed;
-
- /* require methods to set, get and clear */
- private int errno;
- private Exception errex;
-
- /* data vars */
-
- public byte buff[];
- public int buffLen;
- public int buffStop;
- public int type;
- public boolean isAnythingWritten;
- public boolean rawWrite;
- public FCGIRequest request;
-
- public FileOutputStream out;
-
- /**
- * Creates a new output stream to manage fcgi prototcol stuff
- * @param out the output stream buflen length of buffer streamType
- */
- public FCGIOutputStream(FileOutputStream outStream,
- int bufLen, int streamType,
- FCGIRequest inreq) {
- out = outStream;
- buffLen = Math.min(bufLen, FCGIGlobalDefs.def_FCGIMaxLen);
- buff = new byte[buffLen];
- type = streamType;
- stop = buffStop = buffLen;
- isAnythingWritten = false;
- rawWrite = false;
- wrNext = FCGIGlobalDefs.def_FCGIHeaderLen;
- isClosed = false;
- request = inreq;
- }
-
- /**
- * Writes a byte to the output stream.
- */
- public void write(int c) throws IOException {
- if(wrNext != stop) {
- buff[wrNext++] = (byte)c;
- return;
- }
- if(isClosed) {
- throw new EOFException();
- }
- empty(false);
- if(wrNext != stop) {
- buff[wrNext++] = (byte)c;
- return;
- }
- /* NOTE: ASSERT(stream->isClosed); */
- /* bug in emptyBuffProc if not */
- throw new EOFException();
- }
-
- /**
- * Writes an array of bytes. This method will block until the bytes
- * are actually written.
- * @param b the data to be written
- */
- public void write(byte b[]) throws IOException{
- write(b, 0, b.length);
- }
-
- /**
- * Writes len consecutive bytes from off in the array b
- * into the output stream. Performs no interpretation
- * of the output bytes. Making the user convert the string to
- * bytes is in line with current Java practice.
- */
- public void write(byte b[], int off, int len) throws IOException {
- int m, bytesMoved;
- /*
- * Fast path: room for n bytes in the buffer
- */
- if(len <= (stop - wrNext)) {
- System.arraycopy(b, off, buff, wrNext, len);
- wrNext += len;
- return;
- }
- /*
- * General case: stream is closed or buffer empty procedure
- * needs to be called
- */
- bytesMoved = 0;
- for (;;) {
- if(wrNext != stop) {
- m = Math.min(len - bytesMoved, stop - wrNext);
- System.arraycopy(b, off, buff, wrNext, m);
- bytesMoved += m;
- wrNext += m;
- if(bytesMoved == len) {
- return;
- }
- off += m;
- }
- if(isClosed) {
- throw new EOFException();
- }
- empty(false);
- }
- }
-
- /**
- * Encapsulates any buffered stream content in a FastCGI
- * record. If !doClose, writes the data, making the buffer
- * empty.
- */
- public void empty(boolean doClose) throws IOException {
- int cLen;
- /*
- * Alignment padding omitted in Java
- */
- if (!rawWrite) {
- cLen = wrNext - FCGIGlobalDefs.def_FCGIHeaderLen;
- if(cLen > 0) {
- System.arraycopy(new FCGIMessage().makeHeader(type,
- request.requestID, cLen, 0),
- 0, buff, 0,
- FCGIGlobalDefs.def_FCGIHeaderLen);
- }
- else {
- wrNext = 0;
- }
- }
- if (doClose) {
- writeCloseRecords();
- }
- if (wrNext != 0) {
- isAnythingWritten = true;
- try {
- out.write(buff, 0, wrNext);
- } catch (IOException e) {
- setException(e);
- return;
- }
- wrNext = 0;
- }
- /*
- * The buffer is empty.
- */
- if(!rawWrite) {
- wrNext += FCGIGlobalDefs.def_FCGIHeaderLen;
- }
- }
-
- /**
- * Close the stream.
- */
- public void close() throws IOException {
- if (isClosed) {
- return;
- }
- empty(true);
- /*
- * if isClosed, will return with EOFException from write.
- */
- isClosed = true;
- stop = wrNext;
- return;
- }
-
- /**
- * Flushes any buffered output.
- * Server-push is a legitimate application of flush.
- * Otherwise, it is not very useful, since FCGIAccept
- * does it implicitly. flush may reduce performance
- * by increasing the total number of operating system calls
- * the application makes.
- */
- public void flush() throws IOException {
- if (isClosed) {
- return;
- }
- empty(false);
- /*
- * if isClosed, will return with EOFException from write.
- */
- return;
- }
-
- /**
- * An FCGI error has occurred. Save the error code in the stream
- * for diagnostic purposes and set the stream state so that
- * reads return EOF
- */
- public void setFCGIError(int errnum) {
- /*
- * Preserve only the first error.
- */
- if (errno == 0) {
- errno = errnum;
- }
- isClosed = true;
- }
-
- /**
- * An Exception has occurred. Save the Exception in the stream
- * for diagnostic purposes and set the stream state so that
- * reads return EOF
- */
- public void setException(Exception errexpt) {
- /*
- * Preserve only the first error.
- */
- if (errex == null) {
- errex = errexpt;
- }
- isClosed = true;
- }
-
- /**
- * Clear the stream error code and end-of-file indication.
- */
- public void clearFCGIError() {
- errno = 0;
- /*
- * isClosed = false;
- * XXX: should clear isClosed but work is needed to make it safe
- * to do so.
- */
- }
-
- /**
- * Clear the stream error code and end-of-file indication.
- */
- public void clearException() {
- errex = null;
- /*
- * isClosed = false;
- * XXX: should clear isClosed but work is needed to make it safe
- * to do so.
- */
- }
-
- /**
- * accessor method since var is private
- */
- public int etFCGIError() {
- return errno;
- }
-
- /**
- * accessor method since var is private
- */
- public Exception getException() {
- return errex;
- }
-
- /**
- * Writes an EOF record for the stream content if necessary.
- * If this is the last writer to close, writes an FCGI_END_REQUEST
- * record.
- */
- public void writeCloseRecords() throws IOException {
- FCGIMessage msg = new FCGIMessage();
- /*
- * Enter rawWrite mode so final records won't be
- * encapsulated as
- * stream data.
- */
- rawWrite = true;
- /*
- * Generate EOF for stream content if needed.
- */
- if(!(type == FCGIGlobalDefs.def_FCGIStderr
- && wrNext == 0
- && !isAnythingWritten)) {
- byte hdr[] =
- new byte[FCGIGlobalDefs.def_FCGIHeaderLen];
- System.arraycopy(msg.makeHeader(type,
- request.requestID,
- 0, 0),
- 0, hdr,0,
- FCGIGlobalDefs.def_FCGIHeaderLen);
- write(hdr, 0, hdr.length);
- }
- /*
- * Generate FCGI_END_REQUEST record if needed.
- */
- if(request.numWriters == 1) {
- byte endReq[] =
- new byte[FCGIGlobalDefs.def_FCGIHeaderLen
- + FCGIGlobalDefs.def_FCGIEndReqBodyLen];
- System.arraycopy(msg.makeHeader(
- FCGIGlobalDefs.def_FCGIEndRequest,
- request.requestID,
- FCGIGlobalDefs.def_FCGIEndReqBodyLen,0),
- 0, endReq, 0,
- FCGIGlobalDefs.def_FCGIHeaderLen);
- System.arraycopy(msg.makeEndrequestBody(
- request.appStatus,
- FCGIGlobalDefs.def_FCGIRequestComplete),
- 0,endReq,
- FCGIGlobalDefs.def_FCGIHeaderLen,
- FCGIGlobalDefs.def_FCGIEndReqBodyLen);
- write(endReq,0, FCGIGlobalDefs.def_FCGIHeaderLen
- + FCGIGlobalDefs.def_FCGIEndReqBodyLen);
- }
- request.numWriters--;
- }
-}
-
+++ /dev/null
-/*
- * @(#)FCGIRequest.java
- *
- * FastCGi compatibility package Interface
- *
- * Copyright (c) 1996 Open Market, Inc.
- *
- * See the file "LICENSE.TERMS" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * $Id: FCGIRequest.java,v 1.2 1998/12/12 04:42:23 roberts Exp $
- */
-
-import java.net.*;
-import java.io.FileDescriptor;
-import java.util.Properties;
-import FCGIInputStream;
-import FCGIOutputStream;
-public class FCGIRequest {
-
- /* This class has no methods. Right now we are single threaded
- * so there is only one request object at any given time which
- * is refrenced by an FCGIInterface class variable . All of this
- * object's data could just as easily be declared directly there.
- * When we thread, this will change, so we might as well use a
- * seperate class. In line with this thinking, though somewhat
- * more perversely, we kept the socket here.
- */
- /*
- * class variables
- */
- /*public static Socket socket; */
- // same for all requests
-
- /*
- * instance variables
- */
- public Socket socket;
- public boolean isBeginProcessed;
- public int requestID;
- public boolean keepConnection;
- public int role;
- public int appStatus;
- public int numWriters;
- public FCGIInputStream inStream;
- public FCGIOutputStream outStream;
- public FCGIOutputStream errStream;
- public Properties params;
-}
-
-