Example #1
0
        public unsafe void Send(long sequence, RIO_BUF *bufferSegmentDescriptor, bool flush)
        {
            var lockTaken = false;
            var spinlock  = new SpinLock();

            try
            {
                spinlock.Enter(ref lockTaken);

                var rioSendFlags = flush ? RIO_SEND_FLAGS.NONE : RIO_SEND_FLAGS.DEFER;

                rioSendFlags |= RIO_SEND_FLAGS.DONT_NOTIFY;

                if (!WinSock.Extensions.Send(_handle, bufferSegmentDescriptor, 1, rioSendFlags, sequence))
                {
                    WinSock.ThrowLastWsaError();
                }
            }
            finally
            {
                if (lockTaken)
                {
                    spinlock.Exit();
                }
            }
        }
Example #2
0
 private unsafe void FlushReceives()
 {
     if (!WinSock.Extensions.Receive(_handle, null, 0, RIO_RECEIVE_FLAGS.COMMIT_ONLY, 0))
     {
         WinSock.ThrowLastWsaError();
     }
 }
Example #3
0
 private void Listen()
 {
     if (WinSock.listen(_listeningSocket, WinSock.Consts.SOMAXCONN) != 0)
     {
         WinSock.ThrowLastWsaError();
     }
 }
Example #4
0
        private void ListenAndRunAcceptLoop(ManualResetEventSlim listeningSignal)
        {
            Thread.CurrentThread.Name = "Server Listening Worker";

            if (!Bind(_listeningSocket, _listeningPort))
            {
                return;
            }

            ListeningPort = GetSocketPort();

            Listen();

            listeningSignal.Set();

            while (_isListening)
            {
                var acceptSocket = WinSock.accept(_listeningSocket, IntPtr.Zero, IntPtr.Zero);
                if (acceptSocket == (IntPtr)WinSock.Consts.INVALID_SOCKET)
                {
                    var lastErrorCode = WinSock.WSAGetLastError();
                    if (lastErrorCode == WinSock.Consts.WSAEINTR)
                    {
                        break;
                    }

                    WinSock.ThrowLastWsaError();
                    continue;
                }

                InitClientSession(acceptSocket);
            }
        }
Example #5
0
 private unsafe void FlushSends()
 {
     if (!WinSock.Extensions.Send(_handle, null, 0, RIO_SEND_FLAGS.COMMIT_ONLY, 0))
     {
         WinSock.ThrowLastWsaError();
     }
 }
Example #6
0
        internal int TryGetCompletionResults(CancellationToken cancellationToken, RIO_RESULT *results, int maxCompletionResults)
        {
            var completionQueue = QueueHandle;

            var spinwait = new SpinWait();

            while (!cancellationToken.IsCancellationRequested)
            {
                var resultCount = WinSock.Extensions.DequeueCompletion(completionQueue, results, (uint)maxCompletionResults);

                if (resultCount == 0)
                {
                    spinwait.SpinOnce();
                    continue;
                }

                if (resultCount == WinSock.Consts.RIO_CORRUPT_CQ)
                {
                    WinSock.ThrowLastWsaError();
                    break;
                }

                return((int)resultCount);
            }

            return(0);
        }
Example #7
0
        public unsafe void Receive(RioBufferSegment *bufferSegment, int bufferSegmentId, bool flush)
        {
            var lockTaken = false;
            var spinlock  = new SpinLock();

            try
            {
                spinlock.Enter(ref lockTaken);

                var rioReceiveFlags = flush ? RIO_RECEIVE_FLAGS.NONE : RIO_RECEIVE_FLAGS.DEFER;

                rioReceiveFlags |= RIO_RECEIVE_FLAGS.DONT_NOTIFY;

                if (!WinSock.Extensions.Receive(_handle, bufferSegment->GetRioBufferDescriptor(), 1, rioReceiveFlags, bufferSegmentId))
                {
                    WinSock.ThrowLastWsaError();
                }
            }
            finally
            {
                if (lockTaken)
                {
                    spinlock.Exit();
                }
            }
        }
Example #8
0
        public unsafe void Send(long sequence, RIO_BUF *bufferSegmentDescriptor, bool flush)
        {
            var rioSendFlags = flush ? RIO_SEND_FLAGS.NONE : RIO_SEND_FLAGS.DEFER;

            if (!WinSock.Extensions.Send(_handle, bufferSegmentDescriptor, 1, rioSendFlags, sequence))
            {
                WinSock.ThrowLastWsaError();
            }
        }
