Review Board 1.7.22


Offer possible resolution of StringIndexOutOfBoundsException in Request.updateCounters when AJP packetSize is too small.

Review Request #595 - Created April 13, 2011 and updated

Erik Meade
Reviewers
tomcat
tomcat-6.0.x
Could we improve the error message If the AJP packetSize is not large enough?  As is we get:

org.apache.coyote.ajp.AjpAprProtocol$AjpConnectionHandler process                                                                                                                 
SEVERE: Error reading request, ignored                                                                                                                                            
java.lang.StringIndexOutOfBoundsException: String index out of range: 13628                                                                                                       
        at java.lang.String.checkBounds(String.java:401)                                                                                                                          
        at java.lang.String.<init>(String.java:442)                                                                                                                               
        at org.apache.tomcat.util.buf.ByteChunk.toStringInternal(ByteChunk.java:497)                                                                                              
        at org.apache.tomcat.util.buf.StringCache.toString(StringCache.java:216)                                                                                                  
        at org.apache.tomcat.util.buf.ByteChunk.toString(ByteChunk.java:490)                                                                                                      
        at org.apache.tomcat.util.buf.MessageBytes.toString(MessageBytes.java:213)                                                                                                
        at org.apache.coyote.RequestInfo.updateCounters(RequestInfo.java:156)                                                                                                     
        at org.apache.coyote.Request.updateCounters(Request.java:518)                                                                                                             
        at org.apache.coyote.ajp.AjpAprProcessor.process(AjpAprProcessor.java:455)                                                                                                
        at org.apache.coyote.ajp.AjpAprProtocol$AjpConnectionHandler.process(AjpAprProtocol.java:384)                                                                             
        at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1665)                                                                                               
        at java.lang.Thread.run(Thread.java:662)                                                                                                                                  
                                                                                                                                                                                  
                                                                                                                                     
[Fri Apr 08 17:23:44 2011] [error] ajp_read_header: ajp_ilink_receive failed                                                                                                      
[Fri Apr 08 17:23:44 2011] [error] (120006)APR does not understand                                                                                                                
this error code: proxy: read response failed from 127.0.0.1:8003                                                                                                                  
(127.0.0.1)                                                                                                                                                                       
[Fri Apr 08 17:23:44 2011] [error] (104)Connection reset by peer:                                                                                                                 
ajp_ilink_receive() can't receive header      

 

Diff revision 1 (Latest)

  1. /trunk/java/org/apache/coyote/ajp/AjpProcessor.java: Loading...
/trunk/java/org/apache/coyote/ajp/AjpProcessor.java
Revision 1091721 New Change
1
/*
1
/*
2
 *  Licensed to the Apache Software Foundation (ASF) under one or more
2
 *  Licensed to the Apache Software Foundation (ASF) under one or more
3
 *  contributor license agreements.  See the NOTICE file distributed with
3
 *  contributor license agreements.  See the NOTICE file distributed with
4
 *  this work for additional information regarding copyright ownership.
4
 *  this work for additional information regarding copyright ownership.
5
 *  The ASF licenses this file to You under the Apache License, Version 2.0
5
 *  The ASF licenses this file to You under the Apache License, Version 2.0
6
 *  (the "License"); you may not use this file except in compliance with
6
 *  (the "License"); you may not use this file except in compliance with
7
 *  the License.  You may obtain a copy of the License at
7
 *  the License.  You may obtain a copy of the License at
8
 *
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
10
 *
11
 *  Unless required by applicable law or agreed to in writing, software
11
 *  Unless required by applicable law or agreed to in writing, software
12
 *  distributed under the License is distributed on an "AS IS" BASIS,
12
 *  distributed under the License is distributed on an "AS IS" BASIS,
13
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 *  See the License for the specific language governing permissions and
14
 *  See the License for the specific language governing permissions and
15
 *  limitations under the License.
15
 *  limitations under the License.
16
 */
16
 */
17

    
   
17

   
18
package org.apache.coyote.ajp;
18
package org.apache.coyote.ajp;
19

    
   
19

   
20
import java.io.ByteArrayInputStream;
20
import java.io.ByteArrayInputStream;
21
import java.io.IOException;
21
import java.io.IOException;
22
import java.io.InputStream;
22
import java.io.InputStream;
23
import java.io.InterruptedIOException;
23
import java.io.InterruptedIOException;
24
import java.io.OutputStream;
24
import java.io.OutputStream;
25
import java.net.InetAddress;
25
import java.net.InetAddress;
26
import java.net.Socket;
26
import java.net.Socket;
27
import java.security.cert.CertificateFactory;
27
import java.security.cert.CertificateFactory;
28
import java.security.cert.X509Certificate;
28
import java.security.cert.X509Certificate;
29

    
   
29

   
30
import org.apache.coyote.ActionCode;
30
import org.apache.coyote.ActionCode;
31
import org.apache.coyote.ActionHook;
31
import org.apache.coyote.ActionHook;
32
import org.apache.coyote.Adapter;
32
import org.apache.coyote.Adapter;
33
import org.apache.coyote.InputBuffer;
33
import org.apache.coyote.InputBuffer;
34
import org.apache.coyote.OutputBuffer;
34
import org.apache.coyote.OutputBuffer;
35
import org.apache.coyote.Request;
35
import org.apache.coyote.Request;
36
import org.apache.coyote.RequestInfo;
36
import org.apache.coyote.RequestInfo;
37
import org.apache.coyote.Response;
37
import org.apache.coyote.Response;
38
import org.apache.tomcat.util.buf.ByteChunk;
38
import org.apache.tomcat.util.buf.ByteChunk;
39
import org.apache.tomcat.util.buf.HexUtils;
39
import org.apache.tomcat.util.buf.HexUtils;
40
import org.apache.tomcat.util.buf.MessageBytes;
40
import org.apache.tomcat.util.buf.MessageBytes;
41
import org.apache.tomcat.util.http.HttpMessages;
41
import org.apache.tomcat.util.http.HttpMessages;
42
import org.apache.tomcat.util.http.MimeHeaders;
42
import org.apache.tomcat.util.http.MimeHeaders;
43
import org.apache.tomcat.util.net.JIoEndpoint;
43
import org.apache.tomcat.util.net.JIoEndpoint;
44
import org.apache.tomcat.util.res.StringManager;
44
import org.apache.tomcat.util.res.StringManager;
45

    
   
45

   
46

    
   
46

   
47
/**
47
/**
48
 * Processes HTTP requests.
48
 * Processes HTTP requests.
49
 *
49
 *
50
 * @author Remy Maucherat
50
 * @author Remy Maucherat
51
 * @author Henri Gomez
51
 * @author Henri Gomez
52
 * @author Dan Milstein
52
 * @author Dan Milstein
53
 * @author Keith Wannamaker
53
 * @author Keith Wannamaker
54
 * @author Kevin Seguin
54
 * @author Kevin Seguin
55
 * @author Costin Manolache
55
 * @author Costin Manolache
56
 * @author Bill Barker
56
 * @author Bill Barker
57
 */
57
 */
