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));
}
}
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();
}
}
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;
}
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;
}
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();
}
}
}
Aggregations