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: [email protected]
For additional commands, e-mail: [email protected]