58
public class AjpProcessor implements ActionHook {
58
public class AjpProcessor implements ActionHook {
59

    
   
59

   
60

    
   
60

   
61
    /**
61
    /**
62
     * Logger.
62
     * Logger.
63
     */
63
     */
64
    protected static org.apache.juli.logging.Log log
64
    protected static org.apache.juli.logging.Log log
65
        = org.apache.juli.logging.LogFactory.getLog(AjpProcessor.class);
65
        = org.apache.juli.logging.LogFactory.getLog(AjpProcessor.class);
66

    
   
66

   
67
    /**
67
    /**
68
     * The string manager for this package.
68
     * The string manager for this package.
69
     */
69
     */
70
    protected static StringManager sm =
70
    protected static StringManager sm =
71
        StringManager.getManager(Constants.Package);
71
        StringManager.getManager(Constants.Package);
72

    
   
72

   
73

    
   
73

   
74
    // ----------------------------------------------------------- Constructors
74
    // ----------------------------------------------------------- Constructors
75

    
   
75

   
76

    
   
76

   
77
    public AjpProcessor(int packetSize, JIoEndpoint endpoint) {
77
    public AjpProcessor(int packetSize, JIoEndpoint endpoint) {
78

    
   
78

   
79
        this.endpoint = endpoint;
79
        this.endpoint = endpoint;
80

    
   
80

   
81
        request = new Request();
81
        request = new Request();
82
        request.setInputBuffer(new SocketInputBuffer());
82
        request.setInputBuffer(new SocketInputBuffer());
83

    
   
83

   
84
        response = new Response();
84
        response = new Response();
85
        response.setHook(this);
85
        response.setHook(this);
86
        response.setOutputBuffer(new SocketOutputBuffer());
86
        response.setOutputBuffer(new SocketOutputBuffer());
87
        request.setResponse(response);
87
        request.setResponse(response);
88

    
   
88

   
89
        this.packetSize = packetSize;
89
        this.packetSize = packetSize;
90
        requestHeaderMessage = new AjpMessage(packetSize);
90
        requestHeaderMessage = new AjpMessage(packetSize);
91
        responseHeaderMessage = new AjpMessage(packetSize);
91
        responseHeaderMessage = new AjpMessage(packetSize);
92
        bodyMessage = new AjpMessage(packetSize);
92
        bodyMessage = new AjpMessage(packetSize);
93

    
   
93

   
94
        // Set the get body message buffer
94
        // Set the get body message buffer
95
        AjpMessage getBodyMessage = new AjpMessage(16);
95
        AjpMessage getBodyMessage = new AjpMessage(16);
96
        getBodyMessage.reset();
96
        getBodyMessage.reset();
97
        getBodyMessage.appendByte(Constants.JK_AJP13_GET_BODY_CHUNK);
97
        getBodyMessage.appendByte(Constants.JK_AJP13_GET_BODY_CHUNK);
98
        // Adjust allowed size if packetSize != default (Constants.MAX_PACKET_SIZE)
98
        // Adjust allowed size if packetSize != default (Constants.MAX_PACKET_SIZE)
99
        getBodyMessage.appendInt(Constants.MAX_READ_SIZE + packetSize - Constants.MAX_PACKET_SIZE);
99
        getBodyMessage.appendInt(Constants.MAX_READ_SIZE + packetSize - Constants.MAX_PACKET_SIZE);
100
        getBodyMessage.end();
100
        getBodyMessage.end();
101
        getBodyMessageArray = new byte[getBodyMessage.getLen()];
101
        getBodyMessageArray = new byte[getBodyMessage.getLen()];
102
        System.arraycopy(getBodyMessage.getBuffer(), 0, getBodyMessageArray, 
102
        System.arraycopy(getBodyMessage.getBuffer(), 0, getBodyMessageArray, 
103
                         0, getBodyMessage.getLen());
103
                         0, getBodyMessage.getLen());
104

    
   
104

   
105
        // Cause loading of HexUtils
105
        // Cause loading of HexUtils
106
        int foo = HexUtils.DEC[0];
106
        int foo = HexUtils.DEC[0];
107

    
   
107

   
108
        // Cause loading of HttpMessages
108
        // Cause loading of HttpMessages
109
        HttpMessages.getMessage(200);
109
        HttpMessages.getMessage(200);
110

    
   
110

   
111
    }
111
    }
112

    
   
112

   
113

    
   
113

   
114
    // ----------------------------------------------------- Instance Variables
114
    // ----------------------------------------------------- Instance Variables
115

    
   
115

   
116

    
   
116

   
117
    /**
117
    /**
118
     * Associated adapter.
118
     * Associated adapter.
119
     */
119
     */
120
    protected Adapter adapter = null;
120
    protected Adapter adapter = null;
121

    
   
121

   
122

    
   
122

   
123
    /**
123
    /**
124
     * Request object.
124
     * Request object.
125
     */
125
     */
126
    protected Request request = null;
126
    protected Request request = null;
127

    
   
127

   
128

    
   
128

   
129
    /**
129
    /**
130
     * Response object.
130
     * Response object.
131
     */
131
     */
132
    protected Response response = null;
132
    protected Response response = null;
133

    
   
133

   
134

    
   
134

   
135
    /**
135
    /**
136
     * The socket timeout used when reading the first block of the request
136
     * The socket timeout used when reading the first block of the request
137
     * header.
137
     * header.
138
     */
138
     */
139
    protected int packetSize;
139
    protected int packetSize;
140

    
   
140

   
141
    /**
141
    /**
142
     * Header message. Note that this header is merely the one used during the
142
     * Header message. Note that this header is merely the one used during the
143
     * processing of the first message of a "request", so it might not be a request
143
     * processing of the first message of a "request", so it might not be a request
144
     * header. It will stay unchanged during the processing of the whole request.
144
     * header. It will stay unchanged during the processing of the whole request.
145
     */
145
     */
146
    protected AjpMessage requestHeaderMessage = null;
146
    protected AjpMessage requestHeaderMessage = null;
147

    
   
147

   
148

    
   
148

   
149
    /**
149
    /**
150
     * Message used for response header composition.
150
     * Message used for response header composition.
151
     */
151
     */
152
    protected AjpMessage responseHeaderMessage = null;
152
    protected AjpMessage responseHeaderMessage = null;
153

    
   
153

   
154

    
   
154

   
155
    /**
155
    /**
156
     * Body message.
156
     * Body message.
157
     */
157
     */
158
    protected AjpMessage bodyMessage = null;
158
    protected AjpMessage bodyMessage = null;
159

    
   
159

   
160

    
   
160

   
161
    /**
161
    /**
162
     * Body message.
162
     * Body message.
163
     */
163
     */
164
    protected MessageBytes bodyBytes = MessageBytes.newInstance();
164
    protected MessageBytes bodyBytes = MessageBytes.newInstance();
165

    
   
165

   
166

    
   
166

   
167
    /**
167
    /**
168
     * State flag.
168
     * State flag.
169
     */
169
     */
170
    protected boolean started = false;
170
    protected boolean started = false;
171

    
   
171

   
172

    
   
172

   
173
    /**
173
    /**
174
     * Error flag.
174
     * Error flag.
175
     */
175
     */
176
    protected boolean error = false;
176
    protected boolean error = false;
177

    
   
177

   
178

    
   
178

   
179
    /**
179
    /**
180
     * Socket associated with the current connection.
180
     * Socket associated with the current connection.
181
     */
181
     */
182
    protected Socket socket;
182
    protected Socket socket;
183

    
   
183

   
184
    
184
    
185
    /**
185
    /**
186
     * Input stream.
186
     * Input stream.
187
     */
187
     */
188
    protected InputStream input;
188
    protected InputStream input;
189
    
189
    
190
    
190
    
191
    /**
191
    /**
192
     * Output stream.
192
     * Output stream.
193
     */
193
     */
194
    protected OutputStream output;
194
    protected OutputStream output;
195
    
195
    
196

    
   
196

   
197
    /**
197
    /**
198
     * Host name (used to avoid useless B2C conversion on the host name).
198
     * Host name (used to avoid useless B2C conversion on the host name).
199
     */
199
     */
200
    protected char[] hostNameC = new char[0];
200
    protected char[] hostNameC = new char[0];
201

    
   
201

   
202

    
   
202

   
203
    /**
203
    /**
204
     * Associated endpoint.
204
     * Associated endpoint.
205
     */
205
     */
206
    protected JIoEndpoint endpoint;
206
    protected JIoEndpoint endpoint;
207

    
   
207

   
208

    
   
208

   
209
    /**
209
    /**
210
     * The socket timeout used when reading the first block of the request
210
     * The socket timeout used when reading the first block of the request
211
     * header.
211
     * header.
212
     */
212
     */
213
    protected long readTimeout;
213
    protected long readTimeout;
214

    
   
214

   
215

    
   
215

   
216
    /**
216
    /**
217
     * Temp message bytes used for processing.
217
     * Temp message bytes used for processing.
218
     */
218
     */
219
    protected MessageBytes tmpMB = MessageBytes.newInstance();
219
    protected MessageBytes tmpMB = MessageBytes.newInstance();
220

    
   
220

   
221

    
   
221

   
222
    /**
222
    /**
223
     * Byte chunk for certs.
223
     * Byte chunk for certs.
224
     */
224
     */
225
    protected MessageBytes certificates = MessageBytes.newInstance();
225
    protected MessageBytes certificates = MessageBytes.newInstance();
226

    
   
226

   
227

    
   
227

   
228
    /**
228
    /**
229
     * End of stream flag.
229
     * End of stream flag.
230
     */
230
     */
231
    protected boolean endOfStream = false;
231
    protected boolean endOfStream = false;
232

    
   
232

   
233

    
   
233

   
234
    /**
234
    /**
235
     * Body empty flag.
235
     * Body empty flag.
236
     */
236
     */
237
    protected boolean empty = true;
237
    protected boolean empty = true;
238

    
   
238

   
239

    
   
239

   
240
    /**
240
    /**
241
     * First read.
241
     * First read.
242
     */
242
     */
243
    protected boolean first = true;
243
    protected boolean first = true;
244

    
   
244

   
245

    
   
245

   
246
    /**
246
    /**
247
     * Replay read.
247
     * Replay read.
248
     */
248
     */
249
    protected boolean replay = false;
249
    protected boolean replay = false;
250

    
   
250

   
251

    
   
251

   
252
    /**
252
    /**
253
     * Finished response.
253
     * Finished response.
254
     */
254
     */
255
    protected boolean finished = false;
255
    protected boolean finished = false;
256

    
   
256

   
257

    
   
257

   
258
    /**
258
    /**
259
     * Direct buffer used for sending right away a get body message.
259
     * Direct buffer used for sending right away a get body message.
260
     */
260
     */
261
    protected final byte[] getBodyMessageArray;
261
    protected final byte[] getBodyMessageArray;
262

    
   
262

   
263

    
   
263

   
264
    /**
264
    /**
265
     * Direct buffer used for sending right away a pong message.
265
     * Direct buffer used for sending right away a pong message.
266
     */
266
     */
267
    protected static final byte[] pongMessageArray;
267
    protected static final byte[] pongMessageArray;
268

    
   
268

   
269

    
   
269

   
270
    /**
270
    /**
271
     * End message array.
271
     * End message array.
272
     */
272
     */
273
    protected static final byte[] endMessageArray;
273
    protected static final byte[] endMessageArray;
274

    
   
274

   
275
    /**
275
    /**
276
     * Flush message array.
276
     * Flush message array.
277
     */
277
     */
278
    protected static final byte[] flushMessageArray;
278
    protected static final byte[] flushMessageArray;
279

    
   
279

   
280

    
   
280

   
281
    // ----------------------------------------------------- Static Initializer
281
    // ----------------------------------------------------- Static Initializer
282

    
   
282

   
283

    
   
283

   
284
    static {
284
    static {
285

    
   
285

   
286
        // Set the read body message buffer
286
        // Set the read body message buffer
287
        AjpMessage pongMessage = new AjpMessage(16);
287
        AjpMessage pongMessage = new AjpMessage(16);
288
        pongMessage.reset();
288
        pongMessage.reset();
289
        pongMessage.appendByte(Constants.JK_AJP13_CPONG_REPLY);
289
        pongMessage.appendByte(Constants.JK_AJP13_CPONG_REPLY);
290
        pongMessage.end();
290
        pongMessage.end();
291
        pongMessageArray = new byte[pongMessage.getLen()];
291
        pongMessageArray = new byte[pongMessage.getLen()];
292
        System.arraycopy(pongMessage.getBuffer(), 0, pongMessageArray, 
292
        System.arraycopy(pongMessage.getBuffer(), 0, pongMessageArray, 
293
                0, pongMessage.getLen());
293
                0, pongMessage.getLen());
294

    
   
294

   
295
        // Allocate the end message array
295
        // Allocate the end message array
296
        AjpMessage endMessage = new AjpMessage(16);
296
        AjpMessage endMessage = new AjpMessage(16);
297
        endMessage.reset();
297
        endMessage.reset();
298
        endMessage.appendByte(Constants.JK_AJP13_END_RESPONSE);
298
        endMessage.appendByte(Constants.JK_AJP13_END_RESPONSE);
299
        endMessage.appendByte(1);
299
        endMessage.appendByte(1);
300
        endMessage.end();
300
        endMessage.end();
301
        endMessageArray = new byte[endMessage.getLen()];
301
        endMessageArray = new byte[endMessage.getLen()];
302
        System.arraycopy(endMessage.getBuffer(), 0, endMessageArray, 0,
302
        System.arraycopy(endMessage.getBuffer(), 0, endMessageArray, 0,
303
                endMessage.getLen());
303
                endMessage.getLen());
304

    
   
304

   
305
        // Allocate the flush message array
305
        // Allocate the flush message array
306
        AjpMessage flushMessage = new AjpMessage(16);
306
        AjpMessage flushMessage = new AjpMessage(16);
307
        flushMessage.reset();
307
        flushMessage.reset();
308
        flushMessage.appendByte(Constants.JK_AJP13_SEND_BODY_CHUNK);
308
        flushMessage.appendByte(Constants.JK_AJP13_SEND_BODY_CHUNK);
309
        flushMessage.appendInt(0);
309
        flushMessage.appendInt(0);
310
        flushMessage.appendByte(0);
310
        flushMessage.appendByte(0);
311
        flushMessage.end();
311
        flushMessage.end();
312
        flushMessageArray = new byte[flushMessage.getLen()];
312
        flushMessageArray = new byte[flushMessage.getLen()];
313
        System.arraycopy(flushMessage.getBuffer(), 0, flushMessageArray, 0,
313
        System.arraycopy(flushMessage.getBuffer(), 0, flushMessageArray, 0,
314
                flushMessage.getLen());
314
                flushMessage.getLen());
315

    
   
315

   
316
    }
316
    }
317

    
   
317

   
318

    
   
318

   
319
    // ------------------------------------------------------------- Properties
319
    // ------------------------------------------------------------- Properties
320

    
   
320

   
321

    
   
321

   
322
    /**
322
    /**
323
     * Use Tomcat authentication ?
323
     * Use Tomcat authentication ?
324
     */
324
     */
325
    protected boolean tomcatAuthentication = true;
325
    protected boolean tomcatAuthentication = true;
326
    public boolean getTomcatAuthentication() { return tomcatAuthentication; }
326
    public boolean getTomcatAuthentication() { return tomcatAuthentication; }
327
    public void setTomcatAuthentication(boolean tomcatAuthentication) { this.tomcatAuthentication = tomcatAuthentication; }
327
    public void setTomcatAuthentication(boolean tomcatAuthentication) { this.tomcatAuthentication = tomcatAuthentication; }
328

    
   
328

   
329

    
   
329

   
330
    /**
330
    /**
331
     * Required secret.
331
     * Required secret.
332
     */
332
     */
333
    protected String requiredSecret = null;
333
    protected String requiredSecret = null;
334
    public void setRequiredSecret(String requiredSecret) { this.requiredSecret = requiredSecret; }
334
    public void setRequiredSecret(String requiredSecret) { this.requiredSecret = requiredSecret; }
335

    
   
335

   
336

    
   
336

   
337
    /**
337
    /**
338
     * The number of milliseconds Tomcat will wait for a subsequent request
338
     * The number of milliseconds Tomcat will wait for a subsequent request
339
     * before closing the connection. The default is the same as for
339
     * before closing the connection. The default is the same as for
340
     * Apache HTTP Server (15 000 milliseconds).
340
     * Apache HTTP Server (15 000 milliseconds).
341
     */
341
     */
342
    protected int keepAliveTimeout = -1;
342
    protected int keepAliveTimeout = -1;
343
    public int getKeepAliveTimeout() { return keepAliveTimeout; }
343
    public int getKeepAliveTimeout() { return keepAliveTimeout; }
344
    public void setKeepAliveTimeout(int timeout) { keepAliveTimeout = timeout; }
344
    public void setKeepAliveTimeout(int timeout) { keepAliveTimeout = timeout; }
345

    
   
345

   
346

    
   
346

   
347
    // --------------------------------------------------------- Public Methods
347
    // --------------------------------------------------------- Public Methods
348

    
   
348

   
349

    
   
349

   
350
    /** Get the request associated with this processor.
350
    /** Get the request associated with this processor.
351
     *
351
     *
352
     * @return The request
352
     * @return The request
353
     */
353
     */
354
    public Request getRequest() {
354
    public Request getRequest() {
355
        return request;
355
        return request;
356
    }
356
    }
357

    
   
357

   
358

    
   
358

   
359
    /**
359
    /**
360
     * Process pipelined HTTP requests using the specified input and output
360
     * Process pipelined HTTP requests using the specified input and output
361
     * streams.
361
     * streams.
362
     *
362
     *
363
     * @throws IOException error during an I/O operation
363
     * @throws IOException error during an I/O operation
364
     */
364
     */
365
    public void process(Socket socket)
365
    public void process(Socket socket)
366
        throws IOException {
366
        throws IOException {
367
        RequestInfo rp = request.getRequestProcessor();
367
        RequestInfo rp = request.getRequestProcessor();
368
        rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
368
        rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
369

    
   
369

   
370
        // Setting up the socket
370
        // Setting up the socket
371
        this.socket = socket;
371
        this.socket = socket;
372
        input = socket.getInputStream();
372
        input = socket.getInputStream();
373
        output = socket.getOutputStream();
373
        output = socket.getOutputStream();
374
        int soTimeout = -1;
374
        int soTimeout = -1;
375
        if (keepAliveTimeout > 0) {
375
        if (keepAliveTimeout > 0) {
376
            soTimeout = socket.getSoTimeout();
376
            soTimeout = socket.getSoTimeout();
377
        }
377
        }
378

    
   
378

   
379
        // Error flag
379
        // Error flag
380
        error = false;
380
        error = false;
381

    
   
381

   
382
        while (started && !error) {
382
        while (started && !error) {
383

    
   
383

   
384
            // Parsing the request header
384
            // Parsing the request header
385
            try {
385
            try {
386
                // Set keep alive timeout if enabled
386
                // Set keep alive timeout if enabled
387
                if (keepAliveTimeout > 0) {
387
                if (keepAliveTimeout > 0) {
388
                    socket.setSoTimeout(keepAliveTimeout);
388
                    socket.setSoTimeout(keepAliveTimeout);
389
                }
389
                }
390
                // Get first message of the request
390
                // Get first message of the request
391
                if (!readMessage(requestHeaderMessage)) {
391
                if (!readMessage(requestHeaderMessage)) {
392
                    // This means a connection timeout
392
                    // This means a connection timeout
393
                    rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
393
                    rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
394
                    break;
394
                    break;
395
                }
395
                }
396
                // Set back timeout if keep alive timeout is enabled
396
                // Set back timeout if keep alive timeout is enabled
397
                if (keepAliveTimeout > 0) {
397
                if (keepAliveTimeout > 0) {
398
                    socket.setSoTimeout(soTimeout);
398
                    socket.setSoTimeout(soTimeout);
399
                }
399
                }
400
                // Check message type, process right away and break if
400
                // Check message type, process right away and break if
401
                // not regular request processing
401
                // not regular request processing
402
                int type = requestHeaderMessage.getByte();
402
                int type = requestHeaderMessage.getByte();
403
                if (type == Constants.JK_AJP13_CPING_REQUEST) {
403
                if (type == Constants.JK_AJP13_CPING_REQUEST) {
404
                    try {
404
                    try {
405
                        output.write(pongMessageArray);
405
                        output.write(pongMessageArray);
406
                    } catch (IOException e) {
406
                    } catch (IOException e) {
407
                        error = true;
407
                        error = true;
408
                    }
408
                    }
409
                    continue;
409
                    continue;
410
                } else if(type != Constants.JK_AJP13_FORWARD_REQUEST) {
410
                } else if(type != Constants.JK_AJP13_FORWARD_REQUEST) {
411
                    // Usually the servlet didn't read the previous request body
411
                    // Usually the servlet didn't read the previous request body
412
                    if(log.isDebugEnabled()) {
412
                    if(log.isDebugEnabled()) {
413
                        log.debug("Unexpected message: "+type);
413
                        log.debug("Unexpected message: "+type);
414
                    }
414
                    }
415
                    continue;
415
                    continue;
416
                }
416
                }
417

    
   
417

   
418
                request.setStartTime(System.currentTimeMillis());
418
                request.setStartTime(System.currentTimeMillis());
419
            } catch (IOException e) {
419
            } catch (IOException e) {
420
                error = true;
420
                error = true;
421
                break;
421
                break;
422
            } catch (Throwable t) {
422
            } catch (Throwable t) {
423
                log.debug(sm.getString("ajpprocessor.header.error"), t);
423
                log.debug(sm.getString("ajpprocessor.header.error"), t);
424
                // 400 - Bad Request
424
                // 400 - Bad Request
425
                response.setStatus(400);
425
                response.setStatus(400);
426
                adapter.log(request, response, 0);
426
                adapter.log(request, response, 0);
427
                error = true;
427
                error = true;
428
            }
428
            }
429

    
   
429

   
430
            // Setting up filters, and parse some request headers
430
            // Setting up filters, and parse some request headers
431
            rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
431
            rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
432
            try {
432
            try {
433
                prepareRequest();
433
                prepareRequest();
434
            } catch (Throwable t) {
434
            } catch (Throwable t) {
435
                log.debug(sm.getString("ajpprocessor.request.prepare"), t);
435
                log.debug(sm.getString("ajpprocessor.request.prepare"), t);
436
                // 400 - Internal Server Error
436
                // 400 - Internal Server Error
437
                response.setStatus(400);
437
                response.setStatus(400);
438
                adapter.log(request, response, 0);
438
                adapter.log(request, response, 0);
439
                error = true;
439
                error = true;
440
            }
440
            }
441

    
   
441

   
442
            // Process the request in the adapter
442
            // Process the request in the adapter
443
            if (!error) {
443
            if (!error) {
444
                try {
444
                try {
445
                    rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
445
                    rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
446
                    adapter.service(request, response);
446
                    adapter.service(request, response);
447
                } catch (InterruptedIOException e) {
447
                } catch (InterruptedIOException e) {
448
                    error = true;
448
                    error = true;
449
                } catch (Throwable t) {
449
                } catch (Throwable t) {
450
                    log.error(sm.getString("ajpprocessor.request.process"), t);
450
                    log.error(sm.getString("ajpprocessor.request.process"), t);
451
                    // 500 - Internal Server Error
451
                    // 500 - Internal Server Error
452
                    response.setStatus(500);
452
                    response.setStatus(500);
453
                    adapter.log(request, response, 0);
453
                    adapter.log(request, response, 0);
454
                    error = true;
454
                    error = true;
455
                }
455
                }
456
            }
456
            }
457

    
   
457

   
458
            // Finish the response if not done yet
458
            // Finish the response if not done yet
459
            if (!finished) {
459
            if (!finished) {
460
                try {
460
                try {
461
                    finish();
461
                    finish();
462
                } catch (Throwable t) {
462
                } catch (Throwable t) {
463
                    error = true;
463
                    error = true;
464
                }
464
                }
465
            }
465
            }
466

    
   
466

   
467
            // If there was an error, make sure the request is counted as
467
            // If there was an error, make sure the request is counted as
468
            // and error, and update the statistics counter
468
            // and error, and update the statistics counter
469
            if (error) {
469
            if (error) {
470
                response.setStatus(500);
470
                response.setStatus(500);
471
            }
471
            }

    
   
472

   

    
   
473
            try {
472
            request.updateCounters();
474
                request.updateCounters();

    
   
475
            } catch (StringIndexOutOfBoundsException e) {

    
   
476
                log.error("Possible resolution increase AJP packetSize in server.xml see AJP configuration docs for details.", e);

    
   
477
                // 500 - Internal Server Error

    
   
478
                response.setStatus(500);

    
   
479
                adapter.log(request, response, 0);

    
   
480
                error = true;

    
   
481
            }
473

    
   
482

   
474
            rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
483
            rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
475
            recycle();
484
            recycle();
476

    
   
485

   
477
        }
486
        }
478

    
   
487

   
479
        rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
488
        rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
480
        recycle();
489
        recycle();
481
        input = null;
490
        input = null;
482
        output = null;
491
        output = null;
483
        
492
        
484
    }
493
    }
485

    
   
494

   
486

    
   
495

   
487
    // ----------------------------------------------------- ActionHook Methods
496
    // ----------------------------------------------------- ActionHook Methods
488

    
   
497

   
489

    
   
498

   
490
    /**
499
    /**
491
     * Send an action to the connector.
500
     * Send an action to the connector.
492
     *
501
     *
493
     * @param actionCode Type of the action
502
     * @param actionCode Type of the action
494
     * @param param Action parameter
503
     * @param param Action parameter
495
     */
504
     */
496
    public void action(ActionCode actionCode, Object param) {
505
    public void action(ActionCode actionCode, Object param) {
497

    
   
506

   
498
        if (actionCode == ActionCode.ACTION_COMMIT) {
507
        if (actionCode == ActionCode.ACTION_COMMIT) {
499

    
   
508

   
500
            if (response.isCommitted())
509
            if (response.isCommitted())
501
                return;
510
                return;
502

    
   
511

   
503
            // Validate and write response headers
512
            // Validate and write response headers
504
            try {
513
            try {
505
                prepareResponse();
514
                prepareResponse();
506
            } catch (IOException e) {
515
            } catch (IOException e) {
507
                // Set error flag
516
                // Set error flag
508
                error = true;
517
                error = true;
509
            }
518
            }
510

    
   
519

   
511
        } else if (actionCode == ActionCode.ACTION_CLIENT_FLUSH) {
520
        } else if (actionCode == ActionCode.ACTION_CLIENT_FLUSH) {
512

    
   
521

   
513
            if (!response.isCommitted()) {
522
            if (!response.isCommitted()) {
514
                // Validate and write response headers
523
                // Validate and write response headers
515
                try {
524
                try {
516
                    prepareResponse();
525
                    prepareResponse();
517
                } catch (IOException e) {
526
                } catch (IOException e) {
518
                    // Set error flag
527
                    // Set error flag
519
                    error = true;
528
                    error = true;
520
                    return;
529
                    return;
521
                }
530
                }
522
            }
531
            }
523

    
   
532

   
524
            try {
533
            try {
525
                flush();
534
                flush();
526
            } catch (IOException e) {
535
            } catch (IOException e) {
527
                // Set error flag
536
                // Set error flag
528
                error = true;
537
                error = true;
529
            }
538
            }
530

    
   
539

   
531
        } else if (actionCode == ActionCode.ACTION_CLOSE) {
540
        } else if (actionCode == ActionCode.ACTION_CLOSE) {
532
            // Close
541
            // Close
533

    
   
542

   
534
            // End the processing of the current request, and stop any further
543
            // End the processing of the current request, and stop any further
535
            // transactions with the client
544
            // transactions with the client
536

    
   
545

   
537
            try {
546
            try {
538
                finish();
547
                finish();
539
            } catch (IOException e) {
548
            } catch (IOException e) {
540
                // Set error flag
549
                // Set error flag
541
                error = true;
550
                error = true;
542
            }
551
            }
543

    
   
552

   
544
        } else if (actionCode == ActionCode.ACTION_START) {
553
        } else if (actionCode == ActionCode.ACTION_START) {
545

    
   
554

   
546
            started = true;
555
            started = true;
547

    
   
556

   
548
        } else if (actionCode == ActionCode.ACTION_STOP) {
557
        } else if (actionCode == ActionCode.ACTION_STOP) {
549

    
   
558

   
550
            started = false;
559
            started = false;
551

    
   
560

   
552
        } else if (actionCode == ActionCode.ACTION_REQ_SSL_ATTRIBUTE ) {
561
        } else if (actionCode == ActionCode.ACTION_REQ_SSL_ATTRIBUTE ) {
553

    
   
562

   
554
            if (!certificates.isNull()) {
563
            if (!certificates.isNull()) {
555
                ByteChunk certData = certificates.getByteChunk();
564
                ByteChunk certData = certificates.getByteChunk();
556
                X509Certificate jsseCerts[] = null;
565
                X509Certificate jsseCerts[] = null;
557
                ByteArrayInputStream bais =
566
                ByteArrayInputStream bais =
558
                    new ByteArrayInputStream(certData.getBytes(),
567
                    new ByteArrayInputStream(certData.getBytes(),
559
                            certData.getStart(),
568
                            certData.getStart(),
560
                            certData.getLength());
569
                            certData.getLength());
561
                // Fill the elements.
570
                // Fill the elements.
562
                try {
571
                try {
563
                    CertificateFactory cf =
572
                    CertificateFactory cf =
564
                        CertificateFactory.getInstance("X.509");
573
                        CertificateFactory.getInstance("X.509");
565
                    while(bais.available() > 0) {
574
                    while(bais.available() > 0) {
566
                        X509Certificate cert = (X509Certificate)
575
                        X509Certificate cert = (X509Certificate)
567
                            cf.generateCertificate(bais);
576
                            cf.generateCertificate(bais);
568
                        if(jsseCerts == null) {
577
                        if(jsseCerts == null) {
569
                            jsseCerts = new X509Certificate[1];
578
                            jsseCerts = new X509Certificate[1];
570
                            jsseCerts[0] = cert;
579
                            jsseCerts[0] = cert;
571
                        } else {
580
                        } else {
572
                            X509Certificate [] temp = new X509Certificate[jsseCerts.length+1];
581
                            X509Certificate [] temp = new X509Certificate[jsseCerts.length+1];
573
                            System.arraycopy(jsseCerts,0,temp,0,jsseCerts.length);
582
                            System.arraycopy(jsseCerts,0,temp,0,jsseCerts.length);
574
                            temp[jsseCerts.length] = cert;
583
                            temp[jsseCerts.length] = cert;
575
                            jsseCerts = temp;
584
                            jsseCerts = temp;
576
                        }
585
                        }
577
                    }
586
                    }
578
                } catch (java.security.cert.CertificateException e) {
587
                } catch (java.security.cert.CertificateException e) {
579
                    log.error(sm.getString("ajpprocessor.certs.fail"), e);
588
                    log.error(sm.getString("ajpprocessor.certs.fail"), e);
580
                    return;
589
                    return;
581
                }
590
                }
582
                request.setAttribute(JIoEndpoint.CERTIFICATE_KEY, jsseCerts);
591
                request.setAttribute(JIoEndpoint.CERTIFICATE_KEY, jsseCerts);
583
            }
592
            }
584

    
   
593

   
585
        } else if (actionCode == ActionCode.ACTION_REQ_HOST_ATTRIBUTE) {
594
        } else if (actionCode == ActionCode.ACTION_REQ_HOST_ATTRIBUTE) {
586

    
   
595

   
587
            // Get remote host name using a DNS resolution
596
            // Get remote host name using a DNS resolution
588
            if (request.remoteHost().isNull()) {
597
            if (request.remoteHost().isNull()) {
589
                try {
598
                try {
590
                    request.remoteHost().setString(InetAddress.getByName
599
                    request.remoteHost().setString(InetAddress.getByName
591
                            (request.remoteAddr().toString()).getHostName());
600
                            (request.remoteAddr().toString()).getHostName());
592
                } catch (IOException iex) {
601
                } catch (IOException iex) {
593
                    // Ignore
602
                    // Ignore
594
                }
603
                }
595
            }
604
            }
596

    
   
605

   
597
        } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_ADDR_ATTRIBUTE) {
606
        } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_ADDR_ATTRIBUTE) {
598

    
   
607

   
599
            // Copy from local name for now, which should simply be an address
608
            // Copy from local name for now, which should simply be an address
600
            request.localAddr().setString(request.localName().toString());
609
            request.localAddr().setString(request.localName().toString());
601

    
   
610

   
602
        } else if (actionCode == ActionCode.ACTION_REQ_SET_BODY_REPLAY) {
611
        } else if (actionCode == ActionCode.ACTION_REQ_SET_BODY_REPLAY) {
603

    
   
612

   
604
            // Set the given bytes as the content
613
            // Set the given bytes as the content
605
            ByteChunk bc = (ByteChunk) param;
614
            ByteChunk bc = (ByteChunk) param;
606
            int length = bc.getLength();
615
            int length = bc.getLength();
607
            bodyBytes.setBytes(bc.getBytes(), bc.getStart(), length);
616
            bodyBytes.setBytes(bc.getBytes(), bc.getStart(), length);
608
            request.setContentLength(length);
617
            request.setContentLength(length);
609
            first = false;
618
            first = false;
610
            empty = false;
619
            empty = false;
611
            replay = true;
620
            replay = true;
612

    
   
621

   
613
        }
622
        }
614

    
   
623

   
615

    
   
624

   
616
    }
625
    }
