~ubuntu-branches/ubuntu/natty/tomcat6/natty-proposed

« back to all changes in this revision

Viewing changes to .pc/0016-CVE-2011-2526.patch/java/org/apache/tomcat/util/net/AprEndpoint.java

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2011-09-26 11:27:14 UTC
  • Revision ID: package-import@ubuntu.com-20110926112714-ngfuvuxfnr5oe2x8
Tags: 6.0.28-10ubuntu2.2
* SECURITY UPDATE: information disclosure via log file
  - debian/patches/0015-CVE-2011-2204.patch: fix logging in
    java/org/apache/catalina/mbeans/MemoryUserDatabaseMBean.java,
    java/org/apache/catalina/users/MemoryUserDatabase.java,
    java/org/apache/catalina/users/MemoryUser.java.
  - CVE-2011-2204
* SECURITY UPDATE: file restriction bypass or denial of service via
  untrusted web application.
  - debian/patches/0016-CVE-2011-2526.patch: check canonical name in
    java/org/apache/catalina/connector/LocalStrings.properties,
    java/org/apache/catalina/connector/Request.java,
    java/org/apache/catalina/servlets/DefaultServlet.java,
    java/org/apache/coyote/http11/Http11AprProcessor.java,
    java/org/apache/coyote/http11/LocalStrings.properties,
    java/org/apache/tomcat/util/net/AprEndpoint.java,
    java/org/apache/tomcat/util/net/NioEndpoint.java.
  - CVE-2011-2526
