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
            }
        }
示例#2
0
        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));
        }
示例#3
0
        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));
        }
示例#4
0
        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();
            }
        }
示例#5
0
        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);
                }
            }
        }
示例#7
0
        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);
        }
示例#8
0
        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);
        }
示例#10
0
        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));
        }
示例#13
0
        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);
            }
        }
示例#14
0
        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);
            }
        }
示例#15
0
        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));
        }
示例#16
0
        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));
        }