private void write0(SctpChannelImpl channel) { boolean open = true; boolean addOpWrite = false; boolean removeOpWrite = false; long writtenBytes = 0; final SctpSendBufferPool sendBufferPool = this.sendBufferPool; final com.sun.nio.sctp.SctpChannel ch = channel.channel; final Queue<MessageEvent> writeBuffer = channel.writeBuffer; final int writeSpinCount = channel.getConfig().getWriteSpinCount(); synchronized (channel.writeLock) { channel.inWriteNowLoop = true; for (; ; ) { MessageEvent evt = channel.currentWriteEvent; SendBuffer buf; if (evt == null) { if ((channel.currentWriteEvent = evt = writeBuffer.poll()) == null) { removeOpWrite = true; channel.writeSuspended = false; break; } channel.currentWriteBuffer = buf = sendBufferPool.acquire(evt.getMessage()); } else { buf = channel.currentWriteBuffer; } ChannelFuture future = evt.getFuture(); try { long localWrittenBytes = 0; for (int i = writeSpinCount; i > 0; i--) { localWrittenBytes = buf.transferTo(ch); if (localWrittenBytes != 0) { writtenBytes += localWrittenBytes; break; } if (buf.finished()) { break; } } if (buf.finished()) { // Successful write - proceed to the next message. buf.release(); channel.currentWriteEvent = null; channel.currentWriteBuffer = null; evt = null; buf = null; future.setSuccess(); } else { // Not written fully - perhaps the kernel buffer is full. addOpWrite = true; channel.writeSuspended = true; if (localWrittenBytes > 0) { // Notify progress listeners if necessary. future.setProgress(localWrittenBytes, buf.writtenBytes(), buf.totalBytes()); } break; } } catch (AsynchronousCloseException e) { // Doesn't need a user attention - ignore. } catch (Throwable t) { buf.release(); channel.currentWriteEvent = null; channel.currentWriteBuffer = null; buf = null; evt = null; future.setFailure(t); fireExceptionCaught(channel, t); if (t instanceof IOException) { open = false; close(channel, succeededFuture(channel)); } } } channel.inWriteNowLoop = false; } if (open) { if (addOpWrite) { setOpWrite(channel); } else if (removeOpWrite) { clearOpWrite(channel); } } fireWriteComplete(channel, writtenBytes); }
private boolean read(SelectionKey k) { final SctpChannelImpl channel = (SctpChannelImpl) k.attachment(); final ReceiveBufferSizePredictor predictor = channel.getConfig().getReceiveBufferSizePredictor(); final int predictedRecvBufSize = predictor.nextReceiveBufferSize(); boolean messageReceived = false; boolean failure = true; MessageInfo messageInfo = null; ByteBuffer bb = recvBufferPool.acquire(predictedRecvBufSize); try { messageInfo = channel.channel.receive(bb, null, notificationHandler); if (messageInfo != null) { messageReceived = true; if (!messageInfo.isUnordered()) { failure = false; } else { if (logger.isErrorEnabled()) { logger.error("Received unordered SCTP Packet"); } failure = true; } } else { messageReceived = false; failure = false; } } catch (ClosedChannelException e) { // Can happen, and does not need a user attention. } catch (Throwable t) { fireExceptionCaught(channel, t); } if (messageReceived) { bb.flip(); final ChannelBufferFactory bufferFactory = channel.getConfig().getBufferFactory(); final int receivedBytes = bb.remaining(); final ChannelBuffer buffer = bufferFactory.getBuffer(receivedBytes); buffer.setBytes(0, bb); buffer.writerIndex(receivedBytes); recvBufferPool.release(bb); // Update the predictor. predictor.previousReceiveBufferSize(receivedBytes); // Fire the event. fireMessageReceived(channel, new SctpFrame(messageInfo, buffer), messageInfo.address()); } else { recvBufferPool.release(bb); } if (channel.channel.isBlocking() && !messageReceived || failure) { k.cancel(); // Some JDK implementations run into an infinite loop without this. close(channel, succeededFuture(channel)); return false; } return true; }