Search in sources :

Example 11 with StreamSinkChannel

use of org.xnio.channels.StreamSinkChannel in project spring-framework by spring-projects.

the class UndertowServerHttpResponse method writeWith.

@Override
public Mono<Void> writeWith(File file, long position, long count) {
    return doCommit(() -> {
        FileChannel source = null;
        try {
            source = new FileInputStream(file).getChannel();
            StreamSinkChannel destination = getUndertowExchange().getResponseChannel();
            Channels.transferBlocking(destination, source, position, count);
            return Mono.empty();
        } catch (IOException ex) {
            return Mono.error(ex);
        } finally {
            if (source != null) {
                try {
                    source.close();
                } catch (IOException ex) {
                // ignore
                }
            }
        }
    });
}
Also used : FileChannel(java.nio.channels.FileChannel) StreamSinkChannel(org.xnio.channels.StreamSinkChannel) IOException(java.io.IOException) FileInputStream(java.io.FileInputStream)

Example 12 with StreamSinkChannel

use of org.xnio.channels.StreamSinkChannel in project undertow by undertow-io.

the class UndertowOutputStream method close.

/**
     * {@inheritDoc}
     */
public void close() throws IOException {
    if (anyAreSet(state, FLAG_CLOSED))
        return;
    try {
        state |= FLAG_CLOSED;
        if (anyAreClear(state, FLAG_WRITE_STARTED) && channel == null) {
            if (buffer == null) {
                exchange.getResponseHeaders().put(Headers.CONTENT_LENGTH, "0");
            } else {
                exchange.getResponseHeaders().put(Headers.CONTENT_LENGTH, "" + buffer.position());
            }
        }
        if (buffer != null) {
            writeBufferBlocking(true);
        }
        if (channel == null) {
            channel = exchange.getResponseChannel();
        }
        if (channel == null) {
            return;
        }
        StreamSinkChannel channel = this.channel;
        channel.shutdownWrites();
        Channels.flushBlocking(channel);
    } finally {
        if (pooledBuffer != null) {
            pooledBuffer.close();
            buffer = null;
        } else {
            buffer = null;
        }
    }
}
Also used : StreamSinkChannel(org.xnio.channels.StreamSinkChannel)

Example 13 with StreamSinkChannel

use of org.xnio.channels.StreamSinkChannel in project undertow by undertow-io.

the class AsyncSenderImpl method send.

@Override
public void send(final ByteBuffer buffer, final IoCallback callback) {
    if (callback == null) {
        throw UndertowMessages.MESSAGES.argumentCannotBeNull("callback");
    }
    if (exchange.isResponseComplete()) {
        throw UndertowMessages.MESSAGES.responseComplete();
    }
    if (this.buffer != null || this.fileChannel != null) {
        throw UndertowMessages.MESSAGES.dataAlreadyQueued();
    }
    long responseContentLength = exchange.getResponseContentLength();
    if (responseContentLength > 0 && buffer.remaining() > responseContentLength) {
        invokeOnException(callback, UndertowLogger.ROOT_LOGGER.dataLargerThanContentLength(buffer.remaining(), responseContentLength));
        return;
    }
    StreamSinkChannel channel = this.channel;
    if (channel == null) {
        if (callback == IoCallback.END_EXCHANGE) {
            if (responseContentLength == -1 && !exchange.getResponseHeaders().contains(Headers.TRANSFER_ENCODING)) {
                exchange.setResponseContentLength(buffer.remaining());
            }
        }
        this.channel = channel = exchange.getResponseChannel();
        if (channel == null) {
            throw UndertowMessages.MESSAGES.responseChannelAlreadyProvided();
        }
    }
    this.callback = callback;
    if (inCallback) {
        this.buffer = new ByteBuffer[] { buffer };
        return;
    }
    try {
        do {
            if (buffer.remaining() == 0) {
                callback.onComplete(exchange, this);
                return;
            }
            int res = channel.write(buffer);
            if (res == 0) {
                this.buffer = new ByteBuffer[] { buffer };
                this.callback = callback;
                if (writeListener == null) {
                    initWriteListener();
                }
                channel.getWriteSetter().set(writeListener);
                channel.resumeWrites();
                return;
            }
        } while (buffer.hasRemaining());
        invokeOnComplete();
    } catch (IOException e) {
        invokeOnException(callback, e);
    }
}
Also used : StreamSinkChannel(org.xnio.channels.StreamSinkChannel) IOException(java.io.IOException)

Example 14 with StreamSinkChannel

