use of java.nio.channels.ClosedChannelException in project undertow by undertow-io.
the class PipeliningBufferingStreamSinkConduit method write.
@Override
public int write(ByteBuffer src) throws IOException {
if (anyAreSet(state, SHUTDOWN)) {
throw new ClosedChannelException();
}
if (anyAreSet(state, FLUSHING)) {
boolean res = flushBuffer();
if (!res) {
return 0;
}
}
PooledByteBuffer pooled = this.buffer;
if (pooled == null) {
this.buffer = pooled = pool.allocate();
}
final ByteBuffer buffer = pooled.getBuffer();
if (buffer.remaining() > src.remaining()) {
int put = src.remaining();
buffer.put(src);
return put;
} else {
return (int) flushBufferWithUserData(new ByteBuffer[] { src }, 0, 1);
}
}
use of java.nio.channels.ClosedChannelException in project undertow by undertow-io.
the class ServerSentEventConnection method send.
/**
* Sends an event to the remote client
*
* @param data The event data
* @param event The event name
* @param id The event ID
* @param callback A callback that is notified on Success or failure
*/
public synchronized void send(String data, String event, String id, EventCallback callback) {
if (open == 0 || shutdown) {
if (callback != null) {
callback.failed(this, data, event, id, new ClosedChannelException());
}
return;
}
queue.add(new SSEData(event, data, id, callback));
sink.getIoThread().execute(new Runnable() {
@Override
public void run() {
synchronized (ServerSentEventConnection.this) {
if (pooled == null) {
fillBuffer();
writeListener.handleEvent(sink);
}
}
}
});
}
use of java.nio.channels.ClosedChannelException in project undertow by undertow-io.
the class ServerSentEventConnection method sendRetry.
/**
* Sends the 'retry' message to the client, instructing it how long to wait before attempting a reconnect.
*
* @param retry The retry time in milliseconds
* @param callback The callback that is notified on success or failure
*/
public synchronized void sendRetry(long retry, EventCallback callback) {
if (open == 0 || shutdown) {
if (callback != null) {
callback.failed(this, null, null, null, new ClosedChannelException());
}
return;
}
queue.add(new SSEData(retry, callback));
sink.getIoThread().execute(new Runnable() {
@Override
public void run() {
synchronized (ServerSentEventConnection.this) {
if (pooled == null) {
fillBuffer();
writeListener.handleEvent(sink);
}
}
}
});
}
use of java.nio.channels.ClosedChannelException in project undertow by undertow-io.
the class AbstractFramedChannel method receive.
/**
* receive method, returns null if no frame is ready. Otherwise returns a
* channel that can be used to read the frame contents.
* <p>
* Calling this method can also have the side effect of making additional data available to
* existing source channels. In general if you suspend receives or don't have some other way
* of calling this method then it can prevent frame channels for being fully consumed.
*/
public synchronized R receive() throws IOException {
if (readChannelDone && receiver == null) {
//however it is much simpler just to have it here
if (readData != null) {
readData.close();
readData = null;
}
channel.getSourceChannel().suspendReads();
channel.getSourceChannel().shutdownReads();
return null;
}
ReferenceCountedPooled pooled = this.readData;
boolean hasData;
if (pooled == null) {
pooled = allocateReferenceCountedBuffer();
if (pooled == null) {
return null;
}
hasData = false;
} else if (pooled.isFreed()) {
//we attempt to re-used an existing buffer
if (!pooled.tryUnfree()) {
pooled = allocateReferenceCountedBuffer();
if (pooled == null) {
return null;
}
} else {
pooled.getBuffer().limit(pooled.getBuffer().capacity());
}
hasData = false;
} else {
hasData = pooled.getBuffer().hasRemaining();
}
boolean forceFree = false;
int read = 0;
try {
if (!hasData) {
pooled.getBuffer().clear();
read = channel.getSourceChannel().read(pooled.getBuffer());
if (read == 0) {
//no data, we just free the buffer
forceFree = true;
return null;
} else if (read == -1) {
forceFree = true;
readChannelDone = true;
lastDataRead();
return null;
} else if (isLastFrameReceived() && frameDataRemaining == 0) {
//we got data, although we should have received the last frame
forceFree = true;
markReadsBroken(new ClosedChannelException());
}
pooled.getBuffer().flip();
}
if (frameDataRemaining > 0) {
if (frameDataRemaining >= pooled.getBuffer().remaining()) {
frameDataRemaining -= pooled.getBuffer().remaining();
if (receiver != null) {
//we still create a pooled view, this means that if the buffer is still active we can re-used it
//which prevents attacks based on sending lots of small fragments
ByteBuffer buf = pooled.getBuffer().duplicate();
pooled.getBuffer().position(pooled.getBuffer().limit());
PooledByteBuffer frameData = pooled.createView(buf);
receiver.dataReady(null, frameData);
} else {
//we are dropping a frame
pooled.close();
readData = null;
}
if (frameDataRemaining == 0) {
receiver = null;
}
return null;
} else {
ByteBuffer buf = pooled.getBuffer().duplicate();
buf.limit((int) (buf.position() + frameDataRemaining));
pooled.getBuffer().position((int) (pooled.getBuffer().position() + frameDataRemaining));
frameDataRemaining = 0;
PooledByteBuffer frameData = pooled.createView(buf);
if (receiver != null) {
receiver.dataReady(null, frameData);
} else {
//we are dropping the frame
frameData.close();
}
receiver = null;
}
//and not by the selector mechanism
return null;
}
FrameHeaderData data = parseFrame(pooled.getBuffer());
if (data != null) {
PooledByteBuffer frameData;
if (data.getFrameLength() >= pooled.getBuffer().remaining()) {
frameDataRemaining = data.getFrameLength() - pooled.getBuffer().remaining();
frameData = pooled.createView(pooled.getBuffer().duplicate());
pooled.getBuffer().position(pooled.getBuffer().limit());
} else {
ByteBuffer buf = pooled.getBuffer().duplicate();
buf.limit((int) (buf.position() + data.getFrameLength()));
pooled.getBuffer().position((int) (pooled.getBuffer().position() + data.getFrameLength()));
frameData = pooled.createView(buf);
}
AbstractFramedStreamSourceChannel<?, ?, ?> existing = data.getExistingChannel();
if (existing != null) {
if (data.getFrameLength() > frameData.getBuffer().remaining()) {
receiver = (R) existing;
}
existing.dataReady(data, frameData);
if (isLastFrameReceived()) {
handleLastFrame(existing);
}
return null;
} else {
boolean moreData = data.getFrameLength() > frameData.getBuffer().remaining();
R newChannel = createChannel(data, frameData);
if (newChannel != null) {
if (!newChannel.isComplete()) {
receivers.add(newChannel);
}
if (moreData) {
receiver = newChannel;
}
if (isLastFrameReceived()) {
handleLastFrame(newChannel);
}
} else {
frameData.close();
}
return newChannel;
}
}
return null;
} catch (IOException | RuntimeException e) {
//something has code wrong with parsing, close the read side
//we don't close the write side, as the underlying implementation will most likely want to send an error
markReadsBroken(e);
forceFree = true;
throw e;
} finally {
//which will make readData null
if (readData != null) {
if (!pooled.getBuffer().hasRemaining() || forceFree) {
if (pooled.getBuffer().limit() * 2 > pooled.getBuffer().capacity() || forceFree) {
//if we have used more than half the buffer we don't allow it to be re-aquired
readData = null;
}
//even though this is freed we may un-free it if we get a new packet
//this prevents many small reads resulting in a large number of allocated buffers
pooled.close();
}
}
}
}
use of java.nio.channels.ClosedChannelException in project undertow by undertow-io.
the class AbstractFramedChannel method close.
/**
* Forcibly closes the {@link io.undertow.server.protocol.framed.AbstractFramedChannel}.
*/
@Override
public void close() throws IOException {
if (UndertowLogger.REQUEST_IO_LOGGER.isDebugEnabled()) {
UndertowLogger.REQUEST_IO_LOGGER.debugf(new ClosedChannelException(), "Channel %s is being closed", this);
}
safeClose(channel);
if (readData != null) {
readData.close();
readData = null;
}
}
Aggregations