* SECURITY UPDATE: AJP request spoofing and authentication bypass
  (LP: #843701)
  - debian/patches/0017-CVE-2011-3190.patch: Properly handle request
    bodies in java/org/apache/coyote/ajp/AjpAprProcessor.java,
    java/org/apache/coyote/ajp/AjpProcessor.java.
  - CVE-2011-3190
* SECURITY UPDATE: HTTP DIGEST authentication weaknesses
  - debian/patches/0018-CVE-2011-1184.patch: add new nonce options in
    java/org/apache/catalina/authenticator/DigestAuthenticator.java,
    java/org/apache/catalina/authenticator/LocalStrings.properties,
    java/org/apache/catalina/authenticator/mbeans-descriptors.xml,
    java/org/apache/catalina/realm/RealmBase.java,
    webapps/docs/config/valve.xml.
  - CVE-2011-1184

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 
3
 *  contributor license agreements.  See the NOTICE file distributed with
 
4
 *  this work for additional information regarding copyright ownership.
 
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
 
7
 *  the License.  You may obtain a copy of the License at
 
8
 *
 
9
 *      http://www.apache.org/licenses/LICENSE-2.0
 
10
 *
 
11
 *  Unless required by applicable law or agreed to in writing, software
 
12
 *  distributed under the License is distributed on an "AS IS" BASIS,
 
13
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
14
 *  See the License for the specific language governing permissions and
 
15
 *  limitations under the License.
 
16
 */
 
17
 
 
18
package org.apache.tomcat.util.net;
 
19
 
 
20
import java.io.OutputStreamWriter;
 
21
import java.net.InetAddress;
 
22
import java.net.InetSocketAddress;
 
23
import java.util.ArrayList;
 
24
import java.util.HashMap;
 
25
import java.util.concurrent.Executor;
 
26
 
 
27
import org.apache.juli.logging.Log;
 
28
import org.apache.juli.logging.LogFactory;
 
29
import org.apache.tomcat.jni.Address;
 
30
import org.apache.tomcat.jni.Error;
 
31
import org.apache.tomcat.jni.File;
 
32
import org.apache.tomcat.jni.Library;
 
33
import org.apache.tomcat.jni.OS;
 
34
import org.apache.tomcat.jni.Poll;
 
35
import org.apache.tomcat.jni.Pool;
 
36
import org.apache.tomcat.jni.SSL;
 
37
import org.apache.tomcat.jni.SSLContext;
 
38
import org.apache.tomcat.jni.SSLSocket;
 
39
import org.apache.tomcat.jni.Socket;
 
40
import org.apache.tomcat.jni.Status;
 
41
import org.apache.tomcat.util.res.StringManager;
 
42
 
 
43
/**
 
44
 * APR tailored thread pool, providing the following services:
 
45
 * <ul>
 
46
 * <li>Socket acceptor thread</li>
 
47
 * <li>Socket poller thread</li>
 
48
 * <li>Sendfile thread</li>
 
49
 * <li>Worker threads pool</li>
 
50
 * </ul>
 
51
 *
 
52
 * When switching to Java 5, there's an opportunity to use the virtual
 
53
 * machine's thread pool.
 
54
 *
 
55
 * @author Mladen Turk
 
56
 * @author Remy Maucherat
 
57
 */
 
58
public class AprEndpoint {
 
59
 
 
60
 
 
61
    // -------------------------------------------------------------- Constants
 
62
 
 
63
 
 
64
    protected static Log log = LogFactory.getLog(AprEndpoint.class);
 
65
 
 
66
    protected static StringManager sm =
 
67
        StringManager.getManager("org.apache.tomcat.util.net.res");
 
68
 
 
69
 
 
70
    /**
 
71
     * The Request attribute key for the cipher suite.
 
72
     */
 
73
    public static final String CIPHER_SUITE_KEY = "javax.servlet.request.cipher_suite";
 
74
 
 
75
    /**
 
76
     * The Request attribute key for the key size.
 
77
     */
 
78
    public static final String KEY_SIZE_KEY = "javax.servlet.request.key_size";
 
79
 
 
80
    /**
 
81
     * The Request attribute key for the client certificate chain.
 
82
     */
 
83
    public static final String CERTIFICATE_KEY = "javax.servlet.request.X509Certificate";
 
84
 
 
85
    /**
 
86
     * The Request attribute key for the session id.
 
87
     * This one is a Tomcat extension to the Servlet spec.
 
88
     */
 
89
    public static final String SESSION_ID_KEY = "javax.servlet.request.ssl_session";
 
90
 
 
91
 
 
92
    // ----------------------------------------------------------------- Fields
 
93
 
 
94
 
 
95
    /**
 
96
     * Available workers.
 
97
     */
 
98
    protected WorkerStack workers = null;
 
99
 
 
100
 
 
101
    /**
 
102
     * Running state of the endpoint.
 
103
     */
 
104
    protected volatile boolean running = false;
 
105
 
 
106
 
 
107
    /**
 
108
     * Will be set to true whenever the endpoint is paused.
 
109
     */
 
110
    protected volatile boolean paused = false;
 
111
 
 
112
 
 
113
    /**
 
114
     * Track the initialization state of the endpoint.
 
115
     */
 
116
    protected boolean initialized = false;
 
117
 
 
118
 
 
119
    /**
 
120
     * Current worker threads busy count.
 
121
     */
 
122
    protected int curThreadsBusy = 0;
 
123
 
 
124
 
 
125
    /**
 
126
     * Current worker threads count.
 
127
     */
 
128
    protected int curThreads = 0;
 
129
 
 
130
 
 
131
    /**
 
132
     * Sequence number used to generate thread names.
 
133
     */
 
134
    protected int sequence = 0;
 
135
 
 
136
 
 
137
    /**
 
138
     * Root APR memory pool.
 
139
     */
 
140
    protected long rootPool = 0;
 
141
 
 
142
 
 
143
    /**
 
144
     * Server socket "pointer".
 
145
     */
 
146
    protected long serverSock = 0;
 
147
 
 
148
 
 
149
    /**
 
150
     * APR memory pool for the server socket.
 
151
     */
 
152
    protected long serverSockPool = 0;
 
153
 
 
154
 
 
155
    /**
 
156
     * SSL context.
 
157
     */
 
158
    protected long sslContext = 0;
 
159
 
 
160
    
 
161
    // ------------------------------------------------------------- Properties
 
162
 
 
163
 
 
164
    /**
 
165
     * Defer accept.
 
166
     */
 
167
    protected boolean deferAccept = true;
 
168
    public void setDeferAccept(boolean deferAccept) { this.deferAccept = deferAccept; }
 
169
    public boolean getDeferAccept() { return deferAccept; }
 
170
    
 
171
 
 
172
    /**
 
173
     * External Executor based thread pool.
 
174
     */
 
175
    protected Executor executor = null;
 
176
    public void setExecutor(Executor executor) { this.executor = executor; }
 
177
    public Executor getExecutor() { return executor; }
 
178
 
 
179
 
 
180
    /**
 
181
     * Maximum amount of worker threads.
 
182
     */
 
183
    protected int maxThreads = 200;
 
184
    public void setMaxThreads(int maxThreads) {
 
185
        this.maxThreads = maxThreads;
 
186
        if (running) {
 
187
            synchronized(workers) {
 
188
                workers.resize(maxThreads);
 
189
            }
 
190
        }
 
191
    }
 
192
    public int getMaxThreads() {
 
193
        if (executor != null) {
 
194
            return -1;
 
195
        } else {
 
196
            return maxThreads;
 
197
        }
 
198
    }
 
199
 
 
200
 
 
201
    /**
 
202
     * Priority of the acceptor and poller threads.
 
203
     */
 
204
    protected int threadPriority = Thread.NORM_PRIORITY;
 
205
    public void setThreadPriority(int threadPriority) { this.threadPriority = threadPriority; }
 
206
    public int getThreadPriority() { return threadPriority; }
 
207
 
 
208
 
 
209
    /**
 
210
     * Size of the socket poller.
 
211
     */
 
212
    protected int pollerSize = 8 * 1024;
 
213
    public void setPollerSize(int pollerSize) { this.pollerSize = pollerSize; }
 
214
    public int getPollerSize() { return pollerSize; }
 
215
 
 
216
 
 
217
    /**
 
218
     * Size of the sendfile (= concurrent files which can be served).
 
219
     */
 
220
    protected int sendfileSize = 1 * 1024;
 
221
    public void setSendfileSize(int sendfileSize) { this.sendfileSize = sendfileSize; }
 
222
    public int getSendfileSize() { return sendfileSize; }
 
223
 
 
224
 
 
225
    /**
 
226
     * Server socket port.
 
227
     */
 
228
    protected int port;
 
229
    public int getPort() { return port; }
 
230
    public void setPort(int port ) { this.port=port; }
 
231
 
 
232
 
 
233
    /**
 
234
     * Address for the server socket.
 
235
     */
 
236
    protected InetAddress address;
 
237
    public InetAddress getAddress() { return address; }
 
238
    public void setAddress(InetAddress address) { this.address = address; }
 
239
 
 
240
 
 
241
    /**
 
242
     * Handling of accepted sockets.
 
243
     */
 
244
    protected Handler handler = null;
 
245
    public void setHandler(Handler handler ) { this.handler = handler; }
 
246
    public Handler getHandler() { return handler; }
 
247
 
 
248
 
 
249
    /**
 
250
     * Allows the server developer to specify the backlog that
 
251
     * should be used for server sockets. By default, this value
 
252
     * is 100.
 
253
     */
 
254
    protected int backlog = 100;
 
255
    public void setBacklog(int backlog) { if (backlog > 0) this.backlog = backlog; }
 
256
    public int getBacklog() { return backlog; }
 
257
 
 
258
 
 
259
    /**
 
260
     * Socket TCP no delay.
 
261
     */
 
262
    protected boolean tcpNoDelay = false;
 
263
    public boolean getTcpNoDelay() { return tcpNoDelay; }
 
264
    public void setTcpNoDelay(boolean tcpNoDelay) { this.tcpNoDelay = tcpNoDelay; }
 
265
 
 
266
 
 
267
    /**
 
268
     * Socket linger.
 
269
     */
 
270
    protected int soLinger = 100;
 
271
    public int getSoLinger() { return soLinger; }
 
272
    public void setSoLinger(int soLinger) { this.soLinger = soLinger; }
 
273
 
 
274
 
 
275
    /**
 
276
     * Socket timeout.
 
277
     */
 
278
    protected int soTimeout = -1;
 
279
    public int getSoTimeout() { return soTimeout; }
 
280
    public void setSoTimeout(int soTimeout) { this.soTimeout = soTimeout; }
 
281
 
 
282
 
 
283
    /**
 
284
     * Keep-Alive timeout.
 
285
     */
 
286
    protected int keepAliveTimeout = -1;
 
287
    public int getKeepAliveTimeout() { return keepAliveTimeout; }
 
288
    public void setKeepAliveTimeout(int keepAliveTimeout) { this.keepAliveTimeout = keepAliveTimeout; }
 
289
 
 
290
 
 
291
    /**
 
292
     * Poll interval, in microseconds. The smaller the value, the more CPU the poller
 
293
     * will use, but the more responsive to activity it will be.
 
294
     */
 
295
    protected int pollTime = 2000;
 
296
    public int getPollTime() { return pollTime; }
 
297
    public void setPollTime(int pollTime) { if (pollTime > 0) { this.pollTime = pollTime; } }
 
298
 
 
299
 
 
300
    /**
 
301
     * The default is true - the created threads will be
 
302
     *  in daemon mode. If set to false, the control thread
 
303
     *  will not be daemon - and will keep the process alive.
 
304
     */
 
305
    protected boolean daemon = true;
 
306
    public void setDaemon(boolean b) { daemon = b; }
 
307
    public boolean getDaemon() { return daemon; }
 
308
 
 
309
 
 
310
    /**
 
311
     * Name of the thread pool, which will be used for naming child threads.
 
312
     */
 
313
    protected String name = "TP";
 
314
    public void setName(String name) { this.name = name; }
 
315
    public String getName() { return name; }
 
316
 
 
317
 
 
318
    /**
 
319
     * Use endfile for sending static files.
 
320
     */
 
321
    protected boolean useSendfile = Library.APR_HAS_SENDFILE;
 
322
    public void setUseSendfile(boolean useSendfile) { this.useSendfile = useSendfile; }
 
323
    public boolean getUseSendfile() { return useSendfile; }
 
324
 
 
325
 
 
326
    /**
 
327
     * Allow comet request handling.
 
328
     */
 
329
    protected boolean useComet = true;
 
330
    public void setUseComet(boolean useComet) { this.useComet = useComet; }
 
331
    public boolean getUseComet() { return useComet; }
 
332
 
 
333
 
 
334
    /**
 
335
     * Acceptor thread count.
 
336
     */
 
337
    protected int acceptorThreadCount = 0;
 
338
    public void setAcceptorThreadCount(int acceptorThreadCount) { this.acceptorThreadCount = acceptorThreadCount; }
 
339
    public int getAcceptorThreadCount() { return acceptorThreadCount; }
 
340
 
 
341
 
 
342
    /**
 
343
     * Sendfile thread count.
 
344
     */
 
345
    protected int sendfileThreadCount = 0;
 
346
    public void setSendfileThreadCount(int sendfileThreadCount) { this.sendfileThreadCount = sendfileThreadCount; }
 
347
    public int getSendfileThreadCount() { return sendfileThreadCount; }
 
348
 
 
349
 
 
350
    /**
 
351
     * Poller thread count.
 
352
     */
 
353
    protected int pollerThreadCount = 0;
 
354
    public void setPollerThreadCount(int pollerThreadCount) { this.pollerThreadCount = pollerThreadCount; }
 
355
    public int getPollerThreadCount() { return pollerThreadCount; }
 
356
 
 
357
 
 
358
    /**
 
359
     * The socket poller.
 
360
     */
 
361
    protected Poller[] pollers = null;
 
362
    protected int pollerRoundRobin = 0;
 
363
    public Poller getPoller() {
 
364
        pollerRoundRobin = (pollerRoundRobin + 1) % pollers.length;
 
365
        return pollers[pollerRoundRobin];
 
366
    }
 
367
 
 
368
 
 
369
    /**
 
370
     * The socket poller used for Comet support.
 
371
     */
 
372
    protected Poller[] cometPollers = null;
 
373
    protected int cometPollerRoundRobin = 0;
 
374
    public Poller getCometPoller() {
 
375
        cometPollerRoundRobin = (cometPollerRoundRobin + 1) % cometPollers.length;
 
376
        return cometPollers[cometPollerRoundRobin];
 
377
    }
 
378
 
 
379
 
 
380
    /**
 
381
     * The static file sender.
 
382
     */
 
383
    protected Sendfile[] sendfiles = null;
 
384
    protected int sendfileRoundRobin = 0;
 
385
    public Sendfile getSendfile() {
 
386
        sendfileRoundRobin = (sendfileRoundRobin + 1) % sendfiles.length;
 
387
        return sendfiles[sendfileRoundRobin];
 
388
    }
 
389
 
 
390
 
 
391
    /**
 
392
     * Dummy maxSpareThreads property.
 
393
     */
 
394
    public int getMaxSpareThreads() { return 0; }
 
395
 
 
396
 
 
397
    /**
 
398
     * Dummy minSpareThreads property.
 
399
     */
 
400
    public int getMinSpareThreads() { return 0; }
 
401
 
 
402
 
 
403
    /**
 
404
     * Unlock timeout.
 
405
     */
 
406
    protected int unlockTimeout = 250;
 
407
    public int getUnlockTimeout() { return unlockTimeout; }
 
408
    public void setUnlockTimeout(int unlockTimeout) {
 
409
        this.unlockTimeout = unlockTimeout;
 
410
    }
 
411
 
 
412
    
 
413
    /**
 
414
     * SSL engine.
 
415
     */
 
416
    protected boolean SSLEnabled = false;
 
417
    public boolean isSSLEnabled() { return SSLEnabled; }
 
418
    public void setSSLEnabled(boolean SSLEnabled) { this.SSLEnabled = SSLEnabled; }
 
419
 
 
420
 
 
421
    /**
 
422
     * SSL protocols.
 
423
     */
 
424
    protected String SSLProtocol = "all";
 
425
    public String getSSLProtocol() { return SSLProtocol; }
 
426
    public void setSSLProtocol(String SSLProtocol) { this.SSLProtocol = SSLProtocol; }
 
427
 
 
428
 
 
429
    /**
 
430
     * SSL password (if a cert is encrypted, and no password has been provided, a callback
 
431
     * will ask for a password).
 
432
     */
 
433
    protected String SSLPassword = null;
 
434
    public String getSSLPassword() { return SSLPassword; }
 
435
    public void setSSLPassword(String SSLPassword) { this.SSLPassword = SSLPassword; }
 
436
 
 
437
 
 
438
    /**
 
439
     * SSL cipher suite.
 
440
     */
 
441
    protected String SSLCipherSuite = "ALL";
 
442
    public String getSSLCipherSuite() { return SSLCipherSuite; }
 
443
    public void setSSLCipherSuite(String SSLCipherSuite) { this.SSLCipherSuite = SSLCipherSuite; }
 
444
 
 
445
 
 
446
    /**
 
447
     * SSL certificate file.
 
448
     */
 
449
    protected String SSLCertificateFile = null;
 
450
    public String getSSLCertificateFile() { return SSLCertificateFile; }
 
451
    public void setSSLCertificateFile(String SSLCertificateFile) { this.SSLCertificateFile = SSLCertificateFile; }
 
452
 
 
453
 
 
454
    /**
 
455
     * SSL certificate key file.
 
456
     */
 
457
    protected String SSLCertificateKeyFile = null;
 
458
    public String getSSLCertificateKeyFile() { return SSLCertificateKeyFile; }
 
459
    public void setSSLCertificateKeyFile(String SSLCertificateKeyFile) { this.SSLCertificateKeyFile = SSLCertificateKeyFile; }
 
460
 
 
461
 
 
462
    /**
 
463
     * SSL certificate chain file.
 
464
     */
 
465
    protected String SSLCertificateChainFile = null;
 
466
    public String getSSLCertificateChainFile() { return SSLCertificateChainFile; }
 
467
    public void setSSLCertificateChainFile(String SSLCertificateChainFile) { this.SSLCertificateChainFile = SSLCertificateChainFile; }
 
468
 
 
469
 
 
470
    /**
 
471
     * SSL CA certificate path.
 
472
     */
 
473
    protected String SSLCACertificatePath = null;
 
474
    public String getSSLCACertificatePath() { return SSLCACertificatePath; }
 
475
    public void setSSLCACertificatePath(String SSLCACertificatePath) { this.SSLCACertificatePath = SSLCACertificatePath; }
 
476
 
 
477
 
 
478
    /**
 
479
     * SSL CA certificate file.
 
480
     */
 
481
    protected String SSLCACertificateFile = null;
 
482
    public String getSSLCACertificateFile() { return SSLCACertificateFile; }
 
483
    public void setSSLCACertificateFile(String SSLCACertificateFile) { this.SSLCACertificateFile = SSLCACertificateFile; }
 
484
 
 
485
 
 
486
    /**
 
487
     * SSL CA revocation path.
 
488
     */
 
489
    protected String SSLCARevocationPath = null;
 
490
    public String getSSLCARevocationPath() { return SSLCARevocationPath; }
 
491
    public void setSSLCARevocationPath(String SSLCARevocationPath) { this.SSLCARevocationPath = SSLCARevocationPath; }
 
492
 
 
493
 
 
494
    /**
 
495
     * SSL CA revocation file.
 
496
     */
 
497
    protected String SSLCARevocationFile = null;
 
498
    public String getSSLCARevocationFile() { return SSLCARevocationFile; }
 
499
    public void setSSLCARevocationFile(String SSLCARevocationFile) { this.SSLCARevocationFile = SSLCARevocationFile; }
 
500
 
 
501
 
 
502
    /**
 
503
     * SSL verify client.
 
504
     */
 
505
    protected String SSLVerifyClient = "none";
 
506
    public String getSSLVerifyClient() { return SSLVerifyClient; }
 
507
    public void setSSLVerifyClient(String SSLVerifyClient) { this.SSLVerifyClient = SSLVerifyClient; }
 
508
 
 
509
 
 
510
    /**
 
511
     * SSL verify depth.
 
512
     */
 
513
    protected int SSLVerifyDepth = 10;
 
514
    public int getSSLVerifyDepth() { return SSLVerifyDepth; }
 
515
    public void setSSLVerifyDepth(int SSLVerifyDepth) { this.SSLVerifyDepth = SSLVerifyDepth; }
 
516
 
 
517
 
 
518
    // --------------------------------------------------------- Public Methods
 
519
 
 
520
 
 
521
    /**
 
522
     * Number of keepalive sockets.
 
523
     */
 
524
    public int getKeepAliveCount() {
 
525
        if (pollers == null) {
 
526
            return 0;
 
527
        } else {
 
528
            int keepAliveCount = 0;
 
529
            for (int i = 0; i < pollers.length; i++) {
 
530
                keepAliveCount += pollers[i].getKeepAliveCount();
 
531
            }
 
532
            return keepAliveCount;
 
533
        }
 
534
    }
 
535
 
 
536
 
 
537
    /**
 
538
     * Number of sendfile sockets.
 
539
     */
 
540
    public int getSendfileCount() {
 
541
        if (sendfiles == null) {
 
542
            return 0;
 
543
        } else {
 
544
            int sendfileCount = 0;
 
545
            for (int i = 0; i < sendfiles.length; i++) {
 
546
                sendfileCount += sendfiles[i].getSendfileCount();
 
547
            }
 
548
            return sendfileCount;
 
549
        }
 
550
    }
 
551
 
 
552
 
 
553
    /**
 
554
     * Return the amount of threads that are managed by the pool.
 
555
     *
 
556
     * @return the amount of threads that are managed by the pool
 
557
     */
 
558
    public int getCurrentThreadCount() {
 
559
        if (executor != null) {
 
560
            return -1;
 
561
        } else {
 
562
            return curThreads;
 
563
        }
 
564
    }
 
565
 
 
566
    /**
 
567
     * Return the amount of threads that are in use 
 
568
     *
 
569
     * @return the amount of threads that are in use
 
570
     */
 
571
    public int getCurrentThreadsBusy() {
 
572
        if (executor!=null) {
 
573
            return -1;
 
574
        } else {
 
575
            return workers!=null?curThreads - workers.size():0;
 
576
        }
 
577
    }
 
578
 
 
579
 
 
580
    /**
 
581
     * Return the state of the endpoint.
 
582
     *
 
583
     * @return true if the endpoint is running, false otherwise
 
584
     */
 
585
    public boolean isRunning() {
 
586
        return running;
 
587
    }
 
588
 
 
589
 
 
590
    /**
 
591
     * Return the state of the endpoint.
 
592
     *
 
593
     * @return true if the endpoint is paused, false otherwise
 
594
     */
 
595
    public boolean isPaused() {
 
596
        return paused;
 
597
    }
 
598
 
 
599
 
 
600
    // ----------------------------------------------- Public Lifecycle Methods
 
601
 
 
602
 
 
603
    /**
 
604
     * Initialize the endpoint.
 
605
     */
 
606
    public void init()
 
607
        throws Exception {
 
608
 
 
609
        if (initialized)
 
610
            return;
 
611
        
 
612
        // Create the root APR memory pool
 
613
        rootPool = Pool.create(0);
 
614
        // Create the pool for the server socket
 
615
        serverSockPool = Pool.create(rootPool);
 
616
        // Create the APR address that will be bound
 
617
        String addressStr = null;
 
618
        if (address == null) {
 
619
            addressStr = null;
 
620
        } else {
 
621
            addressStr = address.getHostAddress();
 
622
        }
 
623
        int family = Socket.APR_INET;
 
624
        if (Library.APR_HAVE_IPV6) {
 
625
            if (addressStr == null) {
 
626
                if (!OS.IS_BSD && !OS.IS_WIN32 && !OS.IS_WIN64)
 
627
                    family = Socket.APR_UNSPEC;
 
628
            } else if (addressStr.indexOf(':') >= 0) {
 
629
                family = Socket.APR_UNSPEC;
 
630
            }
 
631
         }
 
632
 
 
633
        long inetAddress = Address.info(addressStr, family,
 
634
                port, 0, rootPool);
 
635
        // Create the APR server socket
 
636
        serverSock = Socket.create(Address.getInfo(inetAddress).family,
 
637
                Socket.SOCK_STREAM,
 
638
                Socket.APR_PROTO_TCP, rootPool);
 
639
        if (OS.IS_UNIX) {
 
640
            Socket.optSet(serverSock, Socket.APR_SO_REUSEADDR, 1);
 
641
        }
 
642
        // Deal with the firewalls that tend to drop the inactive sockets
 
643
        Socket.optSet(serverSock, Socket.APR_SO_KEEPALIVE, 1);
 
644
        // Bind the server socket
 
645
        int ret = Socket.bind(serverSock, inetAddress);
 
646
        if (ret != 0) {
 
647
            throw new Exception(sm.getString("endpoint.init.bind", "" + ret, Error.strerror(ret)));
 
648
        }
 
649
        // Start listening on the server socket
 
650
        ret = Socket.listen(serverSock, backlog);
 
651
        if (ret != 0) {
 
652
            throw new Exception(sm.getString("endpoint.init.listen", "" + ret, Error.strerror(ret)));
 
653
        }
 
654
        if (OS.IS_WIN32 || OS.IS_WIN64) {
 
655
            // On Windows set the reuseaddr flag after the bind/listen
 
656
            Socket.optSet(serverSock, Socket.APR_SO_REUSEADDR, 1);
 
657
        }
 
658
 
 
659
        // Sendfile usage on systems which don't support it cause major problems
 
660
        if (useSendfile && !Library.APR_HAS_SENDFILE) {
 
661
            useSendfile = false;
 
662
        }
 
663
 
 
664
        // Initialize thread count defaults for acceptor, poller and sendfile
 
665
        if (acceptorThreadCount == 0) {
 
666
            // FIXME: Doesn't seem to work that well with multiple accept threads
 
667
            acceptorThreadCount = 1;
 
668
        }
 
669
        if (pollerThreadCount == 0) {
 
670
            if ((OS.IS_WIN32 || OS.IS_WIN64) && (pollerSize > 1024)) {
 
671
                // The maximum per poller to get reasonable performance is 1024
 
672
                pollerThreadCount = pollerSize / 1024;
 
673
                // Adjust poller size so that it won't reach the limit
 
674
                pollerSize = pollerSize - (pollerSize % 1024);
 
675
            } else {
 
676
                // No explicit poller size limitation
 
677
                pollerThreadCount = 1;
 
678
            }
 
679
        }
 
680
        if (sendfileThreadCount == 0) {
 
681
            if ((OS.IS_WIN32 || OS.IS_WIN64) && (sendfileSize > 1024)) {
 
682
                // The maximum per poller to get reasonable performance is 1024
 
683
                sendfileThreadCount = sendfileSize / 1024;
 
684
                // Adjust poller size so that it won't reach the limit
 
685
                sendfileSize = sendfileSize - (sendfileSize % 1024);
 
686
            } else {
 
687
                // No explicit poller size limitation
 
688
                // FIXME: Default to one per CPU ?
 
689
                sendfileThreadCount = 1;
 
690
            }
 
691
        }
 
692
        
 
693
        // Delay accepting of new connections until data is available
 
694
        // Only Linux kernels 2.4 + have that implemented
 
695
        // on other platforms this call is noop and will return APR_ENOTIMPL.
 
696
        if (deferAccept) {
 
697
            if (Socket.optSet(serverSock, Socket.APR_TCP_DEFER_ACCEPT, 1) == Status.APR_ENOTIMPL) {
 
698
                deferAccept = false;
 
699
            }
 
700
        }
 
701
 
 
702
        // Initialize SSL if needed
 
703
        if (SSLEnabled) {
 
704
            
 
705
            // SSL protocol
 
706
            int value = SSL.SSL_PROTOCOL_ALL;
 
707
            if ("SSLv2".equalsIgnoreCase(SSLProtocol)) {
 
708
                value = SSL.SSL_PROTOCOL_SSLV2;
 
709
            } else if ("SSLv3".equalsIgnoreCase(SSLProtocol)) {
 
710
                value = SSL.SSL_PROTOCOL_SSLV3;
 
711
            } else if ("TLSv1".equalsIgnoreCase(SSLProtocol)) {
 
712
                value = SSL.SSL_PROTOCOL_TLSV1;
 
713
            } else if ("SSLv2+SSLv3".equalsIgnoreCase(SSLProtocol)) {
 
714
                value = SSL.SSL_PROTOCOL_SSLV2 | SSL.SSL_PROTOCOL_SSLV3;
 
715
            }
 
716
            // Create SSL Context
 
717
            sslContext = SSLContext.make(rootPool, value, SSL.SSL_MODE_SERVER);
 
718
            // List the ciphers that the client is permitted to negotiate
 
719
            SSLContext.setCipherSuite(sslContext, SSLCipherSuite);
 
720
            // Load Server key and certificate
 
721
            SSLContext.setCertificate(sslContext, SSLCertificateFile, SSLCertificateKeyFile, SSLPassword, SSL.SSL_AIDX_RSA);
 
722
            // Set certificate chain file
 
723
            SSLContext.setCertificateChainFile(sslContext, SSLCertificateChainFile, false);
 
724
            // Support Client Certificates
 
725
            SSLContext.setCACertificate(sslContext, SSLCACertificateFile, SSLCACertificatePath);
 
726
            // Set revocation
 
727
            SSLContext.setCARevocation(sslContext, SSLCARevocationFile, SSLCARevocationPath);
 
728
            // Client certificate verification
 
729
            value = SSL.SSL_CVERIFY_NONE;
 
730
            if ("optional".equalsIgnoreCase(SSLVerifyClient)) {
 
731
                value = SSL.SSL_CVERIFY_OPTIONAL;
 
732
            } else if ("require".equalsIgnoreCase(SSLVerifyClient)) {
 
733
                value = SSL.SSL_CVERIFY_REQUIRE;
 
734
            } else if ("optionalNoCA".equalsIgnoreCase(SSLVerifyClient)) {
 
735
                value = SSL.SSL_CVERIFY_OPTIONAL_NO_CA;
 
736
            }
 
737
            SSLContext.setVerify(sslContext, value, SSLVerifyDepth);
 
738
            // For now, sendfile is not supported with SSL
 
739
            useSendfile = false;
 
740
        }
 
741
 
 
742
        initialized = true;
 
743
 
 
744
    }
 
745
 
 
746
 
 
747
    /**
 
748
     * Start the APR endpoint, creating acceptor, poller and sendfile threads.
 
749
     */
 
750
    public void start()
 
751
        throws Exception {
 
752
        // Initialize socket if not done before
 
753
        if (!initialized) {
 
754
            init();
 
755
        }
 
756
        if (!running) {
 
757
            running = true;
 
758
            paused = false;
 
759
 
 
760
            // Create worker collection
 
761
            if (executor == null) {
 
762
                workers = new WorkerStack(maxThreads);
 
763
            }
 
764
 
 
765
            // Start poller threads
 
766
            pollers = new Poller[pollerThreadCount];
 
767
            for (int i = 0; i < pollerThreadCount; i++) {
 
768
                pollers[i] = new Poller(false);
 
769
                pollers[i].init();
 
770
                Thread pollerThread = new Thread(pollers[i], getName() + "-Poller-" + i);
 
771
                pollerThread.setPriority(threadPriority);
 
772
                pollerThread.setDaemon(true);
 
773
                pollerThread.start();
 
774
            }
 
775
 
 
776
            // Start comet poller threads
 
777
            cometPollers = new Poller[pollerThreadCount];
 
778
            for (int i = 0; i < pollerThreadCount; i++) {
 
779
                cometPollers[i] = new Poller(true);
 
780
                cometPollers[i].init();
 
781
                Thread pollerThread = new Thread(cometPollers[i], getName() + "-CometPoller-" + i);
 
782
                pollerThread.setPriority(threadPriority);
 
783
                pollerThread.setDaemon(true);
 
784
                pollerThread.start();
 
785
            }
 
786
 
 
787
            // Start sendfile threads
 
788
            if (useSendfile) {
 
789
                sendfiles = new Sendfile[sendfileThreadCount];
 
790
                for (int i = 0; i < sendfileThreadCount; i++) {
 
791
                    sendfiles[i] = new Sendfile();
 
792
                    sendfiles[i].init();
 
793
                    Thread sendfileThread = new Thread(sendfiles[i], getName() + "-Sendfile-" + i);
 
794
                    sendfileThread.setPriority(threadPriority);
 
795
                    sendfileThread.setDaemon(true);
 
796
                    sendfileThread.start();
 
797
                }
 
798
            }
 
799
 
 
800
            // Start acceptor threads
 
801
            for (int i = 0; i < acceptorThreadCount; i++) {
 
802
                Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i);
 
803
                acceptorThread.setPriority(threadPriority);
 
804
                acceptorThread.setDaemon(daemon);
 
805
                acceptorThread.start();
 
806
            }
 
807
 
 
808
        }
 
809
    }
 
810
 
 
811
 
 
812
    /**
 
813
     * Pause the endpoint, which will make it stop accepting new sockets.
 
814
     */
 
815
    public void pause() {
 
816
        if (running && !paused) {
 
817
            paused = true;
 
818
            unlockAccept();
 
819
        }
 
820
    }
 
821
 
 
822
 
 
823
    /**
 
824
     * Resume the endpoint, which will make it start accepting new sockets
 
825
     * again.
 
826
     */
 
827
    public void resume() {
 
828
        if (running) {
 
829
            paused = false;
 
830
        }
 
831
    }
 
832
 
 
833
 
 
834
    /**
 
835
     * Stop the endpoint. This will cause all processing threads to stop.
 
836
     */
 
837
    public void stop() {
 
838
        if (running) {
 
839
            running = false;
 
840
            unlockAccept();
 
841
            for (int i = 0; i < pollers.length; i++) {
 
842
                pollers[i].destroy();
 
843
            }
 
844
            pollers = null;
 
845
            for (int i = 0; i < cometPollers.length; i++) {
 
846
                cometPollers[i].destroy();
 
847
            }
 
848
            cometPollers = null;
 
849
            if (useSendfile) {
 
850
                for (int i = 0; i < sendfiles.length; i++) {
 
851
                    sendfiles[i].destroy();
 
852
                }
 
853
                sendfiles = null;
 
854
            }
 
855
        }
 
856
    }
 
857
 
 
858
 
 
859
    /**
 
860
     * Deallocate APR memory pools, and close server socket.
 
861
     */
 
862
    public void destroy() throws Exception {
 
863
        if (running) {
 
864
            stop();
 
865
        }
 
866
        Pool.destroy(serverSockPool);
 
867
        serverSockPool = 0;
 
868
        // Close server socket
 
869
        Socket.close(serverSock);
 
870
        serverSock = 0;
 
871
        sslContext = 0;
 
872
        // Close all APR memory pools and resources
 
873
        Pool.destroy(rootPool);
 
874
        rootPool = 0;
 
875
        initialized = false;
 
876
    }
 
877
 
 
878
 
 
879
    // ------------------------------------------------------ Protected Methods
 
880
 
 
881
 
 
882
    /**
 
883
     * Get a sequence number used for thread naming.
 
884
     */
 
885
    protected int getSequence() {
 
886
        return sequence++;
 
887
    }
 
888
 
 
889
 
 
890
    /**
 
891
     * Unlock the server socket accept using a bugus connection.
 
892
     */
 
893
    protected void unlockAccept() {
 
894
        java.net.Socket s = null;
 
895
        InetSocketAddress saddr = null;
 
896
        try {
 
897
            // Need to create a connection to unlock the accept();
 
898
            if (address == null) {
 
899
                saddr = new InetSocketAddress("localhost", port);
 
900
            } else {
 
901
                saddr = new InetSocketAddress(address,port);
 
902
            }
 
903
            s = new java.net.Socket();
 
904
            s.setSoTimeout(soTimeout);
 
905
            s.setSoLinger(true ,0);
 
906
            if (log.isDebugEnabled()) {
 
907
                log.debug("About to unlock socket for: " + saddr);
 
908
            }
 
909
            s.connect(saddr, unlockTimeout);
 
910
            /*
 
911
             * In the case of a deferred accept / accept filters we need to
 
912
             * send data to wake up the accept. Send OPTIONS * to bypass even
 
913
             * BSD accept filters. The Acceptor will discard it.
 
914
             */
 
915
            if (deferAccept) {
 
916
                OutputStreamWriter sw;
 
917
 
 
918
                sw = new OutputStreamWriter(s.getOutputStream(), "ISO-8859-1");
 
919
                sw.write("OPTIONS * HTTP/1.0\r\n"
 
920
                        + "User-Agent: Tomcat wakeup connection\r\n\r\n");
 
921
                sw.flush();
 
922
            }
 
923
        } catch(Exception e) {
 
924
            if (log.isDebugEnabled()) {
 
925
                log.debug(sm.getString("endpoint.debug.unlock", "" + port), e);
 
926
            }
 
927
        } finally {
 
928
            if (s != null) {
 
929
                try {
 
930
                    s.close();
 
931
                } catch (Exception e) {
 
932
                    // Ignore
 
933
                }
 
934
            }
 
935
        }
 
936
    }
 
937
 
 
938
 
 
939
    /**
 
940
     * Process the specified connection.
 
941
     */
 
942
    protected boolean setSocketOptions(long socket) {
 
943
        // Process the connection
 
944
        int step = 1;
 
945
        try {
 
946
 
 
947
            // 1: Set socket options: timeout, linger, etc
 
948
            if (soLinger >= 0)
 
949
                Socket.optSet(socket, Socket.APR_SO_LINGER, soLinger);
 
950
            if (tcpNoDelay)
 
951
                Socket.optSet(socket, Socket.APR_TCP_NODELAY, (tcpNoDelay ? 1 : 0));
 
952
            if (soTimeout > 0)
 
953
                Socket.timeoutSet(socket, soTimeout * 1000);
 
954
 
 
955
            // 2: SSL handshake
 
956
            step = 2;
 
957
            if (sslContext != 0) {
 
958
                SSLSocket.attach(sslContext, socket);
 
959
                if (SSLSocket.handshake(socket) != 0) {
 
960
                    if (log.isDebugEnabled()) {
 
961
                        log.debug(sm.getString("endpoint.err.handshake") + ": " + SSL.getLastError());
 
962
                    }
 
963
                    return false;
 
964
                }
 
965
            }
 
966
 
 
967
        } catch (Throwable t) {
 
968
            if (log.isDebugEnabled()) {
 
969
                if (step == 2) {
 
970
                    log.debug(sm.getString("endpoint.err.handshake"), t);
 
971
                } else {
 
972
                    log.debug(sm.getString("endpoint.err.unexpected"), t);
 
973
                }
 
974
            }
 
975
            // Tell to close the socket
 
976
            return false;
 
977
        }
 
978
        return true;
 
979
    }
 
980
 
 
981
 
 
982
    /**
 
983
     * Create (or allocate) and return an available processor for use in
 
984
     * processing a specific HTTP request, if possible.  If the maximum
 
985
     * allowed processors have already been created and are in use, return
 
986
     * <code>null</code> instead.
 
987
     */
 
988
    protected Worker createWorkerThread() {
 
989
 
 
990
        synchronized (workers) {
 
991
            if (workers.size() > 0) {
 
992
                curThreadsBusy++;
 
993
                return (workers.pop());
 
994
            }
 
995
            if ((maxThreads > 0) && (curThreads < maxThreads)) {
 
996
                curThreadsBusy++;
 
997
                if (curThreadsBusy == maxThreads) {
 
998
                    log.info(sm.getString("endpoint.info.maxThreads",
 
999
                            Integer.toString(maxThreads), address,
 
1000
                            Integer.toString(port)));
 
1001
                }
 
1002
                return (newWorkerThread());
 
1003
            } else {
 
1004
                if (maxThreads < 0) {
 
1005
                    curThreadsBusy++;
 
1006
                    return (newWorkerThread());
 
1007
                } else {
 
1008
                    return (null);
 
1009
                }
 
1010
            }
 
1011
        }
 
1012
 
 
1013
    }
 
1014
 
 
1015
 
 
1016
    /**
 
1017
     * Create and return a new processor suitable for processing HTTP
 
1018
     * requests and returning the corresponding responses.
 
1019
     */
 
1020
    protected Worker newWorkerThread() {
 
1021
 
 
1022
        Worker workerThread = new Worker();
 
1023
        workerThread.start();
 
1024
        return (workerThread);
 
1025
 
 
1026
    }
 
1027
 
 
1028
 
 
1029
    /**
 
1030
     * Return a new worker thread, and block while to worker is available.
 
1031
     */
 
1032
    protected Worker getWorkerThread() {
 
1033
        // Allocate a new worker thread
 
1034
        synchronized (workers) {
 
1035
            Worker workerThread;
 
1036
            while ((workerThread = createWorkerThread()) == null) {
 
1037
                try {
 
1038
                    workers.wait();
 
1039
                } catch (InterruptedException e) {
 
1040
                    // Ignore
 
1041
                }
 
1042
            }
 
1043
            return workerThread;
 
1044
        }
 
1045
    }
 
1046
 
 
1047
 
 
1048
    /**
 
1049
     * Recycle the specified Processor so that it can be used again.
 
1050
     *
 
1051
     * @param workerThread The processor to be recycled
 
1052
     */
 
1053
    protected void recycleWorkerThread(Worker workerThread) {
 
1054
        synchronized (workers) {
 
1055
            workers.push(workerThread);
 
1056
            curThreadsBusy--;
 
1057
            workers.notify();
 
1058
        }
 
1059
    }
 
1060
 
 
1061
    
 
1062
    /**
 
1063
     * Allocate a new poller of the specified size.
 
1064
     */
 
1065
    protected long allocatePoller(int size, long pool, int timeout) {
 
1066
        try {
 
1067
            return Poll.create(size, pool, 0, timeout * 1000);
 
1068
        } catch (Error e) {
 
1069
            if (Status.APR_STATUS_IS_EINVAL(e.getError())) {
 
1070
                log.info(sm.getString("endpoint.poll.limitedpollsize", "" + size));
 
1071
                return 0;
 
1072
            } else {
 
1073
                log.error(sm.getString("endpoint.poll.initfail"), e);
 
1074
                return -1;
 
1075
            }
 
1076
        }
 
1077
    }
 
1078
 
 
1079
    
 
1080
    /**
 
1081
     * Process given socket.
 
1082
     */
 
1083
    protected boolean processSocketWithOptions(long socket) {
 
1084
        try {
 
1085
            if (executor == null) {
 
1086
                getWorkerThread().assignWithOptions(socket);
 
1087
            } else {
 
1088
                executor.execute(new SocketWithOptionsProcessor(socket));
 
1089
            }
 
1090
        } catch (Throwable t) {
 
1091
            // This means we got an OOM or similar creating a thread, or that
 
1092
            // the pool and its queue are full
 
1093
            log.error(sm.getString("endpoint.process.fail"), t);
 
1094
            return false;
 
1095
        }
 
1096
        return true;
 
1097
    }
 
1098
    
 
1099
 
 
1100
    /**
 
1101
     * Process given socket.
 
1102
     */
 
1103
    protected boolean processSocket(long socket) {
 
1104
        try {
 
1105
            if (executor == null) {
 
1106
                getWorkerThread().assign(socket);
 
1107
            } else {
 
1108
                executor.execute(new SocketProcessor(socket));
 
1109
            }
 
1110
        } catch (Throwable t) {
 
1111
            // This means we got an OOM or similar creating a thread, or that
 
1112
            // the pool and its queue are full
 
1113
            log.error(sm.getString("endpoint.process.fail"), t);
 
1114
            return false;
 
1115
        }
 
1116
        return true;
 
1117
    }
 
1118
    
 
1119
 
 
1120
    /**
 
1121
     * Process given socket for an event.
 
1122
     */
 
1123
    protected boolean processSocket(long socket, SocketStatus status) {
 
1124
        try {
 
1125
            if (executor == null) {
 
1126
                getWorkerThread().assign(socket, status);
 
1127
            } else {
 
1128
                executor.execute(new SocketEventProcessor(socket, status));
 
1129
            }
 
1130
        } catch (Throwable t) {
 
1131
            // This means we got an OOM or similar creating a thread, or that
 
1132
            // the pool and its queue are full
 
1133
            log.error(sm.getString("endpoint.process.fail"), t);
 
1134
            return false;
 
1135
        }
 
1136
        return true;
 
1137
    }
 
1138
    
 
1139
 
 
1140
    // --------------------------------------------------- Acceptor Inner Class
 
1141
 
 
1142
 
 
1143
    /**
 
1144
     * Server socket acceptor thread.
 
1145
     */
 
1146
    protected class Acceptor implements Runnable {
 
1147
 
 
1148
 
 
1149
        /**
 
1150
         * The background thread that listens for incoming TCP/IP connections and
 
1151
         * hands them off to an appropriate processor.
 
1152
         */
 
1153
        public void run() {
 
1154
 
 
1155
            // Loop until we receive a shutdown command
 
1156
            while (running) {
 
1157
 
 
1158
                // Loop if endpoint is paused
 
1159
                while (paused) {
 
1160
                    try {
 
1161
                        Thread.sleep(1000);
 
1162
                    } catch (InterruptedException e) {
 
1163
                        // Ignore
 
1164
                    }
 
1165
                }
 
1166
 
 
1167
                try {
 
1168
                    // Accept the next incoming connection from the server socket
 
1169
                    long socket = Socket.accept(serverSock);
 
1170
                    /*
 
1171
                     * In the case of a deferred accept unlockAccept needs to
 
1172
                     * send data. This data will be rubbish, so destroy the
 
1173
                     * socket and don't process it.
 
1174
                     */
 
1175
                    if (deferAccept && (paused || !running)) {
 
1176
                        Socket.destroy(socket);
 
1177
                        continue;
 
1178
                    }
 
1179
                    // Hand this socket off to an appropriate processor
 
1180
                    if (!processSocketWithOptions(socket)) {
 
1181
                        // Close socket and pool right away
 
1182
                        Socket.destroy(socket);
 
1183
                    }
 
1184
                } catch (Throwable t) {
 
1185
                    if (running) log.error(sm.getString("endpoint.accept.fail"), t);
 
1186
                }
 
1187
 
 
1188
                // The processor will recycle itself when it finishes
 
1189
 
 
1190
            }
 
1191
 
 
1192
        }
 
1193
 
 
1194
    }
 
1195
 
 
1196
 
 
1197
    // ----------------------------------------------------- Poller Inner Class
 
1198
 
 
1199
 
 
1200
    /**
 
1201
     * Poller class.
 
1202
     */
 
1203
    public class Poller implements Runnable {
 
1204
 
 
1205
        protected long serverPollset = 0;
 
1206
        protected long pool = 0;
 
1207
        protected long[] desc;
 
1208
 
 
1209
        protected long[] addS;
 
1210
        protected volatile int addCount = 0;
 
1211
        
 
1212
        protected boolean comet = true;
 
1213
 
 
1214
        protected volatile int keepAliveCount = 0;
 
1215
        public int getKeepAliveCount() { return keepAliveCount; }
 
1216
 
 
1217
        public Poller(boolean comet) {
 
1218
            this.comet = comet;
 
1219
        }
 
1220
        
 
1221
        /**
 
1222
         * Create the poller. With some versions of APR, the maximum poller size will
 
1223
         * be 62 (recompiling APR is necessary to remove this limitation).
 
1224
         */
 
1225
        protected void init() {
 
1226
            pool = Pool.create(serverSockPool);
 
1227
            int size = pollerSize / pollerThreadCount;
 
1228
            int timeout = keepAliveTimeout;
 
1229
            if (timeout < 0) {
 
1230
                timeout = soTimeout;
 
1231
            }
 
1232
            serverPollset = allocatePoller(size, pool, timeout);
 
1233
            if (serverPollset == 0 && size > 1024) {
 
1234
                size = 1024;
 
1235
                serverPollset = allocatePoller(size, pool, timeout);
 
1236
            }
 
1237
            if (serverPollset == 0) {
 
1238
                size = 62;
 
1239
                serverPollset = allocatePoller(size, pool, timeout);
 
1240
            }
 
1241
            desc = new long[size * 2];
 
1242
            keepAliveCount = 0;
 
1243
            addS = new long[size];
 
1244
            addCount = 0;
 
1245
        }
 
1246
 
 
1247
        /**
 
1248
         * Destroy the poller.
 
1249
         */
 
1250
        protected void destroy() {
 
1251
            // Wait for polltime before doing anything, so that the poller threads
 
1252
            // exit, otherwise parallel descturction of sockets which are still
 
1253
            // in the poller can cause problems
 
1254
            try {
 
1255
                synchronized (this) {
 
1256
                    this.wait(pollTime / 1000);
 
1257
                }
 
1258
            } catch (InterruptedException e) {
 
1259
                // Ignore
 
1260
            }
 
1261
            // Close all sockets in the add queue
 
1262
            for (int i = 0; i < addCount; i++) {
 
1263
                if (comet) {
 
1264
                    processSocket(addS[i], SocketStatus.STOP);
 
1265
                } else {
 
1266
                    Socket.destroy(addS[i]);
 
1267
                }
 
1268
            }
 
1269
            // Close all sockets still in the poller
 
1270
            int rv = Poll.pollset(serverPollset, desc);
 
1271
            if (rv > 0) {
 
1272
                for (int n = 0; n < rv; n++) {
 
1273
                    if (comet) {
 
1274
                        processSocket(desc[n*2+1], SocketStatus.STOP);
 
1275
                    } else {
 
1276
                        Socket.destroy(desc[n*2+1]);
 
1277
                    }
 
1278
                }
 
1279
            }
 
1280
            Pool.destroy(pool);
 
1281
            keepAliveCount = 0;
 
1282
            addCount = 0;
 
1283
        }
 
1284
 
 
1285
        /**
 
1286
         * Add specified socket and associated pool to the poller. The socket will
 
1287
         * be added to a temporary array, and polled first after a maximum amount
 
1288
         * of time equal to pollTime (in most cases, latency will be much lower,
 
1289
         * however).
 
1290
         *
 
1291
         * @param socket to add to the poller
 
1292
         */
 
1293
        public void add(long socket) {
 
1294
            synchronized (this) {
 
1295
                // Add socket to the list. Newly added sockets will wait
 
1296
                // at most for pollTime before being polled
 
1297
                if (addCount >= addS.length) {
 
1298
                    // Can't do anything: close the socket right away
 
1299
                    if (comet) {
 
1300
                        processSocket(socket, SocketStatus.ERROR);
 
1301
                    } else {
 
1302
                        Socket.destroy(socket);
 
1303
                    }
 
1304
                    return;
 
1305
                }
 
1306
                addS[addCount] = socket;
 
1307
                addCount++;
 
1308
                this.notify();
 
1309
            }
 
1310
        }
 
1311
 
 
1312
        /**
 
1313
         * The background thread that listens for incoming TCP/IP connections and
 
1314
         * hands them off to an appropriate processor.
 
1315
         */
 
1316
        public void run() {
 
1317
 
 
1318
            long maintainTime = 0;
 
1319
            // Loop until we receive a shutdown command
 
1320
            while (running) {
 
1321
                // Loop if endpoint is paused
 
1322
                while (paused) {
 
1323
                    try {
 
1324
                        Thread.sleep(1000);
 
1325
                    } catch (InterruptedException e) {
 
1326
                        // Ignore
 
1327
                    }
 
1328
                }
 
1329
 
 
1330
                if (keepAliveCount < 1 && addCount < 1) {
 
1331
                    synchronized (this) {
 
1332
                        while (keepAliveCount < 1 && addCount < 1) {
 
1333
                            // Reset maintain time.
 
1334
                            maintainTime = 0;
 
1335
                            try {
 
1336
                                this.wait();
 
1337
                            } catch (InterruptedException e) {
 
1338
                                // Ignore
 
1339
                            }
 
1340
                        }
 
1341
                    }
 
1342
                }
 
1343
 
 
1344
                try {
 
1345
                    // Add sockets which are waiting to the poller
 
1346
                    if (addCount > 0) {
 
1347
                        synchronized (this) {
 
1348
                            int successCount = 0;
 
1349
                            try {
 
1350
                                for (int i = (addCount - 1); i >= 0; i--) {
 
1351
                                    int rv = Poll.add
 
1352
                                        (serverPollset, addS[i], Poll.APR_POLLIN);
 
1353
                                    if (rv == Status.APR_SUCCESS) {
 
1354
                                        successCount++;
 
1355
                                    } else {
 
1356
                                        // Can't do anything: close the socket right away
 
1357
                                        if (comet) {
 
1358
                                            processSocket(addS[i], SocketStatus.ERROR);
 
1359
                                        } else {
 
1360
                                            Socket.destroy(addS[i]);
 
1361
                                        }
 
1362
                                    }
 
1363
                                }
 
1364
                            } finally {
 
1365
                                keepAliveCount += successCount;
 
1366
                                addCount = 0;
 
1367
                            }
 
1368
                        }
 
1369
                    }
 
1370
 
 
1371
                    maintainTime += pollTime;
 
1372
                    // Pool for the specified interval
 
1373
                    int rv = Poll.poll(serverPollset, pollTime, desc, true);
 
1374
                    if (rv > 0) {
 
1375
                        keepAliveCount -= rv;
 
1376
                        for (int n = 0; n < rv; n++) {
 
1377
                            // Check for failed sockets and hand this socket off to a worker
 
1378
                            if (((desc[n*2] & Poll.APR_POLLHUP) == Poll.APR_POLLHUP)
 
1379
                                    || ((desc[n*2] & Poll.APR_POLLERR) == Poll.APR_POLLERR)
 
1380
                                    || (comet && (!processSocket(desc[n*2+1], SocketStatus.OPEN))) 
 
1381
                                    || (!comet && (!processSocket(desc[n*2+1])))) {
 
1382
                                // Close socket and clear pool
 
1383
                                if (comet) {
 
1384
                                    processSocket(desc[n*2+1], SocketStatus.DISCONNECT);
 
1385
                                } else {
 
1386
                                    Socket.destroy(desc[n*2+1]);
 
1387
                                }
 
1388
                                continue;
 
1389
                            }
 
1390
                        }
 
1391
                    } else if (rv < 0) {
 
1392
                        int errn = -rv;
 
1393
                        /* Any non timeup or interrupted error is critical */
 
1394
                        if ((errn != Status.TIMEUP) && (errn != Status.EINTR)) {
 
1395
                            if (errn >  Status.APR_OS_START_USERERR) {
 
1396
                                errn -=  Status.APR_OS_START_USERERR;
 
1397
                            }
 
1398
                            log.error(sm.getString("endpoint.poll.fail", "" + errn, Error.strerror(errn)));
 
1399
                            // Handle poll critical failure
 
1400
                            synchronized (this) {
 
1401
                                destroy();
 
1402
                                init();
 
1403
                            }
 
1404
                            continue;
 
1405
                        }
 
1406
                    }
 
1407
                    if (soTimeout > 0 && maintainTime > 1000000L && running) {
 
1408
                        rv = Poll.maintain(serverPollset, desc, true);
 
1409
                        maintainTime = 0;
 
1410
                        if (rv > 0) {
 
1411
                            keepAliveCount -= rv;
 
1412
                            for (int n = 0; n < rv; n++) {
 
1413
                                // Close socket and clear pool
 
1414
                                if (comet) {
 
1415
                                    processSocket(desc[n], SocketStatus.TIMEOUT);
 
1416
                                } else {
 
1417
                                    Socket.destroy(desc[n]);
 
1418
                                }
 
1419
                            }
 
1420
                        }
 
1421
                    }
 
1422
                } catch (Throwable t) {
 
1423
                    log.error(sm.getString("endpoint.poll.error"), t);
 
1424
                }
 
1425
 
 
1426
            }
 
1427
 
 
1428
            synchronized (this) {
 
1429
                this.notifyAll();
 
1430
            }
 
1431
 
 
1432
        }
 
1433
        
 
1434
    }
 
1435
 
 
1436
 
 
1437
    // ----------------------------------------------------- Worker Inner Class
 
1438
 
 
1439
 
 
1440
    /**
 
1441
     * Server processor class.
 
1442
     */
 
1443
    protected class Worker implements Runnable {
 
1444
 
 
1445
 
 
1446
        protected Thread thread = null;
 
1447
        protected boolean available = false;
 
1448
        protected long socket = 0;
 
1449
        protected SocketStatus status = null;
 
1450
        protected boolean options = false;
 
1451
 
 
1452
 
 
1453
        /**
 
1454
         * Process an incoming TCP/IP connection on the specified socket.  Any
 
1455
         * exception that occurs during processing must be logged and swallowed.
 
1456
         * <b>NOTE</b>:  This method is called from our Connector's thread.  We
 
1457
         * must assign it to our own thread so that multiple simultaneous
 
1458
         * requests can be handled.
 
1459
         *
 
1460
         * @param socket TCP socket to process
 
1461
         */
 
1462
        protected synchronized void assignWithOptions(long socket) {
 
1463
 
 
1464
            // Wait for the Processor to get the previous Socket
 
1465
            while (available) {
 
1466
                try {
 
1467
                    wait();
 
1468
                } catch (InterruptedException e) {
 
1469
                }
 
1470
            }
 
1471
 
 
1472
            // Store the newly available Socket and notify our thread
 
1473
            this.socket = socket;
 
1474
            status = null;
 
1475
            options = true;
 
1476
            available = true;
 
1477
            notifyAll();
 
1478
 
 
1479
        }
 
1480
 
 
1481
 
 
1482
        /**
 
1483
         * Process an incoming TCP/IP connection on the specified socket.  Any
 
1484
         * exception that occurs during processing must be logged and swallowed.
 
1485
         * <b>NOTE</b>:  This method is called from our Connector's thread.  We
 
1486
         * must assign it to our own thread so that multiple simultaneous
 
1487
         * requests can be handled.
 
1488
         *
 
1489
         * @param socket TCP socket to process
 
1490
         */
 
1491
        protected synchronized void assign(long socket) {
 
1492
 
 
1493
            // Wait for the Processor to get the previous Socket
 
1494
            while (available) {
 
1495
                try {
 
1496
                    wait();
 
1497
                } catch (InterruptedException e) {
 
1498
                }
 
1499
            }
 
1500
 
 
1501
            // Store the newly available Socket and notify our thread
 
1502
            this.socket = socket;
 
1503
            status = null;
 
1504
            options = false;
 
1505
            available = true;
 
1506
            notifyAll();
 
1507
 
 
1508
        }
 
1509
 
 
1510
 
 
1511
        protected synchronized void assign(long socket, SocketStatus status) {
 
1512
 
 
1513
            // Wait for the Processor to get the previous Socket
 
1514
            while (available) {
 
1515
                try {
 
1516
                    wait();
 
1517
                } catch (InterruptedException e) {
 
1518
                }
 
1519
            }
 
1520
 
 
1521
            // Store the newly available Socket and notify our thread
 
1522
            this.socket = socket;
 
1523
            this.status = status;
 
1524
            options = false;
 
1525
            available = true;
 
1526
            notifyAll();
 
1527
 
 
1528
        }
 
1529
 
 
1530
 
 
1531
        /**
 
1532
         * Await a newly assigned Socket from our Connector, or <code>null</code>
 
1533
         * if we are supposed to shut down.
 
1534
         */
 
1535
        protected synchronized long await() {
 
1536
 
 
1537
            // Wait for the Connector to provide a new Socket
 
1538
            while (!available) {
 
1539
                try {
 
1540
                    wait();
 
1541
                } catch (InterruptedException e) {
 
1542
                }
 
1543
            }
 
1544
 
 
1545
            // Notify the Connector that we have received this Socket
 
1546
            long socket = this.socket;
 
1547
            available = false;
 
1548
            notifyAll();
 
1549
 
 
1550
            return (socket);
 
1551
 
 
1552
        }
 
1553
 
 
1554
 
 
1555
        /**
 
1556
         * The background thread that listens for incoming TCP/IP connections and
 
1557
         * hands them off to an appropriate processor.
 
1558
         */
 
1559
        public void run() {
 
1560
 
 
1561
            // Process requests until we receive a shutdown signal
 
1562
            while (running) {
 
1563
 
 
1564
                // Wait for the next socket to be assigned
 
1565
                long socket = await();
 
1566
                if (socket == 0)
 
1567
                    continue;
 
1568
 
 
1569
                if (!deferAccept && options) {
 
1570
                    if (setSocketOptions(socket)) {
 
1571
                        getPoller().add(socket);
 
1572
                    } else {
 
1573
                        // Close socket and pool
 
1574
                        Socket.destroy(socket);
 
1575
                        socket = 0;
 
1576
                    }
 
1577
                } else {
 
1578
 
 
1579
                    // Process the request from this socket
 
1580
                    if ((status != null) && (handler.event(socket, status) == Handler.SocketState.CLOSED)) {
 
1581
                        // Close socket and pool
 
1582
                        Socket.destroy(socket);
 
1583
                        socket = 0;
 
1584
                    } else if ((status == null) && ((options && !setSocketOptions(socket)) 
 
1585
                            || handler.process(socket) == Handler.SocketState.CLOSED)) {
 
1586
                        // Close socket and pool
 
1587
                        Socket.destroy(socket);
 
1588
                        socket = 0;
 
1589
                    }
 
1590
                }
 
1591
 
 
1592
                // Finish up this request
 
1593
                recycleWorkerThread(this);
 
1594
 
 
1595
            }
 
1596
 
 
1597
        }
 
1598
 
 
1599
 
 
1600
        /**
 
1601
         * Start the background processing thread.
 
1602
         */
 
1603
        public void start() {
 
1604
            thread = new Thread(this);
 
1605
            thread.setName(getName() + "-" + (++curThreads));
 
1606
            thread.setDaemon(true);
 
1607
            thread.start();
 
1608
        }
 
1609
 
 
1610
 
 
1611
    }
 
1612
 
 
1613
 
 
1614
    // ----------------------------------------------- SendfileData Inner Class
 
1615
 
 
1616
 
 
1617
    /**
 
1618
     * SendfileData class.
 
1619
     */
 
1620
    public static class SendfileData {
 
1621
        // File
 
1622
        public String fileName;
 
1623
        public long fd;
 
1624
        public long fdpool;
 
1625
        // Range information
 
1626
        public long start;
 
1627
        public long end;
 
1628
        // Socket and socket pool
 
1629
        public long socket;
 
1630
        // Position
 
1631
        public long pos;
 
1632
        // KeepAlive flag
 
1633
        public boolean keepAlive;
 
1634
    }
 
1635
 
 
1636
 
 
1637
    // --------------------------------------------------- Sendfile Inner Class
 
1638
 
 
1639
 
 
1640
    /**
 
1641
     * Sendfile class.
 
1642
     */
 
1643
    public class Sendfile implements Runnable {
 
1644
 
 
1645
        protected long sendfilePollset = 0;
 
1646
        protected long pool = 0;
 
1647
        protected long[] desc;
 
1648
        protected HashMap<Long, SendfileData> sendfileData;
 
1649
        
 
1650
        protected volatile int sendfileCount;
 
1651
        public int getSendfileCount() { return sendfileCount; }
 
1652
 
 
1653
        protected ArrayList<SendfileData> addS;
 
1654
        protected volatile int addCount;
 
1655
 
 
1656
        /**
 
1657
         * Create the sendfile poller. With some versions of APR, the maximum poller size will
 
1658
         * be 62 (reocmpiling APR is necessary to remove this limitation).
 
1659
         */
 
1660
        protected void init() {
 
1661
            pool = Pool.create(serverSockPool);
 
1662
            int size = sendfileSize / sendfileThreadCount;
 
1663
            sendfilePollset = allocatePoller(size, pool, soTimeout);
 
1664
            if (sendfilePollset == 0 && size > 1024) {
 
1665
                size = 1024;
 
1666
                sendfilePollset = allocatePoller(size, pool, soTimeout);
 
1667
            }
 
1668
            if (sendfilePollset == 0) {
 
1669
                size = 62;
 
1670
                sendfilePollset = allocatePoller(size, pool, soTimeout);
 
1671
            }
 
1672
            desc = new long[size * 2];
 
1673
            sendfileData = new HashMap<Long, SendfileData>(size);
 
1674
            addS = new ArrayList<SendfileData>();
 
1675
            addCount = 0;
 
1676
        }
 
1677
 
 
1678
        /**
 
1679
         * Destroy the poller.
 
1680
         */
 
1681
        protected void destroy() {
 
1682
            // Wait for polltime before doing anything, so that the poller threads
 
1683
            // exit, otherwise parallel descturction of sockets which are still
 
1684
            // in the poller can cause problems
 
1685
            try {
 
1686
                synchronized (this) {
 
1687
                    this.wait(pollTime / 1000);
 
1688
                }
 
1689
            } catch (InterruptedException e) {
 
1690
                // Ignore
 
1691
            }
 
1692
            // Close any socket remaining in the add queue
 
1693
            addCount = 0;
 
1694
            for (int i = (addS.size() - 1); i >= 0; i--) {
 
1695
                SendfileData data = addS.get(i);
 
1696
                Socket.destroy(data.socket);
 
1697
            }
 
1698
            // Close all sockets still in the poller
 
1699
            int rv = Poll.pollset(sendfilePollset, desc);
 
1700
            if (rv > 0) {
 
1701
                for (int n = 0; n < rv; n++) {
 
1702
                    Socket.destroy(desc[n*2+1]);
 
1703
                }
 
1704
            }
 
1705
            Pool.destroy(pool);
 
1706
            sendfileData.clear();
 
1707
        }
 
1708
 
 
1709
        /**
 
1710
         * Add the sendfile data to the sendfile poller. Note that in most cases,
 
1711
         * the initial non blocking calls to sendfile will return right away, and
 
1712
         * will be handled asynchronously inside the kernel. As a result,
 
1713
         * the poller will never be used.
 
1714
         *
 
1715
         * @param data containing the reference to the data which should be snet
 
1716
         * @return true if all the data has been sent right away, and false
 
1717
         *              otherwise
 
1718
         */
 
1719
        public boolean add(SendfileData data) {
 
1720
            // Initialize fd from data given
 
1721
            try {
 
1722
                data.fdpool = Socket.pool(data.socket);
 
1723
                data.fd = File.open
 
1724
                    (data.fileName, File.APR_FOPEN_READ
 
1725
                     | File.APR_FOPEN_SENDFILE_ENABLED | File.APR_FOPEN_BINARY,
 
1726
                     0, data.fdpool);
 
1727
                data.pos = data.start;
 
1728
                // Set the socket to nonblocking mode
 
1729
                Socket.timeoutSet(data.socket, 0);
 
1730
                while (true) {
 
1731
                    long nw = Socket.sendfilen(data.socket, data.fd,
 
1732
                                               data.pos, data.end - data.pos, 0);
 
1733
                    if (nw < 0) {
 
1734
                        if (!(-nw == Status.EAGAIN)) {
 
1735
                            Socket.destroy(data.socket);
 
1736
                            data.socket = 0;
 
1737
                            return false;
 
1738
                        } else {
 
1739
                            // Break the loop and add the socket to poller.
 
1740
                            break;
 
1741
                        }
 
1742
                    } else {
 
1743
                        data.pos = data.pos + nw;
 
1744
                        if (data.pos >= data.end) {
 
1745
                            // Entire file has been sent
 
1746
                            Pool.destroy(data.fdpool);
 
1747
                            // Set back socket to blocking mode
 
1748
                            Socket.timeoutSet(data.socket, soTimeout * 1000);
 
1749
                            return true;
 
1750
                        }
 
1751
                    }
 
1752
                }
 
1753
            } catch (Exception e) {
 
1754
                log.error(sm.getString("endpoint.sendfile.error"), e);
 
1755
                return false;
 
1756
            }
 
1757
            // Add socket to the list. Newly added sockets will wait
 
1758
            // at most for pollTime before being polled
 
1759
            synchronized (this) {
 
1760
                addS.add(data);
 
1761
                addCount++;
 
1762
                this.notify();
 
1763
            }
 
1764
            return false;
 
1765
        }
 
1766
 
 
1767
        /**
 
1768
         * Remove socket from the poller.
 
1769
         *
 
1770
         * @param data the sendfile data which should be removed
 
1771
         */
 
1772
        protected void remove(SendfileData data) {
 
1773
            int rv = Poll.remove(sendfilePollset, data.socket);
 
1774
            if (rv == Status.APR_SUCCESS) {
 
1775
                sendfileCount--;
 
1776
            }
 
1777
            sendfileData.remove(new Long(data.socket));
 
1778
        }
 
1779
 
 
1780
        /**
 
1781
         * The background thread that listens for incoming TCP/IP connections and
 
1782
         * hands them off to an appropriate processor.
 
1783
         */
 
1784
        public void run() {
 
1785
 
 
1786
            long maintainTime = 0;
 
1787
            // Loop until we receive a shutdown command
 
1788
            while (running) {
 
1789
 
 
1790
                // Loop if endpoint is paused
 
1791
                while (paused) {
 
1792
                    try {
 
1793
                        Thread.sleep(1000);
 
1794
                    } catch (InterruptedException e) {
 
1795
                        // Ignore
 
1796
                    }
 
1797
                }
 
1798
 
 
1799
                if (sendfileCount < 1 && addCount < 1) {
 
1800
                    synchronized (this) {
 
1801
                        while (sendfileCount < 1 && addS.size() < 1) {
 
1802
                            // Reset maintain time.
 
1803
                            maintainTime = 0;
 
1804
                            try {
 
1805
                                this.wait();
 
1806
                            } catch (InterruptedException e) {
 
1807
                                // Ignore
 
1808
                            }
 
1809
                        }
 
1810
                    }
 
1811
                }
 
1812
 
 
1813
                try {
 
1814
                    // Add socket to the poller
 
1815
                    if (addCount > 0) {
 
1816
                        synchronized (this) {
 
1817
                            int successCount = 0;
 
1818
                            try {
 
1819
                                for (int i = (addS.size() - 1); i >= 0; i--) {
 
1820
                                    SendfileData data = addS.get(i);
 
1821
                                    int rv = Poll.add(sendfilePollset, data.socket, Poll.APR_POLLOUT);
 
1822
                                    if (rv == Status.APR_SUCCESS) {
 
1823
                                        sendfileData.put(new Long(data.socket), data);
 
1824
                                        successCount++;
 
1825
                                    } else {
 
1826
                                        log.warn(sm.getString("endpoint.sendfile.addfail", "" + rv, Error.strerror(rv)));
 
1827
                                        // Can't do anything: close the socket right away
 
1828
                                        Socket.destroy(data.socket);
 
1829
                                    }
 
1830
                                }
 
1831
                            } finally {
 
1832
                                sendfileCount += successCount;
 
1833
                                addS.clear();
 
1834
                                addCount = 0;
 
1835
                            }
 
1836
                        }
 
1837
                    }
 
1838
 
 
1839
                    maintainTime += pollTime;
 
1840
                    // Pool for the specified interval
 
1841
                    int rv = Poll.poll(sendfilePollset, pollTime, desc, false);
 
1842
                    if (rv > 0) {
 
1843
                        for (int n = 0; n < rv; n++) {
 
1844
                            // Get the sendfile state
 
1845
                            SendfileData state =
 
1846
                                sendfileData.get(new Long(desc[n*2+1]));
 
1847
                            // Problem events
 
1848
                            if (((desc[n*2] & Poll.APR_POLLHUP) == Poll.APR_POLLHUP)
 
1849
                                    || ((desc[n*2] & Poll.APR_POLLERR) == Poll.APR_POLLERR)) {
 
1850
                                // Close socket and clear pool
 
1851
                                remove(state);
 
1852
                                // Destroy file descriptor pool, which should close the file
 
1853
                                // Close the socket, as the reponse would be incomplete
 
1854
                                Socket.destroy(state.socket);
 
1855
                                continue;
 
1856
                            }
 
1857
                            // Write some data using sendfile
 
1858
                            long nw = Socket.sendfilen(state.socket, state.fd,
 
1859
                                                       state.pos,
 
1860
                                                       state.end - state.pos, 0);
 
1861
                            if (nw < 0) {
 
1862
                                // Close socket and clear pool
 
1863
                                remove(state);
 
1864
                                // Close the socket, as the reponse would be incomplete
 
1865
                                // This will close the file too.
 
1866
                                Socket.destroy(state.socket);
 
1867
                                continue;
 
1868
                            }
 
1869
 
 
1870
                            state.pos = state.pos + nw;
 
1871
                            if (state.pos >= state.end) {
 
1872
                                remove(state);
 
1873
                                if (state.keepAlive) {
 
1874
                                    // Destroy file descriptor pool, which should close the file
 
1875
                                    Pool.destroy(state.fdpool);
 
1876
                                    Socket.timeoutSet(state.socket, soTimeout * 1000);
 
1877
                                    // If all done put the socket back in the poller for
 
1878
                                    // processing of further requests
 
1879
                                    getPoller().add(state.socket);
 
1880
                                } else {
 
1881
                                    // Close the socket since this is
 
1882
                                    // the end of not keep-alive request.
 
1883
                                    Socket.destroy(state.socket);
 
1884
                                }
 
1885
                            }
 
1886
                        }
 
1887
                    } else if (rv < 0) {
 
1888
                        int errn = -rv;
 
1889
                        /* Any non timeup or interrupted error is critical */
 
1890
                        if ((errn != Status.TIMEUP) && (errn != Status.EINTR)) {
 
1891
                            if (errn >  Status.APR_OS_START_USERERR) {
 
1892
                                errn -=  Status.APR_OS_START_USERERR;
 
1893
                            }
 
1894
                            log.error(sm.getString("endpoint.poll.fail", "" + errn, Error.strerror(errn)));
 
1895
                            // Handle poll critical failure
 
1896
                            synchronized (this) {
 
1897
                                destroy();
 
1898
                                init();
 
1899
                            }
 
1900
                            continue;
 
1901
                        }
 
1902
                    }
 
1903
                    // Call maintain for the sendfile poller
 
1904
                    if (soTimeout > 0 && maintainTime > 1000000L && running) {
 
1905
                        rv = Poll.maintain(sendfilePollset, desc, true);
 
1906
                        maintainTime = 0;
 
1907
                        if (rv > 0) {
 
1908
                            for (int n = 0; n < rv; n++) {
 
1909
                                // Get the sendfile state
 
1910
                                SendfileData state = sendfileData.get(new Long(desc[n]));
 
1911
                                // Close socket and clear pool
 
1912
                                remove(state);
 
1913
                                // Destroy file descriptor pool, which should close the file
 
1914
                                // Close the socket, as the response would be incomplete
 
1915
                                Socket.destroy(state.socket);
 
1916
                            }
 
1917
                        }
 
1918
                    }
 
1919
                } catch (Throwable t) {
 
1920
                    log.error(sm.getString("endpoint.poll.error"), t);
 
1921
                }
 
1922
            }
 
1923
 
 
1924
            synchronized (this) {
 
1925
                this.notifyAll();
 
1926
            }
 
1927
 
 
1928
        }
 
1929
 
 
1930
    }
 
1931
 
 
1932
 
 
1933
    // ------------------------------------------------ Handler Inner Interface
 
1934
 
 
1935
 
 
1936
    /**
 
1937
     * Bare bones interface used for socket processing. Per thread data is to be
 
1938
     * stored in the ThreadWithAttributes extra folders, or alternately in
 
1939
     * thread local fields.
 
1940
     */
 
1941
    public interface Handler {
 
1942
        public enum SocketState {
 
1943
            OPEN, CLOSED, LONG
 
1944
        }
 
1945
        public SocketState process(long socket);
 
1946
        public SocketState event(long socket, SocketStatus status);
 
1947
    }
 
1948
 
 
1949
 
 
1950
    // ------------------------------------------------- WorkerStack Inner Class
 
1951
 
 
1952
 
 
1953
    public class WorkerStack {
 
1954
        
 
1955
        protected Worker[] workers = null;
 
1956
        protected int end = 0;
 
1957
        
 
1958
        public WorkerStack(int size) {
 
1959
            workers = new Worker[size];
 
1960
        }
 
1961
        
 
1962
        /** 
 
1963
         * Put the object into the queue. If the queue is full (for example if
 
1964
         * the queue has been reduced in size) the object will be dropped.
 
1965
         * 
 
1966
         * @param   object  the object to be appended to the queue (first
 
1967
         *                  element).
 
1968
         */
 
1969
        public void push(Worker worker) {
 
1970
            if (end < workers.length) {
 
1971
                workers[end++] = worker;
 
1972
            } else {
 
1973
                curThreads--;
 
1974
            }
 
1975
        }
 
1976
        
 
1977
        /**
 
1978
         * Get the first object out of the queue. Return null if the queue
 
1979
         * is empty. 
 
1980
         */
 
1981
        public Worker pop() {
 
1982
            if (end > 0) {
 
1983
                return workers[--end];
 
1984
            }
 
1985
            return null;
 
1986
        }
 
1987
        
 
1988
        /**
 
1989
         * Get the first object out of the queue, Return null if the queue
 
1990
         * is empty.
 
1991
         */
 
1992
        public Worker peek() {
 
1993
            return workers[end];
 
1994
        }
 
1995
        
 
1996
        /**
 
1997
         * Is the queue empty?
 
1998
         */
 
1999
        public boolean isEmpty() {
 
2000
            return (end == 0);
 
2001
        }
 
2002
        
 
2003
        /**
 
2004
         * How many elements are there in this queue?
 
2005
         */
 
2006
        public int size() {
 
2007
            return (end);
 
2008
        }
 
2009
        
 
2010
        /**
 
2011
         * Resize the queue. If there are too many objects in the queue for the
 
2012
         * new size, drop the excess.
 
2013
         * 
 
2014
         * @param newSize
 
2015
         */
 
2016
        public void resize(int newSize) {
 
2017
            Worker[] newWorkers = new Worker[newSize];
 
2018
            int len = workers.length;
 
2019
            if (newSize < len) {
 
2020
                len = newSize;
 
2021
            }
 
2022
            System.arraycopy(workers, 0, newWorkers, 0, len);
 
2023
            workers = newWorkers;
 
2024
        }
 
2025
    }
 
2026
 
 
2027
 
 
2028
    // ---------------------------------------------- SocketProcessor Inner Class
 
2029
 
 
2030
 
 
2031
    /**
 
2032
     * This class is the equivalent of the Worker, but will simply use in an
 
2033
     * external Executor thread pool. This will also set the socket options
 
2034
     * and do the handshake.
 
2035
     */
 
2036
    protected class SocketWithOptionsProcessor implements Runnable {
 
2037
        
 
2038
        protected long socket = 0;
 
2039
        
 
2040
        public SocketWithOptionsProcessor(long socket) {
 
2041
            this.socket = socket;
 
2042
        }
 
2043
 
 
2044
        public void run() {
 
2045
 
 
2046
            if (!deferAccept) {
 
2047
                if (setSocketOptions(socket)) {
 
2048
                    getPoller().add(socket);
 
2049
                } else {
 
2050
                    // Close socket and pool
 
2051
                    Socket.destroy(socket);
 
2052
                    socket = 0;
 
2053
                }
 
2054
            } else {
 
2055
                // Process the request from this socket
 
2056
                if (!setSocketOptions(socket) 
 
2057
                        || handler.process(socket) == Handler.SocketState.CLOSED) {
 
2058
                    // Close socket and pool
 
2059
                    Socket.destroy(socket);
 
2060
                    socket = 0;
 
2061
                }
 
2062
            }
 
2063
 
 
2064
        }
 
2065
        
 
2066
    }
 
2067
    
 
2068
    
 
2069
    // ---------------------------------------------- SocketProcessor Inner Class
 
2070
 
 
2071
 
 
2072
    /**
 
2073
     * This class is the equivalent of the Worker, but will simply use in an
 
2074
     * external Executor thread pool.
 
2075
     */
 
2076
    protected class SocketProcessor implements Runnable {
 
2077
        
 
2078
        protected long socket = 0;
 
2079
        
 
2080
        public SocketProcessor(long socket) {
 
2081
            this.socket = socket;
 
2082
        }
 
2083
 
 
2084
        public void run() {
 
2085
 
 
2086
            // Process the request from this socket
 
2087
            if (handler.process(socket) == Handler.SocketState.CLOSED) {
 
2088
                // Close socket and pool
 
2089
                Socket.destroy(socket);
 
2090
                socket = 0;
 
2091
            }
 
2092
 
 
2093
        }
 
2094
        
 
2095
    }
 
2096
    
 
2097
    
 
2098
    // --------------------------------------- SocketEventProcessor Inner Class
 
2099
 
 
2100
 
 
2101
    /**
 
2102
     * This class is the equivalent of the Worker, but will simply use in an
 
2103
     * external Executor thread pool.
 
2104
     */
 
2105
    protected class SocketEventProcessor implements Runnable {
 
2106
        
 
2107
        protected long socket = 0;
 
2108
        protected SocketStatus status = null; 
 
2109
        
 
2110
        public SocketEventProcessor(long socket, SocketStatus status) {
 
2111
            this.socket = socket;
 
2112
            this.status = status;
 
2113
        }
 
2114
 
 
2115
        public void run() {
 
2116
 
 
2117
            // Process the request from this socket
 
2118
            if (handler.event(socket, status) == Handler.SocketState.CLOSED) {
 
2119
                // Close socket and pool
 
2120
                Socket.destroy(socket);
 
2121
                socket = 0;
 
2122
            }
 
2123
 
 
2124
        }
 
2125
        
 
2126
    }
 
2127
    
 
2128
    
 
2129
}