Author: fhanik Date: Wed Jan 14 09:39:07 2009 New Revision: 734454 URL: http://svn.apache.org/viewvc?rev=734454&view=rev Log: NIO Fixes
Added: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/jsse/NioX509KeyManager.java Modified: tomcat/tc6.0.x/trunk/STATUS.txt tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Modified: tomcat/tc6.0.x/trunk/STATUS.txt URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/STATUS.txt?rev=734454&r1=734453&r2=734454&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/STATUS.txt (original) +++ tomcat/tc6.0.x/trunk/STATUS.txt Wed Jan 14 09:39:07 2009 @@ -133,26 +133,6 @@ Just did that for trunk (r711934; but it contains also other changes). Caution: at the moment there's no @VERSION@ substitution for service.bat. -* I have summarized all the NIO fixes into one patch for those who wish to test it -* It includes patch [1]-[6] below and can be found at: -* http://people.apache.org/~fhanik/tomcat/uber-patch.txt - -* [1] Fix send file bug - correctly notify the poller without having to wait for it to wake up - http://svn.apache.org/viewvc?rev=719129&view=rev - +1: fhanik, pero, markt, jim - -1: - -* [2] Prevent async close NPE on already closed sockets - http://people.apache.org/~fhanik/tomcat/comet-close-2.patch - +1: fhanik, markt (need to fix indenting), funkman - -1: - -* [3] Add ability to fix the keyAlias in NIO/SSL - http://svn.apache.org/viewvc?rev=720587&view=rev - http://svn.apache.org/viewvc?rev=720553&view=rev - +1: fhanik, markt, funkman - -1: - * [4] Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=45154 (add sendfile support to NIO/SSL) - performance improvement http://svn.apache.org/viewvc?rev=720724&view=rev http://svn.apache.org/viewvc?rev=720728&view=rev @@ -165,12 +145,6 @@ +1: fhanik, funkman -1: -* [6] Fix file descriptor leak during send file behavior in NIO connector - http://svn.apache.org/viewvc?rev=729191&view=rev - +1: fhanik, markt, jim, funkman - -1: - - * Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=42693 Fix compilation of recursive tags http://svn.apache.org/viewvc?rev=720046&view=rev Modified: tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java?rev=734454&r1=734453&r2=734454&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java Wed Jan 14 09:39:07 2009 @@ -940,7 +940,7 @@ sendfileData.keepAlive = keepAlive; SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector()); //do the first write on this thread, might as well - openSocket = socket.getPoller().processSendfile(key,ka,true); + openSocket = socket.getPoller().processSendfile(key,ka,true,true); break; } @@ -1227,14 +1227,16 @@ } else if (actionCode == ActionCode.ACTION_COMET_END) { comet = false; } else if (actionCode == ActionCode.ACTION_COMET_CLOSE) { - NioEndpoint.KeyAttachment attach = (NioEndpoint.KeyAttachment)socket.getAttachment(false); - attach.setCometOps(NioEndpoint.OP_CALLBACK); + if (socket==null || socket.getAttachment(false)==null) return; + NioEndpoint.KeyAttachment attach = (NioEndpoint.KeyAttachment)socket.getAttachment(false); + attach.setCometOps(NioEndpoint.OP_CALLBACK | attach.getCometOps()); //notify poller if not on a tomcat thread RequestInfo rp = request.getRequestProcessor(); if ( rp.getStage() != org.apache.coyote.Constants.STAGE_SERVICE ) //async handling socket.getPoller().cometInterest(socket); } else if (actionCode == ActionCode.ACTION_COMET_SETTIMEOUT) { if (param==null) return; + if (socket==null || socket.getAttachment(false)==null) return; NioEndpoint.KeyAttachment attach = (NioEndpoint.KeyAttachment)socket.getAttachment(false); long timeout = ((Long)param).longValue(); //if we are not piggy backing on a worker thread, set the timeout Modified: tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java?rev=734454&r1=734453&r2=734454&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java Wed Jan 14 09:39:07 2009 @@ -545,6 +545,10 @@ public void setKeystore(String s) { setKeystoreFile(s);} public String getKeystore(){ return getKeystoreFile();} + public String getKeyAlias() { return ep.getKeyAlias();} + public void setKeyAlias(String s ) { ep.setKeyAlias(s);} + + public String getAlgorithm() { return ep.getAlgorithm();} public void setAlgorithm(String s ) { ep.setAlgorithm(s);} Modified: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?rev=734454&r1=734453&r2=734454&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Wed Jan 14 09:39:07 2009 @@ -44,17 +44,21 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; + +import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLSessionContext; import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509KeyManager; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.IntrospectionUtils; import org.apache.tomcat.util.net.JIoEndpoint.Worker; import org.apache.tomcat.util.net.SecureNioChannel.ApplicationBufferHandler; +import org.apache.tomcat.util.net.jsse.NioX509KeyManager; import org.apache.tomcat.util.res.StringManager; /** @@ -572,6 +576,11 @@ } public void setKeystore(String s ) { setKeystoreFile(s);} public String getKeystore() { return getKeystoreFile();} + + String keyAlias = null; + public String getKeyAlias() { return keyAlias;} + public void setKeyAlias(String s ) { keyAlias = s;} + protected String algorithm = "SunX509"; public String getAlgorithm() { return algorithm;} @@ -785,8 +794,7 @@ ks.load(new FileInputStream(getKeystoreFile()), passphrase); KeyStore ts = null; if (getTruststoreFile()==null) { - ts = KeyStore.getInstance(getKeystoreType()); - ts.load(new FileInputStream(getKeystoreFile()), passphrase); + //no op, same as for BIO connector }else { ts = KeyStore.getInstance(ttype); ts.load(new FileInputStream(getTruststoreFile()), tpassphrase); @@ -799,7 +807,7 @@ tmf.init(ts); sslContext = SSLContext.getInstance(getSslProtocol()); - sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + sslContext.init(wrap(kmf.getKeyManagers()), tmf.getTrustManagers(), null); SSLSessionContext sessionContext = sslContext.getServerSessionContext(); if (sessionContext != null) { @@ -813,6 +821,19 @@ initialized = true; } + + public KeyManager[] wrap(KeyManager[] managers) { + if (managers==null) return null; + KeyManager[] result = new KeyManager[managers.length]; + for (int i=0; i<result.length; i++) { + if (managers[i] instanceof X509KeyManager && getKeyAlias()!=null) { + result[i] = new NioX509KeyManager((X509KeyManager)managers[i],getKeyAlias()); + } else { + result[i] = managers[i]; + } + } + return result; + } /** @@ -1317,6 +1338,7 @@ int ops = key.interestOps() | interestOps; att.interestOps(ops); key.interestOps(ops); + att.setCometOps(ops); } else { cancel = true; } @@ -1459,11 +1481,13 @@ } } + key.attach(null); if (ka!=null) handler.release(ka.getChannel()); if (key.isValid()) key.cancel(); if (key.channel().isOpen()) try {key.channel().close();}catch (Exception ignore){} - try {ka.channel.close(true);}catch (Exception ignore){} - key.attach(null); + try {if (ka!=null) ka.channel.close(true);}catch (Exception ignore){} + try {if (ka!=null && ka.getSendfileData()!=null && ka.getSendfileData().fchannel!=null && ka.getSendfileData().fchannel.isOpen()) ka.getSendfileData().fchannel.close();}catch (Exception ignore){} + if (ka!=null) ka.reset(); } catch (Throwable e) { if ( log.isDebugEnabled() ) log.error("",e); // Ignore @@ -1575,7 +1599,7 @@ NioChannel channel = attachment.getChannel(); if (sk.isReadable() || sk.isWritable() ) { if ( attachment.getSendfileData() != null ) { - processSendfile(sk,attachment,true); + processSendfile(sk,attachment,true, false); } else if ( attachment.getComet() ) { //check if thread is available if ( isWorkerAvailable() ) { @@ -1620,7 +1644,7 @@ return result; } - public boolean processSendfile(SelectionKey sk, KeyAttachment attachment, boolean reg) { + public boolean processSendfile(SelectionKey sk, KeyAttachment attachment, boolean reg, boolean event) { try { //unreg(sk,attachment);//only do this if we do process send file on a separate thread SendfileData sd = attachment.getSendfileData(); @@ -1643,11 +1667,18 @@ log.debug("Send file complete for:"+sd.fileName); } attachment.setSendfileData(null); + try {sd.fchannel.close();}catch(Exception ignore){} if ( sd.keepAlive ) { - if (log.isDebugEnabled()) { - log.debug("Connection is keep alive, registering back for OP_READ"); + if (reg) { + if (log.isDebugEnabled()) { + log.debug("Connection is keep alive, registering back for OP_READ"); + } + if (event) { + this.add(attachment.getChannel(),SelectionKey.OP_READ); + } else { + reg(sk,attachment,SelectionKey.OP_READ); + } } - if (reg) reg(sk,attachment,SelectionKey.OP_READ); } else { if (log.isDebugEnabled()) { log.debug("Send file connection is being closed"); @@ -1658,11 +1689,14 @@ if (log.isDebugEnabled()) { log.debug("OP_WRITE for sendilfe:"+sd.fileName); } - - reg(sk,attachment,SelectionKey.OP_WRITE); + if (event) { + add(attachment.getChannel(),SelectionKey.OP_WRITE); + } else { + reg(sk,attachment,SelectionKey.OP_WRITE); + } } }catch ( IOException x ) { - if ( log.isDebugEnabled() ) log.warn("Unable to complete sendfile request:", x); + if ( log.isDebugEnabled() ) log.debug("Unable to complete sendfile request:", x); cancelledKey(sk,SocketStatus.ERROR,false); return false; }catch ( Throwable t ) { @@ -1681,7 +1715,7 @@ protected void reg(SelectionKey sk, KeyAttachment attachment, int intops) { sk.interestOps(intops); attachment.interestOps(intops); - attachment.setCometOps(intops); + //attachment.setCometOps(intops); } protected void timeout(int keyCount, boolean hasEvents) { Added: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/jsse/NioX509KeyManager.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/jsse/NioX509KeyManager.java?rev=734454&view=auto ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/jsse/NioX509KeyManager.java (added) +++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/jsse/NioX509KeyManager.java Wed Jan 14 09:39:07 2009 @@ -0,0 +1,86 @@ +/* + * 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.jsse; + +import java.net.Socket; +import java.security.Principal; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; + +import javax.net.ssl.SSLEngine; +import javax.net.ssl.X509ExtendedKeyManager; +import javax.net.ssl.X509KeyManager; + +public class NioX509KeyManager extends X509ExtendedKeyManager { + + private X509KeyManager delegate; + private String serverKeyAlias; + + /** + * Constructor. + * + * @param mgr The X509KeyManager used as a delegate + * @param serverKeyAlias The alias name of the server's keypair and + * supporting certificate chain + */ + public NioX509KeyManager(X509KeyManager mgr, String serverKeyAlias) { + this.delegate = mgr; + this.serverKeyAlias = serverKeyAlias; + } + + public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { + return delegate.chooseClientAlias(keyType, issuers, socket); + } + + public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { + if (serverKeyAlias!=null) { + return serverKeyAlias; + } else { + return delegate.chooseServerAlias(keyType, issuers, socket); + } + } + + public X509Certificate[] getCertificateChain(String alias) { + return delegate.getCertificateChain(alias); + } + + public String[] getClientAliases(String keyType, Principal[] issuers) { + return delegate.getClientAliases(keyType, issuers); + } + + public PrivateKey getPrivateKey(String alias) { + return delegate.getPrivateKey(alias); + } + + public String[] getServerAliases(String keyType, Principal[] issuers) { + return delegate.getServerAliases(keyType, issuers); + } + + @Override + public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) { + if (serverKeyAlias!=null) { + return serverKeyAlias; + } else { + return super.chooseEngineServerAlias(keyType, issuers, engine); + } + } + + + + +} Modified: tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml?rev=734454&r1=734453&r2=734454&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Wed Jan 14 09:39:07 2009 @@ -224,6 +224,18 @@ <subsection name="Coyote"> <changelog> <update> + Fix file descriptor leak during NIO send file behavior. (fhanik) + </update> + <update> + Implement usage of keyAlias attribute for NIO, previously attribute was ignored. (fhanik) + </update> + <update> + Prevent server from calling close on an already closed NIO socket. One that had timed out. (fhanik) + </update> + <update> + Fix bug with SEND_FILE behavior in NIO. Send file would delay until selector timed out, even though socket was ready to be written. (fhanik) + </update> + <update> Fix possible NPE in NioEndpoint.java (fhanik) </update> <update> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org