package org.webpieces.frontend.impl; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; import org.webpieces.data.api.DataWrapperGenerator; import org.webpieces.data.api.DataWrapperGeneratorFactory; import org.webpieces.frontend.api.FrontendConfig; import org.webpieces.frontend.api.HttpServerSocket; import org.webpieces.httpcommon.api.Http2EngineFactory; import org.webpieces.httpcommon.api.Http2ServerEngine; import org.webpieces.httpcommon.api.ResponseSender; import org.webpieces.nio.api.channels.Channel; import org.webpieces.nio.api.handlers.DataListener; import org.webpieces.util.logging.Logger; import org.webpieces.util.logging.LoggerFactory; import com.webpieces.hpack.api.HpackParser; import com.webpieces.http2parser.api.dto.SettingsFrame; import com.webpieces.http2parser.api.dto.lib.Http2Setting; class HttpServerSocketImpl implements HttpServerSocket { private Channel channel; private DataListener dataListener; private ResponseSender responseSender; private HpackParser http2Parser; private TimedRequestListener timedRequestListener; private DataWrapperGenerator dataGen = DataWrapperGeneratorFactory.createDataWrapperGenerator(); private Http2ServerEngine http2ServerEngine; private FrontendConfig frontendConfig; private static final Logger log = LoggerFactory.getLogger(HttpServerSocket.class); HttpServerSocketImpl(Channel channel, DataListener http11DataListener, ResponseSender http11ResponseSender, HpackParser http2Parser, TimedRequestListener timedRequestListener, FrontendConfig frontendConfig) { this.channel = channel; this.dataListener = http11DataListener; this.responseSender = http11ResponseSender; this.http2Parser = http2Parser; this.timedRequestListener = timedRequestListener; this.frontendConfig = frontendConfig; } @Override public void upgradeHttp2(Optional<String> maybeSettingsPayload) { http2ServerEngine = Http2EngineFactory.createHttp2ServerEngine(http2Parser, channel, channel.getRemoteAddress(), frontendConfig.getHttp2Settings()); http2ServerEngine.setRequestListener(timedRequestListener); dataListener = http2ServerEngine.getDataListener(); responseSender = http2ServerEngine.getResponseSender(); maybeSettingsPayload.ifPresent(settingsPayload -> { try { SettingsFrame settingsFrame = new SettingsFrame(); List<Http2Setting> headers = http2Parser.unmarshalSettingsPayload(settingsPayload); settingsFrame.setSettings(headers); http2ServerEngine.setRemoteSettings(settingsFrame, false); } catch (Exception e) { log.error("Unable to parse initial settings payload: 0x" + settingsPayload, e); } }); } @Override public void sendLocalRequestedSettings() { log.info("Sending local requested settings"); http2ServerEngine.sendLocalRequestedSettings(); } @Override public CompletableFuture<Void> closeSocket() { // TODO: tell the http engine that we're closing the socket so it can send // GoAway and whatnot? return channel.close().thenAccept(c -> {}); } @Override public Channel getUnderlyingChannel() { return channel; } @Override public ResponseSender getResponseSender() { return responseSender; } @Override public DataListener getDataListener() { return dataListener; } @Override public String toString() { return "HttpSvrSocket["+channel+"]"; } }