📄 nioendpoint.java
字号:
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.tomcat.util.net;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.security.KeyStore;
import java.util.Iterator;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicLong;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManagerFactory;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.IntrospectionUtils;
import org.apache.tomcat.util.net.SecureNioChannel.ApplicationBufferHandler;
import org.apache.tomcat.util.res.StringManager;
import java.util.concurrent.atomic.AtomicInteger;
/**
* NIO tailored thread pool, providing the following services:
* <ul>
* <li>Socket acceptor thread</li>
* <li>Socket poller thread</li>
* <li>Worker threads pool</li>
* </ul>
*
* When switching to Java 5, there's an opportunity to use the virtual
* machine's thread pool.
*
* @author Mladen Turk
* @author Remy Maucherat
* @author Filip Hanik
*/
public class NioEndpoint {
// -------------------------------------------------------------- Constants
protected static Log log = LogFactory.getLog(NioEndpoint.class);
protected static StringManager sm =
StringManager.getManager("org.apache.tomcat.util.net.res");
/**
* The Request attribute key for the cipher suite.
*/
public static final String CIPHER_SUITE_KEY = "javax.servlet.request.cipher_suite";
/**
* The Request attribute key for the key size.
*/
public static final String KEY_SIZE_KEY = "javax.servlet.request.key_size";
/**
* The Request attribute key for the client certificate chain.
*/
public static final String CERTIFICATE_KEY = "javax.servlet.request.X509Certificate";
/**
* The Request attribute key for the session id.
* This one is a Tomcat extension to the Servlet spec.
*/
public static final String SESSION_ID_KEY = "javax.servlet.request.ssl_session";
public static final int OP_REGISTER = -1; //register interest op
// ----------------------------------------------------------------- Fields
/**
* Available workers.
*/
protected WorkerStack workers = null;
/**
* Running state of the endpoint.
*/
protected volatile boolean running = false;
/**
* Will be set to true whenever the endpoint is paused.
*/
protected volatile boolean paused = false;
/**
* Track the initialization state of the endpoint.
*/
protected boolean initialized = false;
/**
* Current worker threads busy count.
*/
protected int curThreadsBusy = 0;
/**
* Current worker threads count.
*/
protected int curThreads = 0;
/**
* Sequence number used to generate thread names.
*/
protected int sequence = 0;
protected NioSelectorPool selectorPool = new NioSelectorPool();
/**
* Server socket "pointer".
*/
protected ServerSocketChannel serverSock = null;
/**
* Cache for key attachment objects
*/
protected ConcurrentLinkedQueue<KeyAttachment> keyCache = new ConcurrentLinkedQueue<KeyAttachment>();
/**
* Cache for poller events
*/
protected ConcurrentLinkedQueue<PollerEvent> eventCache = new ConcurrentLinkedQueue<PollerEvent>();
/**
* Bytebuffer cache, each channel holds a set of buffers (two, except for SSL holds four)
*/
protected ConcurrentLinkedQueue<NioChannel> nioChannels = new ConcurrentLinkedQueue<NioChannel>() {
protected AtomicInteger size = new AtomicInteger(0);
protected AtomicInteger bytes = new AtomicInteger(0);
public boolean offer(NioChannel socket, KeyAttachment att) {
boolean offer = socketProperties.getBufferPool()==-1?true:size.get()<socketProperties.getBufferPool();
offer = offer && (socketProperties.getBufferPoolSize()==-1?true:(bytes.get()+socket.getBufferSize())<socketProperties.getBufferPoolSize());
//avoid over growing our cache or add after we have stopped
if ( running && (!paused) && (offer) ) {
boolean result = super.offer(socket);
if ( result ) {
size.incrementAndGet();
bytes.addAndGet(socket.getBufferSize());
}
return result;
}
else return false;
}
public NioChannel poll() {
NioChannel result = super.poll();
if ( result != null ) {
size.decrementAndGet();
bytes.addAndGet(-result.getBufferSize());
}
return result;
}
public void clear() {
super.clear();
size.set(0);
}
};
// ------------------------------------------------------------- Properties
/**
* External Executor based thread pool.
*/
protected Executor executor = null;
public void setExecutor(Executor executor) { this.executor = executor; }
public Executor getExecutor() { return executor; }
/**
* Maximum amount of worker threads.
*/
protected int maxThreads = 400;
public void setMaxThreads(int maxThreads) { this.maxThreads = maxThreads; }
public int getMaxThreads() { return maxThreads; }
/**
* Priority of the acceptor and poller threads.
*/
protected int threadPriority = Thread.NORM_PRIORITY;
public void setThreadPriority(int threadPriority) { this.threadPriority = threadPriority; }
public int getThreadPriority() { return threadPriority; }
/**
* Server socket port.
*/
protected int port;
public int getPort() { return port; }
public void setPort(int port ) { this.port=port; }
/**
* Address for the server socket.
*/
protected InetAddress address;
public InetAddress getAddress() { return address; }
public void setAddress(InetAddress address) { this.address = address; }
/**
* Handling of accepted sockets.
*/
protected Handler handler = null;
public void setHandler(Handler handler ) { this.handler = handler; }
public Handler getHandler() { return handler; }
/**
* Allows the server developer to specify the backlog that
* should be used for server sockets. By default, this value
* is 100.
*/
protected int backlog = 100;
public void setBacklog(int backlog) { if (backlog > 0) this.backlog = backlog; }
public int getBacklog() { return backlog; }
protected SocketProperties socketProperties = new SocketProperties();
/**
* Socket TCP no delay.
*/
public boolean getTcpNoDelay() { return socketProperties.getTcpNoDelay();}
public void setTcpNoDelay(boolean tcpNoDelay) { socketProperties.setTcpNoDelay(tcpNoDelay); }
/**
* Socket linger.
*/
public int getSoLinger() { return socketProperties.getSoLingerTime(); }
public void setSoLinger(int soLinger) {
socketProperties.setSoLingerTime(soLinger);
socketProperties.setSoLingerOn(soLinger>=0);
}
/**
* Socket timeout.
*/
public int getSoTimeout() { return socketProperties.getSoTimeout(); }
public void setSoTimeout(int soTimeout) { socketProperties.setSoTimeout(soTimeout); }
/**
* Timeout on first request read before going to the poller, in ms.
*/
protected int firstReadTimeout = 60000;
public int getFirstReadTimeout() { return firstReadTimeout; }
public void setFirstReadTimeout(int firstReadTimeout) { this.firstReadTimeout = firstReadTimeout; }
/**
* The default is true - the created threads will be
* in daemon mode. If set to false, the control thread
* will not be daemon - and will keep the process alive.
*/
protected boolean daemon = true;
public void setDaemon(boolean b) { daemon = b; }
public boolean getDaemon() { return daemon; }
/**
* Name of the thread pool, which will be used for naming child threads.
*/
protected String name = "TP";
public void setName(String name) { this.name = name; }
public String getName() { return name; }
/**
* Allow comet request handling.
*/
protected boolean useComet = true;
public void setUseComet(boolean useComet) { this.useComet = useComet; }
public boolean getUseComet() { return useComet; }
/**
* Acceptor thread count.
*/
protected int acceptorThreadCount = 0;
public void setAcceptorThreadCount(int acceptorThreadCount) { this.acceptorThreadCount = acceptorThreadCount; }
public int getAcceptorThreadCount() { return acceptorThreadCount; }
/**
* Poller thread count.
*/
protected int pollerThreadCount = 0;
public void setPollerThreadCount(int pollerThreadCount) { this.pollerThreadCount = pollerThreadCount; }
public int getPollerThreadCount() { return pollerThreadCount; }
protected long selectorTimeout = 1000;
public void setSelectorTimeout(long timeout){ this.selectorTimeout = timeout;}
public long getSelectorTimeout(){ return this.selectorTimeout; }
/**
* The socket poller.
*/
protected Poller[] pollers = null;
protected int pollerRoundRobin = 0;
public Poller getPoller0() {
pollerRoundRobin = (pollerRoundRobin + 1) % pollers.length;
Poller poller = pollers[pollerRoundRobin];
return poller;
}
/**
* The socket poller used for Comet support.
*/
public Poller getCometPoller0() {
Poller poller = getPoller0();
return poller;
}
/**
* Dummy maxSpareThreads property.
*/
public int getMaxSpareThreads() { return Math.min(getMaxThreads(),5); }
/**
* Dummy minSpareThreads property.
*/
public int getMinSpareThreads() { return Math.min(getMaxThreads(),5); }
/**
* Generic properties, introspected
*/
public void setProperty(String name, String value) {
final String selectorPoolName = "selectorPool.";
final String socketName = "socket.";
try {
if (name.startsWith(selectorPoolName)) {
IntrospectionUtils.setProperty(selectorPool, name.substring(selectorPoolName.length()), value);
} else if (name.startsWith(socketName)) {
IntrospectionUtils.setProperty(socketProperties, name.substring(socketName.length()), value);
}
}catch ( Exception x ) {
log.error("Unable to set attribute \""+name+"\" to \""+value+"\"",x);
}
}
// -------------------- SSL related properties --------------------
protected String keystoreFile = System.getProperty("user.home")+"/.keystore";
public String getKeystoreFile() { return keystoreFile;}
public void setKeystoreFile(String s ) { this.keystoreFile = s; }
public void setKeystore(String s ) { setKeystoreFile(s);}
public String getKeystore() { return getKeystoreFile();}
protected String algorithm = "SunX509";
public String getAlgorithm() { return algorithm;}
public void setAlgorithm(String s ) { this.algorithm = s;}
protected boolean clientAuth = false;
public boolean getClientAuth() { return clientAuth;}
public void setClientAuth(boolean b ) { this.clientAuth = b;}
protected String keystorePass = "changeit";
public String getKeystorePass() { return keystorePass;}
public void setKeystorePass(String s ) { this.keystorePass = s;}
protected String keystoreType = "JKS";
public String getKeystoreType() { return keystoreType;}
public void setKeystoreType(String s ) { this.keystoreType = s;}
protected String sslProtocol = "TLS";
public String getSslProtocol() { return sslProtocol;}
public void setSslProtocol(String s) { sslProtocol = s;}
protected String sslEnabledProtocols=null; //"TLSv1,SSLv3,SSLv2Hello"
protected String[] sslEnabledProtocolsarr = new String[0];
public void setSslEnabledProtocols(String s) {
this.sslEnabledProtocols = s;
StringTokenizer t = new StringTokenizer(s,",");
sslEnabledProtocolsarr = new String[t.countTokens()];
for (int i=0; i<sslEnabledProtocolsarr.length; i++ ) sslEnabledProtocolsarr[i] = t.nextToken();
}
protected String ciphers = null;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -