All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.firefly.client.http2.HTTP2ClientHandler Maven / Gradle / Ivy

There is a newer version: 4.0.3.2
Show newest version
package com.firefly.client.http2;

import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLEngine;

import org.eclipse.jetty.alpn.ALPN;

import com.firefly.codec.http2.model.HttpVersion;
import com.firefly.codec.http2.stream.AbstractHTTPHandler;
import com.firefly.codec.http2.stream.HTTP2Configuration;
import com.firefly.net.SSLEventHandler;
import com.firefly.net.Session;
import com.firefly.net.tcp.ssl.SSLSession;

public class HTTP2ClientHandler extends AbstractHTTPHandler {

	private final Map http2ClientContext;

	public HTTP2ClientHandler(HTTP2Configuration config, Map http2ClientContext) {
		super(config);
		this.http2ClientContext = http2ClientContext;
	}

	@Override
	public void sessionOpened(final Session session) throws Throwable {
		final HTTP2ClientContext context = http2ClientContext.get(session.getSessionId());

		if (context == null) {
			log.error("http2 client can not get the client context of session {}", session.getSessionId());
			session.closeNow();
			return;
		}

		if (config.isSecureConnectionEnabled()) {
			if (sslContext == null) {
				context.promise.failed(new IllegalStateException("the ssl context is null"));
				return;
			}

			final SSLEngine sslEngine = sslContext.createSSLEngine();
			session.attachObject(new SSLSession(sslContext, sslEngine, session, true, new SSLEventHandler() {

				@Override
				public void handshakeFinished(SSLSession sslSession) {
					log.debug("client session {} SSL handshake finished", session.getSessionId());
					switch (context.httpVersion) {
					case HTTP_1_1:
						initializeHTTP1ClientConnection(session, context, (SSLSession) session.getAttachment());
						break;
					case HTTP_2:
						initializeHTTP2ClientConnection(session, context, (SSLSession) session.getAttachment());
						break;
					default:
						throw new IllegalStateException(
								"client does not support the http version " + context.httpVersion);
					}
				}
			}, new ALPN.ClientProvider() {

				@Override
				public List protocols() {
					return protocols;
				}

				@Override
				public void unsupported() {
					context.httpVersion = HttpVersion.HTTP_1_1;
					ALPN.remove(sslEngine);
				}

				@Override
				public void selected(String protocol) {
					try {
						for (String clientProtocol : protocols) {
							if (clientProtocol.equals(protocol)) {
								log.debug("HTTP2 client selected protocol {}", protocol);
								if ("http/1.1".equalsIgnoreCase(protocol)) {
									context.httpVersion = HttpVersion.HTTP_1_1;
								} else {
									context.httpVersion = HttpVersion.HTTP_2;
								}
								return;
							}
						}
						log.info("The client can not negotiate protocol. server [{}] - client {}", protocol, protocols);
						session.close();
					} finally {
						ALPN.remove(sslEngine);
					}
				}
			}));
		} else {
			initializeHTTP1ClientConnection(session, context, null);
		}
	}

	private void initializeHTTP1ClientConnection(final Session session, final HTTP2ClientContext context,
			final SSLSession sslSession) {
		try {
			HTTP1ClientConnection http1ClientConnection = new HTTP1ClientConnection(config, session, sslSession);
			session.attachObject(http1ClientConnection);
			context.promise.succeeded(http1ClientConnection);
		} catch (Throwable t) {
			context.promise.failed(t);
		} finally {
			http2ClientContext.remove(session.getSessionId());
		}
	}

	private void initializeHTTP2ClientConnection(final Session session, final HTTP2ClientContext context,
			final SSLSession sslSession) {
		try {
			final HTTP2ClientConnection connection = new HTTP2ClientConnection(config, session, sslSession,
					context.listener);
			session.attachObject(connection);
			connection.initialize(config, context.promise, context.listener);
		} finally {
			http2ClientContext.remove(session.getSessionId());
		}
	}

	@Override
	public void sessionClosed(Session session) throws Throwable {
		try {
			super.sessionClosed(session);
		} finally {
			http2ClientContext.remove(session.getSessionId());
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy