Search in sources :

Example 1 with PooledByteBuffer

use of io.undertow.connector.PooledByteBuffer in project core-ng-project by neowu.

the class RequestBodyReader method read.

public void read(StreamSourceChannel channel) {
    try (PooledByteBuffer poolItem = exchange.getConnection().getByteBufferPool().allocate()) {
        ByteBuffer buffer = poolItem.getBuffer();
        int bytesRead;
        while (true) {
            buffer.clear();
            bytesRead = channel.read(buffer);
            if (bytesRead <= 0)
                break;
            buffer.flip();
            ensureCapacity(bytesRead);
            buffer.get(body, position, bytesRead);
            position += bytesRead;
        }
        if (bytesRead == -1) {
            if (contentLength >= 0 && position < body.length) {
                throw Exceptions.error("body ends prematurely, expected={}, actual={}", contentLength, position);
            } else if (body == null) {
                // without content length and has no body
                body = new byte[0];
            }
            complete = true;
            exchange.putAttachment(REQUEST_BODY, new RequestBody(body, null));
        }
    } catch (Throwable e) {
        // catch all errors during IO, to pass error to action log
        IoUtils.safeClose(channel);
        complete = true;
        exchange.putAttachment(REQUEST_BODY, new RequestBody(null, e));
    }
}
Also used : PooledByteBuffer(io.undertow.connector.PooledByteBuffer) PooledByteBuffer(io.undertow.connector.PooledByteBuffer) ByteBuffer(java.nio.ByteBuffer)

Example 2 with PooledByteBuffer

use of io.undertow.connector.PooledByteBuffer in project undertow by undertow-io.

the class PathResource method serveImpl.

private void serveImpl(final Sender sender, final HttpServerExchange exchange, final long start, final long end, final IoCallback callback, final boolean range) {
    abstract class BaseFileTask implements Runnable {

        protected volatile FileChannel fileChannel;

        protected boolean openFile() {
            try {
                fileChannel = FileChannel.open(file, StandardOpenOption.READ);
                if (range) {
                    fileChannel.position(start);
                }
            } catch (NoSuchFileException e) {
                exchange.setStatusCode(StatusCodes.NOT_FOUND);
                callback.onException(exchange, sender, e);
                return false;
            } catch (IOException e) {
                exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
                callback.onException(exchange, sender, e);
                return false;
            }
            return true;
        }
    }
    class ServerTask extends BaseFileTask implements IoCallback {

        private PooledByteBuffer pooled;

        long remaining = end - start + 1;

        @Override
        public void run() {
            if (range && remaining == 0) {
                // we are done
                if (pooled != null) {
                    pooled.close();
                    pooled = null;
                }
                IoUtils.safeClose(fileChannel);
                callback.onComplete(exchange, sender);
                return;
            }
            if (fileChannel == null) {
                if (!openFile()) {
                    return;
                }
                pooled = exchange.getConnection().getByteBufferPool().allocate();
            }
            if (pooled != null) {
                ByteBuffer buffer = pooled.getBuffer();
                try {
                    buffer.clear();
                    int res = fileChannel.read(buffer);
                    if (res == -1) {
                        // we are done
                        pooled.close();
                        IoUtils.safeClose(fileChannel);
                        callback.onComplete(exchange, sender);
                        return;
                    }
                    buffer.flip();
                    if (range) {
                        if (buffer.remaining() > remaining) {
                            buffer.limit((int) (buffer.position() + remaining));
                        }
                        remaining -= buffer.remaining();
                    }
                    sender.send(buffer, this);
                } catch (IOException e) {
                    onException(exchange, sender, e);
                }
            }
        }

        @Override
        public void onComplete(final HttpServerExchange exchange, final Sender sender) {
            if (exchange.isInIoThread()) {
                exchange.dispatch(this);
            } else {
                run();
            }
        }

        @Override
        public void onException(final HttpServerExchange exchange, final Sender sender, final IOException exception) {
            UndertowLogger.REQUEST_IO_LOGGER.ioException(exception);
            if (pooled != null) {
                pooled.close();
                pooled = null;
            }
            IoUtils.safeClose(fileChannel);
            if (!exchange.isResponseStarted()) {
                exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
            }
            callback.onException(exchange, sender, exception);
        }
    }
    class TransferTask extends BaseFileTask {

        @Override
        public void run() {
            if (!openFile()) {
                return;
            }
            sender.transferFrom(fileChannel, new IoCallback() {

                @Override
                public void onComplete(HttpServerExchange exchange, Sender sender) {
                    try {
                        IoUtils.safeClose(fileChannel);
                    } finally {
                        callback.onComplete(exchange, sender);
                    }
                }

                @Override
                public void onException(HttpServerExchange exchange, Sender sender, IOException exception) {
                    try {
                        IoUtils.safeClose(fileChannel);
                    } finally {
                        callback.onException(exchange, sender, exception);
                    }
                }
            });
        }
    }
    BaseFileTask task;
    try {
        task = manager.getTransferMinSize() > Files.size(file) || range ? new ServerTask() : new TransferTask();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    if (exchange.isInIoThread()) {
        exchange.dispatch(task);
    } else {
        task.run();
    }
}
Also used : FileChannel(java.nio.channels.FileChannel) NoSuchFileException(java.nio.file.NoSuchFileException) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) PooledByteBuffer(io.undertow.connector.PooledByteBuffer) HttpServerExchange(io.undertow.server.HttpServerExchange) Sender(io.undertow.io.Sender) PooledByteBuffer(io.undertow.connector.PooledByteBuffer) IoCallback(io.undertow.io.IoCallback)

Example 3 with PooledByteBuffer

use of io.undertow.connector.PooledByteBuffer in project undertow by undertow-io.

the class PerMessageDeflateFunction method transformForRead.

@Override
public synchronized PooledByteBuffer transformForRead(PooledByteBuffer pooledBuffer, StreamSourceFrameChannel channel, boolean lastFragmentOfMessage) throws IOException {
    if ((channel.getRsv() & 4) == 0) {
        // rsv bit not set, this message is not compressed
        return pooledBuffer;
    }
    // first pass
    PooledByteBuffer output = allocateBufferWithArray(channel.getWebSocketChannel(), 0);
    PooledByteBuffer inputBuffer = null;
    if (currentReadChannel != null && currentReadChannel != channel) {
        // new channel, we did not get a last fragment message which can happens sometimes
        decompress.setInput(TAIL);
        output = decompress(channel.getWebSocketChannel(), output);
    }
    ByteBuffer buffer = pooledBuffer.getBuffer();
    if (buffer.hasArray()) {
        decompress.setInput(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining());
    } else {
        inputBuffer = toArrayBacked(buffer, channel.getWebSocketChannel().getBufferPool());
        decompress.setInput(inputBuffer.getBuffer().array(), inputBuffer.getBuffer().arrayOffset() + inputBuffer.getBuffer().position(), inputBuffer.getBuffer().remaining());
    }
    try {
        output = decompress(channel.getWebSocketChannel(), output);
    } finally {
        // Free the buffer AFTER decompression so it doesn't get re-used out from under us
        IoUtils.safeClose(inputBuffer, pooledBuffer);
    }
    if (lastFragmentOfMessage) {
        decompress.setInput(TAIL);
        output = decompress(channel.getWebSocketChannel(), output);
        currentReadChannel = null;
    } else {
        currentReadChannel = channel;
    }
    output.getBuffer().flip();
    return output;
}
Also used : ImmediatePooledByteBuffer(io.undertow.util.ImmediatePooledByteBuffer) PooledByteBuffer(io.undertow.connector.PooledByteBuffer) ByteBuffer(java.nio.ByteBuffer) ImmediatePooledByteBuffer(io.undertow.util.ImmediatePooledByteBuffer) PooledByteBuffer(io.undertow.connector.PooledByteBuffer)

Example 4 with PooledByteBuffer

use of io.undertow.connector.PooledByteBuffer in project undertow by undertow-io.

the class PerMessageDeflateFunction method transformForWrite.

@Override
public synchronized PooledByteBuffer transformForWrite(PooledByteBuffer pooledBuffer, StreamSinkFrameChannel channel, boolean lastFrame) throws IOException {
    ByteBuffer buffer = pooledBuffer.getBuffer();
    PooledByteBuffer inputBuffer = null;
    if (buffer.hasArray()) {
        compress.setInput(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining());
    } else {
        inputBuffer = toArrayBacked(buffer, channel.getWebSocketChannel().getBufferPool());
        compress.setInput(inputBuffer.getBuffer().array(), inputBuffer.getBuffer().arrayOffset() + inputBuffer.getBuffer().position(), inputBuffer.getBuffer().remaining());
    }
    // first pass
    PooledByteBuffer output = allocateBufferWithArray(channel.getWebSocketChannel(), 0);
    ByteBuffer outputBuffer = output.getBuffer();
    boolean onceOnly = true;
    try {
        while ((!compress.needsInput() && !compress.finished()) || !outputBuffer.hasRemaining() || (onceOnly && lastFrame)) {
            onceOnly = false;
            // we need the hasRemaining check, because if the inflater fails to flush needsInput() will return false but it may have flushed an incomplete deflate block
            if (!outputBuffer.hasRemaining()) {
                output = largerBuffer(output, channel.getWebSocketChannel(), outputBuffer.capacity() * 2);
                outputBuffer = output.getBuffer();
            }
            int n = compress.deflate(outputBuffer.array(), outputBuffer.arrayOffset() + outputBuffer.position(), outputBuffer.remaining(), lastFrame ? Deflater.SYNC_FLUSH : Deflater.NO_FLUSH);
            outputBuffer.position(outputBuffer.position() + n);
        }
    } finally {
        // Free the buffer AFTER compression so it doesn't get re-used out from under us
        IoUtils.safeClose(pooledBuffer, inputBuffer);
    }
    if (lastFrame) {
        outputBuffer.put((byte) 0);
        if (!compressContextTakeover) {
            compress.reset();
        }
    }
    outputBuffer.flip();
    return output;
}
Also used : ImmediatePooledByteBuffer(io.undertow.util.ImmediatePooledByteBuffer) PooledByteBuffer(io.undertow.connector.PooledByteBuffer) ByteBuffer(java.nio.ByteBuffer) ImmediatePooledByteBuffer(io.undertow.util.ImmediatePooledByteBuffer) PooledByteBuffer(io.undertow.connector.PooledByteBuffer)