use of org.xnio.channels.StreamSinkChannel in project undertow by undertow-io.

the class ServerSentEventHandler method handleRequest.

@Override
public void handleRequest(final HttpServerExchange exchange) throws Exception {
    exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/event-stream; charset=UTF-8");
    exchange.setPersistent(false);
    final StreamSinkChannel sink = exchange.getResponseChannel();
    if (!sink.flush()) {
        sink.getWriteSetter().set(ChannelListeners.flushingChannelListener(new ChannelListener<StreamSinkChannel>() {

            @Override
            public void handleEvent(StreamSinkChannel channel) {
                handleConnect(channel, exchange);
            }
        }, new ChannelExceptionHandler<StreamSinkChannel>() {

            @Override
            public void handleException(StreamSinkChannel channel, IOException exception) {
                IoUtils.safeClose(exchange.getConnection());
            }
        }));
        sink.resumeWrites();
    } else {
        exchange.dispatch(exchange.getIoThread(), new Runnable() {

            @Override
            public void run() {
                handleConnect(sink, exchange);
            }
        });
    }
}
Also used : ChannelListener(org.xnio.ChannelListener) StreamSinkChannel(org.xnio.channels.StreamSinkChannel) ChannelExceptionHandler(org.xnio.ChannelExceptionHandler) IOException(java.io.IOException)

Example 15 with StreamSinkChannel

use of org.xnio.channels.StreamSinkChannel in project undertow by undertow-io.

the class AjpReadListener method handleEvent.