Example #9
0
        public unsafe void Receive(RioBufferSegment *bufferSegment, int bufferSegmentId, bool flush)
        {
            var rioSendFlags = flush ? RIO_RECEIVE_FLAGS.NONE : RIO_RECEIVE_FLAGS.DEFER;

            if (!WinSock.Extensions.Receive(_handle, bufferSegment->GetRioBufferDescriptor(), 1, rioSendFlags, bufferSegmentId))
            {
                WinSock.ThrowLastWsaError();
            }
        }
Example #10
0
 public RioCompletionQueue(int size)
 {
     // we want to handle the polling manually, so we don't have to pass any RIO_NOTIFICATION_COMPLETION
     QueueHandle = WinSock.Extensions.CreateCompletionQueue((uint)size);
     if (QueueHandle.IsInvalid)
     {
         WinSock.ThrowLastWsaError();
     }
 }
Example #11
0
        public unsafe void Send(RioBuffer buffer)
        {
            var requestContextKey = new RioRequestContextKey(buffer.Id, RioRequestType.Send);

            if (!WinSock.Extensions.Send(_handle, buffer.BufferDescriptor, 1, RIO_SEND_FLAGS.NONE, requestContextKey.ToRioRequestCorrelationId()))
            {
                WinSock.ThrowLastWsaError();
            }
        }
Example #12
0
        public UnmanagedRioBuffer(int bufferCount, int bufferLength)
        {
            // Example with:
            //  - Length = 2 entries
            //  - BufferLength = 1024 bytes
            //  - Entry of type T having
            //     - A 1 byte field
            //     - A 4 bytes field
            //     - A 4 bytes field
            //
            // |-- Padding --|- Entry reserved space --------------------------------------------------------|- Entry reserved space  -------------------------------------------------------|-- Padding --|
            // |  128 bytes  |                                                                               |                                                                               |  128 bytes  |
            // |             |- Entry #1 -----------------------------------------------|                    |- Entry #2 -----------------------------------------------|                    |             |
            // |             |                                                          |                    |                                                          |                    |             |
            // |             |           |- RIO_BUF ------------------------------------|- Data - ... -------|           |- RIO_BUF ------------------------------------|- Data - ... -------|             |
            // |             |           |                                              |                    |           |                                              |                    |             |
            //[0]           [128]       [137]                 [145]       [149]       [153]                [1177]      [1186]                 [1194]      [1198]      [1202]                 |             |
            // |             +-----------+----------------------+-----------+-----------+-------- ... -------+-----------+----------------------+-----------+-----------+-------- ... -------+             |
            // |             | Fields    | BufferId             | Offset    | Length    | Buffer segment     | Fields    | BufferId             | Offset    | Length    | Buffer segment     |             |
            // |             |           | IntPtr               | int       | int       | bytes              |           | IntPtr               | int       | int       | bytes              |             |
            // |             | 9 bytes   | 8 bytes              | 4         | 4         | 1024               | 9 bytes   | 8 bytes              | 4         | 4         | 1024               |             |
            // |             +-----------+----------------------+-----------+-----------+-------- ... -------+-----------+----------------------+-----------+-----------+-------- ... -------+             |
            // |             |                                  | 153       | 1024      |                                                       | 1202      | 1024      |
            // |                                                  +---------------------^                                                         +---------------------^

            Length = bufferCount;
            var entryLength = sizeof(T);

            EntryReservedSpaceSize = entryLength + bufferLength;

            // Padding is added at the start and the end of the buffer to prevent false sharing when using this UnmanagedRioBuffer
            // as the underlying ring buffer memory of an unmanaged disruptor
            var totalBufferLength = (uint)(_padding + bufferCount * EntryReservedSpaceSize + _padding);

            const int allocationType = Kernel32.Consts.MEM_COMMIT | Kernel32.Consts.MEM_RESERVE;

            _buffer = Kernel32.VirtualAlloc(IntPtr.Zero, totalBufferLength, allocationType, Kernel32.Consts.PAGE_READWRITE);

            _bufferId = WinSock.Extensions.RegisterBuffer(_buffer, totalBufferLength);
            if (_bufferId == WinSock.Consts.RIO_INVALID_BUFFERID)
            {
                WinSock.ThrowLastWsaError();
            }

            var currentEntry = FirstEntry = (T *)((byte *)_buffer.ToPointer() + _padding);

            for (var i = 0; i < bufferCount; i++)
            {
                var bufferDescriptor = currentEntry->GetRioBufferDescriptor();

                bufferDescriptor->BufferId = _bufferId;
                bufferDescriptor->Offset   = _padding + i * EntryReservedSpaceSize + sizeof(T);
                bufferDescriptor->Length   = bufferLength;

                currentEntry = (T *)((byte *)(currentEntry + 1) + bufferLength);
            }
        }