617

    
   
626

   
618

    
   
627

   
619
    // ------------------------------------------------------ Connector Methods
628
    // ------------------------------------------------------ Connector Methods
620

    
   
629

   
621

    
   
630

   
622
    /**
631
    /**
623
     * Set the associated adapter.
632
     * Set the associated adapter.
624
     *
633
     *
625
     * @param adapter the new adapter
634
     * @param adapter the new adapter
626
     */
635
     */
627
    public void setAdapter(Adapter adapter) {
636
    public void setAdapter(Adapter adapter) {
628
        this.adapter = adapter;
637
        this.adapter = adapter;
629
    }
638
    }
630

    
   
639

   
631

    
   
640

   
632
    /**
641
    /**
633
     * Get the associated adapter.
642
     * Get the associated adapter.
634
     *
643
     *
635
     * @return the associated adapter
644
     * @return the associated adapter
636
     */
645
     */
637
    public Adapter getAdapter() {
646
    public Adapter getAdapter() {
638
        return adapter;
647
        return adapter;
639
    }
648
    }
640

    
   
649

   
641

    
   
650

   
642
    // ------------------------------------------------------ Protected Methods
651
    // ------------------------------------------------------ Protected Methods
643

    
   
652

   
644

    
   
653

   
645
    /**
654
    /**
646
     * After reading the request headers, we have to setup the request filters.
655
     * After reading the request headers, we have to setup the request filters.
647
     */
