Esempio n. 1
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));
        }
Esempio n. 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));
        }
Esempio n. 3
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");
                context.ReadFromAppSynchronously();
                PollWrite(context);
            }
            else
            {
                readResult.GetAwaiter().UnsafeOnCompleted(context.OnReadFromApp);
            }
        }
Esempio n. 4
0
        private void FlushRead(IoUringConnectionContext context)
        {
            var flushResult = context.Input.FlushAsync();

            context.FlushResult = flushResult;
            if (flushResult.IsCompleted)
            {
                Debug.WriteLine($"Flushed read from {(int)context.Socket} synchronously");
                context.FlushedToAppSynchronously();
                PollRead(context);
            }
            else
            {
                flushResult.GetAwaiter().UnsafeOnCompleted(context.OnFlushedToApp);
            }
        }
Esempio n. 5
0
        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");
                PollWrite(context);
                return;
            }

            Debug.WriteLine($"Completed write poll on {(int)context.Socket}");
            Write(context);
        }
Esempio n. 6
0
        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 != EAGAIN || -result != EWOULDBLOCK || -result != EINTR)
                {
                    throw new ErrnoException(-result);
                }

                Debug.WriteLine("Read for nothing");
            }
        }
Esempio n. 7
0
        private void CompleteWrite(IoUringConnectionContext context, int result)
        {
            try
            {
                if (result > 0)
                {
                    var lastWrite = context.LastWrite;
                    SequencePosition end;
                    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 != EAGAIN && -result != EWOULDBLOCK && -result != EINTR)
                    {
                        throw new ErrnoException(-result);
                    }

                    Debug.WriteLine("Wrote for nothing");
                }
            }
            finally
            {
                var writeHandles = context.WriteHandles;
                for (int i = 0; i < writeHandles.Length; i++)
                {
                    writeHandles[i].Dispose();
                }
            }
        }
Esempio n. 8
0
        private unsafe void Read(IoUringConnectionContext context)
        {
            var maxBufferSize = _memoryPool.MaxBufferSize;

            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));
        }
Esempio n. 9
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();
            }

            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));
        }
Esempio n. 10
0
        private void CompleteAcceptPoll()
        {
            var socket = _acceptSocket.Accept(out var endPoint);

            if (socket == -1)
            {
                Debug.WriteLine("Polled accept for nothing");
                goto AcceptAgain;
            }

            Debug.WriteLine($"Accepted {(int)socket}");
            // TODO: move server endpoint and memory pool to thread context
            IoUringConnectionContext context = new IoUringConnectionContext(socket, _endPoint, endPoint, _memoryPool, _threadContext);

            _connections[socket] = context;
            _acceptQueue.TryWrite(context);

            PollRead(context);
            ReadFromApp(context);

AcceptAgain:
            Accept();
        }