398872 - SslConnection should not be notified of idle timeouts. First solution.
This commit is contained in:
parent
b5df3a6b76
commit
b2f3852fb3
|
@ -871,6 +871,16 @@ public class HttpClient extends ContainerLifeCycle
|
||||||
return encodingField;
|
return encodingField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected HttpConnection newHttpConnection(HttpClient httpClient, EndPoint endPoint, HttpDestination destination)
|
||||||
|
{
|
||||||
|
return new HttpConnection(httpClient, endPoint, destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SslConnection newSslConnection(HttpClient httpClient, EndPoint endPoint, SSLEngine engine)
|
||||||
|
{
|
||||||
|
return new SslConnection(httpClient.getByteBufferPool(), httpClient.getExecutor(), endPoint, engine);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dump(Appendable out, String indent) throws IOException
|
public void dump(Appendable out, String indent) throws IOException
|
||||||
{
|
{
|
||||||
|
@ -916,12 +926,9 @@ public class HttpClient extends ContainerLifeCycle
|
||||||
SSLEngine engine = sslContextFactory.newSSLEngine(endPoint.getRemoteAddress());
|
SSLEngine engine = sslContextFactory.newSSLEngine(endPoint.getRemoteAddress());
|
||||||
engine.setUseClientMode(true);
|
engine.setUseClientMode(true);
|
||||||
|
|
||||||
SslConnection sslConnection = new SslConnection(getByteBufferPool(), getExecutor(), endPoint, engine);
|
SslConnection sslConnection = newSslConnection(HttpClient.this, endPoint, engine);
|
||||||
// TODO: configureConnection => implies we should use SslConnectionFactory to do it
|
|
||||||
|
|
||||||
EndPoint appEndPoint = sslConnection.getDecryptedEndPoint();
|
EndPoint appEndPoint = sslConnection.getDecryptedEndPoint();
|
||||||
HttpConnection connection = new HttpConnection(HttpClient.this, appEndPoint, destination);
|
HttpConnection connection = newHttpConnection(HttpClient.this, appEndPoint, destination);
|
||||||
// TODO: configureConnection, see above
|
|
||||||
|
|
||||||
appEndPoint.setConnection(connection);
|
appEndPoint.setConnection(connection);
|
||||||
callback.promise.succeeded(connection);
|
callback.promise.succeeded(connection);
|
||||||
|
@ -931,8 +938,7 @@ public class HttpClient extends ContainerLifeCycle
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HttpConnection connection = new HttpConnection(HttpClient.this, endPoint, destination);
|
HttpConnection connection = newHttpConnection(HttpClient.this, endPoint, destination);
|
||||||
// TODO: configureConnection, see above
|
|
||||||
callback.promise.succeeded(connection);
|
callback.promise.succeeded(connection);
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@ import java.io.IOException;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import javax.net.ssl.SSLEngine;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
@ -34,10 +36,13 @@ import org.eclipse.jetty.client.api.Response;
|
||||||
import org.eclipse.jetty.client.api.Result;
|
import org.eclipse.jetty.client.api.Result;
|
||||||
import org.eclipse.jetty.client.util.BufferingResponseListener;
|
import org.eclipse.jetty.client.util.BufferingResponseListener;
|
||||||
import org.eclipse.jetty.client.util.InputStreamContentProvider;
|
import org.eclipse.jetty.client.util.InputStreamContentProvider;
|
||||||
|
import org.eclipse.jetty.io.EndPoint;
|
||||||
|
import org.eclipse.jetty.io.ssl.SslConnection;
|
||||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||||
import org.eclipse.jetty.toolchain.test.annotation.Slow;
|
import org.eclipse.jetty.toolchain.test.annotation.Slow;
|
||||||
import org.eclipse.jetty.util.IO;
|
import org.eclipse.jetty.util.IO;
|
||||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||||
|
import org.hamcrest.Matchers;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -223,6 +228,46 @@ public class HttpClientTimeoutTest extends AbstractHttpClientServerTest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIdleTimeout() throws Throwable
|
||||||
|
{
|
||||||
|
long timeout = 1000;
|
||||||
|
start(new TimeoutHandler(2 * timeout));
|
||||||
|
client.stop();
|
||||||
|
final AtomicBoolean sslIdle = new AtomicBoolean();
|
||||||
|
client = new HttpClient(sslContextFactory)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected SslConnection newSslConnection(HttpClient httpClient, EndPoint endPoint, SSLEngine engine)
|
||||||
|
{
|
||||||
|
return new SslConnection(httpClient.getByteBufferPool(), httpClient.getExecutor(), endPoint, engine)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected boolean onReadTimeout()
|
||||||
|
{
|
||||||
|
sslIdle.set(true);
|
||||||
|
return super.onReadTimeout();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
client.setIdleTimeout(timeout);
|
||||||
|
client.start();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
client.newRequest("localhost", connector.getLocalPort())
|
||||||
|
.scheme(scheme)
|
||||||
|
.send();
|
||||||
|
Assert.fail();
|
||||||
|
}
|
||||||
|
catch (Exception x)
|
||||||
|
{
|
||||||
|
Assert.assertFalse(sslIdle.get());
|
||||||
|
Assert.assertThat(x.getCause(), Matchers.instanceOf(TimeoutException.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class TimeoutHandler extends AbstractHandler
|
private class TimeoutHandler extends AbstractHandler
|
||||||
{
|
{
|
||||||
private final long timeout;
|
private final long timeout;
|
||||||
|
|
|
@ -30,12 +30,12 @@ import org.eclipse.jetty.util.thread.Scheduler;
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
/** An Abstract implementation of an Idle Timeout.
|
/** An Abstract implementation of an Idle Timeout.
|
||||||
*
|
*
|
||||||
* This implementation is optimised that timeout operations are not cancelled on
|
* This implementation is optimised that timeout operations are not cancelled on
|
||||||
* every operation. Rather timeout are allowed to expire and a check is then made
|
* every operation. Rather timeout are allowed to expire and a check is then made
|
||||||
* to see when the last operation took place. If the idle timeout has not expired,
|
* to see when the last operation took place. If the idle timeout has not expired,
|
||||||
* the timeout is rescheduled for the earliest possible time a timeout could occur.
|
* the timeout is rescheduled for the earliest possible time a timeout could occur.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public abstract class IdleTimeout
|
public abstract class IdleTimeout
|
||||||
{
|
{
|
||||||
|
@ -44,7 +44,7 @@ public abstract class IdleTimeout
|
||||||
private final AtomicReference<Scheduler.Task> _timeout = new AtomicReference<>();
|
private final AtomicReference<Scheduler.Task> _timeout = new AtomicReference<>();
|
||||||
private volatile long _idleTimeout;
|
private volatile long _idleTimeout;
|
||||||
private volatile long _idleTimestamp=System.currentTimeMillis();
|
private volatile long _idleTimestamp=System.currentTimeMillis();
|
||||||
|
|
||||||
private final Runnable _idleTask = new Runnable()
|
private final Runnable _idleTask = new Runnable()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
|
@ -63,12 +63,12 @@ public abstract class IdleTimeout
|
||||||
{
|
{
|
||||||
_scheduler=scheduler;
|
_scheduler=scheduler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getIdleTimestamp()
|
public long getIdleTimestamp()
|
||||||
{
|
{
|
||||||
return _idleTimestamp;
|
return _idleTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getIdleTimeout()
|
public long getIdleTimeout()
|
||||||
{
|
{
|
||||||
return _idleTimeout;
|
return _idleTimeout;
|
||||||
|
@ -78,22 +78,22 @@ public abstract class IdleTimeout
|
||||||
{
|
{
|
||||||
long old=_idleTimeout;
|
long old=_idleTimeout;
|
||||||
_idleTimeout = idleTimeout;
|
_idleTimeout = idleTimeout;
|
||||||
|
|
||||||
// Do we have an old timeout
|
// Do we have an old timeout
|
||||||
if (old>0)
|
if (old>0)
|
||||||
{
|
{
|
||||||
// if the old was less than or equal to the new timeout, then nothing more to do
|
// if the old was less than or equal to the new timeout, then nothing more to do
|
||||||
if (old<=_idleTimeout)
|
if (old<=idleTimeout)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// old timeout is too long, so cancel it.
|
// old timeout is too long, so cancel it.
|
||||||
Scheduler.Task oldTimeout = _timeout.getAndSet(null);
|
Scheduler.Task oldTimeout = _timeout.getAndSet(null);
|
||||||
if (oldTimeout != null)
|
if (oldTimeout != null)
|
||||||
oldTimeout.cancel();
|
oldTimeout.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have a new timeout, then check and reschedule
|
// If we have a new timeout, then check and reschedule
|
||||||
if (_idleTimeout>0 && isOpen())
|
if (idleTimeout>0 && isOpen())
|
||||||
_idleTask.run();
|
_idleTask.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ public abstract class IdleTimeout
|
||||||
{
|
{
|
||||||
_idleTimestamp=System.currentTimeMillis();
|
_idleTimestamp=System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scheduleIdleTimeout(long delay)
|
private void scheduleIdleTimeout(long delay)
|
||||||
{
|
{
|
||||||
Scheduler.Task newTimeout = null;
|
Scheduler.Task newTimeout = null;
|
||||||
|
@ -113,20 +113,20 @@ public abstract class IdleTimeout
|
||||||
if (oldTimeout != null)
|
if (oldTimeout != null)
|
||||||
oldTimeout.cancel();
|
oldTimeout.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onOpen()
|
public void onOpen()
|
||||||
{
|
{
|
||||||
if (_idleTimeout>0)
|
if (_idleTimeout>0)
|
||||||
_idleTask.run();
|
_idleTask.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void close()
|
protected void close()
|
||||||
{
|
{
|
||||||
Scheduler.Task oldTimeout = _timeout.getAndSet(null);
|
Scheduler.Task oldTimeout = _timeout.getAndSet(null);
|
||||||
if (oldTimeout != null)
|
if (oldTimeout != null)
|
||||||
oldTimeout.cancel();
|
oldTimeout.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected long checkIdleTimeout()
|
protected long checkIdleTimeout()
|
||||||
{
|
{
|
||||||
if (isOpen())
|
if (isOpen())
|
||||||
|
@ -158,14 +158,14 @@ public abstract class IdleTimeout
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
/** This abstract method is called when the idle timeout has expired.
|
/** This abstract method is called when the idle timeout has expired.
|
||||||
* @param timeout a TimeoutException
|
* @param timeout a TimeoutException
|
||||||
*/
|
*/
|
||||||
abstract protected void onIdleExpired(TimeoutException timeout);
|
abstract protected void onIdleExpired(TimeoutException timeout);
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
/** This abstract method should be called to check if idle timeouts
|
/** This abstract method should be called to check if idle timeouts
|
||||||
* should still be checked.
|
* should still be checked.
|
||||||
|
|
|
@ -100,7 +100,7 @@ public class SslConnection extends AbstractConnection
|
||||||
_decryptedEndPoint.getWriteFlusher().completeWrite();
|
_decryptedEndPoint.getWriteFlusher().completeWrite();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public SslConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, SSLEngine sslEngine)
|
public SslConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, SSLEngine sslEngine)
|
||||||
{
|
{
|
||||||
// This connection does not execute calls to onfillable, so they will be called by the selector thread.
|
// This connection does not execute calls to onfillable, so they will be called by the selector thread.
|
||||||
|
@ -109,7 +109,7 @@ public class SslConnection extends AbstractConnection
|
||||||
this._bufferPool = byteBufferPool;
|
this._bufferPool = byteBufferPool;
|
||||||
this._sslEngine = sslEngine;
|
this._sslEngine = sslEngine;
|
||||||
this._decryptedEndPoint = newDecryptedEndPoint();
|
this._decryptedEndPoint = newDecryptedEndPoint();
|
||||||
|
|
||||||
if (endPoint instanceof SocketBased)
|
if (endPoint instanceof SocketBased)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -220,9 +220,6 @@ public class SslConnection extends AbstractConnection
|
||||||
// the decrypted readInterest and/or writeFlusher so that they will attempt
|
// the decrypted readInterest and/or writeFlusher so that they will attempt
|
||||||
// to do the fill and/or flush again and these calls will do the actually
|
// to do the fill and/or flush again and these calls will do the actually
|
||||||
// handle the cause.
|
// handle the cause.
|
||||||
|
|
||||||
super.onFillInterestedFailed(cause);
|
|
||||||
|
|
||||||
synchronized(_decryptedEndPoint)
|
synchronized(_decryptedEndPoint)
|
||||||
{
|
{
|
||||||
_decryptedEndPoint.getFillInterest().onFail(cause);
|
_decryptedEndPoint.getFillInterest().onFail(cause);
|
||||||
|
@ -482,13 +479,13 @@ public class SslConnection extends AbstractConnection
|
||||||
LOG.debug("{} filled {} encrypted bytes", SslConnection.this, net_filled);
|
LOG.debug("{} filled {} encrypted bytes", SslConnection.this, net_filled);
|
||||||
if (net_filled > 0)
|
if (net_filled > 0)
|
||||||
_underFlown = false;
|
_underFlown = false;
|
||||||
|
|
||||||
// Let's try the SSL thang even if we have no net data because in that
|
// Let's try the SSL thang even if we have no net data because in that
|
||||||
// case we want to fall through to the handshake handling
|
// case we want to fall through to the handshake handling
|
||||||
int pos = BufferUtil.flipToFill(app_in);
|
int pos = BufferUtil.flipToFill(app_in);
|
||||||
|
|
||||||
SSLEngineResult unwrapResult = _sslEngine.unwrap(_encryptedInput, app_in);
|
SSLEngineResult unwrapResult = _sslEngine.unwrap(_encryptedInput, app_in);
|
||||||
|
|
||||||
BufferUtil.flipToFlush(app_in, pos);
|
BufferUtil.flipToFlush(app_in, pos);
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
LOG.debug("{} unwrap {}", SslConnection.this, unwrapResult);
|
LOG.debug("{} unwrap {}", SslConnection.this, unwrapResult);
|
||||||
|
@ -663,7 +660,7 @@ public class SslConnection extends AbstractConnection
|
||||||
BufferUtil.flipToFlush(_encryptedOutput, pos);
|
BufferUtil.flipToFlush(_encryptedOutput, pos);
|
||||||
if (wrapResult.bytesConsumed()>0)
|
if (wrapResult.bytesConsumed()>0)
|
||||||
consumed+=wrapResult.bytesConsumed();
|
consumed+=wrapResult.bytesConsumed();
|
||||||
|
|
||||||
boolean all_consumed=true;
|
boolean all_consumed=true;
|
||||||
// clear empty buffers to prevent position creeping up the buffer
|
// clear empty buffers to prevent position creeping up the buffer
|
||||||
for (ByteBuffer b : appOuts)
|
for (ByteBuffer b : appOuts)
|
||||||
|
|
|
@ -20,11 +20,9 @@ package org.eclipse.jetty.io;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.SocketChannel;
|
import java.nio.channels.SocketChannel;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import javax.net.ssl.SSLEngine;
|
import javax.net.ssl.SSLEngine;
|
||||||
import javax.net.ssl.SSLEngineResult;
|
import javax.net.ssl.SSLEngineResult;
|
||||||
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
|
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
|
||||||
|
@ -42,9 +40,7 @@ import org.junit.Test;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.greaterThan;
|
import static org.hamcrest.Matchers.greaterThan;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
|
|
||||||
public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
|
public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
|
||||||
|
@ -226,51 +222,6 @@ public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
|
||||||
super.testIdle();
|
super.testIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void testBlockedReadIdle() throws Exception
|
|
||||||
{
|
|
||||||
Socket client = newClient();
|
|
||||||
OutputStream clientOutputStream = client.getOutputStream();
|
|
||||||
|
|
||||||
client.setSoTimeout(5000);
|
|
||||||
|
|
||||||
SocketChannel server = _connector.accept();
|
|
||||||
server.configureBlocking(false);
|
|
||||||
|
|
||||||
_manager.accept(server);
|
|
||||||
|
|
||||||
// Write client to server
|
|
||||||
clientOutputStream.write("HelloWorld".getBytes("UTF-8"));
|
|
||||||
|
|
||||||
// Verify echo server to client
|
|
||||||
for (char c : "HelloWorld".toCharArray())
|
|
||||||
{
|
|
||||||
int b = client.getInputStream().read();
|
|
||||||
assertTrue(b>0);
|
|
||||||
assertEquals(c,(char)b);
|
|
||||||
}
|
|
||||||
|
|
||||||
assertTrue(_lastEndPointLatch.await(1, TimeUnit.SECONDS));
|
|
||||||
_lastEndPoint.setIdleTimeout(500);
|
|
||||||
|
|
||||||
// Write 8 and cause block waiting for 10
|
|
||||||
_blockAt=10;
|
|
||||||
clientOutputStream.write("12345678".getBytes("UTF-8"));
|
|
||||||
clientOutputStream.flush();
|
|
||||||
|
|
||||||
// read until idle shutdown received
|
|
||||||
long start=System.currentTimeMillis();
|
|
||||||
int b=client.getInputStream().read();
|
|
||||||
assertEquals(-1,b);
|
|
||||||
long idle=System.currentTimeMillis()-start;
|
|
||||||
assertTrue(idle>400);
|
|
||||||
assertTrue(idle<2000);
|
|
||||||
|
|
||||||
Thread.sleep(1000);
|
|
||||||
|
|
||||||
assertFalse(_lastEndPoint.isOpen());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Override
|
@Override
|
||||||
@Stress("Requires a relatively idle (network wise) environment")
|
@Stress("Requires a relatively idle (network wise) environment")
|
||||||
|
|
|
@ -18,12 +18,6 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.io;
|
package org.eclipse.jetty.io;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.greaterThan;
|
|
||||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -52,6 +46,12 @@ import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.greaterThan;
|
||||||
|
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class SelectChannelEndPointTest
|
public class SelectChannelEndPointTest
|
||||||
{
|
{
|
||||||
private static final Logger LOG = Log.getLogger(SelectChannelEndPointTest.class);
|
private static final Logger LOG = Log.getLogger(SelectChannelEndPointTest.class);
|
||||||
|
@ -220,7 +220,7 @@ public class SelectChannelEndPointTest
|
||||||
{
|
{
|
||||||
Socket client = newClient();
|
Socket client = newClient();
|
||||||
|
|
||||||
client.setSoTimeout(60000);
|
client.setSoTimeout(60000);
|
||||||
|
|
||||||
SocketChannel server = _connector.accept();
|
SocketChannel server = _connector.accept();
|
||||||
server.configureBlocking(false);
|
server.configureBlocking(false);
|
||||||
|
@ -425,6 +425,7 @@ public class SelectChannelEndPointTest
|
||||||
public void testBlockedReadIdle() throws Exception
|
public void testBlockedReadIdle() throws Exception
|
||||||
{
|
{
|
||||||
Socket client = newClient();
|
Socket client = newClient();
|
||||||
|
InputStream clientInputStream = client.getInputStream();
|
||||||
OutputStream clientOutputStream = client.getOutputStream();
|
OutputStream clientOutputStream = client.getOutputStream();
|
||||||
|
|
||||||
client.setSoTimeout(5000);
|
client.setSoTimeout(5000);
|
||||||
|
@ -440,7 +441,7 @@ public class SelectChannelEndPointTest
|
||||||
// Verify echo server to client
|
// Verify echo server to client
|
||||||
for (char c : "HelloWorld".toCharArray())
|
for (char c : "HelloWorld".toCharArray())
|
||||||
{
|
{
|
||||||
int b = client.getInputStream().read();
|
int b = clientInputStream.read();
|
||||||
assertTrue(b > 0);
|
assertTrue(b > 0);
|
||||||
assertEquals(c, (char)b);
|
assertEquals(c, (char)b);
|
||||||
}
|
}
|
||||||
|
@ -456,7 +457,7 @@ public class SelectChannelEndPointTest
|
||||||
|
|
||||||
// read until idle shutdown received
|
// read until idle shutdown received
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
int b = client.getInputStream().read();
|
int b = clientInputStream.read();
|
||||||
assertEquals('E', b);
|
assertEquals('E', b);
|
||||||
long idle = System.currentTimeMillis() - start;
|
long idle = System.currentTimeMillis() - start;
|
||||||
assertTrue(idle > idleTimeout / 2);
|
assertTrue(idle > idleTimeout / 2);
|
||||||
|
@ -464,10 +465,12 @@ public class SelectChannelEndPointTest
|
||||||
|
|
||||||
for (char c : "E: 12345678".toCharArray())
|
for (char c : "E: 12345678".toCharArray())
|
||||||
{
|
{
|
||||||
b = client.getInputStream().read();
|
b = clientInputStream.read();
|
||||||
assertTrue(b > 0);
|
assertTrue(b > 0);
|
||||||
assertEquals(c, (char)b);
|
assertEquals(c, (char)b);
|
||||||
}
|
}
|
||||||
|
b = clientInputStream.read();
|
||||||
|
assertEquals(-1,b);
|
||||||
|
|
||||||
// But endpoint is still open.
|
// But endpoint is still open.
|
||||||
if(_lastEndPoint.isOpen())
|
if(_lastEndPoint.isOpen())
|
||||||
|
|
Loading…
Reference in New Issue