656
     */
648
    protected void prepareRequest() {
657
    protected void prepareRequest() {
649

    
   
658

   
650
        // Translate the HTTP method code to a String.
659
        // Translate the HTTP method code to a String.
651
        byte methodCode = requestHeaderMessage.getByte();
660
        byte methodCode = requestHeaderMessage.getByte();
652
        if (methodCode != Constants.SC_M_JK_STORED) {
661
        if (methodCode != Constants.SC_M_JK_STORED) {
653
            String methodName = Constants.methodTransArray[(int)methodCode - 1];
662
            String methodName = Constants.methodTransArray[(int)methodCode - 1];
654
            request.method().setString(methodName);
663
            request.method().setString(methodName);
655
        }
664
        }
656

    
   
665

   
657
        requestHeaderMessage.getBytes(request.protocol());
666
        requestHeaderMessage.getBytes(request.protocol());
658
        requestHeaderMessage.getBytes(request.requestURI());
667
        requestHeaderMessage.getBytes(request.requestURI());
659

    
   
668

   
660
        requestHeaderMessage.getBytes(request.remoteAddr());
669
        requestHeaderMessage.getBytes(request.remoteAddr());
661
        requestHeaderMessage.getBytes(request.remoteHost());
670
        requestHeaderMessage.getBytes(request.remoteHost());
662
        requestHeaderMessage.getBytes(request.localName());
671
        requestHeaderMessage.getBytes(request.localName());
663
        request.setLocalPort(requestHeaderMessage.getInt());
672
        request.setLocalPort(requestHeaderMessage.getInt());
664

    
   
673

   
665
        boolean isSSL = requestHeaderMessage.getByte() != 0;
674
        boolean isSSL = requestHeaderMessage.getByte() != 0;
666
        if (isSSL) {
675
        if (isSSL) {
667
            request.scheme().setString("https");
676
            request.scheme().setString("https");
668
        }
677
        }
669

    
   
678

   
670
        // Decode headers
679
        // Decode headers
671
        MimeHeaders headers = request.getMimeHeaders();
680
        MimeHeaders headers = request.getMimeHeaders();
672

    
   
681

   
673
        int hCount = requestHeaderMessage.getInt();
682
        int hCount = requestHeaderMessage.getInt();
674
        for(int i = 0 ; i < hCount ; i++) {
683
        for(int i = 0 ; i < hCount ; i++) {
675
            String hName = null;
684
            String hName = null;
676

    
   
685

   
677
            // Header names are encoded as either an integer code starting
686
            // Header names are encoded as either an integer code starting
678
            // with 0xA0, or as a normal string (in which case the first
687
            // with 0xA0, or as a normal string (in which case the first
679
            // two bytes are the length).
688
            // two bytes are the length).
680
            int isc = requestHeaderMessage.peekInt();
689
            int isc = requestHeaderMessage.peekInt();
681
            int hId = isc & 0xFF;
690
            int hId = isc & 0xFF;
682

    
   
691

   
683
            MessageBytes vMB = null;
692
            MessageBytes vMB = null;
684
            isc &= 0xFF00;
693
            isc &= 0xFF00;
685
            if(0xA000 == isc) {
694
            if(0xA000 == isc) {
686
                requestHeaderMessage.getInt(); // To advance the read position
695
                requestHeaderMessage.getInt(); // To advance the read position
687
                hName = Constants.headerTransArray[hId - 1];
696
                hName = Constants.headerTransArray[hId - 1];
688
                vMB = headers.addValue(hName);
697
                vMB = headers.addValue(hName);
689
            } else {
698
            } else {
690
                // reset hId -- if the header currently being read
699
                // reset hId -- if the header currently being read
691
                // happens to be 7 or 8 bytes long, the code below
700
                // happens to be 7 or 8 bytes long, the code below
692
                // will think it's the content-type header or the
701
                // will think it's the content-type header or the
693
                // content-length header - SC_REQ_CONTENT_TYPE=7,
702
                // content-length header - SC_REQ_CONTENT_TYPE=7,
694
                // SC_REQ_CONTENT_LENGTH=8 - leading to unexpected
703
                // SC_REQ_CONTENT_LENGTH=8 - leading to unexpected
695
                // behaviour.  see bug 5861 for more information.
704
                // behaviour.  see bug 5861 for more information.
696
                hId = -1;
705
                hId = -1;
697
                requestHeaderMessage.getBytes(tmpMB);
706
                requestHeaderMessage.getBytes(tmpMB);
698
                ByteChunk bc = tmpMB.getByteChunk();
707
                ByteChunk bc = tmpMB.getByteChunk();
699
                vMB = headers.addValue(bc.getBuffer(),
708
                vMB = headers.addValue(bc.getBuffer(),
700
                        bc.getStart(), bc.getLength());
709
                        bc.getStart(), bc.getLength());
701
            }
710
            }
702

    
   
711

   
703
            requestHeaderMessage.getBytes(vMB);
712
            requestHeaderMessage.getBytes(vMB);
704

    
   
713

   
705
            if (hId == Constants.SC_REQ_CONTENT_LENGTH ||
714
            if (hId == Constants.SC_REQ_CONTENT_LENGTH ||
706
                    (hId == -1 && tmpMB.equalsIgnoreCase("Content-Length"))) {
715
                    (hId == -1 && tmpMB.equalsIgnoreCase("Content-Length"))) {
707
                // just read the content-length header, so set it
716
                // just read the content-length header, so set it
708
                long cl = vMB.getLong();
717
                long cl = vMB.getLong();
709
                if(cl < Integer.MAX_VALUE)
718
                if(cl < Integer.MAX_VALUE)
710
                    request.setContentLength( (int)cl );
719
                    request.setContentLength( (int)cl );
711
            } else if (hId == Constants.SC_REQ_CONTENT_TYPE ||
720
            } else if (hId == Constants.SC_REQ_CONTENT_TYPE ||
712
                    (hId == -1 && tmpMB.equalsIgnoreCase("Content-Type"))) {
721
                    (hId == -1 && tmpMB.equalsIgnoreCase("Content-Type"))) {
713
                // just read the content-type header, so set it
722
                // just read the content-type header, so set it
714
                ByteChunk bchunk = vMB.getByteChunk();
723
                ByteChunk bchunk = vMB.getByteChunk();
715
                request.contentType().setBytes(bchunk.getBytes(),
724
                request.contentType().setBytes(bchunk.getBytes(),
716
                        bchunk.getOffset(),
725
                        bchunk.getOffset(),
717
                        bchunk.getLength());
726
                        bchunk.getLength());
718
            }
727
            }
719
        }
728
        }
720

    
   
729

   
721
        // Decode extra attributes
730
        // Decode extra attributes
722
        boolean secret = false;
731
        boolean secret = false;
723
        byte attributeCode;
732
        byte attributeCode;
724
        while ((attributeCode = requestHeaderMessage.getByte())
733
        while ((attributeCode = requestHeaderMessage.getByte())
725
                != Constants.SC_A_ARE_DONE) {
734
                != Constants.SC_A_ARE_DONE) {
726

    
   
735

   
727
            switch (attributeCode) {
736
            switch (attributeCode) {
728

    
   
737

   
729
            case Constants.SC_A_REQ_ATTRIBUTE :
738
            case Constants.SC_A_REQ_ATTRIBUTE :
730
                requestHeaderMessage.getBytes(tmpMB);
739
                requestHeaderMessage.getBytes(tmpMB);
731
                String n = tmpMB.toString();
740
                String n = tmpMB.toString();
732
                requestHeaderMessage.getBytes(tmpMB);
741
                requestHeaderMessage.getBytes(tmpMB);
733
                String v = tmpMB.toString();
742
                String v = tmpMB.toString();
734
                /*
743
                /*
735
                 * AJP13 misses to forward the remotePort.
744
                 * AJP13 misses to forward the remotePort.
736
                 * Allow the AJP connector to add this info via
745
                 * Allow the AJP connector to add this info via
737
                 * a private request attribute.
746
                 * a private request attribute.
738
                 * We will accept the forwarded data as the remote port,
747
                 * We will accept the forwarded data as the remote port,
739
                 * and remove it from the public list of request attributes.
748
                 * and remove it from the public list of request attributes.
740
                 */
749
                 */
741
                if(n.equals(Constants.SC_A_REQ_REMOTE_PORT)) {
750
                if(n.equals(Constants.SC_A_REQ_REMOTE_PORT)) {
742
                    try {
751
                    try {
743
                        request.setRemotePort(Integer.parseInt(v));
752
                        request.setRemotePort(Integer.parseInt(v));
744
                    } catch (NumberFormatException nfe) {
753
                    } catch (NumberFormatException nfe) {
745
                    }
754
                    }
746
                } else {
755
                } else {
747
                    request.setAttribute(n, v );
756
                    request.setAttribute(n, v );
748
                }
757
                }
749
                break;
758
                break;
750

    
   
759

   
751
            case Constants.SC_A_CONTEXT :
760
            case Constants.SC_A_CONTEXT :
752
                requestHeaderMessage.getBytes(tmpMB);
761
                requestHeaderMessage.getBytes(tmpMB);
753
                // nothing
762
                // nothing
754
                break;
763
                break;
755

    
   
764

   
756
            case Constants.SC_A_SERVLET_PATH :
765
            case Constants.SC_A_SERVLET_PATH :
757
                requestHeaderMessage.getBytes(tmpMB);
766
                requestHeaderMessage.getBytes(tmpMB);
758
                // nothing
767
                // nothing
759
                break;
768
                break;
760

    
   
769

   
761
            case Constants.SC_A_REMOTE_USER :
770
            case Constants.SC_A_REMOTE_USER :
762
                if (tomcatAuthentication) {
771
                if (tomcatAuthentication) {
763
                    // ignore server
772
                    // ignore server
764
                    requestHeaderMessage.getBytes(tmpMB);
773
                    requestHeaderMessage.getBytes(tmpMB);
765
                } else {
774
                } else {
766
                    requestHeaderMessage.getBytes(request.getRemoteUser());
775
                    requestHeaderMessage.getBytes(request.getRemoteUser());
767
                }
776
                }
768
                break;
777
                break;
769

    
   
778

   
770
            case Constants.SC_A_AUTH_TYPE :
779
            case Constants.SC_A_AUTH_TYPE :
771
                if (tomcatAuthentication) {
780
                if (tomcatAuthentication) {
772
                    // ignore server
781
                    // ignore server
773
                    requestHeaderMessage.getBytes(tmpMB);
782
                    requestHeaderMessage.getBytes(tmpMB);
774
                } else {
783
                } else {
775
                    requestHeaderMessage.getBytes(request.getAuthType());
784
                    requestHeaderMessage.getBytes(request.getAuthType());
776
                }
785
                }
777
                break;
786
                break;
778

    
   
787

   
779
            case Constants.SC_A_QUERY_STRING :
788
            case Constants.SC_A_QUERY_STRING :
780
                requestHeaderMessage.getBytes(request.queryString());
789
                requestHeaderMessage.getBytes(request.queryString());
781
                break;
790
                break;
782

    
   
791

   
783
            case Constants.SC_A_JVM_ROUTE :
792
            case Constants.SC_A_JVM_ROUTE :
784
                requestHeaderMessage.getBytes(request.instanceId());
793
                requestHeaderMessage.getBytes(request.instanceId());
785
                break;
794
                break;
786

    
   
795

   
787
            case Constants.SC_A_SSL_CERT :
796
            case Constants.SC_A_SSL_CERT :
788
                request.scheme().setString("https");
797
                request.scheme().setString("https");
789
                // SSL certificate extraction is lazy, moved to JkCoyoteHandler
798
                // SSL certificate extraction is lazy, moved to JkCoyoteHandler
790
                requestHeaderMessage.getBytes(certificates);
799
                requestHeaderMessage.getBytes(certificates);
791
                break;
800
                break;
792

    
   
801

   
793
            case Constants.SC_A_SSL_CIPHER :
802
            case Constants.SC_A_SSL_CIPHER :
794
                request.scheme().setString("https");
803
                request.scheme().setString("https");
795
                requestHeaderMessage.getBytes(tmpMB);
804
                requestHeaderMessage.getBytes(tmpMB);
796
                request.setAttribute(JIoEndpoint.CIPHER_SUITE_KEY,
805
                request.setAttribute(JIoEndpoint.CIPHER_SUITE_KEY,
797
                                     tmpMB.toString());
806
                                     tmpMB.toString());
798
                break;
807
                break;
799

    
   
808

   
800
            case Constants.SC_A_SSL_SESSION :
809
            case Constants.SC_A_SSL_SESSION :
801
                request.scheme().setString("https");
810
                request.scheme().setString("https");
802
                requestHeaderMessage.getBytes(tmpMB);
811
                requestHeaderMessage.getBytes(tmpMB);
803
                request.setAttribute(JIoEndpoint.SESSION_ID_KEY,
812
                request.setAttribute(JIoEndpoint.SESSION_ID_KEY,
804
                                     tmpMB.toString());
813
                                     tmpMB.toString());
805
                break;
814
                break;
806

    
   
815

   
807
            case Constants.SC_A_SSL_KEY_SIZE :
816
            case Constants.SC_A_SSL_KEY_SIZE :
808
                request.setAttribute(JIoEndpoint.KEY_SIZE_KEY,
817
                request.setAttribute(JIoEndpoint.KEY_SIZE_KEY,
809
                                     new Integer(requestHeaderMessage.getInt()));
818
                                     new Integer(requestHeaderMessage.getInt()));
810
                break;
819
                break;
811

    
   
820

   
812
            case Constants.SC_A_STORED_METHOD:
821
            case Constants.SC_A_STORED_METHOD:
813
                requestHeaderMessage.getBytes(request.method());
822
                requestHeaderMessage.getBytes(request.method());
814
                break;
823
                break;
815

    
   
824

   
816
            case Constants.SC_A_SECRET:
825
            case Constants.SC_A_SECRET:
817
                requestHeaderMessage.getBytes(tmpMB);
826
                requestHeaderMessage.getBytes(tmpMB);
818
                if (requiredSecret != null) {
827
                if (requiredSecret != null) {
819
                    secret = true;
828
                    secret = true;
820
                    if (!tmpMB.equals(requiredSecret)) {
829
                    if (!tmpMB.equals(requiredSecret)) {
821
                        response.setStatus(403);
830
                        response.setStatus(403);
822
                        adapter.log(request, response, 0);
831
                        adapter.log(request, response, 0);
823
                        error = true;
832
                        error = true;
824
                    }
833
                    }
825
                }
834
                }
826
                break;
835
                break;
827

    
   
836

   
828
            default:
837
            default:
829
                // Ignore unknown attribute for backward compatibility
838
                // Ignore unknown attribute for backward compatibility
830
                break;
839
                break;
831

    
   
840

   
832
            }
841
            }
833

    
   
842

   
834
        }
843
        }
835

    
   
844

   
836
        // Check if secret was submitted if required
845
        // Check if secret was submitted if required
837
        if ((requiredSecret != null) && !secret) {
846
        if ((requiredSecret != null) && !secret) {
838
            response.setStatus(403);
847
            response.setStatus(403);
839
            adapter.log(request, response, 0);
848
            adapter.log(request, response, 0);
840
            error = true;
849
            error = true;
841
        }
850
        }
842

    
   
851

   
843
        // Check for a full URI (including protocol://host:port/)
852
        // Check for a full URI (including protocol://host:port/)
844
        ByteChunk uriBC = request.requestURI().getByteChunk();
853
        ByteChunk uriBC = request.requestURI().getByteChunk();
845
        if (uriBC.startsWithIgnoreCase("http", 0)) {
854
        if (uriBC.startsWithIgnoreCase("http", 0)) {
846

    
   
855

   
847
            int pos = uriBC.indexOf("://", 0, 3, 4);
856
            int pos = uriBC.indexOf("://", 0, 3, 4);
848
            int uriBCStart = uriBC.getStart();
857
            int uriBCStart = uriBC.getStart();
849
            int slashPos = -1;
858
            int slashPos = -1;
850
            if (pos != -1) {
859
            if (pos != -1) {
851
                byte[] uriB = uriBC.getBytes();
860
                byte[] uriB = uriBC.getBytes();
852
                slashPos = uriBC.indexOf('/', pos + 3);
861
                slashPos = uriBC.indexOf('/', pos + 3);
853
                if (slashPos == -1) {
862
                if (slashPos == -1) {
854
                    slashPos = uriBC.getLength();
863
                    slashPos = uriBC.getLength();
855
                    // Set URI as "/"
864
                    // Set URI as "/"
856
                    request.requestURI().setBytes
865
                    request.requestURI().setBytes
857
                        (uriB, uriBCStart + pos + 1, 1);
866
                        (uriB, uriBCStart + pos + 1, 1);
858
                } else {
867
                } else {
859
                    request.requestURI().setBytes
868
                    request.requestURI().setBytes
860
                        (uriB, uriBCStart + slashPos,
869
                        (uriB, uriBCStart + slashPos,
861
                         uriBC.getLength() - slashPos);
870
                         uriBC.getLength() - slashPos);
862
                }
871
                }
863
                MessageBytes hostMB = headers.setValue("host");
872
                MessageBytes hostMB = headers.setValue("host");
864
                hostMB.setBytes(uriB, uriBCStart + pos + 3,
873
                hostMB.setBytes(uriB, uriBCStart + pos + 3,
865
                                slashPos - pos - 3);
874
                                slashPos - pos - 3);
866
            }
875
            }
867

    
   
876

   
868
        }
877
        }
869

    
   
878

   
870
        MessageBytes valueMB = request.getMimeHeaders().getValue("host");
879
        MessageBytes valueMB = request.getMimeHeaders().getValue("host");
871
        parseHost(valueMB);
880
        parseHost(valueMB);
872

    
   
881

   
873
    }
882
    }
