Hi,
I am trying to use Jetty 9.4.7 + JDK1.8.0_141 as the HTTP2 client. During trying to set up the connection to the HTTP2 server, it seems that the handshake process is successful, however, the HTTP2 client session failed
to be retrieved with idle_timeout. Below is the Jetty log. Could you please do me a favor to have a check on the coding or settings for this try?
1.
Jetty Logs in client
%% No cached client session
*** ClientHello, TLSv1.2
…
qtp1732067653-304, READ: TLSv1.2 Handshake, length = 1495
*** ServerHello, TLSv1.2
…
%% Initialized: [Session-1, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384]
** TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
…
*** Certificate chain
…
*** Diffie-Hellman ServerKeyExchange
…
*** ServerHelloDone
…
*** ClientKeyExchange, DH
…
SESSION KEYGEN:
…
CONNECTION KEYGEN:
Client Nonce:
Server Nonce:
Master Secret:
... no MAC keys used for this cipher
Client write key:
Server write key:
Client write IV:
Server write IV:
qtp1732067653-304, WRITE: TLSv1.2 Change Cipher Spec, length = 1
*** Finished
verify_data: { 169, 55, 60, 153, 205, 185, 129, 58, 62, 132, 64, 241 }
***
*** Finished
verify_data: { 34, 236, 183, 191, 244, 239, 168, 79, 146, 184, 21, 20 }
***
%% Cached client session: [Session-1, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384]
[Raw read (bb)]: length = 58
…
Padded plaintext after DECRYPTION: len = 29
0000: 00 00 14 07 00 00 00 00 00 00 00 00 00 00 00 00 ................
0010: 00 69 64 6C 65 5F 74 69 6D 65 6F 75 74 .idle_timeout
Finalizer, called close()
Finalizer, called closeInternal(true)
Finalizer, called closeSocket(true)
Finalizer, called close()
Finalizer, called closeInternal(true)
Finalizer, called closeSocket(true)
2.
Coding
Actually I used the jetty sample client code. The difference is that I put it to an eclipse project with ant build, and to build a war package for the deployment.
In below code, after “session = sessionPromise.get(5, TimeUnit.SECONDS);” is executed, my test result shows that “The
retrieved session is null” is printed. So the client session failed to be retrieved.
//------------------------------------------------------------------------------------------------------------------------
// Fetch/Create and start HTTP2Client.
FuturePromise<Session> sessionPromise = new FuturePromise<>();
HTTP2Client client = null;
// createHttp2Connection(host, port);
PLogger.warn("Creating Http2 connection to " + host + ":" + port);
ALPN.debug = true;
SslContextFactory sslContextFactory = new SslContextFactory(true);
// sslContextFactory.addExcludeCipherSuites("TLS_DHE_RSA.*");
client = new HTTP2Client();
client.addBean(sslContextFactory);
try {
client.start();
} catch (Exception e2) {
e2.printStackTrace();
}
client.connect(sslContextFactory,
new InetSocketAddress(host, port),
new ServerSessionListener.Adapter(), sessionPromise);
long connTime = System.currentTimeMillis();
PLogger.warn("Connected to " + host + ":" + port + " in ms" + (connTime - startTime));
// Obtain the client Session object.
Session session = null;
try {
session = sessionPromise.get(5, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e1) {
e1.printStackTrace();
}
if (null == session) {
PLogger.warn("The retrieved session is null");
} else {
PLogger.warn("Successfully retrieved session");
}
long sessionTime = System.currentTimeMillis();
PLogger.warn("POST session in ms" + (sessionTime - connTime) + " to " + host + ":" + port);
// Prepare the HTTP request headers.
HttpFields requestFields = new HttpFields();
requestFields.put("User-Agent", client.getClass().getName() + "/" + Jetty.VERSION);
requestFields.put("Content-Type", "application/xml");
// Prepare the HTTP request object.
MetaData.Request request = new MetaData.Request( "POST",
new HttpURI("https://" + host + ":" + port + "/ParlayREST/callnotification/v1/subscriptions/callEvent"),
HttpVersion.HTTP_2, requestFields);
// Create the HTTP/2 HEADERS frame representing the HTTP request.
HeadersFrame headersFrame = new HeadersFrame(request, null, false);
CountDownLatch latch = new CountDownLatch(1);
// Prepare the listener to receive the HTTP response frames.
Stream.Listener responseListener = new Stream.Listener.Adapter() {
@Override
public void onHeaders(Stream stream, HeadersFrame frame) {
int duration1 = (int) TimeUnit.NANOSECONDS.toSeconds(System.currentTimeMillis() - sessionTime);
if (frame.isEndStream())
latch.countDown();
PLogger.warn("After ms" + duration1 + " get headers");
}
@Override
public void onData(Stream stream, DataFrame frame, Callback callback) {
byte[] bytes = new byte[frame.getData().remaining()];
frame.getData().get(bytes);
int duration = (int) TimeUnit.NANOSECONDS.toSeconds(System.currentTimeMillis() - sessionTime);
PLogger.warn("After ms" + duration + " get " + new String(bytes));
callback.succeeded();
if (frame.isEndStream())
latch.countDown();
}
};
// Send the HEADERS frame to create a stream.
FuturePromise<Stream> streamPromise = new FuturePromise<Stream>();
if (null == session) {
PLogger.warn("The session is null");
return;
}
session.newStream(headersFrame, streamPromise, responseListener);
//------------------------------------------------------------------------------------------------------------------------
3.
Testing environment
3.1
HTTP2 client
2.1.1 JDK: 1.8.0_141
# java -version
openjdk version "1.8.0_141"
OpenJDK Runtime Environment (build 1.8.0_141-b16)
OpenJDK 64-Bit Server VM (build 25.141-b16, mixed mode)
2.1.2 ALPN:
Change RUN_ARGS in $JETTY_HOME/bin/jetty.sh to include the alpn bootclasspath.
RUN_ARGS=(-Xbootclasspath/p:/root/work/jetty/alpn-boot-8.1.11.v20170118.jar -jar "$JETTY_START" ${JETTY_ARGS[*]} ${JETTY_OPTIONS[@]})
$JETTY_HOME/modules/alpn-impl/alpn-1.8.0_141.mod, also change:
[exec]
-Xbootclasspath/p:/root/work/jetty/alpn-boot-8.1.11.v20170118.jar
2.1.3 The libs used in the client side (some may not be used actually):
alpn-api-1.1.3.v20160715.jar
http2-client-9.4.7.v20170914.jar
http2-common-9.4.7.v20170914.jar
http2-hpack-9.4.7.v20170914.jar
http2-http-client-transport-9.4.7.v20170914.jar
http2-server-9.4.7.v20170914.jar
jetty-alpn-client-9.4.7.v20170914.jar
jetty-client-9.4.7.v20170914.jar
jetty-http-9.4.7.v20170914.jar
jetty-io-9.4.7.v20170914.jar
jetty-util-9.4.7.v20170914.jar
3.2
HTTP2 server
JDK: 1.8.0_101
# java -version
openjdk version "1.8.0_101"
OpenJDK Runtime Environment (build 1.8.0_101-b13)
OpenJDK 64-Bit Server VM (build 25.101-b13, mixed mode)
ALPN:
$JETTY_HOME/modules/alpn-impl/alpn-1.8.0_101.mod, set below line
[exec]
-Xbootclasspath/p:lib/alpn/alpn-boot-8.1.9.v20160720.jar
Best Regards,
William
Email:
william.cao@xxxxxxxxxxxxxxx