Example 5 with PooledByteBuffer

use of io.undertow.connector.PooledByteBuffer in project undertow by undertow-io.

the class AsyncWebSocketHttpServerExchange method readRequestData.

@Override
public IoFuture<byte[]> readRequestData() {
    final ByteArrayOutputStream data = new ByteArrayOutputStream();
    final PooledByteBuffer pooled = exchange.getConnection().getByteBufferPool().allocate();
    final ByteBuffer buffer = pooled.getBuffer();
    final StreamSourceChannel channel = exchange.getRequestChannel();
    int res;
    for (; ; ) {
        try {
            res = channel.read(buffer);
            if (res == -1) {
                return new FinishedIoFuture<>(data.toByteArray());
            } else if (res == 0) {
                // callback
                final FutureResult<byte[]> future = new FutureResult<>();
                channel.getReadSetter().set(new ChannelListener<StreamSourceChannel>() {

                    @Override
                    public void handleEvent(final StreamSourceChannel channel) {
                        int res;
                        try {
                            res = channel.read(buffer);
                            if (res == -1) {
                                future.setResult(data.toByteArray());
                                channel.suspendReads();
                                return;
                            } else if (res == 0) {
                                return;
                            } else {
                                buffer.flip();
                                while (buffer.hasRemaining()) {
                                    data.write(buffer.get());
                                }
                                buffer.clear();
                            }
                        } catch (IOException e) {
                            future.setException(e);
                        }
                    }
                });
                channel.resumeReads();
                return future.getIoFuture();
            } else {
                buffer.flip();
                while (buffer.hasRemaining()) {
                    data.write(buffer.get());
                }
                buffer.clear();
            }
        } catch (IOException e) {
            final FutureResult<byte[]> future = new FutureResult<>();
            future.setException(e);
            return future.getIoFuture();
        }
    }
}
Also used : StreamSourceChannel(org.xnio.channels.StreamSourceChannel) FinishedIoFuture(org.xnio.FinishedIoFuture) ChannelListener(org.xnio.ChannelListener) FutureResult(org.xnio.FutureResult) PooledByteBuffer(io.undertow.connector.PooledByteBuffer) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) PooledByteBuffer(io.undertow.connector.PooledByteBuffer)

Aggregations

PooledByteBuffer (io.undertow.connector.PooledByteBuffer)58 ByteBuffer (java.nio.ByteBuffer)47 IOException (java.io.IOException)29 ImmediatePooledByteBuffer (io.undertow.util.ImmediatePooledByteBuffer)10 StreamSourceChannel (org.xnio.channels.StreamSourceChannel)8 HttpServerExchange (io.undertow.server.HttpServerExchange)7 ClosedChannelException (java.nio.channels.ClosedChannelException)7 ByteArrayOutputStream (java.io.ByteArrayOutputStream)5 ChannelListener (org.xnio.ChannelListener)5 HttpHandler (io.undertow.server.HttpHandler)4 HeaderMap (io.undertow.util.HeaderMap)4 StreamSinkChannel (org.xnio.channels.StreamSinkChannel)4 SendFrameHeader (io.undertow.server.protocol.framed.SendFrameHeader)3 HttpString (io.undertow.util.HttpString)3 ByteBufferPool (io.undertow.connector.ByteBufferPool)2 HeaderValues (io.undertow.util.HeaderValues)2 InterruptedIOException (java.io.InterruptedIOException)2 CharBuffer (java.nio.CharBuffer)2 CharsetDecoder (java.nio.charset.CharsetDecoder)2 IoCallback (io.undertow.io.IoCallback)1