874

    
   
883

   
875

    
   
884

   
876
    /**
885
    /**
877
     * Parse host.
886
     * Parse host.
878
     */
887
     */
879
    public void parseHost(MessageBytes valueMB) {
888
    public void parseHost(MessageBytes valueMB) {
880

    
   
889

   
881
        if (valueMB == null || (valueMB != null && valueMB.isNull()) ) {
890
        if (valueMB == null || (valueMB != null && valueMB.isNull()) ) {
882
            // HTTP/1.0
891
            // HTTP/1.0
883
            request.setServerPort(request.getLocalPort());
892
            request.setServerPort(request.getLocalPort());
884
            try {
893
            try {
885
                request.serverName().duplicate(request.localName());
894
                request.serverName().duplicate(request.localName());
886
            } catch (IOException e) {
895
            } catch (IOException e) {
887
                response.setStatus(400);
896
                response.setStatus(400);
888
                adapter.log(request, response, 0);
897
                adapter.log(request, response, 0);
889
                error = true;
898
                error = true;
890
            }
899
            }
891
            return;
900
            return;
892
        }
901
        }
893

    
   
902

   
894
        ByteChunk valueBC = valueMB.getByteChunk();
903
        ByteChunk valueBC = valueMB.getByteChunk();
895
        byte[] valueB = valueBC.getBytes();
904
        byte[] valueB = valueBC.getBytes();
896
        int valueL = valueBC.getLength();
905
        int valueL = valueBC.getLength();
897
        int valueS = valueBC.getStart();
906
        int valueS = valueBC.getStart();
898
        int colonPos = -1;
907
        int colonPos = -1;
899
        if (hostNameC.length < valueL) {
908
        if (hostNameC.length < valueL) {
900
            hostNameC = new char[valueL];
909
            hostNameC = new char[valueL];
901
        }
910
        }
902

    
   
911

   
903
        boolean ipv6 = (valueB[valueS] == '[');
912
        boolean ipv6 = (valueB[valueS] == '[');
904
        boolean bracketClosed = false;
913
        boolean bracketClosed = false;
905
        for (int i = 0; i < valueL; i++) {
914
        for (int i = 0; i < valueL; i++) {
906
            char b = (char) valueB[i + valueS];
915
            char b = (char) valueB[i + valueS];
907
            hostNameC[i] = b;
916
            hostNameC[i] = b;
908
            if (b == ']') {
917
            if (b == ']') {
909
                bracketClosed = true;
918
                bracketClosed = true;
910
            } else if (b == ':') {
919
            } else if (b == ':') {
911
                if (!ipv6 || bracketClosed) {
920
                if (!ipv6 || bracketClosed) {
912
                    colonPos = i;
921
                    colonPos = i;
913
                    break;
922
                    break;
914
                }
923
                }
915
            }
924
            }
916
        }
925
        }
917

    
   
926

   
918
        if (colonPos < 0) {
927
        if (colonPos < 0) {
919
            if (request.scheme().equalsIgnoreCase("https")) {
928
            if (request.scheme().equalsIgnoreCase("https")) {
920
                // 443 - Default HTTPS port
929
                // 443 - Default HTTPS port
921
                request.setServerPort(443);
930
                request.setServerPort(443);
922
            } else {
931
            } else {
923
                // 80 - Default HTTTP port
932
                // 80 - Default HTTTP port
924
                request.setServerPort(80);
933
                request.setServerPort(80);
925
            }
934
            }
926
            request.serverName().setChars(hostNameC, 0, valueL);
935
            request.serverName().setChars(hostNameC, 0, valueL);
927
        } else {
936
        } else {
928

    
   
937

   
929
            request.serverName().setChars(hostNameC, 0, colonPos);
938
            request.serverName().setChars(hostNameC, 0, colonPos);
930

    
   
939

   
931
            int port = 0;
940
            int port = 0;
932
            int mult = 1;
941
            int mult = 1;
933
            for (int i = valueL - 1; i > colonPos; i--) {
942
            for (int i = valueL - 1; i > colonPos; i--) {
934
                int charValue = HexUtils.DEC[(int) valueB[i + valueS]];
943
                int charValue = HexUtils.DEC[(int) valueB[i + valueS]];
935
                if (charValue == -1) {
944
                if (charValue == -1) {
936
                    // Invalid character
945
                    // Invalid character
937
                    error = true;
946
                    error = true;
938
                    // 400 - Bad request
947
                    // 400 - Bad request
939
                    response.setStatus(400);
948
                    response.setStatus(400);
940
                    adapter.log(request, response, 0);
949
                    adapter.log(request, response, 0);
941
                    break;
950
                    break;
942
                }
951
                }
943
                port = port + (charValue * mult);
952
                port = port + (charValue * mult);
944
                mult = 10 * mult;
953
                mult = 10 * mult;
945
            }
954
            }
946
            request.setServerPort(port);
955
            request.setServerPort(port);
947

    
   
956

   
948
        }
957
        }
949

    
   
958

   
950
    }
959
    }