Example #13
0
        public static RioRequestQueue Create(int correlationId, IntPtr socket, IRioCompletionQueue sendingCompletionQueue, uint maxOutstandingSends, IRioCompletionQueue receivingCompletionQueue, uint maxOutstandingReceives)
        {
            var requestQueue = WinSock.Extensions.CreateRequestQueue(socket, maxOutstandingReceives, 1, maxOutstandingSends, 1, receivingCompletionQueue.QueueHandle, sendingCompletionQueue.QueueHandle, correlationId);

            if (requestQueue == IntPtr.Zero)
            {
                WinSock.ThrowLastWsaError();
            }

            return(new RioRequestQueue(requestQueue));
        }
Example #14
0
        private unsafe int GetSocketPort()
        {
            SockaddrIn sockaddr;
            var        sockaddrSize = sizeof(SockaddrIn);

            if (WinSock.getsockname(_listeningSocket, (byte *)&sockaddr, ref sockaddrSize) != 0)
            {
                WinSock.ThrowLastWsaError();
            }

            return(WinSock.ntohs(sockaddr.sin_port));
        }
Example #15
0
        internal int TryGetCompletionResults(RIO_RESULT *results, int maxCompletionResults)
        {
            var completionQueue = QueueHandle;

            var resultCount = WinSock.Extensions.DequeueCompletion(completionQueue, results, (uint)maxCompletionResults);

            if (resultCount == WinSock.Consts.RIO_CORRUPT_CQ)
            {
                WinSock.ThrowLastWsaError();
            }

            return((int)resultCount);
        }
Example #16
0
        private unsafe static void Connect(IntPtr socket, IPEndPoint ipEndPoint)
        {
            var endPointAddressBytes = ipEndPoint.Address.GetAddressBytes();
            var inAddress            = new InAddr(endPointAddressBytes);

            var sa = new SockaddrIn
            {
                sin_family = AddressFamilies.AF_INET,
                sin_port   = WinSock.htons((ushort)ipEndPoint.Port),
                sin_addr   = inAddress
            };

            var errorCode = WinSock.connect(socket, ref sa, sizeof(SockaddrIn));

            if (errorCode == WinSock.Consts.SOCKET_ERROR)
            {
                WinSock.ThrowLastWsaError();
            }
        }
Example #17
0
        private RioBufferManager(int bufferCount, int bufferLength)
        {
            if (bufferLength <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(bufferLength));
            }

            if (bufferCount <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(bufferCount));
            }

            var underlyingBufferLength = (uint)(bufferLength * bufferCount);

            _underlyingBuffer  = Kernel32.VirtualAlloc(IntPtr.Zero, underlyingBufferLength, Kernel32.Consts.MEM_COMMIT | Kernel32.Consts.MEM_RESERVE, Kernel32.Consts.PAGE_READWRITE);
            _bufferDescriptors = Kernel32.VirtualAlloc(IntPtr.Zero, (uint)(Marshal.SizeOf <RIO_BUF>() * bufferCount), Kernel32.Consts.MEM_COMMIT | Kernel32.Consts.MEM_RESERVE, Kernel32.Consts.PAGE_READWRITE);

            _bufferId = WinSock.Extensions.RegisterBuffer(_underlyingBuffer, underlyingBufferLength);
            if (_bufferId == WinSock.Consts.RIO_INVALID_BUFFERID)
            {
                WinSock.ThrowLastWsaError();
            }

            _buffers = new RioBuffer[bufferCount];

            var dataPointer    = (byte *)_underlyingBuffer.ToPointer();
            var segmentPointer = (RIO_BUF *)_bufferDescriptors.ToPointer();

            for (var segmentIndex = 0; segmentIndex < bufferCount; segmentIndex++)
            {
                segmentPointer->BufferId = _bufferId;
                segmentPointer->Offset   = segmentIndex * bufferLength;
                segmentPointer->Length   = bufferLength;

                var segment = new RioBuffer(segmentIndex, dataPointer, segmentPointer, bufferLength);

                _buffers[segmentIndex] = segment;
                _freeBufferIds.Push(segment.Id);

                segmentPointer++;
                dataPointer += bufferLength;
            }
        }
