private void CompleteRead(IoUringConnectionContext context, int result) { if (result > 0) { Debug.WriteLine($"Read {result} bytes from {(int)context.Socket}"); context.Input.Advance(result); FlushRead(context); } else if (result < 0) { if (-result == ECONNRESET) { context.DisposeAsync(); } else if (-result != EAGAIN && -result != EWOULDBLOCK && -result != EINTR) { throw new ErrnoException(-result); } Debug.WriteLine("Read for nothing"); } else { // TODO: handle connection closed } }
private void PollRead(IoUringConnectionContext context) { var socket = context.Socket; Debug.WriteLine($"Adding read poll on {(int)socket}"); _ring.PreparePollAdd(socket, (ushort)POLLIN, Mask(socket, ReadPollMask)); }
private void PollWrite(IoUringConnectionContext context) { var socket = context.Socket; Debug.WriteLine($"Adding write poll on {(int)socket}"); _ring.PreparePollAdd(socket, (ushort)POLLOUT, Mask(socket, WritePollMask)); }
private void CompleteRead(IoUringConnectionContext context, int result) { var readHandles = context.ReadHandles; for (int i = 0; i < readHandles.Length; i++) { readHandles[i].Dispose(); } if (result > 0) { Debug.WriteLine($"Read {result} from {(int)context.Socket}"); context.Input.Advance(result); FlushRead(context); } else if (result < 0) { if (-result == ECONNRESET) { context.DisposeAsync(); } else if (-result != EAGAIN && -result != EWOULDBLOCK && -result != EINTR) { throw new ErrnoException(-result); } Debug.WriteLine($"Read completed with EAGAIN from {(int)context.Socket}"); } else { context.DisposeAsync(); } }
private void Read(IoUringConnectionContext context) { var writer = context.Input; var readHandles = context.ReadHandles; var readVecs = context.ReadVecs; var memory = writer.GetMemory(_maxBufferSize); var handle = memory.Pin(); readVecs[0].iov_base = handle.Pointer; readVecs[0].iov_len = memory.Length; readHandles[0] = handle; var socket = context.Socket; Debug.WriteLine($"Adding read on {(int)socket}"); Span <Submission> submissions = stackalloc Submission[2]; _ring.AcquireSubmissions(submissions); submissions[0].PreparePollAdd(socket, (ushort)POLLIN, options: SubmissionOption.Link); _ring.Release(submissions[0]); submissions[1].PrepareReadV(socket, readVecs, 1, 0, 0, Mask(socket, ReadMask)); _ring.Release(submissions[1]); }
private void CompleteWrite(IoUringConnectionContext context, int result) { var writeHandles = context.WriteHandles; for (int i = 0; i < writeHandles.Length; i++) { writeHandles[i].Dispose(); } var lastWrite = context.LastWrite; if (result >= 0) { SequencePosition end; if (result == 0) { Debug.WriteLine($"Wrote {result} bytes to {(int)context.Socket}"); end = lastWrite.Start; } else if (lastWrite.Length == result) { Debug.WriteLine($"Wrote all {result} bytes to {(int)context.Socket}"); end = lastWrite.End; } else { Debug.WriteLine($"Wrote some {result} bytes to {(int)context.Socket}"); end = lastWrite.GetPosition(result); } context.Output.AdvanceTo(end); ReadFromApp(context); } else if (result < 0) { if (-result == ECONNRESET || -result == EPIPE) { context.DisposeAsync(); } else if (-result == EAGAIN || -result == EWOULDBLOCK || -result == EINTR) { Debug.WriteLine("Wrote for nothing"); context.Output.AdvanceTo(lastWrite.Start); ReadFromApp(context); } else { throw new ErrnoException(-result); } } }
private void ReadFromApp(IoUringConnectionContext context) { var readResult = context.Output.ReadAsync(); context.ReadResult = readResult; if (readResult.IsCompletedSuccessfully) { Debug.WriteLine($"Read from app synchronously {(int)context.Socket}"); // unlikely context.ReadFromAppSynchronously(); Write(context); return; } readResult.GetAwaiter().UnsafeOnCompleted(context.OnReadFromApp); }
private void FlushRead(IoUringConnectionContext context) { var flushResult = context.Input.FlushAsync(); context.FlushResult = flushResult; if (flushResult.IsCompletedSuccessfully) { Debug.WriteLine($"Flushed to app synchronously {(int)context.Socket}"); // likely context.FlushedToAppSynchronously(); Read(context); return; } flushResult.GetAwaiter().UnsafeOnCompleted(context.OnFlushedToApp); }
private void FlushRead(IoUringConnectionContext context) { var flushResult = context.Input.FlushAsync(); context.FlushResult = flushResult; if (flushResult.IsCompleted) { // likely Debug.WriteLine($"Flushed read from {(int)context.Socket} synchronously"); context.FlushedToAppSynchronously(); ReadPoll(context); return; } flushResult.GetAwaiter().UnsafeOnCompleted(context.OnFlushedToApp); }
private void Write(IoUringConnectionContext context) { var result = context.ReadResult.Result; var buffer = result.Buffer; var socket = context.Socket; if ((buffer.IsEmpty && result.IsCompleted) || result.IsCanceled) { context.DisposeAsync(); _connections.TryRemove(socket, out _); return; } var writeHandles = context.WriteHandles; var writeVecs = context.WriteVecs; int ctr = 0; foreach (var memory in buffer) { var handle = memory.Pin(); writeVecs[ctr].iov_base = handle.Pointer; writeVecs[ctr].iov_len = memory.Length; writeHandles[ctr] = handle; ctr++; if (ctr == IoUringConnectionContext.WriteIOVecCount) { break; } } context.LastWrite = buffer; Debug.WriteLine($"Adding write on {(int)socket}"); Span <Submission> submissions = stackalloc Submission[2]; _ring.AcquireSubmissions(submissions); submissions[0].PreparePollAdd(socket, (ushort)POLLOUT, options: SubmissionOption.Link); _ring.Release(submissions[0]); submissions[1].PrepareWriteV(socket, writeVecs, ctr, 0, 0, Mask(socket, WriteMask)); _ring.Release(submissions[1]); }
private void CompleteWritePoll(IoUringConnectionContext context, int result) { if (result < 0) { if (-result != EAGAIN || -result != EINTR) { throw new ErrnoException(-result); } Debug.WriteLine("Polled write for nothing"); WritePoll(context); return; } Debug.WriteLine($"Completed write poll on {(int)context.Socket}"); Write(context); }
private void Read(IoUringConnectionContext context) { var writer = context.Input; var readHandles = context.ReadHandles; var readVecs = context.ReadVecs; var memory = writer.GetMemory(_maxBufferSize); var handle = memory.Pin(); readVecs[0].iov_base = handle.Pointer; readVecs[0].iov_len = memory.Length; readHandles[0] = handle; var socket = context.Socket; Debug.WriteLine($"Adding read on {(int)socket}"); _ring.PrepareReadV(socket, readVecs, 1, 0, 0, Mask(socket, ReadMask)); }
private void ReadFromApp(IoUringConnectionContext context) { var readResult = context.Output.ReadAsync(); context.ReadResult = readResult; if (readResult.IsCompleted) { Debug.WriteLine($"Read from app for {(int)context.Socket} synchronously"); IoUringTransportEventSource.Log.ReportSyncReadAsync(); context.ReadFromAppSynchronously(); PollWrite(context); } else { // likely IoUringTransportEventSource.Log.ReportAsyncReadAsync(); readResult.GetAwaiter().UnsafeOnCompleted(context.OnReadFromApp); } }
private void FlushRead(IoUringConnectionContext context) { var flushResult = context.Input.FlushAsync(); context.FlushResult = flushResult; if (flushResult.IsCompleted) { // likely Debug.WriteLine($"Flushed read from {(int)context.Socket} synchronously"); IoUringTransportEventSource.Log.ReportSyncFlushAsync(); context.FlushedToAppSynchronously(); PollRead(context); } else { IoUringTransportEventSource.Log.ReportAsyncFlushAsync(); flushResult.GetAwaiter().UnsafeOnCompleted(context.OnFlushedToApp); } }
private unsafe void Write(IoUringConnectionContext context) { var result = context.ReadResult.Result; var socket = context.Socket; if (result.IsCanceled || result.IsCompleted) { context.DisposeAsync(); _connections.Remove(socket); socket.Close(); return; } var writeHandles = context.WriteHandles; var writeVecs = context.WriteVecs; var buffer = result.Buffer; int ctr = 0; foreach (var memory in buffer) { var handle = memory.Pin(); writeVecs[ctr].iov_base = handle.Pointer; writeVecs[ctr].iov_len = memory.Length; writeHandles[ctr] = handle; ctr++; if (ctr == IoUringConnectionContext.WriteIOVecCount) { break; } } context.LastWrite = buffer; Debug.WriteLine($"Adding write on {(int)socket}"); _ring.PrepareWriteV(socket, writeVecs, ctr, 0, 0, Mask(socket, WriteMask)); }
private void CompleteConnect(IoUringConnectionContext context, int result) { var completion = context.ConnectCompletion; if (result < 0) { if (-result != EAGAIN || -result != EINTR) { context.ConnectCompletion = null; completion.TrySetException(new ErrnoException(-result)); } PollWrite(context); return; } PollRead(context); ReadFromApp(context); // TODO once data is available, another useless write poll is submitted context.LocalEndPoint = context.Socket.GetLocalAddress(); context.ConnectCompletion = null; completion.TrySetResult(context); }
private void WritePoll(IoUringConnectionContext context) { var socket = context.Socket; _ring.PreparePollAdd(socket, (ushort)POLLOUT, Mask(socket, WritePollMask)); }