1 /*
2 *
3 * ====================================================================
4 *
5 * The Apache Software License, Version 1.1
6 *
7 * Copyright (c) 1999 The Apache Software Foundation. All rights
8 * reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 *
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
20 * distribution.
21 *
22 * 3. The end-user documentation included with the redistribution, if
23 * any, must include the following acknowlegement:
24 * "This product includes software developed by the
25 * Apache Software Foundation (http://www.apache.org/)."
26 * Alternately, this acknowlegement may appear in the software itself,
27 * if and wherever such third-party acknowlegements normally appear.
28 *
29 * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
30 * Foundation" must not be used to endorse or promote products derived
31 * from this software without prior written permission. For written
32 * permission, please contact apache@apache.org.
33 *
34 * 5. Products derived from this software may not be called "Apache"
35 * nor may "Apache" appear in their names without prior written
36 * permission of the Apache Group.
37 *
38 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
39 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
40 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
41 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
44 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
45 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
46 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
47 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
48 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
49 * SUCH DAMAGE.
50 * ====================================================================
51 *
52 * This software consists of voluntary contributions made by many
53 * individuals on behalf of the Apache Software Foundation. For more
54 * information on the Apache Software Foundation, please see
55 * <http://www.apache.org/>.
56 *
57 * [Additional notices, if required by prior licensing conditions]
58 *
59 */
60
61
62 /*
63 Based on Ajp11ConnectionHandler and Ajp12 implementation of JServ
64 */
65
66 package org.apache.tomcat.service.connector;
67
68 import java.io;
69 import java.net;
70 import java.util;
71 import org.apache.tomcat.core;
72 import org.apache.tomcat.util;
73 import org.apache.tomcat.server;
74 import org.apache.tomcat.service.http;
75 import org.apache.tomcat.service.http.HttpResponseAdapter;
76 import org.apache.tomcat.service.http.HttpRequestAdapter;
77 import org.apache.tomcat.service;
78 import javax.servlet;
79 import javax.servlet.http;
80
81 /* Deprecated - must be rewriten to the connector model.
82 */
83 public class Ajp12ConnectionHandler implements TcpConnectionHandler {
84 StringManager sm = StringManager.getManager("org.apache.tomcat.service");
85
86 ContextManager contextM;
87
88 public Ajp12ConnectionHandler() {
89 }
90
91 public Object[] init() {
92 return null;
93 }
94
95 public void setAttribute(String name, Object value ) {
96 if("context.manager".equals(name) ) {
97 contextM=(ContextManager)value;
98 }
99 }
100
101 public void setContextManager( ContextManager contextM ) {
102 this.contextM=contextM;
103 }
104
105 public void processConnection(TcpConnection connection, Object[] theData) {
106
107 try {
108 Socket socket=connection.getSocket();
109 socket.setSoLinger( true, 100);
110
111 Request request = new Request();
112 AJP12RequestAdapter reqA = new AJP12RequestAdapter(socket);
113 Response response=new Response();
114 AJP12ResponseAdapter resA=new AJP12ResponseAdapter();
115
116 InputStream in=socket.getInputStream();
117 OutputStream out=socket.getOutputStream();
118
119 request.setRequestAdapter(reqA);
120 response.setResponseAdapter( resA );
121 resA.setOutputStream(socket.getOutputStream());
122
123 request.setResponse(response);
124 response.setRequest(request);
125
126 reqA.readNextRequest();
127
128 if (response.getStatus() >= 400) {
129 response.finish();
130
131 socket.close();
132 return;
133 }
134
135 // resolve the server that we are for
136
137 int contentLength = request.getIntHeader("content-length");
138 if (contentLength != -1) {
139 BufferedServletInputStream sis =
140 (BufferedServletInputStream)request.getInputStream();
141 sis.setLimit(contentLength);
142 }
143
144 contextM.service( request, response );
145
146 response.finish();
147 socket.close();
148 } catch (Exception e) {
149 // XXX
150 // this isn't what we want, we want to log the problem somehow
151 System.out.println("HANDLER THREAD PROBLEM: " + e);
152 e.printStackTrace();
153 }
154 }
155 }
156
157 class AJP12RequestAdapter extends RequestAdapterImpl {
158 StringManager sm = StringManager.getManager("org.apache.tomcat.service");
159 Socket socket;
160 InputStream sin;
161 Ajpv12InputStream ajpin;
162
163 public int doRead() throws IOException {
164 return ajpin.read();
165 }
166
167 public int doRead( byte b[], int off, int len ) throws IOException {
168 return ajpin.read(b,off,len);
169 }
170
171 public AJP12RequestAdapter(Socket s) throws IOException {
172 this.socket = s;
173 sin = s.getInputStream();
174 in = new BufferedServletInputStream( this );
175 ajpin = new Ajpv12InputStream(sin);
176 }
177
178 protected void readNextRequest() throws IOException {
179 String dummy,token1,token2;
180 int marker;
181 int signal;
182
183 try {
184 while (true) {
185 marker = ajpin.read();
186 switch (marker) {
187 case 0: //NOP marker useful for testing if stream is OK
188 break;
189
190 case 1: //beginning of request
191 method = ajpin.readString(null); //Method
192 dummy = ajpin.readString(null); //Zone
193 dummy = ajpin.readString(null); //Servlet
194 serverName = ajpin.readString(null); //Server hostname
195 dummy = ajpin.readString(null); //Apache document root
196 dummy = ajpin.readString(null); //Apache parsed path-info
197 dummy = ajpin.readString(null); //Apache parsed path-translated
198 queryString = ajpin.readString(null); //query string
199 remoteAddr = ajpin.readString(""); //remote address
200 remoteHost = ajpin.readString(""); //remote host
201 dummy = ajpin.readString(null); //remote user
202 dummy = ajpin.readString(null); //auth type
203 dummy = ajpin.readString(null); //remote port
204 dummy = ajpin.readString(null); //request method
205 requestURI = ajpin.readString(""); //request uri
206 dummy = ajpin.readString(null); //script filename
207 dummy = ajpin.readString(null); //script name
208 serverName = ajpin.readString(""); //server name
209 try {
210 serverPort = Integer.parseInt(ajpin.readString("80")); //server port
211 } catch (Exception any) {
212 serverPort = 80;
213 }
214 dummy = ajpin.readString(""); //server protocol
215 dummy = ajpin.readString(""); //server signature
216 dummy = ajpin.readString(""); //server software
217 dummy = ajpin.readString(""); //JSERV ROUTE
218 /**
219 * The two following lines are commented out because we don't
220 * want to depend on unreleased versions of the jserv module.
221 * - costin
222 */
223 // dummy = ajpin.readString(""); //SSL_CLIENT_DN
224 // dummy = ajpin.readString(""); //SSL_CLIENT_IDN
225 // XXX all dummy fields will be used after core is changed to make use
226 // of them!
227
228 break;
229
230 case 3: // Header
231 token1 = ajpin.readString(null);
232 token2 = ajpin.readString("");
233 headers.putHeader(token1.toLowerCase(), token2);
234 break;
235
236 case 254: // Signal
237 signal = ajpin.read();
238
239 if (signal == 0) { // PING implemented as signal
240 try {
241 // close the socket connection after we send reply
242 socket.getOutputStream().write(0); // PING reply
243 sin.close();
244 } catch (IOException ignored) {
245 System.err.println(ignored);
246 }
247 } else {
248 try {
249 // close the socket connection before handling any signal
250 sin.close();
251 } catch (IOException ignored) {
252 System.err.println(ignored);
253 }
254 System.err.println("Signal ignored: " + signal);
255 }
256 return;
257
258 case 4:
259 case 255:
260 return;
261
262 case -1:
263 throw new java.io.IOException("Stream closed prematurely");
264
265
266 default:
267 throw new java.io.IOException("Stream broken");
268
269
270 } // while
271 } // switch
272 } catch (IOException ioe) {
273 throw ioe;
274 } catch (Exception e) {
275 System.err.println("Uncaught exception" + e);
276 }
277
278 // REQUEST_URI includes query string
279 int idQ= requestURI.indexOf("?");
280 if ( idQ > -1) {
281 requestURI = requestURI.substring(0, idQ);
282 }
283
284
285 // System.out.println("Request: " + requestURI );
286 // System.out.println("Query: " + queryString );
287 // System.out.println("ENV: " + env_vars );
288 // System.out.println("HEADERS: " + headers_in );
289 // System.out.println("PARAMETERS: " + parameters );
290
291
292 //processCookies();
293
294 contentLength = headers.getIntHeader("content-length");
295 contentType = headers.getHeader("content-type");
296
297 // XXX
298 // detect for real whether or not we have more requests
299 // coming
300
301 // XXX
302 // Support persistent connection in AJP21
303 //moreRequests = false;
304 }
305
306 }
307
308
309 // Ajp use Status: instead of Status
310 class AJP12ResponseAdapter extends HttpResponseAdapter {
311 /** Override setStatus
312 */
313 public void setStatus( int status, String message) throws IOException {
314 statusSB.setLength(0);
315 statusSB.append("Status: " ).append( status ).append("\r\n");
316 sout.write(statusSB.toString().getBytes());
317 }
318 }
319
320 class Ajpv12InputStream extends BufferedInputStream {
321
322 public Ajpv12InputStream(InputStream in) {
323 super(in);
324 }
325
326 public Ajpv12InputStream(InputStream in, int bufsize) {
327 super(in,bufsize);
328 }
329
330
331 public int readWord() throws java.io.IOException {
332 int b1 = read();
333 if( b1 == -1)
334 return -1;
335
336 int b2 = read();
337 if ( b2==-1)
338 return -1;
339
340 return ((int)((b1 << 8) | b2)) & 0xffff;
341 }
342
343 public String readString(String def) throws java.io.IOException {
344 int len = readWord();
345
346 if( len == 0xffff)
347 return def;
348
349 if( len == -1)
350 throw new java.io.IOException("Stream broken");
351
352 byte[] b = new byte[len];
353 int p = 0;
354 int r;
355 while(p<len) {
356 r = read(b,p, len - p);
357 if( r< 0) {
358 throw new java.io.IOException("Stream broken, couldn't demarshal string :"+len+":"+p);
359 }
360 p = p+r;
361 }
362 return new String(b);
363 }
364 }
365
366