[undertow] 03/05: Add alpn-not-supported.patch

Markus Koschany apo-guest at moszumanska.debian.org
Sat Oct 31 16:27:13 UTC 2015


This is an automated email from the git hooks/post-receive script.

apo-guest pushed a commit to branch master
in repository undertow.

commit 374d7a3041d3f1124d5ea9552941e21581961da6
Author: Markus Koschany <apo at debian.org>
Date:   Sat Oct 31 15:12:58 2015 +0100

    Add alpn-not-supported.patch
---
 debian/patches/alpn-not-supported.patch | 1333 +++++++++++++++++++++++++++++++
 debian/patches/series                   |    1 +
 2 files changed, 1334 insertions(+)

diff --git a/debian/patches/alpn-not-supported.patch b/debian/patches/alpn-not-supported.patch
new file mode 100644
index 0000000..5bb8c67
--- /dev/null
+++ b/debian/patches/alpn-not-supported.patch
@@ -0,0 +1,1333 @@
+From: Markus Koschany <apo at debian.org>
+Date: Sat, 31 Oct 2015 15:11:58 +0100
+Subject: alpn not supported
+
+---
+ core/src/main/java/io/undertow/Undertow.java       |  23 +-
+ .../undertow/client/http/HttpClientProvider.java   |  14 +-
+ .../undertow/client/http2/Http2ClientProvider.java |  68 ----
+ .../undertow/client/spdy/SpdyClientConnection.java | 331 -------------------
+ .../undertow/client/spdy/SpdyClientExchange.java   | 140 --------
+ .../undertow/client/spdy/SpdyClientProvider.java   | 356 ---------------------
+ .../server/protocol/http/AlpnOpenListener.java     | 279 ----------------
+ 7 files changed, 2 insertions(+), 1209 deletions(-)
+ delete mode 100644 core/src/main/java/io/undertow/client/spdy/SpdyClientConnection.java
+ delete mode 100644 core/src/main/java/io/undertow/client/spdy/SpdyClientExchange.java
+ delete mode 100644 core/src/main/java/io/undertow/client/spdy/SpdyClientProvider.java
+ delete mode 100644 core/src/main/java/io/undertow/server/protocol/http/AlpnOpenListener.java
+
+diff --git a/core/src/main/java/io/undertow/Undertow.java b/core/src/main/java/io/undertow/Undertow.java
+index 1d36782..e8746fa 100644
+--- a/core/src/main/java/io/undertow/Undertow.java
++++ b/core/src/main/java/io/undertow/Undertow.java
+@@ -22,10 +22,8 @@ import io.undertow.protocols.ssl.UndertowXnioSsl;
+ import io.undertow.server.DefaultByteBufferPool;
+ import io.undertow.server.HttpHandler;
+ import io.undertow.server.protocol.ajp.AjpOpenListener;
+-import io.undertow.server.protocol.http.AlpnOpenListener;
+ import io.undertow.server.protocol.http.HttpOpenListener;
+ import io.undertow.server.protocol.http2.Http2OpenListener;
+-import io.undertow.server.protocol.spdy.SpdyOpenListener;
+ import org.xnio.ChannelListener;
+ import org.xnio.ChannelListeners;
+ import org.xnio.IoUtils;
+@@ -142,26 +140,7 @@ public final class Undertow {
+ 
+                         HttpOpenListener httpOpenListener = new HttpOpenListener(buffers, undertowOptions);
+                         httpOpenListener.setRootHandler(rootHandler);
+-
+-                        boolean spdy = serverOptions.get(UndertowOptions.ENABLE_SPDY, false);
+-                        boolean http2 = serverOptions.get(UndertowOptions.ENABLE_HTTP2, false);
+-                        if(spdy || http2) {
+-                            AlpnOpenListener alpn = new AlpnOpenListener(buffers, undertowOptions, httpOpenListener);
+-                            if(spdy) {
+-                                SpdyOpenListener spdyListener = new SpdyOpenListener(buffers, new DefaultByteBufferPool(false, 1024, -1, 2, 0), undertowOptions);
+-                                spdyListener.setRootHandler(rootHandler);
+-                                alpn.addProtocol(SpdyOpenListener.SPDY_3_1, spdyListener, 5);
+-                            }
+-                            if(http2) {
+-                                Http2OpenListener http2Listener = new Http2OpenListener(buffers, undertowOptions);
+-                                http2Listener.setRootHandler(rootHandler);
+-                                alpn.addProtocol(Http2OpenListener.HTTP2, http2Listener, 10);
+-                                alpn.addProtocol(Http2OpenListener.HTTP2_14, http2Listener, 7);
+-                            }
+-                            openListener = alpn;
+-                        } else {
+-                            openListener = httpOpenListener;
+-                        }
++                        openListener = httpOpenListener;
+                         ChannelListener<AcceptingChannel<StreamConnection>> acceptListener = ChannelListeners.openListenerAdapter(openListener);
+                         XnioSsl xnioSsl;
+                         if (listener.sslContext != null) {
+diff --git a/core/src/main/java/io/undertow/client/http/HttpClientProvider.java b/core/src/main/java/io/undertow/client/http/HttpClientProvider.java
+index ccb32f0..572e45d 100644
+--- a/core/src/main/java/io/undertow/client/http/HttpClientProvider.java
++++ b/core/src/main/java/io/undertow/client/http/HttpClientProvider.java
+@@ -24,7 +24,6 @@ import io.undertow.client.ClientCallback;
+ import io.undertow.client.ClientConnection;
+ import io.undertow.client.ClientProvider;
+ import io.undertow.client.http2.Http2ClientProvider;
+-import io.undertow.client.spdy.SpdyClientProvider;
+ import org.xnio.ChannelListener;
+ import org.xnio.IoFuture;
+ import org.xnio.OptionMap;
+@@ -129,18 +128,7 @@ public class HttpClientProvider implements ClientProvider {
+ 
+ 
+     private void handleConnected(final StreamConnection connection, final ClientCallback<ClientConnection> listener, final ByteBufferPool bufferPool, final OptionMap options, URI uri) {
+-        if (options.get(UndertowOptions.ENABLE_SPDY, false) && connection instanceof SslConnection && SpdyClientProvider.isEnabled()) {
+-            try {
+-                SpdyClientProvider.handlePotentialSpdyConnection(connection, listener, bufferPool, options, new ChannelListener<SslConnection>() {
+-                    @Override
+-                    public void handleEvent(SslConnection channel) {
+-                        listener.completed(new HttpClientConnection(connection, options, bufferPool));
+-                    }
+-                });
+-            } catch (Exception e) {
+-                listener.failed(new IOException(e));
+-            }
+-        } else if (options.get(UndertowOptions.ENABLE_HTTP2, false) && connection instanceof SslConnection && Http2ClientProvider.isEnabled()) {
++        if (options.get(UndertowOptions.ENABLE_HTTP2, false) && connection instanceof SslConnection && Http2ClientProvider.isEnabled()) {
+             try {
+                 Http2ClientProvider.handlePotentialHttp2Connection(connection, listener, bufferPool, options, new ChannelListener<SslConnection>() {
+                     @Override
+diff --git a/core/src/main/java/io/undertow/client/http2/Http2ClientProvider.java b/core/src/main/java/io/undertow/client/http2/Http2ClientProvider.java
+index 0af0977..80dc0f1 100644
+--- a/core/src/main/java/io/undertow/client/http2/Http2ClientProvider.java
++++ b/core/src/main/java/io/undertow/client/http2/Http2ClientProvider.java
+@@ -36,7 +36,6 @@ import io.undertow.conduits.ByteActivityCallback;
+ import io.undertow.conduits.BytesReceivedStreamSourceConduit;
+ import io.undertow.conduits.BytesSentStreamSinkConduit;
+ import io.undertow.protocols.ssl.UndertowXnioSsl;
+-import org.eclipse.jetty.alpn.ALPN;
+ import org.xnio.ChannelListener;
+ import org.xnio.IoFuture;
+ import org.xnio.OptionMap;
+@@ -181,29 +180,12 @@ public class Http2ClientProvider implements ClientProvider {
+         final SslConnection sslConnection = (SslConnection) connection;
+         final SSLEngine sslEngine = UndertowXnioSsl.getSslEngine(sslConnection);
+ 
+-        final Http2SelectionProvider http2SelectionProvider = new Http2SelectionProvider(sslEngine);
+-        try {
+-            ALPN_PUT_METHOD.invoke(null, sslEngine, http2SelectionProvider);
+-        } catch (Exception e) {
+-            http2FailedListener.handleEvent(sslConnection);
+-            return;
+-        }
+-
+         try {
+             sslConnection.startHandshake();
+             sslConnection.getSourceChannel().getReadSetter().set(new ChannelListener<StreamSourceChannel>() {
+                 @Override
+                 public void handleEvent(StreamSourceChannel channel) {
+ 
+-                    if (http2SelectionProvider.selected != null) {
+-                        if (http2SelectionProvider.selected.equals(HTTP_1_1)) {
+-                            sslConnection.getSourceChannel().suspendReads();
+-                            http2FailedListener.handleEvent(sslConnection);
+-                            return;
+-                        } else if (http2SelectionProvider.selected.equals(HTTP2)) {
+-                            listener.completed(createHttp2Channel(connection, bufferPool, options, uri.getHost()));
+-                        }
+-                    } else {
+                         ByteBuffer buf = ByteBuffer.allocate(100);
+                         try {
+                             int read = channel.read(buf);
+@@ -213,25 +195,10 @@ public class Http2ClientProvider implements ClientProvider {
+                                 pb.pushBack(new ImmediatePooled<>(buf));
+                                 connection.getSourceChannel().setConduit(pb);
+                             }
+-                            if (http2SelectionProvider.selected == null) {
+-                                http2SelectionProvider.selected = (String) sslEngine.getSession().getValue(PROTOCOL_KEY);
+-                            }
+-                            if ((http2SelectionProvider.selected == null && read > 0) || HTTP_1_1.equals(http2SelectionProvider.selected)) {
+-                                sslConnection.getSourceChannel().suspendReads();
+-                                http2FailedListener.handleEvent(sslConnection);
+-                                return;
+-                            } else if (http2SelectionProvider.selected != null) {
+-                                //we have spdy
+-                                if (http2SelectionProvider.selected.equals(HTTP2)) {
+-                                    listener.completed(createHttp2Channel(connection, bufferPool, options, uri.getHost()));
+-                                }
+-                            }
+                         } catch (IOException e) {
+                             listener.failed(e);
+                         }
+-                    }
+                 }
+-
+             });
+             sslConnection.getSourceChannel().resumeReads();
+         } catch (IOException e) {
+@@ -268,41 +235,6 @@ public class Http2ClientProvider implements ClientProvider {
+         return new Http2ClientConnection(http2Channel, false, defaultHost, clientStatistics);
+     }
+ 
+-    private static class Http2SelectionProvider implements ALPN.ClientProvider {
+-        private String selected;
+-        private final SSLEngine sslEngine;
+-
+-        private Http2SelectionProvider(SSLEngine sslEngine) {
+-            this.sslEngine = sslEngine;
+-        }
+-
+-        @Override
+-        public boolean supports() {
+-            return true;
+-        }
+-
+-        @Override
+-        public List<String> protocols() {
+-            return PROTOCOLS;
+-        }
+-
+-        @Override
+-        public void unsupported() {
+-            selected = HTTP_1_1;
+-        }
+-
+-        @Override
+-        public void selected(String s) {
+-
+-            ALPN.remove(sslEngine);
+-            selected = s;
+-            sslEngine.getHandshakeSession().putValue(PROTOCOL_KEY, selected);
+-        }
+-
+-        private String getSelected() {
+-            return selected;
+-        }
+-    }
+ 
+ 
+     private static class ClientStatisticsImpl implements ClientStatistics {
+diff --git a/core/src/main/java/io/undertow/client/spdy/SpdyClientConnection.java b/core/src/main/java/io/undertow/client/spdy/SpdyClientConnection.java
+deleted file mode 100644
+index c5a05be..0000000
+--- a/core/src/main/java/io/undertow/client/spdy/SpdyClientConnection.java
++++ /dev/null
+@@ -1,331 +0,0 @@
+-/*
+- * JBoss, Home of Professional Open Source.
+- * Copyright 2014 Red Hat, Inc., and individual contributors
+- * as indicated by the @author tags.
+- *
+- * Licensed under the Apache License, Version 2.0 (the "License");
+- * you may not use this file except in compliance with the License.
+- * You may obtain a copy of the License at
+- *
+- *     http://www.apache.org/licenses/LICENSE-2.0
+- *
+- *  Unless required by applicable law or agreed to in writing, software
+- *  distributed under the License is distributed on an "AS IS" BASIS,
+- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+- *  See the License for the specific language governing permissions and
+- *  limitations under the License.
+- */
+-
+-package io.undertow.client.spdy;
+-
+-import io.undertow.UndertowLogger;
+-import io.undertow.UndertowMessages;
+-import io.undertow.client.ClientCallback;
+-import io.undertow.client.ClientConnection;
+-import io.undertow.client.ClientExchange;
+-import io.undertow.client.ClientRequest;
+-import io.undertow.client.ClientStatistics;
+-import io.undertow.protocols.spdy.SpdyChannel;
+-import io.undertow.protocols.spdy.SpdyPingStreamSourceChannel;
+-import io.undertow.protocols.spdy.SpdyRstStreamStreamSourceChannel;
+-import io.undertow.protocols.spdy.SpdyStreamSourceChannel;
+-import io.undertow.protocols.spdy.SpdySynReplyStreamSourceChannel;
+-import io.undertow.protocols.spdy.SpdySynStreamStreamSinkChannel;
+-import io.undertow.util.Headers;
+-import io.undertow.util.HttpString;
+-import org.xnio.ChannelExceptionHandler;
+-import org.xnio.ChannelListener;
+-import org.xnio.ChannelListeners;
+-import org.xnio.IoUtils;
+-import org.xnio.Option;
+-import io.undertow.connector.ByteBufferPool;
+-import org.xnio.StreamConnection;
+-import org.xnio.XnioIoThread;
+-import org.xnio.XnioWorker;
+-import org.xnio.channels.StreamSinkChannel;
+-
+-import java.io.IOException;
+-import java.net.SocketAddress;
+-import java.util.Map;
+-import java.util.concurrent.ConcurrentHashMap;
+-
+-import static io.undertow.util.Headers.CONTENT_LENGTH;
+-import static io.undertow.util.Headers.TRANSFER_ENCODING;
+-
+-/**
+- * @author Stuart Douglas
+- */
+-public class SpdyClientConnection implements ClientConnection {
+-
+-
+-    static final HttpString METHOD = new HttpString(":method");
+-    static final HttpString PATH = new HttpString(":path");
+-    static final HttpString SCHEME = new HttpString(":scheme");
+-    static final HttpString VERSION = new HttpString(":version");
+-    static final HttpString HOST = new HttpString(":host");
+-    static final HttpString STATUS = new HttpString(":status");
+-
+-    private final SpdyChannel spdyChannel;
+-    private final ChannelListener.SimpleSetter<ClientConnection> closeSetter = new ChannelListener.SimpleSetter<>();
+-
+-    private final Map<Integer, SpdyClientExchange> currentExchanges = new ConcurrentHashMap<>();
+-
+-    private final ClientStatistics clientStatistics;
+-    public SpdyClientConnection(SpdyChannel spdyChannel, ClientStatistics clientStatistics) {
+-        this.spdyChannel = spdyChannel;
+-        this.clientStatistics = clientStatistics;
+-        spdyChannel.getReceiveSetter().set(new SpdyReceiveListener());
+-        spdyChannel.resumeReceives();
+-        spdyChannel.addCloseTask(new ChannelListener<SpdyChannel>() {
+-            @Override
+-            public void handleEvent(SpdyChannel channel) {
+-                ChannelListeners.invokeChannelListener(SpdyClientConnection.this, closeSetter.get());
+-            }
+-        });
+-    }
+-
+-    @Override
+-    public void sendRequest(ClientRequest request, ClientCallback<ClientExchange> clientCallback) {
+-        request.getRequestHeaders().put(PATH, request.getPath());
+-        request.getRequestHeaders().put(SCHEME, "https");
+-        request.getRequestHeaders().put(VERSION, request.getProtocol().toString());
+-        request.getRequestHeaders().put(METHOD, request.getMethod().toString());
+-        request.getRequestHeaders().put(HOST, request.getRequestHeaders().getFirst(Headers.HOST));
+-        request.getRequestHeaders().remove(Headers.HOST);
+-
+-        SpdySynStreamStreamSinkChannel sinkChannel;
+-        try {
+-            sinkChannel = spdyChannel.createStream(request.getRequestHeaders());
+-        } catch (IOException e) {
+-            clientCallback.failed(e);
+-            return;
+-        }
+-        SpdyClientExchange exchange = new SpdyClientExchange(this, sinkChannel, request);
+-        currentExchanges.put(sinkChannel.getStreamId(), exchange);
+-
+-
+-        boolean hasContent = true;
+-
+-        String fixedLengthString = request.getRequestHeaders().getFirst(CONTENT_LENGTH);
+-        String transferEncodingString = request.getRequestHeaders().getLast(TRANSFER_ENCODING);
+-        if (fixedLengthString != null) {
+-            try {
+-                long length = Long.parseLong(fixedLengthString);
+-                hasContent = length != 0;
+-            } catch (NumberFormatException e) {
+-                handleError(new IOException(e));
+-                return;
+-            }
+-        } else if (transferEncodingString == null) {
+-            hasContent = false;
+-        }
+-        if(clientCallback != null) {
+-            clientCallback.completed(exchange);
+-        }
+-        if (!hasContent) {
+-            //if there is no content we flush the response channel.
+-            //otherwise it is up to the user
+-            try {
+-                sinkChannel.shutdownWrites();
+-                if (!sinkChannel.flush()) {
+-                    sinkChannel.getWriteSetter().set(ChannelListeners.flushingChannelListener(null, new ChannelExceptionHandler<StreamSinkChannel>() {
+-                        @Override
+-                        public void handleException(StreamSinkChannel channel, IOException exception) {
+-                            handleError(exception);
+-                        }
+-                    }));
+-                    sinkChannel.resumeWrites();
+-                }
+-            } catch (IOException e) {
+-                handleError(e);
+-            }
+-        } else if (!sinkChannel.isWriteResumed()) {
+-            try {
+-                //TODO: this needs some more thought
+-                if (!sinkChannel.flush()) {
+-                    sinkChannel.getWriteSetter().set(new ChannelListener<StreamSinkChannel>() {
+-                        @Override
+-                        public void handleEvent(StreamSinkChannel channel) {
+-                            try {
+-                                if (channel.flush()) {
+-                                    channel.suspendWrites();
+-                                }
+-                            } catch (IOException e) {
+-                                handleError(e);
+-                            }
+-                        }
+-                    });
+-                    sinkChannel.resumeWrites();
+-                }
+-            } catch (IOException e) {
+-                handleError(e);
+-            }
+-        }
+-    }
+-
+-    private void handleError(IOException e) {
+-
+-        UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
+-        IoUtils.safeClose(SpdyClientConnection.this);
+-        for (Map.Entry<Integer, SpdyClientExchange> entry : currentExchanges.entrySet()) {
+-            try {
+-                entry.getValue().failed(e);
+-            } catch (Exception ex) {
+-                UndertowLogger.REQUEST_IO_LOGGER.ioException(new IOException(ex));
+-            }
+-        }
+-    }
+-
+-    @Override
+-    public StreamConnection performUpgrade() throws IOException {
+-        throw UndertowMessages.MESSAGES.upgradeNotSupported();
+-    }
+-
+-    @Override
+-    public ByteBufferPool getBufferPool() {
+-        return spdyChannel.getBufferPool();
+-    }
+-
+-    @Override
+-    public SocketAddress getPeerAddress() {
+-        return spdyChannel.getPeerAddress();
+-    }
+-
+-    @Override
+-    public <A extends SocketAddress> A getPeerAddress(Class<A> type) {
+-        return spdyChannel.getPeerAddress(type);
+-    }
+-
+-    @Override
+-    public ChannelListener.Setter<? extends ClientConnection> getCloseSetter() {
+-        return closeSetter;
+-    }
+-
+-    @Override
+-    public SocketAddress getLocalAddress() {
+-        return spdyChannel.getLocalAddress();
+-    }
+-
+-    @Override
+-    public <A extends SocketAddress> A getLocalAddress(Class<A> type) {
+-        return spdyChannel.getLocalAddress(type);
+-    }
+-
+-    @Override
+-    public XnioWorker getWorker() {
+-        return spdyChannel.getWorker();
+-    }
+-
+-    @Override
+-    public XnioIoThread getIoThread() {
+-        return spdyChannel.getIoThread();
+-    }
+-
+-    @Override
+-    public boolean isOpen() {
+-        return spdyChannel.isOpen();
+-    }
+-
+-    @Override
+-    public void close() throws IOException {
+-        spdyChannel.sendGoAway(SpdyChannel.CLOSE_OK);
+-    }
+-
+-    @Override
+-    public boolean supportsOption(Option<?> option) {
+-        return false;
+-    }
+-
+-    @Override
+-    public <T> T getOption(Option<T> option) throws IOException {
+-        return null;
+-    }
+-
+-    @Override
+-    public <T> T setOption(Option<T> option, T value) throws IllegalArgumentException, IOException {
+-        return null;
+-    }
+-
+-    @Override
+-    public boolean isUpgraded() {
+-        return false;
+-    }
+-
+-    @Override
+-    public boolean isPushSupported() {
+-        return true;
+-    }
+-
+-    @Override
+-    public boolean isMultiplexingSupported() {
+-        return true;
+-    }
+-
+-    @Override
+-    public ClientStatistics getStatistics() {
+-        return clientStatistics;
+-    }
+-
+-    private class SpdyReceiveListener implements ChannelListener<SpdyChannel> {
+-
+-        @Override
+-        public void handleEvent(SpdyChannel channel) {
+-            try {
+-                SpdyStreamSourceChannel result = channel.receive();
+-                if (result instanceof SpdySynReplyStreamSourceChannel) {
+-                    final int streamId = ((SpdySynReplyStreamSourceChannel) result).getStreamId();
+-                    SpdyClientExchange request = currentExchanges.get(streamId);
+-                    result.addCloseTask(new ChannelListener<SpdyStreamSourceChannel>() {
+-                        @Override
+-                        public void handleEvent(SpdyStreamSourceChannel channel) {
+-                            currentExchanges.remove(streamId);
+-                        }
+-                    });
+-                    if (request == null) {
+-
+-                        //server side initiated stream, we can't deal with that at the moment
+-                        //just fail
+-                        //TODO: either handle this properly or at the very least send RST_STREAM
+-                        channel.sendGoAway(SpdyChannel.CLOSE_PROTOCOL_ERROR);
+-                        IoUtils.safeClose(SpdyClientConnection.this);
+-                        return;
+-                    }
+-                    request.responseReady((SpdySynReplyStreamSourceChannel) result);
+-
+-                } else if (result instanceof SpdyPingStreamSourceChannel) {
+-                    handlePing((SpdyPingStreamSourceChannel) result);
+-                } else if (result instanceof SpdyRstStreamStreamSourceChannel) {
+-                    int stream = ((SpdyRstStreamStreamSourceChannel)result).getStreamId();
+-                    UndertowLogger.REQUEST_LOGGER.debugf("Client received RST_STREAM for stream %s", stream);
+-                    SpdyClientExchange exchange = currentExchanges.get(stream);
+-                    if(exchange != null) {
+-                        exchange.failed(UndertowMessages.MESSAGES.spdyStreamWasReset());
+-                    }
+-                } else if(!channel.isOpen()) {
+-                    throw UndertowMessages.MESSAGES.channelIsClosed();
+-                }
+-
+-            } catch (IOException e) {
+-                UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
+-                IoUtils.safeClose(SpdyClientConnection.this);
+-                for (Map.Entry<Integer, SpdyClientExchange> entry : currentExchanges.entrySet()) {
+-                    try {
+-                        entry.getValue().failed(e);
+-                    } catch (Exception ex) {
+-                        UndertowLogger.REQUEST_IO_LOGGER.ioException(new IOException(ex));
+-                    }
+-                }
+-            }
+-
+-        }
+-
+-        private void handlePing(SpdyPingStreamSourceChannel frame) {
+-            int id = frame.getId();
+-            if (id % 2 == 0) {
+-                //server side ping, return it
+-                frame.getSpdyChannel().sendPing(id);
+-            }
+-        }
+-
+-    }
+-}
+diff --git a/core/src/main/java/io/undertow/client/spdy/SpdyClientExchange.java b/core/src/main/java/io/undertow/client/spdy/SpdyClientExchange.java
+deleted file mode 100644
+index ae282bf..0000000
+--- a/core/src/main/java/io/undertow/client/spdy/SpdyClientExchange.java
++++ /dev/null
+@@ -1,140 +0,0 @@
+-/*
+- * JBoss, Home of Professional Open Source.
+- * Copyright 2014 Red Hat, Inc., and individual contributors
+- * as indicated by the @author tags.
+- *
+- * Licensed under the Apache License, Version 2.0 (the "License");
+- * you may not use this file except in compliance with the License.
+- * You may obtain a copy of the License at
+- *
+- *     http://www.apache.org/licenses/LICENSE-2.0
+- *
+- *  Unless required by applicable law or agreed to in writing, software
+- *  distributed under the License is distributed on an "AS IS" BASIS,
+- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+- *  See the License for the specific language governing permissions and
+- *  limitations under the License.
+- */
+-
+-package io.undertow.client.spdy;
+-
+-import io.undertow.client.ClientCallback;
+-import io.undertow.client.ClientConnection;
+-import io.undertow.client.ClientExchange;
+-import io.undertow.client.ClientRequest;
+-import io.undertow.client.ClientResponse;
+-import io.undertow.client.ContinueNotification;
+-import io.undertow.client.PushCallback;
+-import io.undertow.protocols.spdy.SpdyStreamSinkChannel;
+-import io.undertow.protocols.spdy.SpdyStreamSourceChannel;
+-import io.undertow.protocols.spdy.SpdySynReplyStreamSourceChannel;
+-import io.undertow.util.AbstractAttachable;
+-import io.undertow.util.HeaderMap;
+-import io.undertow.util.Headers;
+-import org.xnio.channels.StreamSinkChannel;
+-import org.xnio.channels.StreamSourceChannel;
+-
+-import java.io.IOException;
+-
+-/**
+- * @author Stuart Douglas
+- */
+-public class SpdyClientExchange extends AbstractAttachable implements ClientExchange {
+-    private ClientCallback<ClientExchange> responseListener;
+-    private ContinueNotification continueNotification;
+-    private SpdyStreamSourceChannel response;
+-    private ClientResponse clientResponse;
+-    private final ClientConnection clientConnection;
+-    private final SpdyStreamSinkChannel request;
+-    private final ClientRequest clientRequest;
+-    private IOException failedReason;
+-    private PushCallback pushCallback;
+-
+-    public SpdyClientExchange(ClientConnection clientConnection, SpdyStreamSinkChannel request, ClientRequest clientRequest) {
+-        this.clientConnection = clientConnection;
+-        this.request = request;
+-        this.clientRequest = clientRequest;
+-    }
+-
+-    @Override
+-    public void setResponseListener(ClientCallback<ClientExchange> responseListener) {
+-        this.responseListener = responseListener;
+-        if (responseListener != null) {
+-            if (failedReason != null) {
+-                responseListener.failed(failedReason);
+-            } else if (clientResponse != null) {
+-                responseListener.completed(this);
+-            }
+-        }
+-    }
+-
+-    @Override
+-    public void setContinueHandler(ContinueNotification continueHandler) {
+-        String expect = clientRequest.getRequestHeaders().getFirst(Headers.EXPECT);
+-        if ("100-continue".equalsIgnoreCase(expect)) {
+-            continueHandler.handleContinue(this);
+-        }
+-    }
+-
+-    @Override
+-    public void setPushHandler(PushCallback pushCallback) {
+-        this.pushCallback = pushCallback;
+-    }
+-
+-    PushCallback getPushCallback() {
+-        return pushCallback;
+-    }
+-
+-    @Override
+-    public StreamSinkChannel getRequestChannel() {
+-        return request;
+-    }
+-
+-    @Override
+-    public StreamSourceChannel getResponseChannel() {
+-        return response;
+-    }
+-
+-    @Override
+-    public ClientRequest getRequest() {
+-        return clientRequest;
+-    }
+-
+-    @Override
+-    public ClientResponse getResponse() {
+-        return clientResponse;
+-    }
+-
+-    @Override
+-    public ClientResponse getContinueResponse() {
+-        return null;
+-    }
+-
+-    @Override
+-    public ClientConnection getConnection() {
+-        return clientConnection;
+-    }
+-
+-    void failed(final IOException e) {
+-        this.failedReason = e;
+-        if(responseListener != null) {
+-            responseListener.failed(e);
+-        }
+-    }
+-
+-    void responseReady(SpdySynReplyStreamSourceChannel result) {
+-        this.response = result;
+-        HeaderMap headers = result.getHeaders();
+-        final String status = result.getHeaders().getFirst(SpdyClientConnection.STATUS);
+-        int statusCode = 500;
+-        if (status != null && status.length() > 3) {
+-            statusCode = Integer.parseInt(status.substring(0, 3));
+-        }
+-        headers.remove(SpdyClientConnection.VERSION);
+-        headers.remove(SpdyClientConnection.STATUS);
+-        clientResponse = new ClientResponse(statusCode, status != null ? status.substring(3) : "", clientRequest.getProtocol(), headers);
+-        if (responseListener != null) {
+-            responseListener.completed(this);
+-        }
+-    }
+-}
+diff --git a/core/src/main/java/io/undertow/client/spdy/SpdyClientProvider.java b/core/src/main/java/io/undertow/client/spdy/SpdyClientProvider.java
+deleted file mode 100644
+index 7540f6e..0000000
+--- a/core/src/main/java/io/undertow/client/spdy/SpdyClientProvider.java
++++ /dev/null
+@@ -1,356 +0,0 @@
+-/*
+- * JBoss, Home of Professional Open Source.
+- * Copyright 2014 Red Hat, Inc., and individual contributors
+- * as indicated by the @author tags.
+- *
+- * Licensed under the Apache License, Version 2.0 (the "License");
+- * you may not use this file except in compliance with the License.
+- * You may obtain a copy of the License at
+- *
+- *     http://www.apache.org/licenses/LICENSE-2.0
+- *
+- *  Unless required by applicable law or agreed to in writing, software
+- *  distributed under the License is distributed on an "AS IS" BASIS,
+- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+- *  See the License for the specific language governing permissions and
+- *  limitations under the License.
+- */
+-
+-package io.undertow.client.spdy;
+-
+-import java.io.IOException;
+-import java.lang.reflect.Method;
+-import java.net.InetSocketAddress;
+-import java.net.URI;
+-import java.nio.ByteBuffer;
+-import java.util.Arrays;
+-import java.util.Collections;
+-import java.util.HashSet;
+-import java.util.List;
+-import java.util.Set;
+-import javax.net.ssl.SSLEngine;
+-
+-import io.undertow.UndertowOptions;
+-import io.undertow.client.ClientStatistics;
+-import io.undertow.conduits.ByteActivityCallback;
+-import io.undertow.conduits.BytesReceivedStreamSourceConduit;
+-import io.undertow.conduits.BytesSentStreamSinkConduit;
+-import io.undertow.protocols.ssl.UndertowXnioSsl;
+-import io.undertow.server.DefaultByteBufferPool;
+-import org.eclipse.jetty.alpn.ALPN;
+-import org.xnio.ChannelListener;
+-import org.xnio.IoFuture;
+-import org.xnio.OptionMap;
+-import org.xnio.Options;
+-import io.undertow.connector.ByteBufferPool;
+-import org.xnio.StreamConnection;
+-import org.xnio.XnioIoThread;
+-import org.xnio.XnioWorker;
+-import org.xnio.channels.StreamSourceChannel;
+-import org.xnio.conduits.PushBackStreamSourceConduit;
+-import org.xnio.ssl.SslConnection;
+-import org.xnio.ssl.XnioSsl;
+-
+-import io.undertow.UndertowLogger;
+-import io.undertow.UndertowMessages;
+-import io.undertow.client.ClientCallback;
+-import io.undertow.client.ClientConnection;
+-import io.undertow.client.ClientProvider;
+-import io.undertow.protocols.spdy.SpdyChannel;
+-import io.undertow.util.ImmediatePooled;
+-
+-/**
+- * Dedicated SPDY client that will never fall back to HTTPS
+- *
+- * @author Stuart Douglas
+- */
+-public class SpdyClientProvider implements ClientProvider {
+-
+-    private static final String PROTOCOL_KEY = SpdyClientProvider.class.getName() + ".protocol";
+-
+-    private static final String SPDY_3 = "spdy/3";
+-    private static final String SPDY_3_1 = "spdy/3.1";
+-    private static final String HTTP_1_1 = "http/1.1";
+-
+-    private static final List<String> PROTOCOLS = Collections.unmodifiableList(Arrays.asList(SPDY_3_1, HTTP_1_1));
+-
+-    private static final Method ALPN_PUT_METHOD;
+-
+-    static {
+-        Method npnPutMethod;
+-        try {
+-            Class<?> npnClass = Class.forName("org.eclipse.jetty.alpn.ALPN", false, SpdyClientProvider.class.getClassLoader());
+-            npnPutMethod = npnClass.getDeclaredMethod("put", SSLEngine.class, Class.forName("org.eclipse.jetty.alpn.ALPN$Provider", false, SpdyClientProvider.class.getClassLoader()));
+-        } catch (Exception e) {
+-            UndertowLogger.CLIENT_LOGGER.jettyALPNNotFound("SPDY");
+-            npnPutMethod = null;
+-        }
+-        ALPN_PUT_METHOD = npnPutMethod;
+-    }
+-
+-
+-    @Override
+-    public void connect(final ClientCallback<ClientConnection> listener, final URI uri, final XnioWorker worker, final XnioSsl ssl, final ByteBufferPool bufferPool, final OptionMap options) {
+-        connect(listener, null, uri, worker, ssl, bufferPool, options);
+-    }
+-
+-    @Override
+-    public void connect(final ClientCallback<ClientConnection> listener, final URI uri, final XnioIoThread ioThread, final XnioSsl ssl, final ByteBufferPool bufferPool, final OptionMap options) {
+-        connect(listener, null, uri, ioThread, ssl, bufferPool, options);
+-    }
+-
+-    @Override
+-    public Set<String> handlesSchemes() {
+-        return new HashSet<>(Arrays.asList(new String[]{"spdy", "spdy-plain"}));
+-    }
+-
+-    @Override
+-    public void connect(final ClientCallback<ClientConnection> listener, InetSocketAddress bindAddress, final URI uri, final XnioWorker worker, final XnioSsl ssl, final ByteBufferPool bufferPool, final OptionMap options) {
+-        if(uri.getScheme().equals("spdy-plain")) {
+-
+-            if(bindAddress == null) {
+-                worker.openStreamConnection(new InetSocketAddress(uri.getHost(), uri.getPort() == -1 ? 443 : uri.getPort()), createOpenListener(listener, uri, ssl, bufferPool, options), options).addNotifier(createNotifier(listener), null);
+-            } else {
+-                worker.openStreamConnection(bindAddress, new InetSocketAddress(uri.getHost(), uri.getPort() == -1 ? 443 : uri.getPort()), createOpenListener(listener, uri, ssl, bufferPool, options), null, options).addNotifier(createNotifier(listener), null);
+-            }
+-            return;
+-        }
+-
+-
+-        if(ALPN_PUT_METHOD == null) {
+-            listener.failed(UndertowMessages.MESSAGES.jettyNPNNotAvailable());
+-            return;
+-        }
+-        if (ssl == null) {
+-            listener.failed(UndertowMessages.MESSAGES.sslWasNull());
+-            return;
+-        }
+-        OptionMap tlsOptions = OptionMap.builder().addAll(options).set(Options.SSL_STARTTLS, true).getMap();
+-        if(bindAddress == null) {
+-            ssl.openSslConnection(worker, new InetSocketAddress(uri.getHost(), uri.getPort() == -1 ? 443 : uri.getPort()), createOpenListener(listener, uri, ssl, bufferPool, tlsOptions), tlsOptions).addNotifier(createNotifier(listener), null);
+-        } else {
+-            ssl.openSslConnection(worker, bindAddress, new InetSocketAddress(uri.getHost(), uri.getPort() == -1 ? 443 : uri.getPort()), createOpenListener(listener, uri, ssl, bufferPool, tlsOptions), tlsOptions).addNotifier(createNotifier(listener), null);
+-        }
+-
+-    }
+-
+-    @Override
+-    public void connect(final ClientCallback<ClientConnection> listener, InetSocketAddress bindAddress, final URI uri, final XnioIoThread ioThread, final XnioSsl ssl, final ByteBufferPool bufferPool, final OptionMap options) {
+-        if(uri.getScheme().equals("spdy-plain")) {
+-
+-            if(bindAddress == null) {
+-                ioThread.openStreamConnection(new InetSocketAddress(uri.getHost(), uri.getPort() == -1 ? 443 : uri.getPort()), createOpenListener(listener, uri, ssl, bufferPool, options), options).addNotifier(createNotifier(listener), null);
+-            } else {
+-                ioThread.openStreamConnection(bindAddress, new InetSocketAddress(uri.getHost(), uri.getPort() == -1 ? 443 : uri.getPort()), createOpenListener(listener, uri, ssl, bufferPool, options), null, options).addNotifier(createNotifier(listener), null);
+-            }
+-            return;
+-        }
+-
+-        if(ALPN_PUT_METHOD == null) {
+-            listener.failed(UndertowMessages.MESSAGES.jettyNPNNotAvailable());
+-            return;
+-        }
+-        if (ssl == null) {
+-            listener.failed(UndertowMessages.MESSAGES.sslWasNull());
+-            return;
+-        }
+-        OptionMap tlsOptions = OptionMap.builder().addAll(options).set(Options.SSL_STARTTLS, true).getMap();
+-        if(bindAddress == null) {
+-            ssl.openSslConnection(ioThread, new InetSocketAddress(uri.getHost(), uri.getPort() == -1 ? 443 : uri.getPort()), createOpenListener(listener, uri, ssl, bufferPool, tlsOptions), tlsOptions).addNotifier(createNotifier(listener), null);
+-        } else {
+-            ssl.openSslConnection(ioThread, bindAddress, new InetSocketAddress(uri.getHost(), uri.getPort() == -1 ? 443 : uri.getPort()), createOpenListener(listener, uri, ssl, bufferPool, tlsOptions), tlsOptions).addNotifier(createNotifier(listener), null);
+-        }
+-
+-    }
+-
+-    private IoFuture.Notifier<StreamConnection, Object> createNotifier(final ClientCallback<ClientConnection> listener) {
+-        return new IoFuture.Notifier<StreamConnection, Object>() {
+-            @Override
+-            public void notify(IoFuture<? extends StreamConnection> ioFuture, Object o) {
+-                if (ioFuture.getStatus() == IoFuture.Status.FAILED) {
+-                    listener.failed(ioFuture.getException());
+-                }
+-            }
+-        };
+-    }
+-
+-    private ChannelListener<StreamConnection> createOpenListener(final ClientCallback<ClientConnection> listener, final URI uri, final XnioSsl ssl, final ByteBufferPool bufferPool, final OptionMap options) {
+-        return new ChannelListener<StreamConnection>() {
+-            @Override
+-            public void handleEvent(StreamConnection connection) {
+-                handleConnected(connection, listener, uri, ssl, bufferPool, options);
+-            }
+-        };
+-    }
+-
+-    private void handleConnected(StreamConnection connection, final ClientCallback<ClientConnection> listener, URI uri, XnioSsl ssl, ByteBufferPool bufferPool, OptionMap options) {
+-        if(connection instanceof SslConnection) {
+-            handlePotentialSpdyConnection(connection, listener, bufferPool, options, new ChannelListener<SslConnection>() {
+-                @Override
+-                public void handleEvent(SslConnection channel) {
+-                    listener.failed(UndertowMessages.MESSAGES.spdyNotSupported());
+-                }
+-            });
+-        } else {
+-            listener.completed(createSpdyChannel(connection, bufferPool, options));
+-        }
+-    }
+-
+-    public static boolean isEnabled() {
+-        return ALPN_PUT_METHOD != null;
+-    }
+-
+-    /**
+-     * Not really part of the public API, but is used by the HTTP client to initiate a SPDY connection for HTTPS requests.
+-     */
+-    public static void handlePotentialSpdyConnection(final StreamConnection connection, final ClientCallback<ClientConnection> listener, final ByteBufferPool bufferPool, final OptionMap options, final ChannelListener<SslConnection> spdyFailedListener) {
+-
+-        final SslConnection sslConnection = (SslConnection) connection;
+-        final SSLEngine sslEngine = UndertowXnioSsl.getSslEngine(sslConnection);
+-
+-        final SpdySelectionProvider spdySelectionProvider = new SpdySelectionProvider(sslEngine);
+-        try {
+-            ALPN_PUT_METHOD.invoke(null, sslEngine, spdySelectionProvider);
+-        } catch (Exception e) {
+-            spdyFailedListener.handleEvent(sslConnection);
+-            return;
+-        }
+-
+-        try {
+-            sslConnection.startHandshake();
+-            sslConnection.getSourceChannel().getReadSetter().set(new ChannelListener<StreamSourceChannel>() {
+-                @Override
+-                public void handleEvent(StreamSourceChannel channel) {
+-
+-                    if (spdySelectionProvider.selected != null) {
+-                        if (spdySelectionProvider.selected.equals(HTTP_1_1)) {
+-                            sslConnection.getSourceChannel().suspendReads();
+-                            spdyFailedListener.handleEvent(sslConnection);
+-                            return;
+-                        } else if (spdySelectionProvider.selected.equals(SPDY_3) || spdySelectionProvider.selected.equals(SPDY_3_1)) {
+-                            listener.completed(createSpdyChannel(connection, bufferPool, options));
+-                        }
+-                    } else {
+-                        ByteBuffer buf = ByteBuffer.allocate(100);
+-                        try {
+-                            int read = channel.read(buf);
+-                            if (read > 0) {
+-                                buf.flip();
+-                                PushBackStreamSourceConduit pb = new PushBackStreamSourceConduit(connection.getSourceChannel().getConduit());
+-                                pb.pushBack(new ImmediatePooled<>(buf));
+-                                connection.getSourceChannel().setConduit(pb);
+-                            }
+-                            if(spdySelectionProvider.selected == null) {
+-                                spdySelectionProvider.selected = (String) sslEngine.getSession().getValue(PROTOCOL_KEY);
+-                            }
+-                            if ((spdySelectionProvider.selected == null && read > 0) || HTTP_1_1.equals(spdySelectionProvider.selected)) {
+-                                sslConnection.getSourceChannel().suspendReads();
+-                                spdyFailedListener.handleEvent(sslConnection);
+-                                return;
+-                            } else if (spdySelectionProvider.selected != null) {
+-                                //we have spdy
+-                                if (spdySelectionProvider.selected.equals(SPDY_3) || spdySelectionProvider.selected.equals(SPDY_3_1)) {
+-                                    listener.completed(createSpdyChannel(connection, bufferPool, options));
+-                                }
+-                            }
+-                        } catch (IOException e) {
+-                            listener.failed(e);
+-                        }
+-                    }
+-                }
+-
+-            });
+-            sslConnection.getSourceChannel().resumeReads();
+-        } catch (IOException e) {
+-            listener.failed(e);
+-        }
+-
+-
+-    }
+-
+-    private static SpdyClientConnection createSpdyChannel(StreamConnection connection, ByteBufferPool bufferPool, OptionMap options) {
+-
+-        final ClientStatisticsImpl clientStatistics;
+-        //first we set up statistics, if required
+-        if (options.get(UndertowOptions.ENABLE_STATISTICS, false)) {
+-            clientStatistics = new ClientStatisticsImpl();
+-            connection.getSinkChannel().setConduit(new BytesSentStreamSinkConduit(connection.getSinkChannel().getConduit(), new ByteActivityCallback() {
+-                @Override
+-                public void activity(long bytes) {
+-                    clientStatistics.written += bytes;
+-                }
+-            }));
+-            connection.getSourceChannel().setConduit(new BytesReceivedStreamSourceConduit(connection.getSourceChannel().getConduit(), new ByteActivityCallback() {
+-                @Override
+-                public void activity(long bytes) {
+-                    clientStatistics.read += bytes;
+-                }
+-            }));
+-        } else {
+-            clientStatistics = null;
+-        }
+-        SpdyChannel spdyChannel = new SpdyChannel(connection, bufferPool, null, new DefaultByteBufferPool(false, 8192), true, options);
+-        return new SpdyClientConnection(spdyChannel, clientStatistics);
+-    }
+-
+-    private static class SpdySelectionProvider implements ALPN.ClientProvider {
+-        private String selected;
+-        private final SSLEngine sslEngine;
+-
+-        private SpdySelectionProvider(SSLEngine sslEngine) {
+-            this.sslEngine = sslEngine;
+-        }
+-
+-        @Override
+-        public boolean supports() {
+-            return true;
+-        }
+-
+-        @Override
+-        public List<String> protocols() {
+-            return PROTOCOLS;
+-        }
+-
+-        @Override
+-        public void unsupported() {
+-            selected = HTTP_1_1;
+-        }
+-
+-        @Override
+-        public void selected(String s) {
+-
+-            ALPN.remove(sslEngine);
+-            selected = s;
+-            sslEngine.getHandshakeSession().putValue(PROTOCOL_KEY, selected);
+-        }
+-
+-        private String getSelected() {
+-            return selected;
+-        }
+-    }
+-
+-    private static class ClientStatisticsImpl implements ClientStatistics {
+-        private long requestCount, read, written;
+-        @Override
+-        public long getRequests() {
+-            return requestCount;
+-        }
+-
+-        @Override
+-        public long getRead() {
+-            return read;
+-        }
+-
+-        @Override
+-        public long getWritten() {
+-            return written;
+-        }
+-
+-        @Override
+-        public void reset() {
+-            read = 0;
+-            written = 0;
+-            requestCount = 0;
+-        }
+-    }
+-}
+diff --git a/core/src/main/java/io/undertow/server/protocol/http/AlpnOpenListener.java b/core/src/main/java/io/undertow/server/protocol/http/AlpnOpenListener.java
+deleted file mode 100644
+index 75c5a16..0000000
+--- a/core/src/main/java/io/undertow/server/protocol/http/AlpnOpenListener.java
++++ /dev/null
+@@ -1,279 +0,0 @@
+-/*
+- * JBoss, Home of Professional Open Source.
+- * Copyright 2014 Red Hat, Inc., and individual contributors
+- * as indicated by the @author tags.
+- *
+- * Licensed under the Apache License, Version 2.0 (the "License");
+- * you may not use this file except in compliance with the License.
+- * You may obtain a copy of the License at
+- *
+- *     http://www.apache.org/licenses/LICENSE-2.0
+- *
+- *  Unless required by applicable law or agreed to in writing, software
+- *  distributed under the License is distributed on an "AS IS" BASIS,
+- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+- *  See the License for the specific language governing permissions and
+- *  limitations under the License.
+- */
+-
+-package io.undertow.server.protocol.http;
+-
+-import java.io.IOException;
+-import java.nio.ByteBuffer;
+-import java.util.ArrayList;
+-import java.util.HashMap;
+-import java.util.List;
+-import java.util.Map;
+-
+-import javax.net.ssl.SSLEngine;
+-
+-import io.undertow.UndertowLogger;
+-import io.undertow.UndertowMessages;
+-import io.undertow.UndertowOptions;
+-import io.undertow.protocols.ssl.UndertowXnioSsl;
+-import io.undertow.server.AggregateConnectorStatistics;
+-import io.undertow.server.ConnectorStatistics;
+-import io.undertow.server.DelegateOpenListener;
+-import io.undertow.server.HttpHandler;
+-import io.undertow.server.OpenListener;
+-import io.undertow.server.XnioByteBufferPool;
+-import org.eclipse.jetty.alpn.ALPN;
+-import org.xnio.ChannelListener;
+-import org.xnio.IoUtils;
+-import org.xnio.OptionMap;
+-import io.undertow.connector.ByteBufferPool;
+-import io.undertow.connector.PooledByteBuffer;
+-import org.xnio.Pool;
+-import org.xnio.StreamConnection;
+-import org.xnio.channels.StreamSourceChannel;
+-import org.xnio.ssl.SslConnection;
+-
+-/**
+- * Open listener adaptor for ALPN connections
+- *
+- * Not a proper open listener as such, but more a mechanism for selecting between them
+- *
+- * @author Stuart Douglas
+- */
+-public class AlpnOpenListener implements ChannelListener<StreamConnection>, OpenListener {
+-
+-    private static final String PROTOCOL_KEY = AlpnOpenListener.class.getName() + ".protocol";
+-
+-    private final ByteBufferPool bufferPool;
+-
+-    private final Map<String, ListenerEntry> listeners = new HashMap<>();
+-    private final String fallbackProtocol;
+-    private volatile HttpHandler rootHandler;
+-    private volatile OptionMap undertowOptions;
+-    private volatile boolean statisticsEnabled;
+-
+-    public AlpnOpenListener(Pool<ByteBuffer> bufferPool, OptionMap undertowOptions, DelegateOpenListener httpListener) {
+-        this(bufferPool, undertowOptions, "http/1.1", httpListener);
+-    }
+-
+-    public AlpnOpenListener(Pool<ByteBuffer> bufferPool,  OptionMap undertowOptions) {
+-        this(bufferPool, undertowOptions, null, null);
+-    }
+-
+-    public AlpnOpenListener(Pool<ByteBuffer> bufferPool, OptionMap undertowOptions, String fallbackProtocol, DelegateOpenListener fallbackListener) {
+-        this(new XnioByteBufferPool(bufferPool), undertowOptions, fallbackProtocol, fallbackListener);
+-    }
+-
+-    public AlpnOpenListener(ByteBufferPool bufferPool, OptionMap undertowOptions, DelegateOpenListener httpListener) {
+-        this(bufferPool, undertowOptions, "http/1.1", httpListener);
+-    }
+-
+-    public AlpnOpenListener(ByteBufferPool bufferPool) {
+-        this(bufferPool, OptionMap.EMPTY, null, null);
+-    }
+-    public AlpnOpenListener(ByteBufferPool bufferPool,  OptionMap undertowOptions) {
+-        this(bufferPool, undertowOptions, null, null);
+-    }
+-
+-    public AlpnOpenListener(ByteBufferPool bufferPool, OptionMap undertowOptions, String fallbackProtocol, DelegateOpenListener fallbackListener) {
+-        this.bufferPool = bufferPool;
+-        this.fallbackProtocol = fallbackProtocol;
+-        if(fallbackProtocol != null && fallbackListener != null) {
+-            addProtocol(fallbackProtocol, fallbackListener, 0);
+-        }
+-        statisticsEnabled = undertowOptions.get(UndertowOptions.ENABLE_CONNECTOR_STATISTICS, false);
+-        this.undertowOptions = undertowOptions;
+-    }
+-
+-
+-    @Override
+-    public HttpHandler getRootHandler() {
+-        return rootHandler;
+-    }
+-
+-    @Override
+-    public void setRootHandler(HttpHandler rootHandler) {
+-        this.rootHandler = rootHandler;
+-        for(Map.Entry<String, ListenerEntry> delegate : listeners.entrySet()) {
+-            delegate.getValue().listener.setRootHandler(rootHandler);
+-        }
+-    }
+-
+-    @Override
+-    public OptionMap getUndertowOptions() {
+-        return undertowOptions;
+-    }
+-
+-    @Override
+-    public void setUndertowOptions(OptionMap undertowOptions) {
+-        if (undertowOptions == null) {
+-            throw UndertowMessages.MESSAGES.argumentCannotBeNull("undertowOptions");
+-        }
+-        this.undertowOptions = undertowOptions;
+-        for(Map.Entry<String, ListenerEntry> delegate : listeners.entrySet()) {
+-            delegate.getValue().listener.setRootHandler(rootHandler);
+-        }
+-        statisticsEnabled = undertowOptions.get(UndertowOptions.ENABLE_CONNECTOR_STATISTICS, false);
+-    }
+-
+-    @Override
+-    public ByteBufferPool getBufferPool() {
+-        return bufferPool;
+-    }
+-
+-    @Override
+-    public ConnectorStatistics getConnectorStatistics() {
+-        if(statisticsEnabled) {
+-            List<ConnectorStatistics> stats = new ArrayList<>();
+-            for(Map.Entry<String, ListenerEntry> l : listeners.entrySet()) {
+-                ConnectorStatistics c = l.getValue().listener.getConnectorStatistics();
+-                if(c != null) {
+-                    stats.add(c);
+-                }
+-            }
+-            return new AggregateConnectorStatistics(stats.toArray(new ConnectorStatistics[stats.size()]));
+-        }
+-        return null;
+-    }
+-
+-    private static class ListenerEntry {
+-        DelegateOpenListener listener;
+-        int weight;
+-
+-        public ListenerEntry(DelegateOpenListener listener, int weight) {
+-            this.listener = listener;
+-            this.weight = weight;
+-        }
+-    }
+-
+-    public AlpnOpenListener addProtocol(String name, DelegateOpenListener listener, int weight) {
+-        listeners.put(name, new ListenerEntry(listener, weight));
+-        return this;
+-    }
+-
+-    public void handleEvent(final StreamConnection channel) {
+-        if (UndertowLogger.REQUEST_LOGGER.isTraceEnabled()) {
+-            UndertowLogger.REQUEST_LOGGER.tracef("Opened connection with %s", channel.getPeerAddress());
+-        }
+-        final AlpnConnectionListener potentialConnection = new AlpnConnectionListener(channel);
+-        channel.getSourceChannel().setReadListener(potentialConnection);
+-        final SSLEngine sslEngine = UndertowXnioSsl.getSslEngine((SslConnection) channel);
+-        ALPN.put(sslEngine, new ALPN.ServerProvider() {
+-            @Override
+-            public void unsupported() {
+-                final String existing = (String) sslEngine.getHandshakeSession().getValue(PROTOCOL_KEY);
+-                if (existing == null || !listeners.containsKey(existing)) {
+-                    if(fallbackProtocol == null) {
+-                        UndertowLogger.REQUEST_IO_LOGGER.noALPNFallback(channel.getPeerAddress());
+-                        IoUtils.safeClose(channel);
+-                    }
+-                    potentialConnection.selected = fallbackProtocol;
+-                } else {
+-                    potentialConnection.selected = existing;
+-                }
+-            }
+-
+-            @Override
+-            public String select(List<String> strings) {
+-
+-                ALPN.remove(sslEngine);
+-
+-                String match = null;
+-                int lastWeight = -1;
+-                for (String s : strings) {
+-                    ListenerEntry listener = listeners.get(s);
+-                    if (listener != null && listener.weight > lastWeight) {
+-                        match = s;
+-                        lastWeight = listener.weight;
+-                    }
+-                }
+-
+-                if (match != null) {
+-                    sslEngine.getHandshakeSession().putValue(PROTOCOL_KEY, match);
+-                    return potentialConnection.selected = match;
+-                }
+-
+-                if(fallbackProtocol == null) {
+-                    UndertowLogger.REQUEST_IO_LOGGER.noALPNFallback(channel.getPeerAddress());
+-                    IoUtils.safeClose(channel);
+-                    return null;
+-                }
+-                sslEngine.getHandshakeSession().putValue(PROTOCOL_KEY, fallbackProtocol);
+-                potentialConnection.selected = fallbackProtocol;
+-                return fallbackProtocol;
+-            }
+-        });
+-        potentialConnection.handleEvent(channel.getSourceChannel());
+-
+-    }
+-
+-    private class AlpnConnectionListener implements ChannelListener<StreamSourceChannel> {
+-        private String selected;
+-        private final StreamConnection channel;
+-
+-        private AlpnConnectionListener(StreamConnection channel) {
+-            this.channel = channel;
+-        }
+-
+-        @Override
+-        public void handleEvent(StreamSourceChannel source) {
+-            PooledByteBuffer buffer = bufferPool.allocate();
+-            boolean free = true;
+-            try {
+-                while (true) {
+-                    int res = channel.getSourceChannel().read(buffer.getBuffer());
+-                    if (res == -1) {
+-                        IoUtils.safeClose(channel);
+-                        return;
+-                    }
+-                    buffer.getBuffer().flip();
+-                    if(selected != null) {
+-                        DelegateOpenListener listener = listeners.get(selected).listener;
+-                        source.getReadSetter().set(null);
+-                        listener.handleEvent(channel, buffer);
+-                        free = false;
+-                        return;
+-                    } else if(res > 0) {
+-                        if(fallbackProtocol == null) {
+-                            UndertowLogger.REQUEST_IO_LOGGER.noALPNFallback(channel.getPeerAddress());
+-                            IoUtils.safeClose(channel);
+-                            return;
+-                        }
+-                        DelegateOpenListener listener = listeners.get(fallbackProtocol).listener;
+-                        source.getReadSetter().set(null);
+-                        listener.handleEvent(channel, buffer);
+-                        free = false;
+-                        return;
+-                    } else if (res == 0) {
+-                        channel.getSourceChannel().resumeReads();
+-                        return;
+-                    }
+-                }
+-
+-            } catch (IOException e) {
+-                UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
+-                IoUtils.safeClose(channel);
+-            } finally {
+-                if (free) {
+-                    buffer.close();
+-                }
+-            }
+-        }
+-    }
+-
+-}
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..b8238fe
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1 @@
+alpn-not-supported.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/undertow.git



More information about the pkg-java-commits mailing list