protected override void DoWrite(ChannelOutboundBuffer input)
{
while (true)
{
int size = input.Count;
if (size == 0)
{
// All written
break;
}
long writtenBytes = 0;
bool done = false;
bool setOpWrite = false;
// Ensure the pending writes are made of ByteBufs only.
List<ArraySegment<byte>> nioBuffers = input.GetNioBuffers();
int nioBufferCnt = nioBuffers.Count;
long expectedWrittenBytes = input.NioBufferSize;
Socket socket = this.Socket;
// Always use nioBuffers() to workaround data-corruption.
// See https://github.com/netty/netty/issues/2761
switch (nioBufferCnt)
{
case 0:
// We have something else beside ByteBuffers to write so fallback to normal writes.
base.DoWrite(input);
return;
case 1:
// Only one ByteBuf so use non-gathering write
ArraySegment<byte> nioBuffer = nioBuffers[0];
for (int i = this.Configuration.WriteSpinCount - 1; i >= 0; i--)
{
SocketError errorCode;
int localWrittenBytes = socket.Send(nioBuffer.Array, nioBuffer.Offset, nioBuffer.Count,
SocketFlags.None, out errorCode);
if (errorCode != SocketError.Success && errorCode != SocketError.WouldBlock)
{
throw new SocketException((int) errorCode);
}
if (localWrittenBytes == 0)
{
setOpWrite = true;
break;
}
expectedWrittenBytes -= localWrittenBytes;
writtenBytes += localWrittenBytes;
if (expectedWrittenBytes == 0)
{
done = true;
break;
}
}
break;
default:
for (int i = this.Configuration.WriteSpinCount - 1; i >= 0; i--)
{
SocketError errorCode;
long localWrittenBytes = socket.Send(nioBuffers, SocketFlags.None, out errorCode);
if (errorCode != SocketError.Success && errorCode != SocketError.WouldBlock)
{
throw new SocketException((int) errorCode);
}
if (localWrittenBytes == 0)
{
setOpWrite = true;
break;
}
expectedWrittenBytes -= localWrittenBytes;
writtenBytes += localWrittenBytes;
if (expectedWrittenBytes == 0)
{
done = true;
break;
}
}
break;
}
// Release the fully written buffers, and update the indexes of the partially written buffer.
input.RemoveBytes(writtenBytes);
if (!done)
{
SocketChannelAsyncOperation asyncOperation = this.PrepareWriteOperation(nioBuffers);
// Did not write all buffers completely.
this.IncompleteWrite(setOpWrite, asyncOperation);
break;
}
}
}