/java/org/apache/tomcat/util/net/AprEndpoint.java
Java | 2410 lines | 1520 code | 283 blank | 607 comment | 409 complexity | df08c18d2ca87283827c555d542e3def 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 */ 17package org.apache.tomcat.util.net; 18 19import java.util.ArrayList; 20import java.util.HashMap; 21import java.util.Map; 22import java.util.concurrent.ConcurrentHashMap; 23import java.util.concurrent.Executor; 24import java.util.concurrent.RejectedExecutionException; 25import java.util.concurrent.atomic.AtomicInteger; 26 27import org.apache.juli.logging.Log; 28import org.apache.juli.logging.LogFactory; 29import org.apache.tomcat.jni.Address; 30import org.apache.tomcat.jni.Error; 31import org.apache.tomcat.jni.File; 32import org.apache.tomcat.jni.Library; 33import org.apache.tomcat.jni.OS; 34import org.apache.tomcat.jni.Poll; 35import org.apache.tomcat.jni.Pool; 36import org.apache.tomcat.jni.SSL; 37import org.apache.tomcat.jni.SSLContext; 38import org.apache.tomcat.jni.SSLSocket; 39import org.apache.tomcat.jni.Sockaddr; 40import org.apache.tomcat.jni.Socket; 41import org.apache.tomcat.jni.Status; 42import org.apache.tomcat.util.ExceptionUtils; 43import org.apache.tomcat.util.net.AbstractEndpoint.Acceptor.AcceptorState; 44import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState; 45 46 47/** 48 * APR tailored thread pool, providing the following services: 49 * <ul> 50 * <li>Socket acceptor thread</li> 51 * <li>Socket poller thread</li> 52 * <li>Sendfile thread</li> 53 * <li>Worker threads pool</li> 54 * </ul> 55 * 56 * When switching to Java 5, there's an opportunity to use the virtual 57 * machine's thread pool. 58 * 59 * @author Mladen Turk 60 * @author Remy Maucherat 61 */ 62public class AprEndpoint extends AbstractEndpoint<Long> { 63 64 65 // -------------------------------------------------------------- Constants 66 67 68 private static final Log log = LogFactory.getLog(AprEndpoint.class); 69 70 // ----------------------------------------------------------------- Fields 71 /** 72 * Root APR memory pool. 73 */ 74 protected long rootPool = 0; 75 76 77 /** 78 * Server socket "pointer". 79 */ 80 protected long serverSock = 0; 81 82 83 /** 84 * APR memory pool for the server socket. 85 */ 86 protected long serverSockPool = 0; 87 88 89 /** 90 * SSL context. 91 */ 92 protected long sslContext = 0; 93 94 95 private final Map<Long,AprSocketWrapper> connections = new ConcurrentHashMap<>(); 96 97 // ------------------------------------------------------------ Constructor 98 99 public AprEndpoint() { 100 // Need to override the default for maxConnections to align it with what 101 // was pollerSize (before the two were merged) 102 setMaxConnections(8 * 1024); 103 } 104 105 // ------------------------------------------------------------- Properties 106 107 108 /** 109 * Defer accept. 110 */ 111 protected boolean deferAccept = true; 112 public void setDeferAccept(boolean deferAccept) { this.deferAccept = deferAccept; } 113 @Override 114 public boolean getDeferAccept() { return deferAccept; } 115 116 117 /** 118 * Size of the sendfile (= concurrent files which can be served). 119 */ 120 protected int sendfileSize = 1 * 1024; 121 public void setSendfileSize(int sendfileSize) { this.sendfileSize = sendfileSize; } 122 public int getSendfileSize() { return sendfileSize; } 123 124 125 /** 126 * Handling of accepted sockets. 127 */ 128 protected Handler handler = null; 129 public void setHandler(Handler handler ) { this.handler = handler; } 130 public Handler getHandler() { return handler; } 131 132 133 /** 134 * Poll interval, in microseconds. The smaller the value, the more CPU the poller 135 * will use, but the more responsive to activity it will be. 136 */ 137 protected int pollTime = 2000; 138 public int getPollTime() { return pollTime; } 139 public void setPollTime(int pollTime) { if (pollTime > 0) { this.pollTime = pollTime; } } 140 141 142 /** 143 * Use sendfile for sending static files. 144 */ 145 protected boolean useSendfile = false; 146 /* 147 * When the endpoint is created and configured, the APR library will not 148 * have been initialised. This flag is used to determine if the default 149 * value of useSendFile should be changed if the APR library indicates it 150 * supports send file once it has been initialised. If useSendFile is set 151 * by configuration, that configuration will always take priority. 152 */ 153 private boolean useSendFileSet = false; 154 public void setUseSendfile(boolean useSendfile) { 155 useSendFileSet = true; 156 this.useSendfile = useSendfile; 157 } 158 @Override 159 public boolean getUseSendfile() { return useSendfile; } 160 161 162 /** 163 * Allow comet request handling. 164 */ 165 protected boolean useComet = true; 166 public void setUseComet(boolean useComet) { this.useComet = useComet; } 167 @Override 168 public boolean getUseComet() { return useComet; } 169 @Override 170 public boolean getUseCometTimeout() { return false; } // Not supported 171 @Override 172 public boolean getUsePolling() { return true; } // Always supported 173 174 175 /** 176 * Sendfile thread count. 177 */ 178 protected int sendfileThreadCount = 0; 179 public void setSendfileThreadCount(int sendfileThreadCount) { this.sendfileThreadCount = sendfileThreadCount; } 180 public int getSendfileThreadCount() { return sendfileThreadCount; } 181 182 183 /** 184 * The socket poller. 185 */ 186 protected Poller poller = null; 187 public Poller getPoller() { 188 return poller; 189 } 190 191 192 /** 193 * The static file sender. 194 */ 195 protected Sendfile sendfile = null; 196 public Sendfile getSendfile() { 197 return sendfile; 198 } 199 200 201 /** 202 * SSL protocols. 203 */ 204 protected String SSLProtocol = "all"; 205 public String getSSLProtocol() { return SSLProtocol; } 206 public void setSSLProtocol(String SSLProtocol) { this.SSLProtocol = SSLProtocol; } 207 208 209 /** 210 * SSL password (if a cert is encrypted, and no password has been provided, a callback 211 * will ask for a password). 212 */ 213 protected String SSLPassword = null; 214 public String getSSLPassword() { return SSLPassword; } 215 public void setSSLPassword(String SSLPassword) { this.SSLPassword = SSLPassword; } 216 217 218 /** 219 * SSL cipher suite. 220 */ 221 protected String SSLCipherSuite = "ALL"; 222 public String getSSLCipherSuite() { return SSLCipherSuite; } 223 public void setSSLCipherSuite(String SSLCipherSuite) { this.SSLCipherSuite = SSLCipherSuite; } 224 225 226 /** 227 * SSL certificate file. 228 */ 229 protected String SSLCertificateFile = null; 230 public String getSSLCertificateFile() { return SSLCertificateFile; } 231 public void setSSLCertificateFile(String SSLCertificateFile) { this.SSLCertificateFile = SSLCertificateFile; } 232 233 234 /** 235 * SSL certificate key file. 236 */ 237 protected String SSLCertificateKeyFile = null; 238 public String getSSLCertificateKeyFile() { return SSLCertificateKeyFile; } 239 public void setSSLCertificateKeyFile(String SSLCertificateKeyFile) { this.SSLCertificateKeyFile = SSLCertificateKeyFile; } 240 241 242 /** 243 * SSL certificate chain file. 244 */ 245 protected String SSLCertificateChainFile = null; 246 public String getSSLCertificateChainFile() { return SSLCertificateChainFile; } 247 public void setSSLCertificateChainFile(String SSLCertificateChainFile) { this.SSLCertificateChainFile = SSLCertificateChainFile; } 248 249 250 /** 251 * SSL CA certificate path. 252 */ 253 protected String SSLCACertificatePath = null; 254 public String getSSLCACertificatePath() { return SSLCACertificatePath; } 255 public void setSSLCACertificatePath(String SSLCACertificatePath) { this.SSLCACertificatePath = SSLCACertificatePath; } 256 257 258 /** 259 * SSL CA certificate file. 260 */ 261 protected String SSLCACertificateFile = null; 262 public String getSSLCACertificateFile() { return SSLCACertificateFile; } 263 public void setSSLCACertificateFile(String SSLCACertificateFile) { this.SSLCACertificateFile = SSLCACertificateFile; } 264 265 266 /** 267 * SSL CA revocation path. 268 */ 269 protected String SSLCARevocationPath = null; 270 public String getSSLCARevocationPath() { return SSLCARevocationPath; } 271 public void setSSLCARevocationPath(String SSLCARevocationPath) { this.SSLCARevocationPath = SSLCARevocationPath; } 272 273 274 /** 275 * SSL CA revocation file. 276 */ 277 protected String SSLCARevocationFile = null; 278 public String getSSLCARevocationFile() { return SSLCARevocationFile; } 279 public void setSSLCARevocationFile(String SSLCARevocationFile) { this.SSLCARevocationFile = SSLCARevocationFile; } 280 281 282 /** 283 * SSL verify client. 284 */ 285 protected String SSLVerifyClient = "none"; 286 public String getSSLVerifyClient() { return SSLVerifyClient; } 287 public void setSSLVerifyClient(String SSLVerifyClient) { this.SSLVerifyClient = SSLVerifyClient; } 288 289 290 /** 291 * SSL verify depth. 292 */ 293 protected int SSLVerifyDepth = 10; 294 public int getSSLVerifyDepth() { return SSLVerifyDepth; } 295 public void setSSLVerifyDepth(int SSLVerifyDepth) { this.SSLVerifyDepth = SSLVerifyDepth; } 296 297 298 /** 299 * SSL allow insecure renegotiation for the the client that does not 300 * support the secure renegotiation. 301 */ 302 protected boolean SSLInsecureRenegotiation = false; 303 public void setSSLInsecureRenegotiation(boolean SSLInsecureRenegotiation) { this.SSLInsecureRenegotiation = SSLInsecureRenegotiation; } 304 public boolean getSSLInsecureRenegotiation() { return SSLInsecureRenegotiation; } 305 306 protected boolean SSLHonorCipherOrder = false; 307 /** 308 * Set to <code>true</code> to enforce the <i>server's</i> cipher order 309 * instead of the default which is to allow the client to choose a 310 * preferred cipher. 311 */ 312 public void setSSLHonorCipherOrder(boolean SSLHonorCipherOrder) { this.SSLHonorCipherOrder = SSLHonorCipherOrder; } 313 public boolean getSSLHonorCipherOrder() { return SSLHonorCipherOrder; } 314 315 /** 316 * Disables compression of the SSL stream. This thwarts CRIME attack 317 * and possibly improves performance by not compressing uncompressible 318 * content such as JPEG, etc. 319 */ 320 protected boolean SSLDisableCompression = false; 321 322 /** 323 * Set to <code>true</code> to disable SSL compression. This thwarts CRIME 324 * attack. 325 */ 326 public void setSSLDisableCompression(boolean SSLDisableCompression) { this.SSLDisableCompression = SSLDisableCompression; } 327 public boolean getSSLDisableCompression() { return SSLDisableCompression; } 328 329 /** 330 * Port in use. 331 */ 332 @Override 333 public int getLocalPort() { 334 long s = serverSock; 335 if (s == 0) { 336 return -1; 337 } else { 338 long sa; 339 try { 340 sa = Address.get(Socket.APR_LOCAL, s); 341 Sockaddr addr = Address.getInfo(sa); 342 return addr.port; 343 } catch (Exception e) { 344 return -1; 345 } 346 } 347 } 348 349 350 @Override 351 public String[] getCiphersUsed() { 352 // TODO : Investigate if it is possible to extract the current list of 353 // available ciphers. Native code changes will be required. 354 return new String[] { getSSLCipherSuite() }; 355 } 356 357 358 // --------------------------------------------------------- Public Methods 359 360 /** 361 * Number of keepalive sockets. 362 */ 363 public int getKeepAliveCount() { 364 if (poller == null) { 365 return 0; 366 } 367 368 return poller.getConnectionCount(); 369 } 370 371 372 /** 373 * Number of sendfile sockets. 374 */ 375 public int getSendfileCount() { 376 if (sendfile == null) { 377 return 0; 378 } 379 380 return sendfile.getSendfileCount(); 381 } 382 383 384 // ----------------------------------------------- Public Lifecycle Methods 385 386 387 /** 388 * Initialize the endpoint. 389 */ 390 @Override 391 public void bind() throws Exception { 392 393 // Create the root APR memory pool 394 try { 395 rootPool = Pool.create(0); 396 } catch (UnsatisfiedLinkError e) { 397 throw new Exception(sm.getString("endpoint.init.notavail")); 398 } 399 400 // Create the pool for the server socket 401 serverSockPool = Pool.create(rootPool); 402 // Create the APR address that will be bound 403 String addressStr = null; 404 if (getAddress() != null) { 405 addressStr = getAddress().getHostAddress(); 406 } 407 int family = Socket.APR_INET; 408 if (Library.APR_HAVE_IPV6) { 409 if (addressStr == null) { 410 if (!OS.IS_BSD && !OS.IS_WIN32 && !OS.IS_WIN64) 411 family = Socket.APR_UNSPEC; 412 } else if (addressStr.indexOf(':') >= 0) { 413 family = Socket.APR_UNSPEC; 414 } 415 } 416 417 long inetAddress = Address.info(addressStr, family, 418 getPort(), 0, rootPool); 419 // Create the APR server socket 420 serverSock = Socket.create(Address.getInfo(inetAddress).family, 421 Socket.SOCK_STREAM, 422 Socket.APR_PROTO_TCP, rootPool); 423 if (OS.IS_UNIX) { 424 Socket.optSet(serverSock, Socket.APR_SO_REUSEADDR, 1); 425 } 426 // Deal with the firewalls that tend to drop the inactive sockets 427 Socket.optSet(serverSock, Socket.APR_SO_KEEPALIVE, 1); 428 // Bind the server socket 429 int ret = Socket.bind(serverSock, inetAddress); 430 if (ret != 0) { 431 throw new Exception(sm.getString("endpoint.init.bind", "" + ret, Error.strerror(ret))); 432 } 433 // Start listening on the server socket 434 ret = Socket.listen(serverSock, getBacklog()); 435 if (ret != 0) { 436 throw new Exception(sm.getString("endpoint.init.listen", "" + ret, Error.strerror(ret))); 437 } 438 if (OS.IS_WIN32 || OS.IS_WIN64) { 439 // On Windows set the reuseaddr flag after the bind/listen 440 Socket.optSet(serverSock, Socket.APR_SO_REUSEADDR, 1); 441 } 442 443 // Enable Sendfile by default if it has not been configured but usage on 444 // systems which don't support it cause major problems 445 if (!useSendFileSet) { 446 useSendfile = Library.APR_HAS_SENDFILE; 447 } else if (useSendfile && !Library.APR_HAS_SENDFILE) { 448 useSendfile = false; 449 } 450 451 // Initialize thread count default for acceptor 452 if (acceptorThreadCount == 0) { 453 // FIXME: Doesn't seem to work that well with multiple accept threads 454 acceptorThreadCount = 1; 455 } 456 457 // Delay accepting of new connections until data is available 458 // Only Linux kernels 2.4 + have that implemented 459 // on other platforms this call is noop and will return APR_ENOTIMPL. 460 if (deferAccept) { 461 if (Socket.optSet(serverSock, Socket.APR_TCP_DEFER_ACCEPT, 1) == Status.APR_ENOTIMPL) { 462 deferAccept = false; 463 } 464 } 465 466 // Initialize SSL if needed 467 if (isSSLEnabled()) { 468 469 if (SSLCertificateFile == null) { 470 // This is required 471 throw new Exception(sm.getString("endpoint.apr.noSslCertFile")); 472 } 473 474 // SSL protocol 475 int value = SSL.SSL_PROTOCOL_NONE; 476 if (SSLProtocol == null || SSLProtocol.length() == 0) { 477 value = SSL.SSL_PROTOCOL_ALL; 478 } else { 479 for (String protocol : SSLProtocol.split("\\+")) { 480 protocol = protocol.trim(); 481 if ("SSLv2".equalsIgnoreCase(protocol)) { 482 value |= SSL.SSL_PROTOCOL_SSLV2; 483 } else if ("SSLv3".equalsIgnoreCase(protocol)) { 484 value |= SSL.SSL_PROTOCOL_SSLV3; 485 } else if ("TLSv1".equalsIgnoreCase(protocol)) { 486 value |= SSL.SSL_PROTOCOL_TLSV1; 487 } else if ("all".equalsIgnoreCase(protocol)) { 488 value |= SSL.SSL_PROTOCOL_ALL; 489 } else { 490 // Protocol not recognized, fail to start as it is safer than 491 // continuing with the default which might enable more than the 492 // is required 493 throw new Exception(sm.getString( 494 "endpoint.apr.invalidSslProtocol", SSLProtocol)); 495 } 496 } 497 } 498 499 // Create SSL Context 500 try { 501 sslContext = SSLContext.make(rootPool, value, SSL.SSL_MODE_SERVER); 502 } catch (Exception e) { 503 // If the sslEngine is disabled on the AprLifecycleListener 504 // there will be an Exception here but there is no way to check 505 // the AprLifecycleListener settings from here 506 throw new Exception( 507 sm.getString("endpoint.apr.failSslContextMake"), e); 508 } 509 510 if (SSLInsecureRenegotiation) { 511 boolean legacyRenegSupported = false; 512 try { 513 legacyRenegSupported = SSL.hasOp(SSL.SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); 514 if (legacyRenegSupported) 515 SSLContext.setOptions(sslContext, SSL.SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); 516 } catch (UnsatisfiedLinkError e) { 517 // Ignore 518 } 519 if (!legacyRenegSupported) { 520 // OpenSSL does not support unsafe legacy renegotiation. 521 log.warn(sm.getString("endpoint.warn.noInsecureReneg", 522 SSL.versionString())); 523 } 524 } 525 526 // Set cipher order: client (default) or server 527 if (SSLHonorCipherOrder) { 528 boolean orderCiphersSupported = false; 529 try { 530 orderCiphersSupported = SSL.hasOp(SSL.SSL_OP_CIPHER_SERVER_PREFERENCE); 531 if (orderCiphersSupported) 532 SSLContext.setOptions(sslContext, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE); 533 } catch (UnsatisfiedLinkError e) { 534 // Ignore 535 } 536 if (!orderCiphersSupported) { 537 // OpenSSL does not support ciphers ordering. 538 log.warn(sm.getString("endpoint.warn.noHonorCipherOrder", 539 SSL.versionString())); 540 } 541 } 542 543 // Disable compression if requested 544 if (SSLDisableCompression) { 545 boolean disableCompressionSupported = false; 546 try { 547 disableCompressionSupported = SSL.hasOp(SSL.SSL_OP_NO_COMPRESSION); 548 if (disableCompressionSupported) 549 SSLContext.setOptions(sslContext, SSL.SSL_OP_NO_COMPRESSION); 550 } catch (UnsatisfiedLinkError e) { 551 // Ignore 552 } 553 if (!disableCompressionSupported) { 554 // OpenSSL does not support ciphers ordering. 555 log.warn(sm.getString("endpoint.warn.noDisableCompression", 556 SSL.versionString())); 557 } 558 } 559 560 // List the ciphers that the client is permitted to negotiate 561 SSLContext.setCipherSuite(sslContext, SSLCipherSuite); 562 // Load Server key and certificate 563 SSLContext.setCertificate(sslContext, SSLCertificateFile, SSLCertificateKeyFile, SSLPassword, SSL.SSL_AIDX_RSA); 564 // Set certificate chain file 565 SSLContext.setCertificateChainFile(sslContext, SSLCertificateChainFile, false); 566 // Support Client Certificates 567 SSLContext.setCACertificate(sslContext, SSLCACertificateFile, SSLCACertificatePath); 568 // Set revocation 569 SSLContext.setCARevocation(sslContext, SSLCARevocationFile, SSLCARevocationPath); 570 // Client certificate verification 571 value = SSL.SSL_CVERIFY_NONE; 572 if ("optional".equalsIgnoreCase(SSLVerifyClient)) { 573 value = SSL.SSL_CVERIFY_OPTIONAL; 574 } else if ("require".equalsIgnoreCase(SSLVerifyClient)) { 575 value = SSL.SSL_CVERIFY_REQUIRE; 576 } else if ("optionalNoCA".equalsIgnoreCase(SSLVerifyClient)) { 577 value = SSL.SSL_CVERIFY_OPTIONAL_NO_CA; 578 } 579 SSLContext.setVerify(sslContext, value, SSLVerifyDepth); 580 // For now, sendfile is not supported with SSL 581 if (useSendfile) { 582 useSendfile = false; 583 if (useSendFileSet) { 584 log.warn(sm.getString("endpoint.apr.noSendfileWithSSL")); 585 } 586 } 587 } 588 } 589 590 public long getJniSslContext() { 591 return sslContext; 592 } 593 594 /** 595 * Start the APR endpoint, creating acceptor, poller and sendfile threads. 596 */ 597 @Override 598 public void startInternal() throws Exception { 599 600 if (!running) { 601 running = true; 602 paused = false; 603 604 // Create worker collection 605 if (getExecutor() == null) { 606 createExecutor(); 607 } 608 609 initializeConnectionLatch(); 610 611 // Start poller thread 612 poller = new Poller(); 613 poller.init(); 614 Thread pollerThread = new Thread(poller, getName() + "-Poller"); 615 pollerThread.setPriority(threadPriority); 616 pollerThread.setDaemon(true); 617 pollerThread.start(); 618 619 // Start sendfile thread 620 if (useSendfile) { 621 sendfile = new Sendfile(); 622 sendfile.init(); 623 Thread sendfileThread = 624 new Thread(sendfile, getName() + "-Sendfile"); 625 sendfileThread.setPriority(threadPriority); 626 sendfileThread.setDaemon(true); 627 sendfileThread.start(); 628 } 629 630 startAcceptorThreads(); 631 632 // Start async timeout thread 633 setAsyncTimeout(new AsyncTimeout()); 634 Thread timeoutThread = new Thread(getAsyncTimeout(), getName() + "-AsyncTimeout"); 635 timeoutThread.setPriority(threadPriority); 636 timeoutThread.setDaemon(true); 637 timeoutThread.start(); 638 } 639 } 640 641 642 /** 643 * Stop the endpoint. This will cause all processing threads to stop. 644 */ 645 @Override 646 public void stopInternal() { 647 releaseConnectionLatch(); 648 if (!paused) { 649 pause(); 650 } 651 if (running) { 652 running = false; 653 poller.stop(); 654 getAsyncTimeout().stop(); 655 unlockAccept(); 656 for (AbstractEndpoint.Acceptor acceptor : acceptors) { 657 long waitLeft = 10000; 658 while (waitLeft > 0 && 659 acceptor.getState() != AcceptorState.ENDED && 660 serverSock != 0) { 661 try { 662 Thread.sleep(50); 663 } catch (InterruptedException e) { 664 // Ignore 665 } 666 waitLeft -= 50; 667 } 668 if (waitLeft == 0) { 669 log.warn(sm.getString("endpoint.warn.unlockAcceptorFailed", 670 acceptor.getThreadName())); 671 // If the Acceptor is still running force 672 // the hard socket close. 673 if (serverSock != 0) { 674 Socket.shutdown(serverSock, Socket.APR_SHUTDOWN_READ); 675 serverSock = 0; 676 } 677 } 678 } 679 try { 680 poller.destroy(); 681 } catch (Exception e) { 682 // Ignore 683 } 684 poller = null; 685 connections.clear(); 686 if (useSendfile) { 687 try { 688 sendfile.destroy(); 689 } catch (Exception e) { 690 // Ignore 691 } 692 sendfile = null; 693 } 694 } 695 shutdownExecutor(); 696 } 697 698 699 /** 700 * Deallocate APR memory pools, and close server socket. 701 */ 702 @Override 703 public void unbind() throws Exception { 704 if (running) { 705 stop(); 706 } 707 708 // Destroy pool if it was initialised 709 if (serverSockPool != 0) { 710 Pool.destroy(serverSockPool); 711 serverSockPool = 0; 712 } 713 714 // Close server socket if it was initialised 715 if (serverSock != 0) { 716 Socket.close(serverSock); 717 serverSock = 0; 718 } 719 720 sslContext = 0; 721 722 // Close all APR memory pools and resources if initialised 723 if (rootPool != 0) { 724 Pool.destroy(rootPool); 725 rootPool = 0; 726 } 727 728 handler.recycle(); 729 } 730 731 732 // ------------------------------------------------------ Protected Methods 733 734 @Override 735 protected AbstractEndpoint.Acceptor createAcceptor() { 736 return new Acceptor(); 737 } 738 739 740 /** 741 * Process the specified connection. 742 */ 743 protected boolean setSocketOptions(long socket) { 744 // Process the connection 745 int step = 1; 746 try { 747 748 // 1: Set socket options: timeout, linger, etc 749 if (socketProperties.getSoLingerOn() && socketProperties.getSoLingerTime() >= 0) 750 Socket.optSet(socket, Socket.APR_SO_LINGER, socketProperties.getSoLingerTime()); 751 if (socketProperties.getTcpNoDelay()) 752 Socket.optSet(socket, Socket.APR_TCP_NODELAY, (socketProperties.getTcpNoDelay() ? 1 : 0)); 753 Socket.timeoutSet(socket, socketProperties.getSoTimeout() * 1000); 754 755 // 2: SSL handshake 756 step = 2; 757 if (sslContext != 0) { 758 SSLSocket.attach(sslContext, socket); 759 if (SSLSocket.handshake(socket) != 0) { 760 if (log.isDebugEnabled()) { 761 log.debug(sm.getString("endpoint.err.handshake") + ": " + SSL.getLastError()); 762 } 763 return false; 764 } 765 } 766 767 } catch (Throwable t) { 768 ExceptionUtils.handleThrowable(t); 769 if (log.isDebugEnabled()) { 770 if (step == 2) { 771 log.debug(sm.getString("endpoint.err.handshake"), t); 772 } else { 773 log.debug(sm.getString("endpoint.err.unexpected"), t); 774 } 775 } 776 // Tell to close the socket 777 return false; 778 } 779 return true; 780 } 781 782 783 /** 784 * Allocate a new poller of the specified size. 785 */ 786 protected long allocatePoller(int size, long pool, int timeout) { 787 try { 788 return Poll.create(size, pool, 0, timeout * 1000); 789 } catch (Error e) { 790 if (Status.APR_STATUS_IS_EINVAL(e.getError())) { 791 log.info(sm.getString("endpoint.poll.limitedpollsize", "" + size)); 792 return 0; 793 } else { 794 log.error(sm.getString("endpoint.poll.initfail"), e); 795 return -1; 796 } 797 } 798 } 799 800 /** 801 * Process given socket. This is called when the socket has been 802 * accepted. 803 */ 804 protected boolean processSocketWithOptions(long socket) { 805 try { 806 // During shutdown, executor may be null - avoid NPE 807 if (running) { 808 if (log.isDebugEnabled()) { 809 log.debug(sm.getString("endpoint.debug.socket", 810 Long.valueOf(socket))); 811 } 812 AprSocketWrapper wrapper = 813 new AprSocketWrapper(Long.valueOf(socket)); 814 wrapper.setKeepAliveLeft(getMaxKeepAliveRequests()); 815 wrapper.setSecure(isSSLEnabled()); 816 connections.put(Long.valueOf(socket), wrapper); 817 getExecutor().execute(new SocketWithOptionsProcessor(wrapper)); 818 } 819 } catch (RejectedExecutionException x) { 820 log.warn("Socket processing request was rejected for:"+socket,x); 821 return false; 822 } catch (Throwable t) { 823 ExceptionUtils.handleThrowable(t); 824 // This means we got an OOM or similar creating a thread, or that 825 // the pool and its queue are full 826 log.error(sm.getString("endpoint.process.fail"), t); 827 return false; 828 } 829 return true; 830 } 831 832 833 /** 834 * Process given socket. Called in non-comet mode, typically keep alive 835 * or upgraded protocol. 836 */ 837 public boolean processSocket(long socket, SocketStatus status) { 838 try { 839 Executor executor = getExecutor(); 840 if (executor == null) { 841 log.warn(sm.getString("endpoint.warn.noExector", 842 Long.valueOf(socket), null)); 843 } else { 844 SocketWrapper<Long> wrapper = 845 connections.get(Long.valueOf(socket)); 846 // Make sure connection hasn't been closed 847 if (wrapper != null) { 848 executor.execute(new SocketProcessor(wrapper, status)); 849 } 850 } 851 } catch (RejectedExecutionException x) { 852 log.warn("Socket processing request was rejected for:"+socket,x); 853 return false; 854 } catch (Throwable t) { 855 ExceptionUtils.handleThrowable(t); 856 // This means we got an OOM or similar creating a thread, or that 857 // the pool and its queue are full 858 log.error(sm.getString("endpoint.process.fail"), t); 859 return false; 860 } 861 return true; 862 } 863 864 865 @Override 866 public void processSocket(SocketWrapper<Long> socket, SocketStatus status, 867 boolean dispatch) { 868 try { 869 // Synchronisation is required here as this code may be called as a 870 // result of calling AsyncContext.dispatch() from a non-container 871 // thread 872 synchronized (socket) { 873 if (waitingRequests.remove(socket)) { 874 SocketProcessor proc = new SocketProcessor(socket, status); 875 Executor executor = getExecutor(); 876 if (dispatch && executor != null) { 877 executor.execute(proc); 878 } else { 879 proc.run(); 880 } 881 } 882 } 883 } catch (RejectedExecutionException ree) { 884 log.warn(sm.getString("endpoint.executor.fail", socket) , ree); 885 } catch (Throwable t) { 886 ExceptionUtils.handleThrowable(t); 887 // This means we got an OOM or similar creating a thread, or that 888 // the pool and its queue are full 889 log.error(sm.getString("endpoint.process.fail"), t); 890 } 891 } 892 893 private void closeSocket(long socket) { 894 // If not running the socket will be destroyed by 895 // parent pool or acceptor socket. 896 // In any case disable double free which would cause JVM core. 897 898 connections.remove(Long.valueOf(socket)); 899 900 // While the connector is running, destroySocket() will call 901 // countDownConnection(). Once the connector is stopped, the latch is 902 // removed so it does not matter that destroySocket() does not call 903 // countDownConnection() in that case 904 Poller poller = this.poller; 905 if (poller != null) { 906 if (!poller.close(socket)) { 907 destroySocket(socket); 908 } 909 } 910 } 911 912 /* 913 * This method should only be called if there is no chance that the socket 914 * is currently being used by the Poller. It is generally a bad idea to call 915 * this directly from a known error condition. 916 */ 917 private void destroySocket(long socket) { 918 connections.remove(Long.valueOf(socket)); 919 if (log.isDebugEnabled()) { 920 String msg = sm.getString("endpoint.debug.destroySocket", 921 Long.valueOf(socket)); 922 if (log.isTraceEnabled()) { 923 log.trace(msg, new Exception()); 924 } else { 925 log.debug(msg); 926 } 927 } 928 // Be VERY careful if you call this method directly. If it is called 929 // twice for the same socket the JVM will core. Currently this is only 930 // called from Poller.closePollset() to ensure kept alive connections 931 // are closed when calling stop() followed by start(). 932 if (socket != 0) { 933 Socket.destroy(socket); 934 countDownConnection(); 935 } 936 } 937 938 @Override 939 protected Log getLog() { 940 return log; 941 } 942 943 // --------------------------------------------------- Acceptor Inner Class 944 /** 945 * The background thread that listens for incoming TCP/IP connections and 946 * hands them off to an appropriate processor. 947 */ 948 protected class Acceptor extends AbstractEndpoint.Acceptor { 949 950 private final Log log = LogFactory.getLog(AprEndpoint.Acceptor.class); 951 952 @Override 953 public void run() { 954 955 int errorDelay = 0; 956 957 // Loop until we receive a shutdown command 958 while (running) { 959 960 // Loop if endpoint is paused 961 while (paused && running) { 962 state = AcceptorState.PAUSED; 963 try { 964 Thread.sleep(50); 965 } catch (InterruptedException e) { 966 // Ignore 967 } 968 } 969 970 if (!running) { 971 break; 972 } 973 state = AcceptorState.RUNNING; 974 975 try { 976 //if we have reached max connections, wait 977 countUpOrAwaitConnection(); 978 979 long socket = 0; 980 try { 981 // Accept the next incoming connection from the server 982 // socket 983 socket = Socket.accept(serverSock); 984 if (log.isDebugEnabled()) { 985 long sa = Address.get(Socket.APR_REMOTE, socket); 986 Sockaddr addr = Address.getInfo(sa); 987 log.debug(sm.getString("endpoint.apr.remoteport", 988 Long.valueOf(socket), 989 Long.valueOf(addr.port))); 990 } 991 } catch (Exception e) { 992 //we didn't get a socket 993 countDownConnection(); 994 // Introduce delay if necessary 995 errorDelay = handleExceptionWithDelay(errorDelay); 996 // re-throw 997 throw e; 998 } 999 // Successful accept, reset the error delay 1000 errorDelay = 0; 1001 1002 if (running && !paused) { 1003 // Hand this socket off to an appropriate processor 1004 if (!processSocketWithOptions(socket)) { 1005 // Close socket right away 1006 closeSocket(socket); 1007 } 1008 } else { 1009 // Close socket right away 1010 // No code path could have added the socket to the 1011 // Poller so use destroySocket() 1012 destroySocket(socket); 1013 } 1014 } catch (Throwable t) { 1015 ExceptionUtils.handleThrowable(t); 1016 if (running) { 1017 String msg = sm.getString("endpoint.accept.fail"); 1018 if (t instanceof Error) { 1019 Error e = (Error) t; 1020 if (e.getError() == 233) { 1021 // Not an error on HP-UX so log as a warning 1022 // so it can be filtered out on that platform 1023 // See bug 50273 1024 log.warn(msg, t); 1025 } else { 1026 log.error(msg, t); 1027 } 1028 } else { 1029 log.error(msg, t); 1030 } 1031 } 1032 } 1033 // The processor will recycle itself when it finishes 1034 } 1035 state = AcceptorState.ENDED; 1036 } 1037 } 1038 1039 1040 // -------------------------------------------------- SocketInfo Inner Class 1041 1042 public static class SocketInfo { 1043 public long socket; 1044 public int timeout; 1045 public int flags; 1046 public boolean read() { 1047 return (flags & Poll.APR_POLLIN) == Poll.APR_POLLIN; 1048 } 1049 public boolean write() { 1050 return (flags & Poll.APR_POLLOUT) == Poll.APR_POLLOUT; 1051 } 1052 public static int merge(int flag1, int flag2) { 1053 return ((flag1 & Poll.APR_POLLIN) | (flag2 & Poll.APR_POLLIN)) 1054 | ((flag1 & Poll.APR_POLLOUT) | (flag2 & Poll.APR_POLLOUT)); 1055 } 1056 @Override 1057 public String toString() { 1058 StringBuilder sb = new StringBuilder(); 1059 sb.append("Socket: ["); 1060 sb.append(socket); 1061 sb.append("], timeout: ["); 1062 sb.append(timeout); 1063 sb.append("], flags: ["); 1064 sb.append(flags); 1065 return sb.toString(); 1066 } 1067 } 1068 1069 1070 // ---------------------------------------------- SocketTimeouts Inner Class 1071 1072 public class SocketTimeouts { 1073 protected int size; 1074 1075 protected long[] sockets; 1076 protected long[] timeouts; 1077 protected int pos = 0; 1078 1079 public SocketTimeouts(int size) { 1080 this.size = 0; 1081 sockets = new long[size]; 1082 timeouts = new long[size]; 1083 } 1084 1085 public void add(long socket, long timeout) { 1086 sockets[size] = socket; 1087 timeouts[size] = timeout; 1088 size++; 1089 } 1090 1091 /** 1092 * Removes the specified socket from the poller. 1093 * 1094 * @return The configured timeout for the socket or zero if the socket 1095 * was not in the list of socket timeouts 1096 */ 1097 public long remove(long socket) { 1098 long result = 0; 1099 for (int i = 0; i < size; i++) { 1100 if (sockets[i] == socket) { 1101 result = timeouts[i]; 1102 sockets[i] = sockets[size - 1]; 1103 timeouts[i] = timeouts[size - 1]; 1104 size--; 1105 break; 1106 } 1107 } 1108 return result; 1109 } 1110 1111 public long check(long date) { 1112 while (pos < size) { 1113 if (date >= timeouts[pos]) { 1114 long result = sockets[pos]; 1115 sockets[pos] = sockets[size - 1]; 1116 timeouts[pos] = timeouts[size - 1]; 1117 size--; 1118 return result; 1119 } 1120 pos++; 1121 } 1122 pos = 0; 1123 return 0; 1124 } 1125 1126 } 1127 1128 1129 // -------------------------------------------------- SocketList Inner Class 1130 1131 public class SocketList { 1132 protected int size; 1133 protected int pos; 1134 1135 protected long[] sockets; 1136 protected int[] timeouts; 1137 protected int[] flags; 1138 1139 protected SocketInfo info = new SocketInfo(); 1140 1141 public SocketList(int size) { 1142 this.size = 0; 1143 pos = 0; 1144 sockets = new long[size]; 1145 timeouts = new int[size]; 1146 flags = new int[size]; 1147 } 1148 1149 public int size() { 1150 return this.size; 1151 } 1152 1153 public SocketInfo get() { 1154 if (pos == size) { 1155 return null; 1156 } else { 1157 info.socket = sockets[pos]; 1158 info.timeout = timeouts[pos]; 1159 info.flags = flags[pos]; 1160 pos++; 1161 return info; 1162 } 1163 } 1164 1165 public void clear() { 1166 size = 0; 1167 pos = 0; 1168 } 1169 1170 public boolean add(long socket, int timeout, int flag) { 1171 if (size == sockets.length) { 1172 return false; 1173 } else { 1174 for (int i = 0; i < size; i++) { 1175 if (sockets[i] == socket) { 1176 flags[i] = SocketInfo.merge(flags[i], flag); 1177 return true; 1178 } 1179 } 1180 sockets[size] = socket; 1181 timeouts[size] = timeout; 1182 flags[size] = flag; 1183 size++; 1184 return true; 1185 } 1186 } 1187 1188 public boolean remove(long socket) { 1189 for (int i = 0; i < size; i++) { 1190 if (sockets[i] == socket) { 1191 sockets[i] = sockets[size - 1]; 1192 timeouts[i] = timeouts[size - 1]; 1193 flags[size] = flags[size -1]; 1194 size--; 1195 return true; 1196 } 1197 } 1198 return false; 1199 } 1200 1201 public void duplicate(SocketList copy) { 1202 copy.size = size; 1203 copy.pos = pos; 1204 System.arraycopy(sockets, 0, copy.sockets, 0, size); 1205 System.arraycopy(timeouts, 0, copy.timeouts, 0, size); 1206 System.arraycopy(flags, 0, copy.flags, 0, size); 1207 } 1208 1209 } 1210 1211 // ------------------------------------------------------ Poller Inner Class 1212 1213 public class Poller implements Runnable { 1214 1215 /** 1216 * Pointers to the pollers. 1217 */ 1218 private long[] pollers = null; 1219 1220 /** 1221 * Actual poller size. 1222 */ 1223 private int actualPollerSize = 0; 1224 1225 /** 1226 * Amount of spots left in the poller. 1227 */ 1228 private int[] pollerSpace = null; 1229 1230 /** 1231 * Amount of low level pollers in use by this poller. 1232 */ 1233 private int pollerCount; 1234 1235 /** 1236 * Timeout value for the poll call. 1237 */ 1238 private int pollerTime; 1239 1240 /** 1241 * Variable poller timeout that adjusts depending on how many poll sets 1242 * are in use so that the total poll time across all poll sets remains 1243 * equal to pollTime. 1244 */ 1245 private int nextPollerTime; 1246 1247 /** 1248 * Root pool. 1249 */ 1250 private long pool = 0; 1251 1252 /** 1253 * Socket descriptors. 1254 */ 1255 private long[] desc; 1256 1257 /** 1258 * List of sockets to be added to the poller. 1259 */ 1260 private SocketList addList = null; 1261 1262 1263 /** 1264 * List of sockets to be closed. 1265 */ 1266 private SocketList closeList = null; 1267 1268 1269 /** 1270 * Structure used for storing timeouts. 1271 */ 1272 private SocketTimeouts timeouts = null; 1273 1274 1275 /** 1276 * Last run of maintain. Maintain will run usually every 5s. 1277 */ 1278 private long lastMaintain = System.currentTimeMillis(); 1279 1280 1281 /** 1282 * The number of connections currently inside this Poller. The correct 1283 * operation of the Poller depends on this figure being correct. If it 1284 * is not, it is possible that the Poller will enter a wait loop where 1285 * it waits for the next connection to be added to the Poller before it 1286 * calls poll when it should still be polling existing connections. 1287 * Although not necessary at the time of writing this comment, it has 1288 * been implemented as an AtomicInteger to ensure that it remains 1289 * thread-safe. 1290 */ 1291 private AtomicInteger connectionCount = new AtomicInteger(0); 1292 public int getConnectionCount() { return connectionCount.get(); } 1293 1294 1295 private volatile boolean pollerRunning = true; 1296 1297 /** 1298 * Create the poller. With some versions of APR, the maximum poller size 1299 * will be 62 (recompiling APR is necessary to remove this limitation). 1300 */ 1301 protected void init() { 1302 1303 pool = Pool.create(serverSockPool); 1304 1305 // Single poller by default 1306 int defaultPollerSize = getMaxConnections(); 1307 1308 if ((OS.IS_WIN32 || OS.IS_WIN64) && (defaultPollerSize > 1024)) { 1309 // The maximum per poller to get reasonable performance is 1024 1310 // Adjust poller size so that it won't reach the limit. This is 1311 // a limitation of XP / Server 2003 that has been fixed in 1312 // Vista / Server 2008 onwards. 1313 actualPollerSize = 1024; 1314 } else { 1315 actualPollerSize = defaultPollerSize; 1316 } 1317 1318 timeouts = new SocketTimeouts(defaultPollerSize); 1319 1320 // At the moment, setting the timeout is useless, but it could get 1321 // used again as the normal poller could be faster using maintain. 1322 // It might not be worth bothering though. 1323 long pollset = allocatePoller(actualPollerSize, pool, -1); 1324 if (pollset == 0 && actualPollerSize > 1024) { 1325 actualPollerSize = 1024; 1326 pollset = allocatePoller(actualPollerSize, pool, -1); 1327 } 1328 if (pollset == 0) { 1329 actualPollerSize = 62; 1330 pollset = allocatePoller(actualPollerSize, pool, -1); 1331 } 1332 1333 pollerCount = defaultPollerSize / actualPollerSize; 1334 pollerTime = pollTime / pollerCount; 1335 nextPollerTime = pollerTime; 1336 1337 pollers = new long[pollerCount]; 1338 pollers[0] = pollset; 1339 for (int i = 1; i < pollerCount; i++) { 1340 pollers[i] = allocatePoller(actualPollerSize, pool, -1); 1341 } 1342 1343 pollerSpace = new int[pollerCount]; 1344 for (int i = 0; i < pollerCount; i++) { 1345 pollerSpace[i] = actualPollerSize; 1346 } 1347 1348 desc = new long[actualPollerSize * 2]; 1349 connectionCount.set(0); 1350 addList = new SocketList(defaultPollerSize); 1351 closeList = new SocketList(defaultPollerSize); 1352 } 1353 1354 1355 /* 1356 * This method is synchronized so that it is not possible for a socket 1357 * to be added to the Poller's addList once this method has completed. 1358 */ 1359 protected synchronized void stop() { 1360 pollerRunning = false; 1361 } 1362 1363 1364 /** 1365 * Destroy the poller. 1366 */ 1367 protected void destroy() { 1368 // Wait for pollerTime before doing anything, so that the poller 1369 // threads exit, otherwise parallel destruction of sockets which are 1370 // still in the poller can cause problems 1371 try { 1372 synchronized (this) { 1373 this.notify(); 1374 this.wait(pollTime / 1000); 1375 } 1376 } catch (InterruptedException e) { 1377 // Ignore 1378 } 1379 // Close all sockets in the add queue 1380 SocketInfo info = addList.get(); 1381 while (info != null) { 1382 boolean comet = 1383 connections.get(Long.valueOf(info.socket)).isComet(); 1384 if (!comet || (comet && !processSocket( 1385 info.socket, SocketStatus.STOP))) { 1386 // Poller isn't running at this point so use destroySocket() 1387 // directly 1388 destroySocket(info.socket); 1389 } 1390 info = addList.get(); 1391 } 1392 addList.clear(); 1393 // Close all sockets still in the poller 1394 for (int i = 0; i < pollerCount; i++) { 1395 int rv = Poll.pollset(pollers[i], desc); 1396 if (rv > 0) { 1397 for (int n = 0; n < rv; n++) { 1398 boolean comet = connections.get( 1399 Long.valueOf(desc[n*2+1])).isComet(); 1400 if (!comet || (comet && !processSocket( 1401 desc[n*2+1], SocketStatus.STOP))) { 1402 destroySocket(desc[n*2+1]); 1403 } 1404 } 1405 } 1406 } 1407 Pool.destroy(pool); 1408 connectionCount.set(0); 1409 } 1410 1411 1412 /** 1413 * Add specified socket and associated pool to the poller. The socket 1414 * will be added to a temporary array, and polled first after a maximum 1415 * amount of time equal to pollTime (in most cases, latency will be much 1416 * lower, however). Note: If both read and write are false, the socket 1417 * will only be checked for timeout; if the socket was already present 1418 * in the poller, a callback event will be generated and the socket will 1419 * be removed from the poller. 1420 * 1421 * @param socket to add to the poller 1422 * @param timeout to use for this connection 1423 * @param read to do read polling 1424 * @param write to do write polling 1425 */ 1426 public void add(long socket, int timeout, boolean read, boolean write) { 1427 add(socket, timeout, 1428 (read ? Poll.APR_POLLIN : 0) | 1429 (wri…
Large files files are truncated, but you can click here to view the full file