You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2019/06/07 16:36:30 UTC
[httpcomponents-core] 01/02: Improved exception handling in the
async HTTP protocol negotiators
This is an automated email from the ASF dual-hosted git repository.
olegk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git
commit 5c28eb27ee7504386aa788fbd688d5f885b6e68f
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Fri Jun 7 11:52:52 2019 +0200
Improved exception handling in the async HTTP protocol negotiators
---
.../impl/nio/ClientHttpProtocolNegotiator.java | 71 ++++++++--------------
.../impl/nio/ServerHttpProtocolNegotiator.java | 32 +++++++---
2 files changed, 47 insertions(+), 56 deletions(-)
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java
index 6b3a97e..3dc0fc1 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java
@@ -32,25 +32,21 @@ import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ByteChannel;
import java.nio.channels.SelectionKey;
+import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.SSLSession;
import org.apache.hc.core5.annotation.Internal;
-import org.apache.hc.core5.http.ConnectionClosedException;
import org.apache.hc.core5.http.EndpointDetails;
import org.apache.hc.core5.http.ProtocolVersion;
import org.apache.hc.core5.http.impl.nio.ClientHttp1IOEventHandler;
import org.apache.hc.core5.http.impl.nio.ClientHttp1StreamDuplexer;
import org.apache.hc.core5.http.impl.nio.ClientHttp1StreamDuplexerFactory;
import org.apache.hc.core5.http.impl.nio.HttpConnectionEventHandler;
-import org.apache.hc.core5.http.nio.AsyncClientExchangeHandler;
-import org.apache.hc.core5.http.nio.command.RequestExecutionCommand;
import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.http2.ssl.ApplicationProtocols;
import org.apache.hc.core5.io.CloseMode;
import org.apache.hc.core5.io.SocketTimeoutExceptionFactory;
-import org.apache.hc.core5.reactor.Command;
-import org.apache.hc.core5.reactor.IOEventHandler;
import org.apache.hc.core5.reactor.IOSession;
import org.apache.hc.core5.reactor.ProtocolIOSession;
import org.apache.hc.core5.reactor.ssl.TlsDetails;
@@ -77,6 +73,7 @@ public class ClientHttpProtocolNegotiator implements HttpConnectionEventHandler
private final ClientHttp1StreamDuplexerFactory http1StreamHandlerFactory;
private final ClientHttp2StreamMultiplexerFactory http2StreamHandlerFactory;
private final HttpVersionPolicy versionPolicy;
+ private final AtomicReference<HttpConnectionEventHandler> protocolHandlerRef;
private volatile ByteBuffer preface;
@@ -89,28 +86,31 @@ public class ClientHttpProtocolNegotiator implements HttpConnectionEventHandler
this.http1StreamHandlerFactory = Args.notNull(http1StreamHandlerFactory, "HTTP/1.1 stream handler factory");
this.http2StreamHandlerFactory = Args.notNull(http2StreamHandlerFactory, "HTTP/2 stream handler factory");
this.versionPolicy = versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE;
+ this.protocolHandlerRef = new AtomicReference<>(null);
}
private void startHttp1(final IOSession session) {
final ClientHttp1StreamDuplexer http1StreamHandler = http1StreamHandlerFactory.create(ioSession);
- final ClientHttp1IOEventHandler newHandler = new ClientHttp1IOEventHandler(http1StreamHandler);
+ final HttpConnectionEventHandler protocolHandler = new ClientHttp1IOEventHandler(http1StreamHandler);
try {
- ioSession.upgrade(newHandler);
- newHandler.connected(session);
+ ioSession.upgrade(protocolHandler);
+ protocolHandlerRef.set(protocolHandler);
+ protocolHandler.connected(session);
} catch (final Exception ex) {
- newHandler.exception(session, ex);
+ protocolHandler.exception(session, ex);
session.close(CloseMode.IMMEDIATE);
}
}
private void startHttp2(final IOSession session) {
final ClientHttp2StreamMultiplexer streamMultiplexer = http2StreamHandlerFactory.create(ioSession);
- final IOEventHandler newHandler = new ClientHttp2IOEventHandler(streamMultiplexer);
+ final HttpConnectionEventHandler protocolHandler = new ClientHttp2IOEventHandler(streamMultiplexer);
try {
- ioSession.upgrade(newHandler);
- newHandler.connected(session);
+ ioSession.upgrade(protocolHandler);
+ protocolHandlerRef.set(protocolHandler);
+ protocolHandler.connected(session);
} catch (final Exception ex) {
- newHandler.exception(session, ex);
+ protocolHandler.exception(session, ex);
session.close(CloseMode.IMMEDIATE);
}
}
@@ -172,43 +172,18 @@ public class ClientHttpProtocolNegotiator implements HttpConnectionEventHandler
@Override
public void exception(final IOSession session, final Exception cause) {
- try {
- for (;;) {
- final Command command = ioSession.poll();
- if (command != null) {
- if (command instanceof RequestExecutionCommand) {
- final RequestExecutionCommand executionCommand = (RequestExecutionCommand) command;
- final AsyncClientExchangeHandler exchangeHandler = executionCommand.getExchangeHandler();
- exchangeHandler.failed(cause);
- exchangeHandler.releaseResources();
- } else {
- command.cancel();
- }
- } else {
- break;
- }
- }
- } finally {
- session.close(CloseMode.IMMEDIATE);
+ final HttpConnectionEventHandler protocolHandler = protocolHandlerRef.get();
+ if (protocolHandler != null) {
+ protocolHandler.exception(session, cause);
}
+ session.close(CloseMode.IMMEDIATE);
}
@Override
public void disconnected(final IOSession session) {
- for (;;) {
- final Command command = ioSession.poll();
- if (command != null) {
- if (command instanceof RequestExecutionCommand) {
- final RequestExecutionCommand executionCommand = (RequestExecutionCommand) command;
- final AsyncClientExchangeHandler exchangeHandler = executionCommand.getExchangeHandler();
- exchangeHandler.failed(new ConnectionClosedException());
- exchangeHandler.releaseResources();
- } else {
- command.cancel();
- }
- } else {
- break;
- }
+ final HttpConnectionEventHandler protocolHandler = protocolHandlerRef.getAndSet(null);
+ if (protocolHandler != null) {
+ protocolHandler.disconnected(ioSession);
}
}
@@ -220,7 +195,8 @@ public class ClientHttpProtocolNegotiator implements HttpConnectionEventHandler
@Override
public EndpointDetails getEndpointDetails() {
- return null;
+ final HttpConnectionEventHandler protocolHandler = protocolHandlerRef.get();
+ return protocolHandler != null ? protocolHandler.getEndpointDetails() : null;
}
@Override
@@ -235,7 +211,8 @@ public class ClientHttpProtocolNegotiator implements HttpConnectionEventHandler
@Override
public ProtocolVersion getProtocolVersion() {
- return null;
+ final HttpConnectionEventHandler protocolHandler = protocolHandlerRef.get();
+ return protocolHandler != null ? protocolHandler.getProtocolVersion() : null;
}
@Override
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java
index 165f10d..84d6714 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java
@@ -30,6 +30,7 @@ package org.apache.hc.core5.http2.impl.nio;
import java.io.IOException;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
+import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.SSLSession;
@@ -47,7 +48,6 @@ import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.http2.ssl.ApplicationProtocols;
import org.apache.hc.core5.io.CloseMode;
import org.apache.hc.core5.io.SocketTimeoutExceptionFactory;
-import org.apache.hc.core5.reactor.IOEventHandler;
import org.apache.hc.core5.reactor.IOSession;
import org.apache.hc.core5.reactor.ProtocolIOSession;
import org.apache.hc.core5.reactor.ssl.TlsDetails;
@@ -71,6 +71,7 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
private final ServerHttp2StreamMultiplexerFactory http2StreamHandlerFactory;
private final HttpVersionPolicy versionPolicy;
private final ByteBuffer bytebuf;
+ private final AtomicReference<HttpConnectionEventHandler> protocolHandlerRef;
private volatile boolean expectValidH2Preface;
@@ -84,6 +85,7 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
this.http2StreamHandlerFactory = Args.notNull(http2StreamHandlerFactory, "HTTP/2 stream handler factory");
this.versionPolicy = versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE;
this.bytebuf = ByteBuffer.allocate(1024);
+ this.protocolHandlerRef = new AtomicReference<>(null);
}
@Override
@@ -107,7 +109,9 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
final ServerHttp1StreamDuplexer http1StreamHandler = http1StreamHandlerFactory.create(
tlsDetails != null ? URIScheme.HTTPS.id : URIScheme.HTTP.id,
ioSession);
- ioSession.upgrade(new ServerHttp1IOEventHandler(http1StreamHandler));
+ final HttpConnectionEventHandler protocolHandler = new ServerHttp1IOEventHandler(http1StreamHandler);
+ ioSession.upgrade(protocolHandler);
+ protocolHandlerRef.set(protocolHandler);
http1StreamHandler.onConnect(null);
break;
}
@@ -140,7 +144,9 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
}
if (validH2Preface) {
final ServerHttp2StreamMultiplexer http2StreamHandler = http2StreamHandlerFactory.create(ioSession);
- ioSession.upgrade(new ServerHttp2IOEventHandler(http2StreamHandler));
+ final HttpConnectionEventHandler protocolHandler = new ServerHttp2IOEventHandler(http2StreamHandler);
+ ioSession.upgrade(protocolHandler);
+ protocolHandlerRef.set(protocolHandler);
http2StreamHandler.onConnect(bytebuf.hasRemaining() ? bytebuf : null);
http2StreamHandler.onInput();
} else {
@@ -148,7 +154,9 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
final ServerHttp1StreamDuplexer http1StreamHandler = http1StreamHandlerFactory.create(
tlsDetails != null ? URIScheme.HTTPS.id : URIScheme.HTTP.id,
ioSession);
- ioSession.upgrade(new ServerHttp1IOEventHandler(http1StreamHandler));
+ final HttpConnectionEventHandler protocolHandler = new ServerHttp1IOEventHandler(http1StreamHandler);
+ ioSession.upgrade(protocolHandler);
+ protocolHandlerRef.set(protocolHandler);
bytebuf.rewind();
http1StreamHandler.onConnect(bytebuf);
http1StreamHandler.onInput();
@@ -174,15 +182,19 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
@Override
public void exception(final IOSession session, final Exception cause) {
- final IOEventHandler sessionHandler = ioSession.getHandler();
- if (sessionHandler != null) {
- sessionHandler.exception(session, cause);
+ final HttpConnectionEventHandler protocolHandler = protocolHandlerRef.get();
+ if (protocolHandler != null) {
+ protocolHandler.exception(session, cause);
}
session.close(CloseMode.IMMEDIATE);
}
@Override
public void disconnected(final IOSession session) {
+ final HttpConnectionEventHandler protocolHandler = protocolHandlerRef.getAndSet(null);
+ if (protocolHandler != null) {
+ protocolHandler.disconnected(ioSession);
+ }
}
@Override
@@ -193,7 +205,8 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
@Override
public EndpointDetails getEndpointDetails() {
- return null;
+ final HttpConnectionEventHandler protocolHandler = protocolHandlerRef.get();
+ return protocolHandler != null ? protocolHandler.getEndpointDetails() : null;
}
@Override
@@ -208,7 +221,8 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
@Override
public ProtocolVersion getProtocolVersion() {
- return null;
+ final HttpConnectionEventHandler protocolHandler = protocolHandlerRef.get();
+ return protocolHandler != null ? protocolHandler.getProtocolVersion() : null;
}
@Override