Example #18
0
        private static unsafe IntPtr CreateListeningSocket()
        {
            var socketFlags     = SocketFlags.WSA_FLAG_REGISTERED_IO | SocketFlags.WSA_FLAG_OVERLAPPED;
            var listeningSocket = WinSock.WSASocket(AddressFamilies.AF_INET, SocketType.SOCK_STREAM, Protocol.IPPROTO_TCP, IntPtr.Zero, 0, socketFlags);

            if (listeningSocket == (IntPtr)WinSock.Consts.INVALID_SOCKET)
            {
                WinSock.ThrowLastWsaError();
                return(IntPtr.Zero);
            }

            var tcpNoDelay = -1;

            WinSock.setsockopt(listeningSocket, WinSock.Consts.IPPROTO_TCP, WinSock.Consts.TCP_NODELAY, (char *)&tcpNoDelay, sizeof(int));

            var reuseAddr = 1;

            WinSock.setsockopt(listeningSocket, WinSock.Consts.SOL_SOCKET, WinSock.Consts.SO_REUSEADDR, (char *)&reuseAddr, sizeof(int));

            return(listeningSocket);
        }
Example #19
0
        private void ListenAndRunAcceptLoop(ManualResetEventSlim listeningSignal)
        {
            Thread.CurrentThread.Name = "Server Listening Worker";

            if (!Bind(_listeningSocket, _configuration.ListeningPort))
            {
                return;
            }

            ListeningPort = GetSocketPort();

            Listen();

            listeningSignal.Set();

            while (_isListening)
            {
                var acceptSocket = WinSock.accept(_listeningSocket, IntPtr.Zero, IntPtr.Zero);
                if (acceptSocket == (IntPtr)WinSock.Consts.INVALID_SOCKET)
                {
                    var lastErrorCode = WinSock.WSAGetLastError();
                    if (lastErrorCode == WinSock.Consts.WSAEINTR)
                    {
                        break;
                    }

                    WinSock.ThrowLastWsaError();
                    continue;
                }

                var clientSession = _sessionManager.Acquire();
                clientSession.Closed          += OnClientSessionClosed;
                clientSession.MessageReceived += OnClientSessionMessageReceived;

                clientSession.Open(acceptSocket);
                clientSession.InitiateReceiving();

                ClientConnected(clientSession.Id);
            }
        }
Example #20
0
        public unsafe void FlushSends()
        {
            var lockTaken = false;
            var spinlock  = new SpinLock();

            try
            {
                spinlock.Enter(ref lockTaken);

                if (!WinSock.Extensions.Send(_handle, null, 0, RIO_SEND_FLAGS.COMMIT_ONLY, 0))
                {
                    WinSock.ThrowLastWsaError();
                }
            }
            finally
            {
                if (lockTaken)
                {
                    spinlock.Exit();
                }
            }
        }
Example #21
0
        private void Listen()
        {
            Thread.CurrentThread.Name = "Server Listening Worker";

            if (!Bind(_listeningSocket, _configuration.ListeningPort))
            {
                return;
            }

            if (WinSock.listen(_listeningSocket, WinSock.Consts.SOMAXCONN) == WinSock.Consts.SOCKET_ERROR)
            {
                return;
            }

            while (_isListening)
            {
                var acceptSocket = WinSock.accept(_listeningSocket, IntPtr.Zero, IntPtr.Zero);
                if (acceptSocket == (IntPtr)WinSock.Consts.INVALID_SOCKET)
                {
                    var lastErrorCode = WinSock.WSAGetLastError();
                    if (lastErrorCode == WinSock.Consts.WSAEINTR)
                    {
                        break;
                    }

                    WinSock.ThrowLastWsaError();
                    continue;
                }

                var clientSession = _sessionManager.Acquire();
                clientSession.Closed          += OnClientSessionClosed;
                clientSession.MessageReceived += OnClientSessionMessageReceived;

                clientSession.Open(acceptSocket);
                clientSession.InitiateReceiving();

                ClientConnected(clientSession.Id);
            }
        }
Example #22
0
        private static unsafe bool Bind(IntPtr listeningSocket, int listeningPort)
        {
            var endPointAddressBytes = IPAddress.Any.GetAddressBytes();
            var inAddress            = new InAddr(endPointAddressBytes);

            var sa = new SockaddrIn
            {
                sin_family = AddressFamilies.AF_INET,
                sin_port   = WinSock.htons((ushort)listeningPort),
                sin_addr   = inAddress
            };

            var errorCode = WinSock.bind(listeningSocket, ref sa, sizeof(SockaddrIn));

            if (errorCode == WinSock.Consts.SOCKET_ERROR)
            {
                WinSock.ThrowLastWsaError();
                return(false);
            }

            return(true);
        }