You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2014/03/15 00:13:00 UTC
svn commit: r1577757 - in /tomcat/trunk/java/org/apache/tomcat/util/net:
Nio2Endpoint.java SecureNio2Channel.java
Author: remm
Date: Fri Mar 14 23:13:00 2014
New Revision: 1577757
URL: http://svn.apache.org/r1577757
Log:
Implement the read/write pending contract in the SSL channel (not doing so would likely still trigger the exception, but would add corruption).
Modified:
tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java
tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java?rev=1577757&r1=1577756&r2=1577757&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java Fri Mar 14 23:13:00 2014
@@ -479,12 +479,11 @@ public class Nio2Endpoint extends Abstra
}
} else {
channel.setIOChannel(socket);
- if ( channel instanceof SecureNio2Channel ) {
+ if (channel instanceof SecureNio2Channel) {
SSLEngine engine = createSSLEngine();
- ((SecureNio2Channel)channel).reset(engine);
- } else {
- channel.reset();
+ ((SecureNio2Channel) channel).setSSLEngine(engine);
}
+ channel.reset();
}
Nio2SocketWrapper socketWrapper = (useCaches) ? socketWrapperCache.pop() : null;
if (socketWrapper == null) {
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java?rev=1577757&r1=1577756&r2=1577757&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java Fri Mar 14 23:13:00 2014
@@ -21,6 +21,7 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
+import java.nio.channels.ReadPendingException;
import java.nio.channels.WritePendingException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@@ -49,8 +50,8 @@ public class SecureNio2Channel extends N
protected boolean closed = false;
protected boolean closing = false;
- protected boolean readPending = false;
- protected boolean writePending = false;
+ protected volatile boolean readPending = false;
+ protected volatile boolean writePending = false;
private CompletionHandler<Integer, SocketWrapper<Nio2Channel>> handshakeReadCompletionHandler;
private CompletionHandler<Integer, SocketWrapper<Nio2Channel>> handshakeWriteCompletionHandler;
@@ -102,9 +103,8 @@ public class SecureNio2Channel extends N
reset();
}
- public void reset(SSLEngine engine) throws IOException {
+ public void setSSLEngine(SSLEngine engine) throws IOException {
this.sslEngine = engine;
- reset();
}
@Override
@@ -152,15 +152,23 @@ public class SecureNio2Channel extends N
@Override
public Boolean get() throws InterruptedException,
ExecutionException {
- int result = integer.get().intValue();
- return Boolean.valueOf(result >= 0);
+ try {
+ int result = integer.get().intValue();
+ return Boolean.valueOf(result >= 0);
+ } finally {
+ writePending = false;
+ }
}
@Override
public Boolean get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException,
TimeoutException {
- int result = integer.get(timeout, unit).intValue();
- return Boolean.valueOf(result >= 0);
+ try {
+ int result = integer.get(timeout, unit).intValue();
+ return Boolean.valueOf(result >= 0);
+ } finally {
+ writePending = false;
+ }
}
}
@@ -174,6 +182,11 @@ public class SecureNio2Channel extends N
@Override
public Future<Boolean> flush()
throws IOException {
+ if (writePending) {
+ throw new WritePendingException();
+ } else {
+ writePending = true;
+ }
return new FutureFlush(sc.write(netOutBuffer));
}
@@ -470,13 +483,21 @@ public class SecureNio2Channel extends N
}
@Override
public Integer get() throws InterruptedException, ExecutionException {
- return unwrap(netInBuffer.position());
+ try {
+ return unwrap(netInBuffer.position());
+ } finally {
+ readPending = false;
+ }
}
@Override
public Integer get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException,
TimeoutException {
- return unwrap(netInBuffer.position());
+ try {
+ return unwrap(netInBuffer.position());
+ } finally {
+ readPending = false;
+ }
}
protected Integer unwrap(int netread) throws ExecutionException {
//are we in the middle of closing or closed?
@@ -544,15 +565,23 @@ public class SecureNio2Channel extends N
}
@Override
public Integer get() throws InterruptedException, ExecutionException {
- int netread = integer.get().intValue();
- return unwrap(netread);
+ try {
+ int netread = integer.get().intValue();
+ return unwrap(netread);
+ } finally {
+ readPending = false;
+ }
}
@Override
public Integer get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException,
TimeoutException {
- int netread = integer.get(timeout, unit).intValue();
- return unwrap(netread);
+ try {
+ int netread = integer.get(timeout, unit).intValue();
+ return unwrap(netread);
+ } finally {
+ readPending = false;
+ }
}
}
@@ -565,6 +594,11 @@ public class SecureNio2Channel extends N
*/
@Override
public Future<Integer> read(ByteBuffer dst) {
+ if (readPending) {
+ throw new ReadPendingException();
+ } else {
+ readPending = true;
+ }
//did we finish our handshake?
if (!handshakeComplete)
throw new IllegalStateException("Handshake incomplete, you must complete handshake before reading data.");
@@ -604,6 +638,7 @@ public class SecureNio2Channel extends N
@Override
public Integer get() throws InterruptedException, ExecutionException {
if (t != null) {
+ writePending = false;
throw new ExecutionException(t);
}
integer.get();
@@ -611,6 +646,7 @@ public class SecureNio2Channel extends N
wrap();
return get();
} else {
+ writePending = false;
return Integer.valueOf(written);
}
}
@@ -619,6 +655,7 @@ public class SecureNio2Channel extends N
throws InterruptedException, ExecutionException,
TimeoutException {
if (t != null) {
+ writePending = false;
throw new ExecutionException(t);
}
integer.get(timeout, unit);
@@ -626,6 +663,7 @@ public class SecureNio2Channel extends N
wrap();
return get(timeout, unit);
} else {
+ writePending = false;
return Integer.valueOf(written);
}
}
@@ -657,6 +695,11 @@ public class SecureNio2Channel extends N
*/
@Override
public Future<Integer> write(ByteBuffer src) {
+ if (writePending) {
+ throw new WritePendingException();
+ } else {
+ writePending = true;
+ }
return new FutureWrite(src);
}
@@ -671,6 +714,7 @@ public class SecureNio2Channel extends N
@Override
public void completed(Integer nBytes, A attach) {
if (nBytes.intValue() < 0) {
+ readPending = false;
handler.failed(new EOFException(), attach);
return;
}
@@ -707,14 +751,17 @@ public class SecureNio2Channel extends N
}
} while ((netInBuffer.position() != 0)); //continue to unwrapping as long as the input buffer has stuff
// If everything is OK, so complete
+ readPending = false;
handler.completed(Integer.valueOf(read), attach);
} catch (Exception e) {
// The operation must fails
+ readPending = false;
handler.failed(e, attach);
}
}
@Override
public void failed(Throwable exc, A attach) {
+ readPending = false;
handler.failed(exc, attach);
}
}
@@ -728,6 +775,11 @@ public class SecureNio2Channel extends N
handler.completed(Integer.valueOf(-1), attachment);
return;
}
+ if (readPending) {
+ throw new ReadPendingException();
+ } else {
+ readPending = true;
+ }
//did we finish our handshake?
if (!handshakeComplete)
throw new IllegalStateException("Handshake incomplete, you must complete handshake before reading data.");
@@ -747,6 +799,11 @@ public class SecureNio2Channel extends N
handler.failed(new IOException("Channel is in closing state."), attachment);
return;
}
+ if (writePending) {
+ throw new WritePendingException();
+ } else {
+ writePending = true;
+ }
try {
// Prepare the output buffer
@@ -759,6 +816,7 @@ public class SecureNio2Channel extends N
if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK)
tasks();
} else {
+ writePending = false;
handler.failed(new IOException("Unable to wrap data, invalid engine state: " +result.getStatus()), attachment);
return;
}
@@ -768,21 +826,25 @@ public class SecureNio2Channel extends N
@Override
public void completed(Integer nBytes, A attach) {
if (nBytes.intValue() < 0) {
+ writePending = false;
handler.failed(new EOFException(), attach);
} else if (written == 0) {
write(src, timeout, unit, attachment, handler);
} else {
// Call the handler completed method with the
// consumed bytes number
+ writePending = false;
handler.completed(Integer.valueOf(written), attach);
}
}
@Override
public void failed(Throwable exc, A attach) {
+ writePending = false;
handler.failed(exc, attach);
}
});
} catch (Throwable exp) {
+ writePending = false;
handler.failed(exp, attachment);
}
}
@@ -819,9 +881,11 @@ public class SecureNio2Channel extends N
@Override
public void completed(Integer nBytes, GatherState<A> attachment) {
if (nBytes.intValue() < 0) {
+ writePending = false;
state.handler.failed(new EOFException(), state.attachment);
} else {
if (state.pos == state.offset + state.length) {
+ writePending = false;
state.handler.completed(Long.valueOf(state.writeCount), state.attachment);
return;
}
@@ -852,6 +916,7 @@ public class SecureNio2Channel extends N
}
@Override
public void failed(Throwable exc, GatherState<A> attachment) {
+ writePending = false;
state.handler.failed(exc, state.attachment);
}
}
@@ -868,6 +933,11 @@ public class SecureNio2Channel extends N
handler.failed(new IOException("Channel is in closing state."), attachment);
return;
}
+ if (writePending) {
+ throw new WritePendingException();
+ } else {
+ writePending = true;
+ }
try {
GatherState<A> state = new GatherState<>(srcs, offset, length,
timeout, unit, attachment, handler);
@@ -881,12 +951,14 @@ public class SecureNio2Channel extends N
if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK)
tasks();
} else {
+ writePending = false;
handler.failed(new IOException("Unable to wrap data, invalid engine state: " +result.getStatus()), attachment);
return;
}
// Write data to the channel
sc.write(netOutBuffer, timeout, unit, state, new GatherCompletionHandler<>(state));
} catch (Throwable exp) {
+ writePending = false;
handler.failed(exp, attachment);
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org