Search in sources :

Example 1 with ReadDataStreamSourceConduit

use of io.undertow.conduits.ReadDataStreamSourceConduit in project undertow by undertow-io.

the class HttpReadListener method exchangeComplete.

public void exchangeComplete(final HttpServerExchange exchange) {
    connection.clearChannel();
    final HttpServerConnection connection = this.connection;
    if (exchange.isPersistent() && !isUpgradeOrConnect(exchange)) {
        final StreamConnection channel = connection.getChannel();
        if (connection.getExtraBytes() == null) {
            //we have to resume from with the io thread
            if (exchange.isInIoThread()) {
                //no need for CAS, we are in the IO thread
                newRequest();
                channel.getSourceChannel().setReadListener(HttpReadListener.this);
                channel.getSourceChannel().resumeReads();
                requestStateUpdater.set(this, 0);
            } else {
                while (true) {
                    if (connection.getOriginalSourceConduit().isReadShutdown() || connection.getOriginalSinkConduit().isWriteShutdown()) {
                        channel.getSourceChannel().suspendReads();
                        channel.getSinkChannel().suspendWrites();
                        IoUtils.safeClose(connection);
                        return;
                    } else {
                        if (requestStateUpdater.compareAndSet(this, 1, 2)) {
                            try {
                                newRequest();
                                channel.getSourceChannel().setReadListener(HttpReadListener.this);
                                channel.getSourceChannel().resumeReads();
                            } finally {
                                requestStateUpdater.set(this, 0);
                            }
                            break;
                        }
                    }
                }
            }
        } else {
            if (exchange.isInIoThread()) {
                //no need to CAS, as we don't actually resume
                requestStateUpdater.set(this, 0);
                newRequest();
                //no need to suspend reads here, the task will always run before the read listener anyway
                channel.getIoThread().execute(this);
            } else {
                while (true) {
                    if (connection.getOriginalSinkConduit().isWriteShutdown()) {
                        channel.getSourceChannel().suspendReads();
                        channel.getSinkChannel().suspendWrites();
                        IoUtils.safeClose(connection);
                        return;
                    } else if (requestStateUpdater.compareAndSet(this, 1, 2)) {
                        try {
                            newRequest();
                            channel.getSourceChannel().suspendReads();
                        } finally {
                            requestStateUpdater.set(this, 0);
                        }
                        break;
                    }
                }
                Executor executor = exchange.getDispatchExecutor();
                if (executor == null) {
                    executor = exchange.getConnection().getWorker();
                }
                executor.execute(this);
            }
        }
    } else if (!exchange.isPersistent()) {
        ConnectionUtils.cleanClose(connection.getChannel(), connection);
    } else {
        //upgrade or connect handling
        if (connection.getExtraBytes() != null) {
            connection.getChannel().getSourceChannel().setConduit(new ReadDataStreamSourceConduit(connection.getChannel().getSourceChannel().getConduit(), connection));
        }
        try {
            if (!connection.getChannel().getSinkChannel().flush()) {
                connection.getChannel().getSinkChannel().setWriteListener(ChannelListeners.flushingChannelListener(new ChannelListener<ConduitStreamSinkChannel>() {

                    @Override
                    public void handleEvent(ConduitStreamSinkChannel conduitStreamSinkChannel) {
                        connection.getUpgradeListener().handleUpgrade(connection.getChannel(), exchange);
                    }
                }, new ClosingChannelExceptionHandler<ConduitStreamSinkChannel>(connection)));
                connection.getChannel().getSinkChannel().resumeWrites();
                return;
            }
            connection.getUpgradeListener().handleUpgrade(connection.getChannel(), exchange);
        } catch (IOException e) {
            UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
            IoUtils.safeClose(connection);
        }
    }
}
Also used : Executor(java.util.concurrent.Executor) ReadDataStreamSourceConduit(io.undertow.conduits.ReadDataStreamSourceConduit) IOException(java.io.IOException) StreamConnection(org.xnio.StreamConnection) ConduitStreamSinkChannel(org.xnio.conduits.ConduitStreamSinkChannel)

Example 2 with ReadDataStreamSourceConduit

use of io.undertow.conduits.ReadDataStreamSourceConduit in project undertow by undertow-io.

the class AjpReadListener method createSourceConduit.

private StreamSourceConduit createSourceConduit(StreamSourceConduit underlyingConduit, AjpServerResponseConduit responseConduit, final HttpServerExchange exchange) {
    ReadDataStreamSourceConduit conduit = new ReadDataStreamSourceConduit(underlyingConduit, (AbstractServerConnection) exchange.getConnection());
    final HeaderMap requestHeaders = exchange.getRequestHeaders();
    HttpString transferEncoding = Headers.IDENTITY;
    Long length;
    final String teHeader = requestHeaders.getLast(Headers.TRANSFER_ENCODING);
    boolean hasTransferEncoding = teHeader != null;
    if (hasTransferEncoding) {
        transferEncoding = new HttpString(teHeader);
    }
    final String requestContentLength = requestHeaders.getFirst(Headers.CONTENT_LENGTH);
    if (hasTransferEncoding && !transferEncoding.equals(Headers.IDENTITY)) {
        //unknown length
        length = null;
    } else if (requestContentLength != null) {
        final long contentLength = Long.parseLong(requestContentLength);
        if (contentLength == 0L) {
            UndertowLogger.REQUEST_LOGGER.trace("No content, starting next request");
            // no content - immediately start the next request, returning an empty stream for this one
            Connectors.terminateRequest(httpServerExchange);
            return new EmptyStreamSourceConduit(conduit.getReadThread());
        } else {
            length = contentLength;
        }
    } else {
        UndertowLogger.REQUEST_LOGGER.trace("No content length or transfer coding, starting next request");
        // no content - immediately start the next request, returning an empty stream for this one
        Connectors.terminateRequest(exchange);
        return new EmptyStreamSourceConduit(conduit.getReadThread());
    }
    return new AjpServerRequestConduit(conduit, exchange, responseConduit, length, new ConduitListener<AjpServerRequestConduit>() {

        @Override
        public void handleEvent(AjpServerRequestConduit channel) {
            Connectors.terminateRequest(exchange);
        }
    });
}
Also used : EmptyStreamSourceConduit(io.undertow.conduits.EmptyStreamSourceConduit) HeaderMap(io.undertow.util.HeaderMap) ReadDataStreamSourceConduit(io.undertow.conduits.ReadDataStreamSourceConduit) HttpString(io.undertow.util.HttpString) HttpString(io.undertow.util.HttpString)

Aggregations

ReadDataStreamSourceConduit (io.undertow.conduits.ReadDataStreamSourceConduit)2 EmptyStreamSourceConduit (io.undertow.conduits.EmptyStreamSourceConduit)1 HeaderMap (io.undertow.util.HeaderMap)1 HttpString (io.undertow.util.HttpString)1 IOException (java.io.IOException)1 Executor (java.util.concurrent.Executor)1 StreamConnection (org.xnio.StreamConnection)1 ConduitStreamSinkChannel (org.xnio.conduits.ConduitStreamSinkChannel)1