951

    
   
960

   
952

    
   
961

   
953
    /**
962
    /**
954
     * When committing the response, we have to validate the set of headers, as
963
     * When committing the response, we have to validate the set of headers, as
955
     * well as setup the response filters.
964
     * well as setup the response filters.
956
     */
965
     */
957
    protected void prepareResponse()
966
    protected void prepareResponse()
958
        throws IOException {
967
        throws IOException {
959

    
   
968

   
960
        response.setCommitted(true);
969
        response.setCommitted(true);
961

    
   
970

   
962
        responseHeaderMessage.reset();
971
        responseHeaderMessage.reset();
963
        responseHeaderMessage.appendByte(Constants.JK_AJP13_SEND_HEADERS);
972
        responseHeaderMessage.appendByte(Constants.JK_AJP13_SEND_HEADERS);
964

    
   
973

   
965
        // HTTP header contents
974
        // HTTP header contents
966
        responseHeaderMessage.appendInt(response.getStatus());
975
        responseHeaderMessage.appendInt(response.getStatus());
967
        String message = null;
976
        String message = null;
968
        if (org.apache.coyote.Constants.USE_CUSTOM_STATUS_MSG_IN_HEADER &&
977
        if (org.apache.coyote.Constants.USE_CUSTOM_STATUS_MSG_IN_HEADER &&
969
                HttpMessages.isSafeInHttpHeader(response.getMessage())) {
978
                HttpMessages.isSafeInHttpHeader(response.getMessage())) {
970
            message = response.getMessage();
979
            message = response.getMessage();
971
        }
980
        }
972
        if (message == null){
981
        if (message == null){
973
            message = HttpMessages.getMessage(response.getStatus());
982
            message = HttpMessages.getMessage(response.getStatus());
974
        }
983
        }
975
        if (message == null) {
984
        if (message == null) {
976
            // mod_jk + httpd 2.x fails with a null status message - bug 45026
985
            // mod_jk + httpd 2.x fails with a null status message - bug 45026
977
            message = Integer.toString(response.getStatus());
986
            message = Integer.toString(response.getStatus());
978
        }
987
        }
979
        tmpMB.setString(message);
988
        tmpMB.setString(message);
980
        responseHeaderMessage.appendBytes(tmpMB);
989
        responseHeaderMessage.appendBytes(tmpMB);
981

    
   
990

   
982
        // Special headers
991
        // Special headers
983
        MimeHeaders headers = response.getMimeHeaders();
992
        MimeHeaders headers = response.getMimeHeaders();
984
        String contentType = response.getContentType();
993
        String contentType = response.getContentType();
985
        if (contentType != null) {
994
        if (contentType != null) {
986
            headers.setValue("Content-Type").setString(contentType);
995
            headers.setValue("Content-Type").setString(contentType);
987
        }
996
        }
988
        String contentLanguage = response.getContentLanguage();
997
        String contentLanguage = response.getContentLanguage();
989
        if (contentLanguage != null) {
998
        if (contentLanguage != null) {
990
            headers.setValue("Content-Language").setString(contentLanguage);
999
            headers.setValue("Content-Language").setString(contentLanguage);
991
        }
1000
        }
992
        long contentLength = response.getContentLengthLong();
1001
        long contentLength = response.getContentLengthLong();
993
        if (contentLength >= 0) {
1002
        if (contentLength >= 0) {
994
            headers.setValue("Content-Length").setLong(contentLength);
1003
            headers.setValue("Content-Length").setLong(contentLength);
995
        }
1004
        }
996

    
   
1005

   
997
        // Other headers
1006
        // Other headers
998
        int numHeaders = headers.size();
1007
        int numHeaders = headers.size();
999
        responseHeaderMessage.appendInt(numHeaders);
1008
        responseHeaderMessage.appendInt(numHeaders);
1000
        for (int i = 0; i < numHeaders; i++) {
1009
        for (int i = 0; i < numHeaders; i++) {
1001
            MessageBytes hN = headers.getName(i);
1010
            MessageBytes hN = headers.getName(i);
1002
            int hC = Constants.getResponseAjpIndex(hN.toString());
1011
            int hC = Constants.getResponseAjpIndex(hN.toString());
1003
            if (hC > 0) {
1012
            if (hC > 0) {
1004
                responseHeaderMessage.appendInt(hC);
1013
                responseHeaderMessage.appendInt(hC);
1005
            }
1014
            }
1006
            else {
1015
            else {
1007
                responseHeaderMessage.appendBytes(hN);
1016
                responseHeaderMessage.appendBytes(hN);
1008
            }
1017
            }
1009
            MessageBytes hV=headers.getValue(i);
1018
            MessageBytes hV=headers.getValue(i);
1010
            responseHeaderMessage.appendBytes(hV);
1019
            responseHeaderMessage.appendBytes(hV);
1011
        }
1020
        }
1012

    
   
1021

   
1013
        // Write to buffer
1022
        // Write to buffer
1014
        responseHeaderMessage.end();
1023
        responseHeaderMessage.end();
1015
        output.write(responseHeaderMessage.getBuffer(), 0, responseHeaderMessage.getLen());
1024
        output.write(responseHeaderMessage.getBuffer(), 0, responseHeaderMessage.getLen());
1016

    
   
1025

   
1017
    }
1026
    }
