File: FCGIInterface.java

package info (click to toggle)
libfcgi 2.4.5-0.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,296 kB
  • sloc: ansic: 4,946; java: 872; cpp: 292; makefile: 178; perl: 145; sh: 4
file content (247 lines) | stat: -rw-r--r-- 8,490 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
/*
 * @(#)FCGIInterface.java
 *
 *
 *      FastCGi compatibility package Interface
 *
 *
 *  Copyright (c) 1996 Open Market, Inc.
 *
 * See the file "LICENSE" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * $Id: FCGIInterface.java,v 1.4 2000/03/27 15:37:25 robs Exp $
 */
package com.fastcgi;

import java.net.*;
import java.io.*;
import java.util.Properties;

/*
 * 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 
{
    private static final String RCSID = "$Id: FCGIInterface.java,v 1.4 2000/03/27 15:37:25 robs Exp $";

    /*
    * 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
                 */
                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) {
                    if (request != null)
                    {
                        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 variables 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 isn't 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;
    }
}