PageRenderTime 61ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

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

#
Java | 1703 lines | 1003 code | 295 blank | 405 comment | 186 complexity | c28ee0c600a18d2c3e1a51273b125a96 MD5 | raw file

Large files files are truncated, but you can click here to view the full 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.io.FileInputStream;
  19. import java.io.IOException;
  20. import java.net.InetAddress;
  21. import java.net.InetSocketAddress;
  22. import java.net.Socket;
  23. import java.nio.ByteBuffer;
  24. import java.nio.channels.CancelledKeyException;
  25. import java.nio.channels.SelectionKey;
  26. import java.nio.channels.Selector;
  27. import java.nio.channels.ServerSocketChannel;
  28. import java.nio.channels.SocketChannel;
  29. import java.security.KeyStore;
  30. import java.util.Iterator;
  31. import java.util.Set;
  32. import java.util.StringTokenizer;
  33. import java.util.concurrent.ConcurrentLinkedQueue;
  34. import java.util.concurrent.Executor;
  35. import java.util.concurrent.atomic.AtomicLong;
  36. import javax.net.ssl.KeyManagerFactory;
  37. import javax.net.ssl.SSLContext;
  38. import javax.net.ssl.SSLEngine;
  39. import javax.net.ssl.TrustManagerFactory;
  40. import org.apache.juli.logging.Log;
  41. import org.apache.juli.logging.LogFactory;
  42. import org.apache.tomcat.util.IntrospectionUtils;
  43. import org.apache.tomcat.util.net.SecureNioChannel.ApplicationBufferHandler;
  44. import org.apache.tomcat.util.res.StringManager;
  45. import java.util.concurrent.atomic.AtomicInteger;
  46. /**
  47. * NIO tailored thread pool, providing the following services:
  48. * <ul>
  49. * <li>Socket acceptor thread</li>
  50. * <li>Socket poller thread</li>
  51. * <li>Worker threads pool</li>
  52. * </ul>
  53. *
  54. * When switching to Java 5, there's an opportunity to use the virtual
  55. * machine's thread pool.
  56. *
  57. * @author Mladen Turk
  58. * @author Remy Maucherat
  59. * @author Filip Hanik
  60. */
  61. public class NioEndpoint {
  62. // -------------------------------------------------------------- Constants
  63. protected static Log log = LogFactory.getLog(NioEndpoint.class);
  64. protected static StringManager sm =
  65. StringManager.getManager("org.apache.tomcat.util.net.res");
  66. /**
  67. * The Request attribute key for the cipher suite.
  68. */
  69. public static final String CIPHER_SUITE_KEY = "javax.servlet.request.cipher_suite";
  70. /**
  71. * The Request attribute key for the key size.
  72. */
  73. public static final String KEY_SIZE_KEY = "javax.servlet.request.key_size";
  74. /**
  75. * The Request attribute key for the client certificate chain.
  76. */
  77. public static final String CERTIFICATE_KEY = "javax.servlet.request.X509Certificate";
  78. /**
  79. * The Request attribute key for the session id.
  80. * This one is a Tomcat extension to the Servlet spec.
  81. */
  82. public static final String SESSION_ID_KEY = "javax.servlet.request.ssl_session";
  83. public static final int OP_REGISTER = -1; //register interest op
  84. // ----------------------------------------------------------------- Fields
  85. /**
  86. * Available workers.
  87. */
  88. protected WorkerStack workers = null;
  89. /**
  90. * Running state of the endpoint.
  91. */
  92. protected volatile boolean running = false;
  93. /**
  94. * Will be set to true whenever the endpoint is paused.
  95. */
  96. protected volatile boolean paused = false;
  97. /**
  98. * Track the initialization state of the endpoint.
  99. */
  100. protected boolean initialized = false;
  101. /**
  102. * Current worker threads busy count.
  103. */
  104. protected int curThreadsBusy = 0;
  105. /**
  106. * Current worker threads count.
  107. */
  108. protected int curThreads = 0;
  109. /**
  110. * Sequence number used to generate thread names.
  111. */
  112. protected int sequence = 0;
  113. protected NioSelectorPool selectorPool = new NioSelectorPool();
  114. /**
  115. * Server socket "pointer".
  116. */
  117. protected ServerSocketChannel serverSock = null;
  118. /**
  119. * Cache for key attachment objects
  120. */
  121. protected ConcurrentLinkedQueue<KeyAttachment> keyCache = new ConcurrentLinkedQueue<KeyAttachment>();
  122. /**
  123. * Cache for poller events
  124. */
  125. protected ConcurrentLinkedQueue<PollerEvent> eventCache = new ConcurrentLinkedQueue<PollerEvent>();
  126. /**
  127. * Bytebuffer cache, each channel holds a set of buffers (two, except for SSL holds four)
  128. */
  129. protected ConcurrentLinkedQueue<NioChannel> nioChannels = new ConcurrentLinkedQueue<NioChannel>() {
  130. protected AtomicInteger size = new AtomicInteger(0);
  131. protected AtomicInteger bytes = new AtomicInteger(0);
  132. public boolean offer(NioChannel socket, KeyAttachment att) {
  133. boolean offer = socketProperties.getBufferPool()==-1?true:size.get()<socketProperties.getBufferPool();
  134. offer = offer && (socketProperties.getBufferPoolSize()==-1?true:(bytes.get()+socket.getBufferSize())<socketProperties.getBufferPoolSize());
  135. //avoid over growing our cache or add after we have stopped
  136. if ( running && (!paused) && (offer) ) {
  137. boolean result = super.offer(socket);
  138. if ( result ) {
  139. size.incrementAndGet();
  140. bytes.addAndGet(socket.getBufferSize());
  141. }
  142. return result;
  143. }
  144. else return false;
  145. }
  146. public NioChannel poll() {
  147. NioChannel result = super.poll();
  148. if ( result != null ) {
  149. size.decrementAndGet();
  150. bytes.addAndGet(-result.getBufferSize());
  151. }
  152. return result;
  153. }
  154. public void clear() {
  155. super.clear();
  156. size.set(0);
  157. }
  158. };
  159. // ------------------------------------------------------------- Properties
  160. /**
  161. * External Executor based thread pool.
  162. */
  163. protected Executor executor = null;
  164. public void setExecutor(Executor executor) { this.executor = executor; }
  165. public Executor getExecutor() { return executor; }
  166. /**
  167. * Maximum amount of worker threads.
  168. */
  169. protected int maxThreads = 400;
  170. public void setMaxThreads(int maxThreads) { this.maxThreads = maxThreads; }
  171. public int getMaxThreads() { return maxThreads; }
  172. /**
  173. * Priority of the acceptor and poller threads.
  174. */
  175. protected int threadPriority = Thread.NORM_PRIORITY;
  176. public void setThreadPriority(int threadPriority) { this.threadPriority = threadPriority; }
  177. public int getThreadPriority() { return threadPriority; }
  178. /**
  179. * Server socket port.
  180. */
  181. protected int port;
  182. public int getPort() { return port; }
  183. public void setPort(int port ) { this.port=port; }
  184. /**
  185. * Address for the server socket.
  186. */
  187. protected InetAddress address;
  188. public InetAddress getAddress() { return address; }
  189. public void setAddress(InetAddress address) { this.address = address; }
  190. /**
  191. * Handling of accepted sockets.
  192. */
  193. protected Handler handler = null;
  194. public void setHandler(Handler handler ) { this.handler = handler; }
  195. public Handler getHandler() { return handler; }
  196. /**
  197. * Allows the server developer to specify the backlog that
  198. * should be used for server sockets. By default, this value
  199. * is 100.
  200. */
  201. protected int backlog = 100;
  202. public void setBacklog(int backlog) { if (backlog > 0) this.backlog = backlog; }
  203. public int getBacklog() { return backlog; }
  204. protected SocketProperties socketProperties = new SocketProperties();
  205. /**
  206. * Socket TCP no delay.
  207. */
  208. public boolean getTcpNoDelay() { return socketProperties.getTcpNoDelay();}
  209. public void setTcpNoDelay(boolean tcpNoDelay) { socketProperties.setTcpNoDelay(tcpNoDelay); }
  210. /**
  211. * Socket linger.
  212. */
  213. public int getSoLinger() { return socketProperties.getSoLingerTime(); }
  214. public void setSoLinger(int soLinger) {
  215. socketProperties.setSoLingerTime(soLinger);
  216. socketProperties.setSoLingerOn(soLinger>=0);
  217. }
  218. /**
  219. * Socket timeout.
  220. */
  221. public int getSoTimeout() { return socketProperties.getSoTimeout(); }
  222. public void setSoTimeout(int soTimeout) { socketProperties.setSoTimeout(soTimeout); }
  223. /**
  224. * Timeout on first request read before going to the poller, in ms.
  225. */
  226. protected int firstReadTimeout = 60000;
  227. public int getFirstReadTimeout() { return firstReadTimeout; }
  228. public void setFirstReadTimeout(int firstReadTimeout) { this.firstReadTimeout = firstReadTimeout; }
  229. /**
  230. * The default is true - the created threads will be
  231. * in daemon mode. If set to false, the control thread
  232. * will not be daemon - and will keep the process alive.
  233. */
  234. protected boolean daemon = true;
  235. public void setDaemon(boolean b) { daemon = b; }
  236. public boolean getDaemon() { return daemon; }
  237. /**
  238. * Name of the thread pool, which will be used for naming child threads.
  239. */
  240. protected String name = "TP";
  241. public void setName(String name) { this.name = name; }
  242. public String getName() { return name; }
  243. /**
  244. * Allow comet request handling.
  245. */
  246. protected boolean useComet = true;
  247. public void setUseComet(boolean useComet) { this.useComet = useComet; }
  248. public boolean getUseComet() { return useComet; }
  249. /**
  250. * Acceptor thread count.
  251. */
  252. protected int acceptorThreadCount = 0;
  253. public void setAcceptorThreadCount(int acceptorThreadCount) { this.acceptorThreadCount = acceptorThreadCount; }
  254. public int getAcceptorThreadCount() { return acceptorThreadCount; }
  255. /**
  256. * Poller thread count.
  257. */
  258. protected int pollerThreadCount = 0;
  259. public void setPollerThreadCount(int pollerThreadCount) { this.pollerThreadCount = pollerThreadCount; }
  260. public int getPollerThreadCount() { return pollerThreadCount; }
  261. protected long selectorTimeout = 1000;
  262. public void setSelectorTimeout(long timeout){ this.selectorTimeout = timeout;}
  263. public long getSelectorTimeout(){ return this.selectorTimeout; }
  264. /**
  265. * The socket poller.
  266. */
  267. protected Poller[] pollers = null;
  268. protected int pollerRoundRobin = 0;
  269. public Poller getPoller0() {
  270. pollerRoundRobin = (pollerRoundRobin + 1) % pollers.length;
  271. Poller poller = pollers[pollerRoundRobin];
  272. return poller;
  273. }
  274. /**
  275. * The socket poller used for Comet support.
  276. */
  277. public Poller getCometPoller0() {
  278. Poller poller = getPoller0();
  279. return poller;
  280. }
  281. /**
  282. * Dummy maxSpareThreads property.
  283. */
  284. public int getMaxSpareThreads() { return Math.min(getMaxThreads(),5); }
  285. /**
  286. * Dummy minSpareThreads property.
  287. */
  288. public int getMinSpareThreads() { return Math.min(getMaxThreads(),5); }
  289. /**
  290. * Generic properties, introspected
  291. */
  292. public void setProperty(String name, String value) {
  293. final String selectorPoolName = "selectorPool.";
  294. final String socketName = "socket.";
  295. try {
  296. if (name.startsWith(selectorPoolName)) {
  297. IntrospectionUtils.setProperty(selectorPool, name.substring(selectorPoolName.length()), value);
  298. } else if (name.startsWith(socketName)) {
  299. IntrospectionUtils.setProperty(socketProperties, name.substring(socketName.length()), value);
  300. }
  301. }catch ( Exception x ) {
  302. log.error("Unable to set attribute \""+name+"\" to \""+value+"\"",x);
  303. }
  304. }
  305. // -------------------- SSL related properties --------------------
  306. protected String keystoreFile = System.getProperty("user.home")+"/.keystore";
  307. public String getKeystoreFile() { return keystoreFile;}
  308. public void setKeystoreFile(String s ) { this.keystoreFile = s; }
  309. public void setKeystore(String s ) { setKeystoreFile(s);}
  310. public String getKeystore() { return getKeystoreFile();}
  311. protected String algorithm = "SunX509";
  312. public String getAlgorithm() { return algorithm;}
  313. public void setAlgorithm(String s ) { this.algorithm = s;}
  314. protected boolean clientAuth = false;
  315. public boolean getClientAuth() { return clientAuth;}
  316. public void setClientAuth(boolean b ) { this.clientAuth = b;}
  317. protected String keystorePass = "changeit";
  318. public String getKeystorePass() { return keystorePass;}
  319. public void setKeystorePass(String s ) { this.keystorePass = s;}
  320. protected String keystoreType = "JKS";
  321. public String getKeystoreType() { return keystoreType;}
  322. public void setKeystoreType(String s ) { this.keystoreType = s;}
  323. protected String sslProtocol = "TLS";
  324. public String getSslProtocol() { return sslProtocol;}
  325. public void setSslProtocol(String s) { sslProtocol = s;}
  326. protected String sslEnabledProtocols=null; //"TLSv1,SSLv3,SSLv2Hello"
  327. protected String[] sslEnabledProtocolsarr = new String[0];
  328. public void setSslEnabledProtocols(String s) {
  329. this.sslEnabledProtocols = s;
  330. StringTokenizer t = new StringTokenizer(s,",");
  331. sslEnabledProtocolsarr = new String[t.countTokens()];
  332. for (int i=0; i<sslEnabledProtocolsarr.length; i++ ) sslEnabledProtocolsarr[i] = t.nextToken();
  333. }
  334. protected String ciphers = null;
  335. protected String[] ciphersarr = new String[0];
  336. public String getCiphers() { return ciphers;}
  337. public void setCiphers(String s) {
  338. ciphers = s;
  339. if ( s == null ) ciphersarr = new String[0];
  340. else {
  341. StringTokenizer t = new StringTokenizer(s,",");
  342. ciphersarr = new String[t.countTokens()];
  343. for (int i=0; i<ciphersarr.length; i++ ) ciphersarr[i] = t.nextToken();
  344. }
  345. }
  346. /**
  347. * SSL engine.
  348. */
  349. protected boolean SSLEnabled = false;
  350. public boolean isSSLEnabled() { return SSLEnabled;}
  351. public void setSSLEnabled(boolean SSLEnabled) {this.SSLEnabled = SSLEnabled;}
  352. protected boolean secure = false;
  353. public boolean getSecure() { return secure;}
  354. public void setSecure(boolean b) { secure = b;}
  355. public void setSelectorPool(NioSelectorPool selectorPool) {
  356. this.selectorPool = selectorPool;
  357. }
  358. public void setSocketProperties(SocketProperties socketProperties) {
  359. this.socketProperties = socketProperties;
  360. }
  361. protected SSLContext sslContext = null;
  362. public SSLContext getSSLContext() { return sslContext;}
  363. public void setSSLContext(SSLContext c) { sslContext = c;}
  364. // --------------------------------------------------------- Public Methods
  365. /**
  366. * Number of keepalive sockets.
  367. */
  368. public int getKeepAliveCount() {
  369. if (pollers == null) {
  370. return 0;
  371. } else {
  372. int keepAliveCount = 0;
  373. for (int i = 0; i < pollers.length; i++) {
  374. keepAliveCount += pollers[i].getKeepAliveCount();
  375. }
  376. return keepAliveCount;
  377. }
  378. }
  379. /**
  380. * Return the amount of threads that are managed by the pool.
  381. *
  382. * @return the amount of threads that are managed by the pool
  383. */
  384. public int getCurrentThreadCount() {
  385. return curThreads;
  386. }
  387. /**
  388. * Return the amount of threads currently busy.
  389. *
  390. * @return the amount of threads currently busy
  391. */
  392. public int getCurrentThreadsBusy() {
  393. return curThreadsBusy;
  394. }
  395. /**
  396. * Return the state of the endpoint.
  397. *
  398. * @return true if the endpoint is running, false otherwise
  399. */
  400. public boolean isRunning() {
  401. return running;
  402. }
  403. /**
  404. * Return the state of the endpoint.
  405. *
  406. * @return true if the endpoint is paused, false otherwise
  407. */
  408. public boolean isPaused() {
  409. return paused;
  410. }
  411. // ----------------------------------------------- Public Lifecycle Methods
  412. /**
  413. * Initialize the endpoint.
  414. */
  415. public void init()
  416. throws Exception {
  417. if (initialized)
  418. return;
  419. serverSock = ServerSocketChannel.open();
  420. InetSocketAddress addr = (address!=null?new InetSocketAddress(address,port):new InetSocketAddress(port));
  421. serverSock.socket().bind(addr,100); //todo, set backlog value
  422. serverSock.configureBlocking(true); //mimic APR behavior
  423. // Initialize thread count defaults for acceptor, poller and sendfile
  424. if (acceptorThreadCount == 0) {
  425. // FIXME: Doesn't seem to work that well with multiple accept threads
  426. acceptorThreadCount = 1;
  427. }
  428. if (pollerThreadCount <= 0) {
  429. //minimum one poller thread
  430. pollerThreadCount = 1;
  431. }
  432. // Initialize SSL if needed
  433. if (isSSLEnabled()) {
  434. // Initialize SSL
  435. char[] passphrase = getKeystorePass().toCharArray();
  436. KeyStore ks = KeyStore.getInstance(getKeystoreType());
  437. ks.load(new FileInputStream(getKeystoreFile()), passphrase);
  438. KeyStore ts = KeyStore.getInstance(getKeystoreType());
  439. ts.load(new FileInputStream(getKeystoreFile()), passphrase);
  440. KeyManagerFactory kmf = KeyManagerFactory.getInstance(getAlgorithm());
  441. kmf.init(ks, passphrase);
  442. TrustManagerFactory tmf = TrustManagerFactory.getInstance(getAlgorithm());
  443. tmf.init(ts);
  444. sslContext = SSLContext.getInstance(getSslProtocol());
  445. sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
  446. }
  447. initialized = true;
  448. }
  449. /**
  450. * Start the APR endpoint, creating acceptor, poller threads.
  451. */
  452. public void start()
  453. throws Exception {
  454. // Initialize socket if not done before
  455. if (!initialized) {
  456. init();
  457. }
  458. if (!running) {
  459. running = true;
  460. paused = false;
  461. // Create worker collection
  462. if (executor == null) {
  463. workers = new WorkerStack(maxThreads);
  464. //executor = new ThreadPoolExecutor(getMinSpareThreads(),getMaxThreads(),5000,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
  465. }
  466. // Start acceptor threads
  467. for (int i = 0; i < acceptorThreadCount; i++) {
  468. Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i);
  469. acceptorThread.setPriority(threadPriority);
  470. acceptorThread.setDaemon(daemon);
  471. acceptorThread.start();
  472. }
  473. // Start poller threads
  474. pollers = new Poller[pollerThreadCount];
  475. for (int i = 0; i < pollerThreadCount; i++) {
  476. pollers[i] = new Poller();
  477. pollers[i].init();
  478. Thread pollerThread = new Thread(pollers[i], getName() + "-Poller-" + i);
  479. pollerThread.setPriority(threadPriority);
  480. pollerThread.setDaemon(true);
  481. pollerThread.start();
  482. }
  483. }
  484. }
  485. /**
  486. * Pause the endpoint, which will make it stop accepting new sockets.
  487. */
  488. public void pause() {
  489. if (running && !paused) {
  490. paused = true;
  491. unlockAccept();
  492. }
  493. }
  494. /**
  495. * Resume the endpoint, which will make it start accepting new sockets
  496. * again.
  497. */
  498. public void resume() {
  499. if (running) {
  500. paused = false;
  501. }
  502. }
  503. /**
  504. * Stop the endpoint. This will cause all processing threads to stop.
  505. */
  506. public void stop() {
  507. if (running) {
  508. running = false;
  509. unlockAccept();
  510. for (int i = 0; i < pollers.length; i++) {
  511. pollers[i].destroy();
  512. }
  513. pollers = null;
  514. }
  515. eventCache.clear();
  516. keyCache.clear();
  517. nioChannels.clear();
  518. }
  519. /**
  520. * Deallocate APR memory pools, and close server socket.
  521. */
  522. public void destroy() throws Exception {
  523. if (running) {
  524. stop();
  525. }
  526. // Close server socket
  527. serverSock.socket().close();
  528. serverSock.close();
  529. serverSock = null;
  530. sslContext = null;
  531. initialized = false;
  532. nioChannels.clear();
  533. }
  534. // ------------------------------------------------------ Protected Methods
  535. /**
  536. * Get a sequence number used for thread naming.
  537. */
  538. protected int getSequence() {
  539. return sequence++;
  540. }
  541. public int getWriteBufSize() {
  542. return socketProperties.getTxBufSize();
  543. }
  544. public int getReadBufSize() {
  545. return socketProperties.getRxBufSize();
  546. }
  547. public NioSelectorPool getSelectorPool() {
  548. return selectorPool;
  549. }
  550. public SocketProperties getSocketProperties() {
  551. return socketProperties;
  552. }
  553. /**
  554. * Unlock the server socket accept using a bogus connection.
  555. */
  556. protected void unlockAccept() {
  557. java.net.Socket s = null;
  558. try {
  559. // Need to create a connection to unlock the accept();
  560. if (address == null) {
  561. s = new java.net.Socket("127.0.0.1", port);
  562. } else {
  563. s = new java.net.Socket(address, port);
  564. // setting soLinger to a small value will help shutdown the
  565. // connection quicker
  566. s.setSoLinger(true, 0);
  567. }
  568. } catch(Exception e) {
  569. if (log.isDebugEnabled()) {
  570. log.debug(sm.getString("endpoint.debug.unlock", "" + port), e);
  571. }
  572. } finally {
  573. if (s != null) {
  574. try {
  575. s.close();
  576. } catch (Exception e) {
  577. // Ignore
  578. }
  579. }
  580. }
  581. }
  582. /**
  583. * Process the specified connection.
  584. */
  585. protected boolean setSocketOptions(SocketChannel socket) {
  586. // Process the connection
  587. int step = 1;
  588. try {
  589. //disable blocking, APR style, we are gonna be polling it
  590. socket.configureBlocking(false);
  591. Socket sock = socket.socket();
  592. socketProperties.setProperties(sock);
  593. NioChannel channel = nioChannels.poll();
  594. if ( channel == null ) {
  595. // 2: SSL setup
  596. step = 2;
  597. if (sslContext != null) {
  598. SSLEngine engine = createSSLEngine();
  599. int appbufsize = engine.getSession().getApplicationBufferSize();
  600. NioBufferHandler bufhandler = new NioBufferHandler(Math.max(appbufsize,getReadBufSize()),
  601. Math.max(appbufsize,getWriteBufSize()),
  602. socketProperties.getDirectBuffer());
  603. channel = new SecureNioChannel(socket, engine, bufhandler, selectorPool);
  604. } else {
  605. NioBufferHandler bufhandler = new NioBufferHandler(getReadBufSize(),
  606. getWriteBufSize(),
  607. socketProperties.getDirectBuffer());
  608. channel = new NioChannel(socket, bufhandler);
  609. }
  610. } else {
  611. channel.setIOChannel(socket);
  612. if ( channel instanceof SecureNioChannel ) {
  613. SSLEngine engine = createSSLEngine();
  614. ((SecureNioChannel)channel).reset(engine);
  615. } else {
  616. channel.reset();
  617. }
  618. }
  619. getPoller0().register(channel);
  620. } catch (Throwable t) {
  621. try {
  622. log.error("",t);
  623. }catch ( Throwable tt){}
  624. // Tell to close the socket
  625. return false;
  626. }
  627. return true;
  628. }
  629. protected SSLEngine createSSLEngine() {
  630. SSLEngine engine = sslContext.createSSLEngine();
  631. engine.setNeedClientAuth(getClientAuth());
  632. engine.setUseClientMode(false);
  633. if ( ciphersarr.length > 0 ) engine.setEnabledCipherSuites(ciphersarr);
  634. if ( sslEnabledProtocolsarr.length > 0 ) engine.setEnabledProtocols(sslEnabledProtocolsarr);
  635. return engine;
  636. }
  637. /**
  638. * Create (or allocate) and return an available processor for use in
  639. * processing a specific HTTP request, if possible. If the maximum
  640. * allowed processors have already been created and are in use, return
  641. * <code>null</code> instead.
  642. */
  643. protected Worker createWorkerThread() {
  644. synchronized (workers) {
  645. if (workers.size() > 0) {
  646. curThreadsBusy++;
  647. return (workers.pop());
  648. }
  649. if ((maxThreads > 0) && (curThreads < maxThreads)) {
  650. curThreadsBusy++;
  651. return (newWorkerThread());
  652. } else {
  653. if (maxThreads < 0) {
  654. curThreadsBusy++;
  655. return (newWorkerThread());
  656. } else {
  657. return (null);
  658. }
  659. }
  660. }
  661. }
  662. /**
  663. * Create and return a new processor suitable for processing HTTP
  664. * requests and returning the corresponding responses.
  665. */
  666. protected Worker newWorkerThread() {
  667. Worker workerThread = new Worker();
  668. workerThread.start();
  669. return (workerThread);
  670. }
  671. /**
  672. * Return a new worker thread, and block while to worker is available.
  673. */
  674. protected Worker getWorkerThread() {
  675. // Allocate a new worker thread
  676. Worker workerThread = createWorkerThread();
  677. while (workerThread == null) {
  678. try {
  679. synchronized (workers) {
  680. workerThread = createWorkerThread();
  681. if ( workerThread == null ) workers.wait();
  682. }
  683. } catch (InterruptedException e) {
  684. // Ignore
  685. }
  686. if ( workerThread == null ) workerThread = createWorkerThread();
  687. }
  688. return workerThread;
  689. }
  690. /**
  691. * Recycle the specified Processor so that it can be used again.
  692. *
  693. * @param workerThread The processor to be recycled
  694. */
  695. protected void recycleWorkerThread(Worker workerThread) {
  696. synchronized (workers) {
  697. workers.push(workerThread);
  698. curThreadsBusy--;
  699. workers.notify();
  700. }
  701. }
  702. protected boolean processSocket(SocketChannel socket) {
  703. try {
  704. if (executor == null) {
  705. getWorkerThread().assign(socket);
  706. } else {
  707. executor.execute(new SocketOptionsProcessor(socket));
  708. }
  709. } catch (Throwable t) {
  710. // This means we got an OOM or similar creating a thread, or that
  711. // the pool and its queue are full
  712. log.error(sm.getString("endpoint.process.fail"), t);
  713. return false;
  714. }
  715. return true;
  716. }
  717. /**
  718. * Process given socket.
  719. */
  720. protected boolean processSocket(NioChannel socket) {
  721. try {
  722. if (executor == null) {
  723. getWorkerThread().assign(socket);
  724. } else {
  725. executor.execute(new SocketProcessor(socket));
  726. }
  727. } catch (Throwable t) {
  728. // This means we got an OOM or similar creating a thread, or that
  729. // the pool and its queue are full
  730. log.error(sm.getString("endpoint.process.fail"), t);
  731. return false;
  732. }
  733. return true;
  734. }
  735. /**
  736. * Process given socket for an event.
  737. */
  738. protected boolean processSocket(NioChannel socket, SocketStatus status) {
  739. try {
  740. if (executor == null) {
  741. getWorkerThread().assign(socket, status);
  742. } else {
  743. executor.execute(new SocketEventProcessor(socket, status));
  744. }
  745. } catch (Throwable t) {
  746. // This means we got an OOM or similar creating a thread, or that
  747. // the pool and its queue are full
  748. log.error(sm.getString("endpoint.process.fail"), t);
  749. return false;
  750. }
  751. return true;
  752. }
  753. // --------------------------------------------------- Acceptor Inner Class
  754. /**
  755. * Server socket acceptor thread.
  756. */
  757. protected class Acceptor implements Runnable {
  758. /**
  759. * The background thread that listens for incoming TCP/IP connections and
  760. * hands them off to an appropriate processor.
  761. */
  762. public void run() {
  763. // Loop until we receive a shutdown command
  764. while (running) {
  765. // Loop if endpoint is paused
  766. while (paused) {
  767. try {
  768. Thread.sleep(1000);
  769. } catch (InterruptedException e) {
  770. // Ignore
  771. }
  772. }
  773. try {
  774. // Accept the next incoming connection from the server socket
  775. SocketChannel socket = serverSock.accept();
  776. // Hand this socket off to an appropriate processor
  777. if ( running && (!paused) && socket != null ) processSocket(socket);
  778. } catch (Throwable t) {
  779. log.error(sm.getString("endpoint.accept.fail"), t);
  780. }
  781. // The processor will recycle itself when it finishes
  782. }
  783. }
  784. }
  785. // ----------------------------------------------------- Poller Inner Classes
  786. /**
  787. *
  788. * PollerEvent, cacheable object for poller events to avoid GC
  789. */
  790. public class PollerEvent implements Runnable {
  791. protected NioChannel socket;
  792. protected int interestOps;
  793. protected KeyAttachment key;
  794. public PollerEvent(NioChannel ch, KeyAttachment k, int intOps) {
  795. reset(ch, k, intOps);
  796. }
  797. public void reset(NioChannel ch, KeyAttachment k, int intOps) {
  798. socket = ch;
  799. interestOps = intOps;
  800. key = k;
  801. }
  802. public void reset() {
  803. reset(null, null, 0);
  804. }
  805. public void run() {
  806. if ( interestOps == OP_REGISTER ) {
  807. try {
  808. socket.getIOChannel().register(socket.getPoller().getSelector(), SelectionKey.OP_READ, key);
  809. } catch (Exception x) {
  810. log.error("", x);
  811. }
  812. } else {
  813. final SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
  814. final KeyAttachment att = (KeyAttachment) key.attachment();
  815. try {
  816. if (key != null) {
  817. key.interestOps(interestOps);
  818. att.interestOps(interestOps);
  819. }
  820. }
  821. catch (CancelledKeyException ckx) {
  822. try {
  823. if (key != null && key.attachment() != null) {
  824. KeyAttachment ka = (KeyAttachment) key.attachment();
  825. ka.setError(true); //set to collect this socket immediately
  826. }
  827. try {
  828. socket.close();
  829. }
  830. catch (Exception ignore) {}
  831. if (socket.isOpen())
  832. socket.close(true);
  833. }
  834. catch (Exception ignore) {}
  835. }
  836. }//end if
  837. }//run
  838. public String toString() {
  839. return super.toString()+"[intOps="+this.interestOps+"]";
  840. }
  841. }
  842. /**
  843. * Poller class.
  844. */
  845. public class Poller implements Runnable {
  846. protected Selector selector;
  847. protected ConcurrentLinkedQueue<Runnable> events = new ConcurrentLinkedQueue<Runnable>();
  848. protected boolean close = false;
  849. protected long nextExpiration = 0;//optimize expiration handling
  850. protected int keepAliveCount = 0;
  851. public int getKeepAliveCount() { return keepAliveCount; }
  852. protected AtomicLong wakeupCounter = new AtomicLong(0l);
  853. public Poller() throws IOException {
  854. this.selector = Selector.open();
  855. }
  856. public Selector getSelector() { return selector;}
  857. /**
  858. * Create the poller. With some versions of APR, the maximum poller size will
  859. * be 62 (reocmpiling APR is necessary to remove this limitation).
  860. */
  861. protected void init() {
  862. keepAliveCount = 0;
  863. }
  864. /**
  865. * Destroy the poller.
  866. */
  867. protected void destroy() {
  868. // Wait for polltime before doing anything, so that the poller threads
  869. // exit, otherwise parallel descturction of sockets which are still
  870. // in the poller can cause problems
  871. close = true;
  872. events.clear();
  873. selector.wakeup();
  874. }
  875. public void addEvent(Runnable event) {
  876. events.offer(event);
  877. if ( wakeupCounter.incrementAndGet() < 3 ) selector.wakeup();
  878. }
  879. /**
  880. * Add specified socket and associated pool to the poller. The socket will
  881. * be added to a temporary array, and polled first after a maximum amount
  882. * of time equal to pollTime (in most cases, latency will be much lower,
  883. * however).
  884. *
  885. * @param socket to add to the poller
  886. */
  887. public void add(final NioChannel socket) {
  888. add(socket,SelectionKey.OP_READ);
  889. }
  890. public void add(final NioChannel socket, final int interestOps) {
  891. PollerEvent r = eventCache.poll();
  892. if ( r==null) r = new PollerEvent(socket,null,interestOps);
  893. else r.reset(socket,null,interestOps);
  894. addEvent(r);
  895. }
  896. public boolean events() {
  897. boolean result = false;
  898. //synchronized (events) {
  899. Runnable r = null;
  900. result = (events.size() > 0);
  901. while ( (r = (Runnable)events.poll()) != null ) {
  902. try {
  903. r.run();
  904. if ( r instanceof PollerEvent ) {
  905. ((PollerEvent)r).reset();
  906. eventCache.offer((PollerEvent)r);
  907. }
  908. } catch ( Exception x ) {
  909. log.error("",x);
  910. }
  911. }
  912. //events.clear();
  913. //}
  914. return result;
  915. }
  916. public void register(final NioChannel socket)
  917. {
  918. socket.setPoller(this);
  919. KeyAttachment key = keyCache.poll();
  920. final KeyAttachment ka = key!=null?key:new KeyAttachment();
  921. ka.reset(this,socket);
  922. PollerEvent r = eventCache.poll();
  923. ka.interestOps(SelectionKey.OP_READ);//this is what OP_REGISTER turns into.
  924. if ( r==null) r = new PollerEvent(socket,ka,OP_REGISTER);
  925. else r.reset(socket,ka,OP_REGISTER);
  926. addEvent(r);
  927. }
  928. public void cancelledKey(SelectionKey key, SocketStatus status) {
  929. try {
  930. KeyAttachment ka = (KeyAttachment) key.attachment();
  931. if (ka != null && ka.getComet()) {
  932. //the comet event takes care of clean up
  933. processSocket(ka.getChannel(), status);
  934. }else {
  935. if (key.isValid()) key.cancel();
  936. if (key.channel().isOpen()) key.channel().close();
  937. key.attach(null);
  938. }
  939. } catch (Throwable e) {
  940. if ( log.isDebugEnabled() ) log.error("",e);
  941. // Ignore
  942. }
  943. }
  944. /**
  945. * The background thread that listens for incoming TCP/IP connections and
  946. * hands them off to an appropriate processor.
  947. */
  948. public void run() {
  949. // Loop until we receive a shutdown command
  950. while (running) {
  951. // Loop if endpoint is paused
  952. while (paused) {
  953. try {
  954. Thread.sleep(1000);
  955. } catch (InterruptedException e) {
  956. // Ignore
  957. }
  958. }
  959. boolean hasEvents = false;
  960. hasEvents = (hasEvents | events());
  961. // Time to terminate?
  962. if (close) return;
  963. int keyCount = 0;
  964. try {
  965. keyCount = selector.select(selectorTimeout);
  966. wakeupCounter.set(0);
  967. if ( close ) { selector.close(); return; }
  968. } catch ( NullPointerException x ) {
  969. //sun bug 5076772 on windows JDK 1.5
  970. if ( wakeupCounter == null || selector == null ) throw x;
  971. continue;
  972. } catch ( CancelledKeyException x ) {
  973. //sun bug 5076772 on windows JDK 1.5
  974. if ( wakeupCounter == null || selector == null ) throw x;
  975. continue;
  976. } catch (Throwable x) {
  977. log.error("",x);
  978. continue;
  979. }
  980. //either we timed out or we woke up, process events first
  981. if ( keyCount == 0 ) hasEvents = (hasEvents | events());
  982. Iterator iterator = keyCount > 0 ? selector.selectedKeys().iterator() : null;
  983. // Walk through the collection of ready keys and dispatch
  984. // any active event.
  985. while (iterator != null && iterator.hasNext()) {
  986. SelectionKey sk = (SelectionKey) iterator.next();
  987. iterator.remove();
  988. KeyAttachment attachment = (KeyAttachment)sk.attachment();
  989. try {
  990. if ( sk.isValid() && attachment != null ) {
  991. attachment.access();
  992. sk.attach(attachment);
  993. sk.interestOps(0); //this is a must, so that we don't have multiple threads messing with the socket
  994. attachment.interestOps(0);
  995. NioChannel channel = attachment.getChannel();
  996. if (sk.isReadable() || sk.isWritable() ) {
  997. if ( attachment.getComet() ) {
  998. if (!processSocket(channel, SocketStatus.OPEN))
  999. processSocket(channel, SocketStatus.DISCONNECT);
  1000. } else {
  1001. boolean close = (!processSocket(channel));
  1002. if ( close ) {
  1003. channel.close();
  1004. channel.getIOChannel().socket().close();
  1005. }
  1006. }
  1007. }
  1008. } else {
  1009. //invalid key
  1010. cancelledKey(sk, SocketStatus.ERROR);
  1011. }
  1012. } catch ( CancelledKeyException ckx ) {
  1013. cancelledKey(sk, SocketStatus.ERROR);
  1014. } catch (Throwable t) {
  1015. log.error("",t);
  1016. }
  1017. }//while
  1018. //process timeouts
  1019. timeout(keyCount,hasEvents);
  1020. }//while
  1021. synchronized (this) {
  1022. this.notifyAll();
  1023. }
  1024. }
  1025. protected void timeout(int keyCount, boolean hasEvents) {
  1026. long now = System.currentTimeMillis();
  1027. //don't process timeouts too frequently, but if the selector simply timed out
  1028. //then we can check timeouts to avoid gaps
  1029. if ( (now < nextExpiration) && (keyCount>0 || hasEvents) ) return;
  1030. nextExpiration = now + (long)socketProperties.getSoTimeout();
  1031. //timeout
  1032. Set<SelectionKey> keys = selector.keys();
  1033. for (Iterator<SelectionKey> iter = keys.iterator(); iter.hasNext(); ) {
  1034. SelectionKey key = iter.next();
  1035. try {
  1036. KeyAttachment ka = (KeyAttachment) key.attachment();
  1037. if ( ka == null ) {
  1038. cancelledKey(key, SocketStatus.ERROR); //we don't support any keys without attachments
  1039. } else if ( ka.getError() ) {
  1040. cancelledKey(key, SocketStatus.DISCONNECT);
  1041. }else if ((ka.interestOps()&SelectionKey.OP_READ) == SelectionKey.OP_READ) {
  1042. //only timeout sockets that we are waiting for a read from
  1043. long delta = now - ka.getLastAccess();
  1044. long timeout = (ka.getTimeout()==-1)?((long) socketProperties.getSoTimeout()):(ka.getTimeout());
  1045. boolean isTimedout = delta > timeout;
  1046. if (isTimedout) {
  1047. key.interestOps(0);
  1048. ka.interestOps(0); //avoid duplicate timeout calls
  1049. cancelledKey(key, SocketStatus.TIMEOUT);
  1050. } else {
  1051. long nextTime = now+(timeout-delta);
  1052. nextExpiration = (nextTime < nextExpiration)?nextTime:nextExpiration;
  1053. }
  1054. }//end if
  1055. }catch ( CancelledKeyException ckx ) {
  1056. cancelledKey(key, SocketStatus.ERROR);
  1057. }
  1058. }//for
  1059. }
  1060. }
  1061. public static class KeyAttachment {
  1062. public KeyAttachment() {
  1063. }
  1064. public void reset(Poller poller, NioChannel channel) {
  1065. this.channel = channel;
  1066. this.poller = poller;
  1067. lastAccess = System.currentTimeMillis();
  1068. currentAccess = false;
  1069. comet = false;
  1070. timeout = -1;
  1071. error = false;
  1072. }
  1073. public void reset() {
  1074. reset(null,null);
  1075. }
  1076. public Poller getPoller() { return poller;}
  1077. public void setPoller(Poller poller){this.poller = poller;}
  1078. public long getLastAccess() { return lastAccess; }
  1079. public void access() { access(System.currentTimeMillis()); }
  1080. public void access(long access) { lastAccess = access; }
  1081. public void setComet(boolean comet) { this.comet = comet; }
  1082. public boolean getComet() { return comet; }
  1083. public boolean getCurrentAccess() { return currentAccess; }
  1084. public void setCurrentAccess(boolean access) { currentAccess = access; }
  1085. public Object getMutex() {return mutex;}
  1086. public void setTimeout(long timeout) {this.timeout = timeout;}
  1087. public long getTimeout() {return this.timeout;}
  1088. public boolean getError() { return error; }
  1089. public void setError(boolean error) { this.error = error; }
  1090. public NioChannel getChannel() { return channel;}
  1091. public void setChannel(NioChannel channel) { this.channel = channel;}
  1092. protected Poller poller = null;
  1093. protected int interestOps = 0;
  1094. public int interestOps() { return interestOps;}
  1095. public int interestOps(int ops) { this.interestOps = ops; return ops; }
  1096. protected Object mutex = new Object();
  1097. protected long lastAccess = -1;
  1098. protected boolean currentAccess = false;
  1099. protected boolean comet = false;
  1100. protected long timeout = -1;
  1101. protected boolean error = false;
  1102. protected NioChannel channel = null;
  1103. }
  1104. // ----------------------------------------------------- Worker Inner Class
  1105. /**
  1106. * Server processor class.
  1107. */
  1108. protected class Worker implements Runnable {
  1109. protected Thread thread = null;
  1110. protected boolean available = false;
  1111. protected Object socket = null;
  1112. protected SocketStatus status = null;
  1113. /**
  1114. * Process an incoming TCP/IP connection on the specified socket. Any
  1115. * exception that occurs during processing must be logged and swallowed.
  1116. * <b>NOTE</b>: This method is called from our Connector's thread. We
  1117. * must assign it to our own thread so that multiple simultaneous
  1118. * requests can be handled.
  1119. *
  1120. * @param socket TCP socket to process
  1121. */
  1122. protected synchronized void assign(Object socket) {
  1123. // Wait for the Processor to get the previous Socket
  1124. while (available) {
  1125. try {
  1126. wait();
  1127. } catch (InterruptedException e) {
  1128. }
  1129. }
  1130. // Store the newly available Socket and notify our thread
  1131. this.socket = socket;
  1132. status = null;
  1133. available = true;
  1134. notifyAll();
  1135. }
  1136. protected synchronized void assign(Object socket, SocketStatus status) {
  1137. // Wait for the Processor to get the previous Socket
  1138. while (available) {
  1139. try {
  1140. wait();
  1141. } catch (InterruptedException e) {
  1142. }
  1143. }
  1144. // Store the newly available Socket and notify our thread
  1145. this.socket = socket;
  1146. this.status = status;
  1147. available = true;
  1148. notifyAll();
  1149. }
  1150. /**
  1151. * Await a newly assigned Socket from our Connector, or <code>null</code>
  1152. * if we are supposed to shut down.
  1153. */
  1154. protected synchronized Object await() {
  1155. // Wait for the Connector to provide a new Socket
  1156. while (!available) {
  1157. try {
  1158. wait();
  1159. } catch (InterruptedException e) {
  1160. }
  1161. }
  1162. // Notify the Connector that we have received this Socket
  1163. Object socket = this.socket;
  1164. available = false;
  1165. notifyAll();
  1166. return (socket);
  1167. }
  1168. /**
  1169. * The background thread that listens for incoming TCP/IP connections and
  1170. * hands them off to an appropriate processor.
  1171. */
  1172. public void run() {
  1173. // Process requests until we receive a shutdown signal
  1174. while (running) {
  1175. try {
  1176. // Wait for the next socket to be assigned
  1177. Object channel = await();
  1178. if (channel == null)
  1179. continue;
  1180. if ( channel instanceof SocketChannel) {
  1181. SocketChannel sc = (SocketChannel)channel;
  1182. if ( !setSocketOptions(sc) ) {
  1183. try {
  1184. sc.socket().close();
  1185. sc.close();
  1186. }catch ( IOException ix ) {
  1187. if ( log.isDebugEnabled() ) log.debug("",ix);
  1188. }
  1189. } else {
  1190. //now we have it registered, remove it from the cache
  1191. }
  1192. } else {
  1193. NioChannel socket = (NioChannel)channel;
  1194. SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
  1195. int handshake = -1;
  1196. try {
  1197. handshake = socket.handshake(key.isReadable(), key.isWritable());
  1198. }catch ( IOException x ) {
  1199. handshake = -1;
  1200. if ( log.isDebugEnabled() ) log.debug("Error during SSL handshake",x);
  1201. }catch ( CancelledKeyException ckx ) {
  1202. handshake = -1;
  1203. }
  1204. if ( handshake == 0 ) {
  1205. // Process the request from this socket
  1206. if ((status != null) && (handler.event(socket, status) == Handler.SocketState.CLOSED)) {
  1207. // Close socket and pool
  1208. try {
  1209. KeyAttachment att = (KeyAttachment)socket.getAttachment(true);
  1210. try {socket.close();}catch (Exception ignore){}
  1211. if ( socket.isOpen() ) socket.close(true);
  1212. key.cancel();
  1213. key.attach(null);
  1214. nioChannels.offer(socket);
  1215. if ( att!=null ) keyCache.offer(att);
  1216. }catch ( Exception x ) {
  1217. log.error("",x);
  1218. }

Large files files are truncated, but you can click here to view the full file