1018

    
   
1027

   
1019

    
   
1028

   
1020
    /**
1029
    /**
1021
     * Finish AJP response.
1030
     * Finish AJP response.
1022
     */
1031
     */
1023
    protected void finish()
1032
    protected void finish()
1024
        throws IOException {
1033
        throws IOException {
1025

    
   
1034

   
1026
        if (!response.isCommitted()) {
1035
        if (!response.isCommitted()) {
1027
            // Validate and write response headers
1036
            // Validate and write response headers
1028
            try {
1037
            try {
1029
                prepareResponse();
1038
                prepareResponse();
1030
            } catch (IOException e) {
1039
            } catch (IOException e) {
1031
                // Set error flag
1040
                // Set error flag
1032
                error = true;
1041
                error = true;
1033
            }
1042
            }
1034
        }
1043
        }
1035

    
   
1044

   
1036
        if (finished)
1045
        if (finished)
1037
            return;
1046
            return;
1038

    
   
1047

   
1039
        finished = true;
1048
        finished = true;
1040

    
   
1049

   
1041
        // Add the end message
1050
        // Add the end message
1042
        output.write(endMessageArray);
1051
        output.write(endMessageArray);
1043

    
   
1052

   
1044
    }
1053
    }
1045

    
   
1054

   
1046

    
   
1055

   
1047
    /**
1056
    /**
1048
     * Read at least the specified amount of bytes, and place them
1057
     * Read at least the specified amount of bytes, and place them
1049
     * in the input buffer.
1058
     * in the input buffer.
1050
     */
1059
     */
1051
    protected boolean read(byte[] buf, int pos, int n)
1060
    protected boolean read(byte[] buf, int pos, int n)
1052
        throws IOException {
1061
        throws IOException {
1053

    
   
1062

   
1054
        int read = 0;
1063
        int read = 0;
1055
        int res = 0;
1064
        int res = 0;
1056
        while (read < n) {
1065
        while (read < n) {
1057
            res = input.read(buf, read + pos, n - read);
1066
            res = input.read(buf, read + pos, n - read);
1058
            if (res > 0) {
1067
            if (res > 0) {
1059
                read += res;
1068
                read += res;
1060
            } else {
1069
            } else {
1061
                throw new IOException(sm.getString("ajpprotocol.failedread"));
1070
                throw new IOException(sm.getString("ajpprotocol.failedread"));
1062
            }
1071
            }
1063
        }
1072
        }
1064
        
1073
        
1065
        return true;
1074
        return true;
1066

    
   
1075

   
1067
    }
1076
    }
1068

    
   
1077

   
1069

    
   
1078

   
1070
    /** Receive a chunk of data. Called to implement the
1079
    /** Receive a chunk of data. Called to implement the
1071
     *  'special' packet in ajp13 and to receive the data
1080
     *  'special' packet in ajp13 and to receive the data
1072
     *  after we send a GET_BODY packet
1081
     *  after we send a GET_BODY packet
1073
     */
1082
     */
1074
    public boolean receive() throws IOException {
1083
    public boolean receive() throws IOException {
1075

    
   
1084

   
1076
        first = false;
1085
        first = false;
1077
        bodyMessage.reset();
1086
        bodyMessage.reset();
1078
        readMessage(bodyMessage);
1087
        readMessage(bodyMessage);
1079

    
   
1088

   
1080
        // No data received.
1089
        // No data received.
1081
        if (bodyMessage.getLen() == 0) {
1090
        if (bodyMessage.getLen() == 0) {
1082
            // just the header
1091
            // just the header
1083
            // Don't mark 'end of stream' for the first chunk.
1092
            // Don't mark 'end of stream' for the first chunk.
1084
            return false;
1093
            return false;
1085
        }
1094
        }
1086
        int blen = bodyMessage.peekInt();
1095
        int blen = bodyMessage.peekInt();
1087
        if (blen == 0) {
1096
        if (blen == 0) {
1088
            return false;
1097
            return false;
1089
        }
1098
        }
1090

    
   
1099

   
1091
        bodyMessage.getBytes(bodyBytes);
1100
        bodyMessage.getBytes(bodyBytes);
1092
        empty = false;
1101
        empty = false;
1093
        return true;
1102
        return true;
1094
    }
1103
    }
1095

    
   
