From cc36ef4cdfdb007c585c9170eb017e446b74b9c3 Mon Sep 17 00:00:00 2001 From: Marek Goldmann Date: Mar 23 2015 07:52:57 +0000 Subject: Upstream release 1.1.0.Final --- diff --git a/.gitignore b/.gitignore index 9d7da88..03f5924 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ /1.0.0.Final.tar.gz /1.0.5.Final.tar.gz /1.0.15.Final.tar.gz +/1.1.0.Final.tar.gz diff --git a/0001-Remove-spdy-protocol-handler-alpn-is-not-available-i.patch b/0001-Remove-spdy-protocol-handler-alpn-is-not-available-i.patch new file mode 100644 index 0000000..0d09213 --- /dev/null +++ b/0001-Remove-spdy-protocol-handler-alpn-is-not-available-i.patch @@ -0,0 +1,1048 @@ +From e2bb461117cbbfa56a88889261af16437439c207 Mon Sep 17 00:00:00 2001 +From: Marek Goldmann +Date: Wed, 14 Jan 2015 10:50:35 +0100 +Subject: [PATCH] Remove spdy protocol handler, alpn is not available in Fedora + +--- + core/src/main/java/io/undertow/Undertow.java | 16 +- + .../undertow/client/http/HttpClientProvider.java | 16 +- + .../undertow/client/spdy/SpdyClientConnection.java | 305 --------------------- + .../undertow/client/spdy/SpdyClientExchange.java | 129 --------- + .../undertow/client/spdy/SpdyClientProvider.java | 302 -------------------- + .../server/protocol/http/AlpnOpenListener.java | 199 -------------- + 6 files changed, 2 insertions(+), 965 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 78859c3..60b0536 100644 +--- a/core/src/main/java/io/undertow/Undertow.java ++++ b/core/src/main/java/io/undertow/Undertow.java +@@ -23,9 +23,7 @@ import io.undertow.security.api.GSSAPIServerSubjectFactory; + import io.undertow.security.idm.IdentityManager; + 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.spdy.SpdyOpenListener; + import org.xnio.BufferAllocator; + import org.xnio.ByteBufferSlicePool; + import org.xnio.ChannelListener; +@@ -145,19 +143,7 @@ public class Undertow { + + HttpOpenListener httpOpenListener = new HttpOpenListener(buffers, undertowOptions); + httpOpenListener.setRootHandler(rootHandler); +- +- boolean spdy = serverOptions.get(UndertowOptions.ENABLE_SPDY, false); +- if(spdy) { +- AlpnOpenListener alpn = new AlpnOpenListener(buffers, httpOpenListener); +- if(spdy) { +- SpdyOpenListener spdyListener = new SpdyOpenListener(buffers, new ByteBufferSlicePool(BufferAllocator.BYTE_BUFFER_ALLOCATOR, 1024, 1024), undertowOptions); +- spdyListener.setRootHandler(rootHandler); +- alpn.addProtocol(SpdyOpenListener.SPDY_3_1, spdyListener, 5); +- } +- openListener = alpn; +- } else { +- openListener = httpOpenListener; +- } ++ openListener = httpOpenListener; + ChannelListener> 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 7c64fa5..d0241eb 100644 +--- a/core/src/main/java/io/undertow/client/http/HttpClientProvider.java ++++ b/core/src/main/java/io/undertow/client/http/HttpClientProvider.java +@@ -23,7 +23,6 @@ import io.undertow.UndertowOptions; + import io.undertow.client.ClientCallback; + import io.undertow.client.ClientConnection; + import io.undertow.client.ClientProvider; +-import io.undertow.client.spdy.SpdyClientProvider; + import org.xnio.ChannelListener; + import org.xnio.IoFuture; + import org.xnio.OptionMap; +@@ -126,19 +125,6 @@ public class HttpClientProvider implements ClientProvider { + + + private void handleConnected(final StreamConnection connection, final ClientCallback listener, final Pool bufferPool, final OptionMap options) { +- if (options.get(UndertowOptions.ENABLE_SPDY, false) && connection instanceof SslConnection && SpdyClientProvider.isEnabled()) { +- try { +- SpdyClientProvider.handlePotentialSpdyConnection(connection, listener, bufferPool, options, new ChannelListener() { +- @Override +- public void handleEvent(SslConnection channel) { +- listener.completed(new HttpClientConnection(connection, options, bufferPool)); +- } +- }); +- } catch (Exception e) { +- listener.failed(new IOException(e)); +- } +- } else { +- listener.completed(new HttpClientConnection(connection, options, bufferPool)); +- } ++ listener.completed(new HttpClientConnection(connection, options, bufferPool)); + } + } +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 55430cf..0000000 +--- a/core/src/main/java/io/undertow/client/spdy/SpdyClientConnection.java ++++ /dev/null +@@ -1,305 +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.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 org.xnio.Pool; +-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.nio.ByteBuffer; +-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 closeSetter = new ChannelListener.SimpleSetter<>(); +- +- private final Map currentExchanges = new ConcurrentHashMap<>(); +- +- public SpdyClientConnection(SpdyChannel spdyChannel) { +- this.spdyChannel = spdyChannel; +- spdyChannel.getReceiveSetter().set(new SpdyReceiveListener()); +- spdyChannel.resumeReceives(); +- spdyChannel.addCloseTask(new ChannelListener() { +- @Override +- public void handleEvent(SpdyChannel channel) { +- ChannelListeners.invokeChannelListener(SpdyClientConnection.this, closeSetter.get()); +- } +- }); +- } +- +- @Override +- public void sendRequest(ClientRequest request, ClientCallback 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() { +- @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() { +- @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 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 Pool getBufferPool() { +- return spdyChannel.getBufferPool(); +- } +- +- @Override +- public SocketAddress getPeerAddress() { +- return spdyChannel.getPeerAddress(); +- } +- +- @Override +- public A getPeerAddress(Class type) { +- return spdyChannel.getPeerAddress(type); +- } +- +- @Override +- public ChannelListener.Setter getCloseSetter() { +- return closeSetter; +- } +- +- @Override +- public SocketAddress getLocalAddress() { +- return spdyChannel.getLocalAddress(); +- } +- +- @Override +- public A getLocalAddress(Class 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 getOption(Option option) throws IOException { +- return null; +- } +- +- @Override +- public T setOption(Option option, T value) throws IllegalArgumentException, IOException { +- return null; +- } +- +- @Override +- public boolean isUpgraded() { +- return false; +- } +- +- private class SpdyReceiveListener implements ChannelListener { +- +- @Override +- public void handleEvent(SpdyChannel channel) { +- try { +- SpdyStreamSourceChannel result = channel.receive(); +- if (result instanceof SpdySynReplyStreamSourceChannel) { +- SpdyClientExchange request = currentExchanges.remove(((SpdySynReplyStreamSourceChannel) result).getStreamId()); +- 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 +- 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 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 dc5481a..0000000 +--- a/core/src/main/java/io/undertow/client/spdy/SpdyClientExchange.java ++++ /dev/null +@@ -1,129 +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.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 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; +- +- public SpdyClientExchange(ClientConnection clientConnection, SpdyStreamSinkChannel request, ClientRequest clientRequest) { +- this.clientConnection = clientConnection; +- this.request = request; +- this.clientRequest = clientRequest; +- } +- +- @Override +- public void setResponseListener(ClientCallback 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 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 4fb4acb..0000000 +--- a/core/src/main/java/io/undertow/client/spdy/SpdyClientProvider.java ++++ /dev/null +@@ -1,302 +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 org.eclipse.jetty.alpn.ALPN; +-import org.xnio.BufferAllocator; +-import org.xnio.ByteBufferSlicePool; +-import org.xnio.ChannelListener; +-import org.xnio.IoFuture; +-import org.xnio.OptionMap; +-import org.xnio.Pool; +-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.JsseXnioSsl; +-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 PROTOCOLS = Collections.unmodifiableList(Arrays.asList(new String[]{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 listener, final URI uri, final XnioWorker worker, final XnioSsl ssl, final Pool bufferPool, final OptionMap options) { +- connect(listener, null, uri, worker, ssl, bufferPool, options); +- } +- +- @Override +- public void connect(final ClientCallback listener, final URI uri, final XnioIoThread ioThread, final XnioSsl ssl, final Pool bufferPool, final OptionMap options) { +- connect(listener, null, uri, ioThread, ssl, bufferPool, options); +- } +- +- @Override +- public Set handlesSchemes() { +- return new HashSet<>(Arrays.asList(new String[]{"spdy", "spdy-plain"})); +- } +- +- @Override +- public void connect(final ClientCallback listener, InetSocketAddress bindAddress, final URI uri, final XnioWorker worker, final XnioSsl ssl, final Pool 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; +- } +- if(bindAddress == null) { +- ssl.openSslConnection(worker, new InetSocketAddress(uri.getHost(), uri.getPort() == -1 ? 443 : uri.getPort()), createOpenListener(listener, uri, ssl, bufferPool, options), options).addNotifier(createNotifier(listener), null); +- } else { +- ssl.openSslConnection(worker, bindAddress, new InetSocketAddress(uri.getHost(), uri.getPort() == -1 ? 443 : uri.getPort()), createOpenListener(listener, uri, ssl, bufferPool, options), options).addNotifier(createNotifier(listener), null); +- } +- +- } +- +- @Override +- public void connect(final ClientCallback listener, InetSocketAddress bindAddress, final URI uri, final XnioIoThread ioThread, final XnioSsl ssl, final Pool 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; +- } +- if(bindAddress == null) { +- ssl.openSslConnection(ioThread, new InetSocketAddress(uri.getHost(), uri.getPort() == -1 ? 443 : uri.getPort()), createOpenListener(listener, uri, ssl, bufferPool, options), options).addNotifier(createNotifier(listener), null); +- } else { +- ssl.openSslConnection(ioThread, bindAddress, new InetSocketAddress(uri.getHost(), uri.getPort() == -1 ? 443 : uri.getPort()), createOpenListener(listener, uri, ssl, bufferPool, options), options).addNotifier(createNotifier(listener), null); +- } +- +- } +- +- private IoFuture.Notifier createNotifier(final ClientCallback listener) { +- return new IoFuture.Notifier() { +- @Override +- public void notify(IoFuture ioFuture, Object o) { +- if (ioFuture.getStatus() == IoFuture.Status.FAILED) { +- listener.failed(ioFuture.getException()); +- } +- } +- }; +- } +- +- private ChannelListener createOpenListener(final ClientCallback listener, final URI uri, final XnioSsl ssl, final Pool bufferPool, final OptionMap options) { +- return new ChannelListener() { +- @Override +- public void handleEvent(StreamConnection connection) { +- handleConnected(connection, listener, uri, ssl, bufferPool, options); +- } +- }; +- } +- +- private void handleConnected(StreamConnection connection, final ClientCallback listener, URI uri, XnioSsl ssl, Pool bufferPool, OptionMap options) { +- if(connection instanceof SslConnection) { +- handlePotentialSpdyConnection(connection, listener, bufferPool, options, new ChannelListener() { +- @Override +- public void handleEvent(SslConnection channel) { +- listener.failed(UndertowMessages.MESSAGES.spdyNotSupported()); +- } +- }); +- } else { +- listener.completed(createSpdyChannel(connection, bufferPool)); +- } +- } +- +- 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 listener, final Pool bufferPool, final OptionMap options, final ChannelListener spdyFailedListener) { +- +- final SslConnection sslConnection = (SslConnection) connection; +- final SSLEngine sslEngine = JsseXnioSsl.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() { +- @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)); +- } +- } else { +- ByteBuffer buf = ByteBuffer.allocate(100); +- try { +- int read = channel.read(buf); +- if (read > 0) { +- 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)); +- } +- } +- } catch (IOException e) { +- listener.failed(e); +- } +- } +- } +- +- }); +- sslConnection.getSourceChannel().resumeReads(); +- } catch (IOException e) { +- listener.failed(e); +- } +- +- +- } +- +- private static SpdyClientConnection createSpdyChannel(StreamConnection connection, Pool bufferPool) { +- SpdyChannel spdyChannel = new SpdyChannel(connection, bufferPool, null, new ByteBufferSlicePool(BufferAllocator.BYTE_BUFFER_ALLOCATOR, 8192, 8192), true); +- return new SpdyClientConnection(spdyChannel); +- } +- +- 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 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; +- } +- } +-} +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 b7e767a..0000000 +--- a/core/src/main/java/io/undertow/server/protocol/http/AlpnOpenListener.java ++++ /dev/null +@@ -1,199 +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.HashMap; +-import java.util.List; +-import java.util.Map; +- +-import javax.net.ssl.SSLEngine; +- +-import io.undertow.UndertowLogger; +-import io.undertow.server.DelegateOpenListener; +-import org.eclipse.jetty.alpn.ALPN; +-import org.xnio.ChannelListener; +-import org.xnio.IoUtils; +-import org.xnio.Pool; +-import org.xnio.Pooled; +-import org.xnio.StreamConnection; +-import org.xnio.channels.StreamSourceChannel; +-import org.xnio.ssl.JsseXnioSsl; +-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 { +- +- private static final String PROTOCOL_KEY = AlpnOpenListener.class.getName() + ".protocol"; +- +- private final Pool bufferPool; +- +- private final Map listeners = new HashMap<>(); +- private final String fallbackProtocol; +- +- private static class ListenerEntry { +- DelegateOpenListener listener; +- int weight; +- +- public ListenerEntry(DelegateOpenListener listener, int weight) { +- this.listener = listener; +- this.weight = weight; +- } +- } +- +- public AlpnOpenListener(Pool bufferPool, String fallbackProtocol, DelegateOpenListener fallbackListener) { +- this.bufferPool = bufferPool; +- this.fallbackProtocol = fallbackProtocol; +- if(fallbackProtocol != null && fallbackListener != null) { +- addProtocol(fallbackProtocol, fallbackListener, 0); +- } +- } +- +- public AlpnOpenListener(Pool bufferPool, DelegateOpenListener httpListener) { +- this(bufferPool, "http/1.1", httpListener); +- } +- +- +- public AlpnOpenListener(Pool bufferPool) { +- this(bufferPool, null, null); +- } +- +- 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 = JsseXnioSsl.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 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 { +- private String selected; +- private final StreamConnection channel; +- +- private AlpnConnectionListener(StreamConnection channel) { +- this.channel = channel; +- } +- +- @Override +- public void handleEvent(StreamSourceChannel source) { +- Pooled buffer = bufferPool.allocate(); +- boolean free = true; +- try { +- while (true) { +- int res = channel.getSourceChannel().read(buffer.getResource()); +- if (res == -1) { +- IoUtils.safeClose(channel); +- return; +- } +- buffer.getResource().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.free(); +- } +- } +- } +- } +- +-} +-- +2.1.0 + diff --git a/sources b/sources index 516ac38..54a3104 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -cf62ed32d49c97f006c89d2fa3bf00a7 1.0.15.Final.tar.gz +f2f2d3a7f434c08e3816aae23fb85580 1.1.0.Final.tar.gz diff --git a/undertow.spec b/undertow.spec index 0049edf..3748788 100644 --- a/undertow.spec +++ b/undertow.spec @@ -2,13 +2,16 @@ %global namedversion %{version}%{?namedreltag} Name: undertow -Version: 1.0.15 +Version: 1.1.0 Release: 1%{?dist} Summary: Java web server using non-blocking IO License: ASL 2.0 and LGPLv2 URL: http://undertow.io/ Source0: https://github.com/undertow-io/undertow/archive/%{namedversion}.tar.gz +# Jetty alpn is not available in fedora, we need to remove spdy protocol +Patch0: 0001-Remove-spdy-protocol-handler-alpn-is-not-available-i.patch + BuildArch: noarch Epoch: 1 @@ -20,7 +23,7 @@ BuildRequires: jboss-parent BuildRequires: jboss-logging BuildRequires: jboss-logging-tools BuildRequires: jboss-logmanager -BuildRequires: xnio >= 3.2.0-0.1 +BuildRequires: xnio >= 3.3.0-1 BuildRequires: easymock3 BuildRequires: junit BuildRequires: netty @@ -28,11 +31,8 @@ BuildRequires: jboss-classfilewriter BuildRequires: jboss-annotations-1.2-api BuildRequires: jboss-jsp-2.3-api BuildRequires: jboss-servlet-3.1-api -BuildRequires: jboss-websocket-1.0-api BuildRequires: jastow >= 1.0.0-1 - -# Undertow doesn't build on JDK8 -BuildRequires: java-1.7.0-openjdk-devel +BuildRequires: mvn(org.jboss.spec.javax.websocket:jboss-websocket-api_1.1_spec) %description Java web server using non-blocking IO @@ -46,6 +46,8 @@ This package contains the API documentation for %{name}. %prep %setup -q -n undertow-%{namedversion} +%patch0 -p1 + rm -rf mac-jdk-fix # Not needed @@ -54,10 +56,15 @@ rm -rf mac-jdk-fix %pom_add_dep org.apache.james:apache-mime4j-core:any:test servlet %pom_remove_plugin :maven-checkstyle-plugin +%pom_remove_plugin org.bitstrings.maven.plugins:dependencypath-maven-plugin core/pom.xml +%pom_remove_plugin org.bitstrings.maven.plugins:dependencypath-maven-plugin servlet/pom.xml %pom_remove_dep io.undertow.build:undertow-checkstyle-config +# Not avialable in Fedora +%pom_remove_dep org.eclipse.jetty.alpn:alpn-api core/pom.xml +%pom_remove_dep org.eclipse.jetty.alpn:alpn-api servlet/pom.xml + %build -export JAVA_HOME=/usr/lib/jvm/java-1.7.0 %mvn_build -f %install @@ -71,6 +78,9 @@ export JAVA_HOME=/usr/lib/jvm/java-1.7.0 %doc LICENSE.txt %changelog +* Mon Jan 12 2015 Marek Goldmann - 1:1.1.0-1 +- Upstream release 1.1.0.Final + * Wed Jun 11 2014 Marek Goldmann - 1:1.0.15-1 - Upstream release 1.0.15.Final