PageRenderTime 56ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/tc6.0.x/tags/TOMCAT_6_0_10/java/org/apache/tomcat/util/net/AprEndpoint.java

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