1104

   
1096
    /**
1105
    /**
1097
     * Get more request body data from the web server and store it in the
1106
     * Get more request body data from the web server and store it in the
1098
     * internal buffer.
1107
     * internal buffer.
1099
     *
1108
     *
1100
     * @return true if there is more data, false if not.
1109
     * @return true if there is more data, false if not.
1101
     */
1110
     */
1102
    private boolean refillReadBuffer() throws IOException {
1111
    private boolean refillReadBuffer() throws IOException {
1103
        // If the server returns an empty packet, assume that that end of
1112
        // If the server returns an empty packet, assume that that end of
1104
        // the stream has been reached (yuck -- fix protocol??).
1113
        // the stream has been reached (yuck -- fix protocol??).
1105
        // FORM support
1114
        // FORM support
1106
        if (replay) {
1115
        if (replay) {
1107
            endOfStream = true; // we've read everything there is
1116
            endOfStream = true; // we've read everything there is
1108
        }
1117
        }
1109
        if (endOfStream) {
1118
        if (endOfStream) {
1110
            return false;
1119
            return false;
1111
        }
1120
        }
1112

    
   
1121

   
1113
        // Request more data immediately
1122
        // Request more data immediately
1114
        output.write(getBodyMessageArray);
1123
        output.write(getBodyMessageArray);
1115

    
   
1124

   
1116
        boolean moreData = receive();
1125
        boolean moreData = receive();
1117
        if( !moreData ) {
1126
        if( !moreData ) {
1118
            endOfStream = true;
1127
            endOfStream = true;
1119
        }
1128
        }
1120
        return moreData;
1129
        return moreData;
1121
    }
1130
    }
1122

    
   
1131

   
1123

    
   
1132

   
1124
    /**
1133
    /**
1125
     * Read an AJP message.
1134
     * Read an AJP message.
1126
     *
1135
     *
1127
     * @return true if the message has been read, false if the short read
1136
     * @return true if the message has been read, false if the short read
1128
     *         didn't return anything
1137
     *         didn't return anything
1129
     * @throws IOException any other failure, including incomplete reads
1138
     * @throws IOException any other failure, including incomplete reads
1130
     */
1139
     */
1131
    protected boolean readMessage(AjpMessage message)
1140
    protected boolean readMessage(AjpMessage message)
1132
        throws IOException {
1141
        throws IOException {
1133

    
   
1142

   
1134
        byte[] buf = message.getBuffer();
1143
        byte[] buf = message.getBuffer();
1135

    
   
1144

   
1136
        read(buf, 0, message.getHeaderLength());
1145
        read(buf, 0, message.getHeaderLength());
1137

    
   
1146

   
1138
        message.processHeader();
1147
        message.processHeader();
1139
        read(buf, message.getHeaderLength(), message.getLen());
1148
        read(buf, message.getHeaderLength(), message.getLen());
1140

    
   
1149

   
1141
        return true;
1150
        return true;
1142

    
   
1151

   
1143
    }
1152
    }
1144

    
   
1153

   
1145

    
   
1154

   
1146
    /**
1155
    /**
1147
     * Recycle the processor.
1156
     * Recycle the processor.
1148
     */
1157
     */
1149
    public void recycle() {
1158
    public void recycle() {
1150

    
   
1159

   
1151
        // Recycle Request object
1160
        // Recycle Request object
1152
        first = true;
1161
        first = true;
1153
        endOfStream = false;
1162
        endOfStream = false;
1154
        empty = true;
1163
        empty = true;
1155
        replay = false;
1164
        replay = false;
1156
        finished = false;
1165
        finished = false;
1157
        request.recycle();
1166
        request.recycle();
1158
        response.recycle();
1167
        response.recycle();
1159
        certificates.recycle();
1168
        certificates.recycle();
1160

    
   
1169

   
1161
    }
1170
    }
1162

    
   
1171

   
1163

    
   
1172

   
1164
    /**
1173
    /**
1165
     * Callback to write data from the buffer.
1174
     * Callback to write data from the buffer.
1166
     */
1175
     */
1167
    protected void flush()
1176
    protected void flush()
1168
        throws IOException {
1177
        throws IOException {
1169
        // Send the flush message
1178
        // Send the flush message
1170
        output.write(flushMessageArray);
1179
        output.write(flushMessageArray);
1171
    }
1180
    }
1172

    
   
1181

   
1173

    
   
1182

   
1174
    // ------------------------------------- InputStreamInputBuffer Inner Class
1183
    // ------------------------------------- InputStreamInputBuffer Inner Class
1175

    
   
1184

   
1176

    
   
1185

   
1177
    /**
1186
    /**
1178
     * This class is an input buffer which will read its data from an input
1187
     * This class is an input buffer which will read its data from an input
1179
     * stream.
1188
     * stream.
1180
     */
1189
     */
1181
    protected class SocketInputBuffer
1190
    protected class SocketInputBuffer
1182
        implements InputBuffer {
1191
        implements InputBuffer {
1183

    
   
1192

   
1184

    
   
1193

   
1185
        /**
1194
        /**
1186
         * Read bytes into the specified chunk.
1195
         * Read bytes into the specified chunk.
1187
         */
1196
         */
1188
        public int doRead(ByteChunk chunk, Request req )
1197
        public int doRead(ByteChunk chunk, Request req )
1189
            throws IOException {
1198
            throws IOException {
1190

    
   
1199

   
1191
            if (endOfStream) {
1200
            if (endOfStream) {
1192
                return -1;
1201
                return -1;
1193
            }
1202
            }
1194
            if (first && req.getContentLengthLong() > 0) {
1203
            if (first && req.getContentLengthLong() > 0) {
1195
                // Handle special first-body-chunk
1204
                // Handle special first-body-chunk
1196
                if (!receive()) {
1205
                if (!receive()) {
1197
                    return 0;
1206
                    return 0;
1198
                }
1207
                }
1199
            } else if (empty) {
1208
            } else if (empty) {
1200
                if (!refillReadBuffer()) {
1209
                if (!refillReadBuffer()) {
1201
                    return -1;
1210
                    return -1;
1202
                }
1211
                }
1203
            }
1212
            }
1204
            ByteChunk bc = bodyBytes.getByteChunk();
1213
            ByteChunk bc = bodyBytes.getByteChunk();
1205
            chunk.setBytes(bc.getBuffer(), bc.getStart(), bc.getLength());
1214
            chunk.setBytes(bc.getBuffer(), bc.getStart(), bc.getLength());
1206
            empty = true;
1215
            empty = true;
1207
            return chunk.getLength();
1216
            return chunk.getLength();
1208

    
   
1217

   
1209
        }
1218
        }
1210

    
   
1219

   
1211
    }
1220
    }
1212

    
   
1221

   
1213

    
   
1222

   
1214
    // ----------------------------------- OutputStreamOutputBuffer Inner Class
1223
    // ----------------------------------- OutputStreamOutputBuffer Inner Class
1215

    
   
1224

   
1216

    
   
1225

   
1217
    /**
1226
    /**
1218
     * This class is an output buffer which will write data to an output
1227
     * This class is an output buffer which will write data to an output
1219
     * stream.
1228
     * stream.
1220
     */
1229
     */
1221
    protected class SocketOutputBuffer
1230
    protected class SocketOutputBuffer
1222
        implements OutputBuffer {
1231
        implements OutputBuffer {
1223

    
   
1232

   
1224

    
   
1233

   
1225
        /**
1234
        /**
1226
         * Write chunk.
1235
         * Write chunk.
1227
         */
1236
         */
1228
        public int doWrite(ByteChunk chunk, Response res)
1237
        public int doWrite(ByteChunk chunk, Response res)
1229
            throws IOException {
1238
            throws IOException {
1230

    
   
1239

   
1231
            if (!response.isCommitted()) {
1240
            if (!response.isCommitted()) {
1232
                // Validate and write response headers
1241
                // Validate and write response headers
1233
                try {
1242
                try {
1234
                    prepareResponse();
1243
                    prepareResponse();
1235
                } catch (IOException e) {
1244
                } catch (IOException e) {
1236
                    // Set error flag
1245
                    // Set error flag
1237
                    error = true;
1246
                    error = true;
1238
                }
1247
                }
1239
            }
1248
            }
1240

    
   
1249

   
1241
            int len = chunk.getLength();
1250
            int len = chunk.getLength();
1242
            // 4 - hardcoded, byte[] marshalling overhead
1251
            // 4 - hardcoded, byte[] marshalling overhead
1243
            // Adjust allowed size if packetSize != default (Constants.MAX_PACKET_SIZE)
1252
            // Adjust allowed size if packetSize != default (Constants.MAX_PACKET_SIZE)
1244
            int chunkSize = Constants.MAX_SEND_SIZE + packetSize - Constants.MAX_PACKET_SIZE;
1253
            int chunkSize = Constants.MAX_SEND_SIZE + packetSize - Constants.MAX_PACKET_SIZE;
1245
            int off = 0;
1254
            int off = 0;
1246
            while (len > 0) {
1255
            while (len > 0) {
1247
                int thisTime = len;
1256
                int thisTime = len;
1248
                if (thisTime > chunkSize) {
1257
                if (thisTime > chunkSize) {
1249
                    thisTime = chunkSize;
1258
                    thisTime = chunkSize;
1250
                }
1259
                }
1251
                len -= thisTime;
1260
                len -= thisTime;
1252
                responseHeaderMessage.reset();
1261
                responseHeaderMessage.reset();
1253
                responseHeaderMessage.appendByte(Constants.JK_AJP13_SEND_BODY_CHUNK);
1262
                responseHeaderMessage.appendByte(Constants.JK_AJP13_SEND_BODY_CHUNK);
1254
                responseHeaderMessage.appendBytes(chunk.getBytes(), chunk.getOffset() + off, thisTime);
1263
                responseHeaderMessage.appendBytes(chunk.getBytes(), chunk.getOffset() + off, thisTime);
1255
                responseHeaderMessage.end();
1264
                responseHeaderMessage.end();
1256
                output.write(responseHeaderMessage.getBuffer(), 0, responseHeaderMessage.getLen());
1265
                output.write(responseHeaderMessage.getBuffer(), 0, responseHeaderMessage.getLen());
1257

    
   
1266

   
1258
                off += thisTime;
1267
                off += thisTime;
1259
            }
1268
            }
1260

    
   
1269

   
1261
            return chunk.getLength();
1270
            return chunk.getLength();
1262

    
   
1271

   
1263
        }
1272
        }
1264

    
   
1273

   
1265

    
   
1274

   
1266
    }
1275
    }
1267

    
   
1276

   
1268

    
   
1277

   
1269
}
1278
}
  1. /trunk/java/org/apache/coyote/ajp/AjpProcessor.java: Loading...