public void handleEvent(final StreamSourceChannel channel) {
    if (connection.getOriginalSinkConduit().isWriteShutdown() || connection.getOriginalSourceConduit().isReadShutdown()) {
        safeClose(connection);
        channel.suspendReads();
        return;
    }
    PooledByteBuffer existing = connection.getExtraBytes();
    final PooledByteBuffer pooled = existing == null ? connection.getByteBufferPool().allocate() : existing;
    final ByteBuffer buffer = pooled.getBuffer();
    boolean free = true;
    boolean bytesRead = false;
    try {
        int res;
        do {
            if (existing == null) {
                buffer.clear();
                try {
                    res = channel.read(buffer);
                } catch (IOException e) {
                    UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
                    safeClose(connection);
                    return;
                }
            } else {
                res = buffer.remaining();
            }
            if (res == 0) {
                if (bytesRead && parseTimeoutUpdater != null) {
                    parseTimeoutUpdater.failedParse();
                }
                if (!channel.isReadResumed()) {
                    channel.getReadSetter().set(this);
                    channel.resumeReads();
                }
                return;
            }
            if (res == -1) {
                try {
                    channel.shutdownReads();
                    final StreamSinkChannel responseChannel = connection.getChannel().getSinkChannel();
                    responseChannel.shutdownWrites();
                    safeClose(connection);
                } catch (IOException e) {
                    UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
                    // fuck it, it's all ruined
                    safeClose(connection);
                    return;
                }
                return;
            }
            bytesRead = true;
            //TODO: we need to handle parse errors
            if (existing != null) {
                existing = null;
                connection.setExtraBytes(null);
            } else {
                buffer.flip();
            }
            int begin = buffer.remaining();
            if (httpServerExchange == null) {
                httpServerExchange = new HttpServerExchange(connection, maxEntitySize);
            }
            parser.parse(buffer, state, httpServerExchange);
            read += begin - buffer.remaining();
            if (buffer.hasRemaining()) {
                free = false;
                connection.setExtraBytes(pooled);
            }
            if (read > maxRequestSize) {
                UndertowLogger.REQUEST_LOGGER.requestHeaderWasTooLarge(connection.getPeerAddress(), maxRequestSize);
                safeClose(connection);
                return;
            }
        } while (!state.isComplete());
        if (parseTimeoutUpdater != null) {
            parseTimeoutUpdater.requestStarted();
        }
        if (state.prefix != AjpRequestParser.FORWARD_REQUEST) {
            if (state.prefix == AjpRequestParser.CPING) {
                UndertowLogger.REQUEST_LOGGER.debug("Received CPING, sending CPONG");
                handleCPing();
            } else if (state.prefix == AjpRequestParser.CPONG) {
                UndertowLogger.REQUEST_LOGGER.debug("Received CPONG, starting next request");
                state = new AjpRequestParseState();
                channel.getReadSetter().set(this);
                channel.resumeReads();
            } else {
                UndertowLogger.REQUEST_LOGGER.ignoringAjpRequestWithPrefixCode(state.prefix);
                safeClose(connection);
            }
            return;
        }
        // we remove ourselves as the read listener from the channel;
        // if the http handler doesn't set any then reads will suspend, which is the right thing to do
        channel.getReadSetter().set(null);
        channel.suspendReads();
        final HttpServerExchange httpServerExchange = this.httpServerExchange;
        final AjpServerResponseConduit responseConduit = new AjpServerResponseConduit(connection.getChannel().getSinkChannel().getConduit(), connection.getByteBufferPool(), httpServerExchange, new ConduitListener<AjpServerResponseConduit>() {

            @Override
            public void handleEvent(AjpServerResponseConduit channel) {
                Connectors.terminateResponse(httpServerExchange);
            }
        }, httpServerExchange.getRequestMethod().equals(Methods.HEAD));
        connection.getChannel().getSinkChannel().setConduit(responseConduit);
        connection.getChannel().getSourceChannel().setConduit(createSourceConduit(connection.getChannel().getSourceChannel().getConduit(), responseConduit, httpServerExchange));
        //we need to set the write ready handler. This allows the response conduit to wrap it
        responseConduit.setWriteReadyHandler(writeReadyHandler);
        try {
            connection.setSSLSessionInfo(state.createSslSessionInfo());
            httpServerExchange.setSourceAddress(state.createPeerAddress());
            httpServerExchange.setDestinationAddress(state.createDestinationAddress());
            if (scheme != null) {
                httpServerExchange.setRequestScheme(scheme);
            }
            if (state.attributes != null) {
                httpServerExchange.putAttachment(HttpServerExchange.REQUEST_ATTRIBUTES, state.attributes);
            }
            AjpRequestParseState oldState = state;
            state = null;
            this.httpServerExchange = null;
            httpServerExchange.setPersistent(true);
            if (recordRequestStartTime) {
                Connectors.setRequestStartTime(httpServerExchange);
            }
            connection.setCurrentExchange(httpServerExchange);
            if (connectorStatistics != null) {
                connectorStatistics.setup(httpServerExchange);
            }
            if (oldState.badRequest) {
                httpServerExchange.setStatusCode(StatusCodes.BAD_REQUEST);
                httpServerExchange.endExchange();
            } else {
                Connectors.executeRootHandler(connection.getRootHandler(), httpServerExchange);
            }
        } catch (Throwable t) {
            //TODO: we should attempt to return a 500 status code in this situation
            UndertowLogger.REQUEST_LOGGER.exceptionProcessingRequest(t);
            safeClose(connection);
        }
    } catch (Exception e) {
        UndertowLogger.REQUEST_LOGGER.exceptionProcessingRequest(e);
        safeClose(connection);
    } finally {
        if (free)
            pooled.close();
    }
}
Also used : StreamSinkChannel(org.xnio.channels.StreamSinkChannel) ConduitStreamSinkChannel(org.xnio.conduits.ConduitStreamSinkChannel) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) PooledByteBuffer(io.undertow.connector.PooledByteBuffer) IOException(java.io.IOException) HttpServerExchange(io.undertow.server.HttpServerExchange) PooledByteBuffer(io.undertow.connector.PooledByteBuffer)

Aggregations

StreamSinkChannel (org.xnio.channels.StreamSinkChannel)19 IOException (java.io.IOException)14 ChannelListener (org.xnio.ChannelListener)5 PooledByteBuffer (io.undertow.connector.PooledByteBuffer)4 HttpServerExchange (io.undertow.server.HttpServerExchange)4 ByteBuffer (java.nio.ByteBuffer)4 ChannelExceptionHandler (org.xnio.ChannelExceptionHandler)4 Channel (java.nio.channels.Channel)3 ByteBufferPool (io.undertow.connector.ByteBufferPool)2 TestHttpClient (io.undertow.testutils.TestHttpClient)2 StringWriteChannelListener (io.undertow.util.StringWriteChannelListener)2 InputStream (java.io.InputStream)2 Test (org.junit.Test)2 ConduitStreamSinkChannel (org.xnio.conduits.ConduitStreamSinkChannel)2 ClientCallback (io.undertow.client.ClientCallback)1 ClientExchange (io.undertow.client.ClientExchange)1 ClientResponse (io.undertow.client.ClientResponse)1 Http2HeadersStreamSinkChannel (io.undertow.protocols.http2.Http2HeadersStreamSinkChannel)1 HttpHandler (io.undertow.server.HttpHandler)1 HttpUpgradeListener (io.undertow.server.HttpUpgradeListener)1