use of io.servicetalk.transport.netty.internal.NettyConnection in project servicetalk by apple.
the class HttpRequestEncoderTest method protocolPayloadEndOutboundShouldNotTriggerOnFailedFlush.
@Test
void protocolPayloadEndOutboundShouldNotTriggerOnFailedFlush() throws Exception {
AtomicReference<CloseHandler> closeHandlerRef = new AtomicReference<>();
try (CompositeCloseable resources = newCompositeCloseable()) {
Processor serverCloseTrigger = newCompletableProcessor();
CountDownLatch serverChannelLatch = new CountDownLatch(1);
AtomicReference<Channel> serverChannelRef = new AtomicReference<>();
ReadOnlyTcpServerConfig sConfig = new TcpServerConfig().asReadOnly();
ServerContext serverContext = resources.prepend(TcpServerBinder.bind(localAddress(0), sConfig, false, SEC, null, (channel, observer) -> DefaultNettyConnection.initChannel(channel, SEC.bufferAllocator(), SEC.executor(), SEC.ioExecutor(), forPipelinedRequestResponse(false, channel.config()), defaultFlushStrategy(), null, new TcpServerChannelInitializer(sConfig, observer).andThen(channel2 -> {
serverChannelRef.compareAndSet(null, channel2);
serverChannelLatch.countDown();
}), defaultStrategy(), mock(Protocol.class), observer, false, __ -> false), connection -> {
}).toFuture().get());
ReadOnlyHttpClientConfig cConfig = new HttpClientConfig().asReadOnly();
assert cConfig.h1Config() != null;
NettyConnection<Object, Object> conn = resources.prepend(TcpConnector.connect(null, serverHostAndPort(serverContext), cConfig.tcpConfig(), false, CEC, (channel, connectionObserver) -> {
CloseHandler closeHandler = spy(forPipelinedRequestResponse(true, channel.config()));
closeHandlerRef.compareAndSet(null, closeHandler);
return DefaultNettyConnection.initChannel(channel, CEC.bufferAllocator(), CEC.executor(), CEC.ioExecutor(), closeHandler, defaultFlushStrategy(), null, new TcpClientChannelInitializer(cConfig.tcpConfig(), connectionObserver).andThen(new HttpClientChannelInitializer(getByteBufAllocator(CEC.bufferAllocator()), cConfig.h1Config(), closeHandler)).andThen(channel2 -> channel2.pipeline().addLast(new ChannelInboundHandlerAdapter() {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
// Propagate the user event in the pipeline before
// triggering the test condition.
ctx.fireUserEventTriggered(evt);
if (evt instanceof ChannelInputShutdownReadComplete) {
serverCloseTrigger.onComplete();
}
}
})), defaultStrategy(), HTTP_1_1, connectionObserver, true, __ -> false);
}, NoopTransportObserver.INSTANCE).toFuture().get());
// The server needs to wait to close the conneciton until after the client has established the connection.
serverChannelLatch.await();
Channel serverChannel = serverChannelRef.get();
assertNotNull(serverChannel);
assumeFalse(serverChannel instanceof NioSocketChannel, "Windows doesn't emit ChannelInputShutdownReadComplete. Investigation Required.");
((SocketChannel) serverChannel).config().setSoLinger(0);
// Close and send RST concurrently with client write
serverChannel.close();
StreamingHttpRequest request = reqRespFactory.post("/closeme");
fromSource(serverCloseTrigger).toFuture().get();
Completable write = conn.write(from(request, allocator.fromAscii("Bye"), EmptyHttpHeaders.INSTANCE));
assertThrows(ExecutionException.class, () -> write.toFuture().get());
CloseHandler closeHandler = closeHandlerRef.get();
assertNotNull(closeHandler);
verify(closeHandler, never()).protocolPayloadEndOutbound(any(), any());
}
}
use of io.servicetalk.transport.netty.internal.NettyConnection in project servicetalk by apple.
the class NettyPipelinedConnectionTest method writeThrowsClosesConnection.
@Test
void writeThrowsClosesConnection() {
TestPublisher<Integer> mockReadPublisher2 = new TestPublisher<>();
@SuppressWarnings("unchecked") NettyConnection<Integer, Integer> mockConnection = mock(NettyConnection.class);
doAnswer((Answer<Publisher<Integer>>) invocation -> mockReadPublisher2).when(mockConnection).read();
doAnswer((Answer<Completable>) invocation -> {
throw DELIBERATE_EXCEPTION;
}).when(mockConnection).write(eq(writePublisher1), any(), any());
doAnswer((Answer<Completable>) invocation -> {
Publisher<Integer> writePub = invocation.getArgument(0);
return writePub.ignoreElements();
}).when(mockConnection).write(eq(writePublisher2), any(), any());
when(mockConnection.closeAsync()).thenReturn(completed());
requester = new NettyPipelinedConnection<>(mockConnection, 2);
toSource(requester.write(writePublisher1)).subscribe(readSubscriber);
toSource(requester.write(writePublisher2)).subscribe(readSubscriber2);
Subscription readSubscription = readSubscriber.awaitSubscription();
readSubscription.request(1);
assertThat(readSubscriber.awaitOnError(), is(DELIBERATE_EXCEPTION));
assertFalse(writePublisher1.isSubscribed());
verify(mockConnection).closeAsync();
}
use of io.servicetalk.transport.netty.internal.NettyConnection in project servicetalk by apple.
the class NettyPipelinedConnectionTest method readSubscribeThrowsWritesStillProcessed.
@Test
void readSubscribeThrowsWritesStillProcessed() {
AtomicBoolean thrownError = new AtomicBoolean();
Publisher<Integer> mockReadPublisher = new Publisher<Integer>() {
@Override
protected void handleSubscribe(final PublisherSource.Subscriber<? super Integer> subscriber) {
if (thrownError.compareAndSet(false, true)) {
throw DELIBERATE_EXCEPTION;
} else {
deliverCompleteFromSource(subscriber);
}
}
};
@SuppressWarnings("unchecked") NettyConnection<Integer, Integer> mockConnection = mock(NettyConnection.class);
when(mockConnection.read()).thenReturn(mockReadPublisher);
doAnswer((Answer<Completable>) invocation -> {
Publisher<Integer> writePub = invocation.getArgument(0);
return writePub.ignoreElements();
}).when(mockConnection).write(any(), any(), any());
requester = new NettyPipelinedConnection<>(mockConnection, 2);
toSource(requester.write(writePublisher1)).subscribe(readSubscriber);
toSource(requester.write(writePublisher2)).subscribe(readSubscriber2);
Subscription readSubscription = readSubscriber.awaitSubscription();
readSubscription.request(1);
assertTrue(writePublisher1.isSubscribed());
writePublisher1.onError(newSecondException());
assertThat(readSubscriber.awaitOnError(), is(DELIBERATE_EXCEPTION));
readSubscriber2.awaitSubscription();
assertTrue(writePublisher2.isSubscribed());
writePublisher2.onComplete();
readSubscriber2.awaitOnComplete();
verify(mockConnection, never()).closeAsync();
}
use of io.servicetalk.transport.netty.internal.NettyConnection in project servicetalk by apple.
the class NettyPipelinedConnectionTest method multiThreadedWritesAllComplete.
@Test
void multiThreadedWritesAllComplete() throws Exception {
// Avoid using EmbeddedChannel because it is not thread safe. This test writes/reads from multiple threads.
@SuppressWarnings("unchecked") NettyConnection<Integer, Integer> connection = mock(NettyConnection.class);
Executor connectionExecutor = Executors.newCachedThreadExecutor();
try {
doAnswer((Answer<Completable>) invocation -> {
Publisher<Integer> writeStream = invocation.getArgument(0);
return writeStream.ignoreElements().concat(connectionExecutor.submit(() -> {
}));
}).when(connection).write(any(), any(), any());
doAnswer((Answer<Publisher<Integer>>) invocation -> connectionExecutor.submit(() -> {
}).concat(Publisher.from(1))).when(connection).read();
final int concurrentRequestCount = 300;
NettyPipelinedConnection<Integer, Integer> pipelinedConnection = new NettyPipelinedConnection<>(connection, concurrentRequestCount);
CyclicBarrier requestStartBarrier = new CyclicBarrier(concurrentRequestCount);
List<Future<Collection<Integer>>> futures = new ArrayList<>(concurrentRequestCount);
ExecutorService executor = new ThreadPoolExecutor(0, concurrentRequestCount, 1, SECONDS, new SynchronousQueue<>());
try {
for (int i = 0; i < concurrentRequestCount; ++i) {
final int finalI = i;
futures.add(executor.submit(() -> {
try {
requestStartBarrier.await();
} catch (Exception e) {
return Single.<Collection<Integer>>failed(new AssertionError("failure during request " + finalI, e)).toFuture().get();
}
return pipelinedConnection.write(Publisher.from(finalI)).toFuture().get();
}));
}
for (Future<Collection<Integer>> future : futures) {
assertThat(future.get(), hasSize(1));
}
} finally {
executor.shutdown();
}
} finally {
connectionExecutor.closeAsync().subscribe();
}
}
use of io.servicetalk.transport.netty.internal.NettyConnection in project servicetalk by apple.
the class SecureTcpTransportObserverErrorsTest method testSslErrors.
@ParameterizedTest(name = "errorReason={0}, clientProvider={1}, serverProvider={2}")
@MethodSource("data")
void testSslErrors(ErrorReason errorReason, SslProvider clientProvider, SslProvider serverProvider) throws Exception {
setUp(errorReason, clientProvider, serverProvider);
CountDownLatch clientConnected = new CountDownLatch(1);
AtomicReference<NettyConnection<Buffer, Buffer>> connection = new AtomicReference<>();
client.connect(CLIENT_CTX, serverAddress).subscribe(c -> {
connection.set(c);
clientConnected.countDown();
});
verify(clientTransportObserver, await()).onNewConnection(any(), any());
verify(serverTransportObserver, await()).onNewConnection(any(), any());
switch(errorReason) {
case SECURE_CLIENT_TO_PLAIN_SERVER:
verify(clientConnectionObserver, await()).onSecurityHandshake();
if (clientProvider == JDK) {
verify(clientSecurityHandshakeObserver, await()).handshakeFailed(any(SSLProtocolException.class));
verify(clientConnectionObserver, await()).connectionClosed(any(SSLProtocolException.class));
} else {
verify(clientSecurityHandshakeObserver, await()).handshakeFailed(any(SSLHandshakeException.class));
verify(clientConnectionObserver, await()).connectionClosed(any(SSLHandshakeException.class));
}
serverConnectionClosed.await();
break;
case PLAIN_CLIENT_TO_SECURE_SERVER:
verify(serverConnectionObserver, await()).onSecurityHandshake();
clientConnected.await();
connection.get().write(from(DEFAULT_ALLOCATOR.fromAscii("Hello"))).toFuture().get();
if (serverProvider == JDK) {
verify(serverSecurityHandshakeObserver, await()).handshakeFailed(any(NotSslRecordException.class));
verify(serverConnectionObserver, await()).connectionClosed(any(NotSslRecordException.class));
} else {
verify(serverSecurityHandshakeObserver, await()).handshakeFailed(any(SSLHandshakeException.class));
verify(serverConnectionObserver, await()).connectionClosed(any(SSLHandshakeException.class));
}
verify(clientConnectionObserver, await()).connectionClosed();
break;
case WRONG_HOSTNAME_VERIFICATION:
case UNTRUSTED_SERVER_CERTIFICATE:
case UNTRUSTED_CLIENT_CERTIFICATE:
case MISSED_CLIENT_CERTIFICATE:
case NOT_MATCHING_PROTOCOLS:
case NOT_MATCHING_CIPHERS:
verify(clientConnectionObserver, await()).onSecurityHandshake();
verify(serverConnectionObserver, await()).onSecurityHandshake();
verify(clientSecurityHandshakeObserver, await()).handshakeFailed(any(SSLException.class));
verify(clientConnectionObserver, await()).connectionClosed(any(SSLException.class));
verify(serverSecurityHandshakeObserver, await()).handshakeFailed(any(SSLException.class));
verify(serverConnectionObserver, await()).connectionClosed(any(SSLException.class));
break;
default:
throw new IllegalArgumentException("Unsupported ErrorSource: " + errorReason);
}
verifyNoMoreInteractions(clientSecurityHandshakeObserver, serverSecurityHandshakeObserver);
}
Aggregations