public unsafe void LeaveMulticastGroup(IPAddress groupAdress, uint interfaceIndex = 0)
        {
            var adress = groupAdress.GetAddressBytes();

            if (groupAdress.AddressFamily == AddressFamily.InterNetwork)
            {
                ip_mreq value = new ip_mreq();
                value.imr_interface.s_b4 = (byte)interfaceIndex;

                fixed(byte *a = adress)
                Unsafe.CopyBlock(value.imr_multiaddr.Address, a, (uint)adress.Length);

                if (SetSocketOption(IPPROTO_IP_SocketOptions.IP_DROP_MEMBERSHIP, (void *)&value, Marshal.SizeOf <ip_mreq>()) != 0)
                {
                    WinSock.ThrowLastWSAError();
                }
            }
            else if (groupAdress.AddressFamily == AddressFamily.InterNetworkV6)
            {
                ipv6_mreq value = new ipv6_mreq();
                value.ipv6mr_interface = interfaceIndex;

                fixed(byte *a = adress)
                Unsafe.CopyBlock(value.ipv6mr_multiaddr.Address, a, (uint)adress.Length);

                if (SetSocketOption(IPPROTO_IPV6_SocketOptions.IPV6_DROP_MEMBERSHIP, (void *)&value, Marshal.SizeOf <ipv6_mreq>()) != 0)
                {
                    WinSock.ThrowLastWSAError();
                }
            }
        }
Example #2
0
        unsafe void ListenIocpComplete(object o)
        {
            IntPtr lpNumberOfBytes;
            IntPtr lpCompletionKey;
            RioNativeOverlapped *lpOverlapped = stackalloc RioNativeOverlapped[1];
            int lpcbTransfer;
            int lpdwFlags;

            while (true)
            {
                if (Kernel32.GetQueuedCompletionStatusRio(_listenIocp, out lpNumberOfBytes, out lpCompletionKey, out lpOverlapped, -1))
                {
                    if (WinSock.WSAGetOverlappedResult(_listenerSocket, lpOverlapped, out lpcbTransfer, false, out lpdwFlags))
                    {
                        var res = allSockets[lpOverlapped->SocketIndex];
                        activeSockets.TryAdd(res.GetHashCode(), res);
                        OnAccepted(res);
                    }
                    else
                    {
                        //recycle socket
                    }
                }
                else
                {
                    var error = Marshal.GetLastWin32Error();

                    if (error != 0 && error != 64) //connection no longer available
                    {
                        throw new Win32Exception(error);
                    }
                }
            }
        }
Example #3
0
        public RioTcpClientPool(RioFixedBufferPool sendPool, RioFixedBufferPool revicePool, uint socketCount,
                                uint maxOutstandingReceive = 1024, uint maxOutstandingSend = 1024)
            : base(sendPool, revicePool, socketCount, ADDRESS_FAMILIES.AF_INET, SOCKET_TYPE.SOCK_STREAM, PROTOCOL.IPPROTO_TCP, maxOutstandingReceive, maxOutstandingSend, (maxOutstandingReceive + maxOutstandingSend) * socketCount)
        {
            foreach (var s in allSockets)
            {
                _freeSockets.Enqueue(s);

                in_addr inAddress = new in_addr();
                inAddress.s_b1 = 0;
                inAddress.s_b2 = 0;
                inAddress.s_b3 = 0;
                inAddress.s_b4 = 0;

                sockaddr_in sa = new sockaddr_in();
                sa.sin_family = adressFam;
                sa.sin_port   = 0;
                //Imports.ThrowLastWSAError();
                sa.sin_addr = inAddress;

                unsafe
                {
                    if (WinSock.bind(s.Socket, ref sa, sizeof(sockaddr_in)) == WinSock.SOCKET_ERROR)
                    {
                        WinSock.ThrowLastWSAError();
                    }
                }
            }
        }
Example #4
0
 internal unsafe void SendInternal(RioBufferSegment segment, RIO_SEND_FLAGS flags)
 {
     if (!RioStatic.Send(_requestQueue, segment.SegmentPointer, 1, flags, segment.Index))
     {
         WinSock.ThrowLastWSAError();
     }
 }
Example #5
0
        public unsafe RioTcpListener(RioFixedBufferPool sendPool, RioFixedBufferPool revicePool, uint socketCount, uint maxOutstandingReceive = 2048, uint maxOutstandingSend = 2048)
            : base(sendPool, revicePool, socketCount, ADDRESS_FAMILIES.AF_INET, SOCKET_TYPE.SOCK_STREAM, PROTOCOL.IPPROTO_TCP, maxOutstandingReceive, maxOutstandingSend)
        {
            if ((_listenerSocket = WinSock.WSASocket(adressFam, sockType, protocol, IntPtr.Zero, 0, SOCKET_FLAGS.REGISTERED_IO | SOCKET_FLAGS.WSA_FLAG_OVERLAPPED)) == IntPtr.Zero)
            {
                WinSock.ThrowLastWSAError();
            }

            int  True    = 1;
            uint dwBytes = 0;

            if (WinSock.WSAIoctlGeneral2(_listenerSocket, WinSock.SIO_LOOPBACK_FAST_PATH, &True, sizeof(int), (void *)0, 0, out dwBytes, IntPtr.Zero, IntPtr.Zero) != 0)
            {
                WinSock.ThrowLastWSAError();
            }
            if (WinSock.setsockopt(_listenerSocket, WinSock.IPPROTO_TCP, WinSock.TCP_NODELAY, &True, 4) != 0)
            {
                WinSock.ThrowLastWSAError();
            }

            if ((_listenIocp = Kernel32.CreateIoCompletionPort(_listenerSocket, _listenIocp, 0, 1)) == IntPtr.Zero)
            {
                Kernel32.ThrowLastError();
            }

            Thread AcceptIocpThread = new Thread(AcceptIocpComplete);

            AcceptIocpThread.IsBackground = true;
            AcceptIocpThread.Start();
        }
Example #6
0
        internal RioSocket(RioFixedBufferPool sendBufferPool, RioFixedBufferPool receiveBufferPool,
                           uint maxOutstandingReceive, uint maxOutstandingSend, IntPtr SendCompletionQueue, IntPtr ReceiveCompletionQueue,
                           ADDRESS_FAMILIES adressFam, SOCKET_TYPE sockType, PROTOCOL protocol)
        {
            if ((Socket = WinSock.WSASocket(adressFam, sockType, protocol, IntPtr.Zero, 0, SOCKET_FLAGS.REGISTERED_IO | SOCKET_FLAGS.WSA_FLAG_OVERLAPPED)) == IntPtr.Zero)
            {
                WinSock.ThrowLastWSAError();
            }

            SendBufferPool    = sendBufferPool;
            ReceiveBufferPool = receiveBufferPool;

            _requestQueue = RioStatic.CreateRequestQueue(Socket, maxOutstandingReceive, 1, maxOutstandingSend, 1, ReceiveCompletionQueue, SendCompletionQueue, GetHashCode());
            WinSock.ThrowLastWSAError();

            onIncommingSegmentWrapper = (socket, segment) =>
            {
                onIncommingSegmentSafe(segment);
                if (segment.CurrentContentLength > 0)
                {
                    socket.BeginReceive();
                }
                else
                {
                    socket.Dispose();
                }
                segment.Dispose();
            };
        }
Example #7
0
        async Task Timeout()
        {
            while (running)
            {
                await Task.Delay(1000);

                foreach (var s in activeSockets.Values)
                {
                    if (!activeSockets.ContainsKey(s.GetHashCode()))
                    {
                        continue;
                    }
                    if ((s.pendingRecives > 0 && CurrentTime - s.lastReceiveStart > s.receiveTimeout) || (s.pendingSends > 0 && CurrentTime - s.lastSendStart > s.sendTimeout))
                    {
                        WinSock.closesocket(s.Socket);
                        s.Socket = IntPtr.Zero;
                    }
                }

                foreach (var s in disconnectingSockets.Values)
                {
                    if (CurrentTime - s.disconnectStartTime > Stopwatch.Frequency * 5)
                    {
                        BeginRecycle(s, true);
                    }
                }
            }

            timouttcs.SetResult(null);
        }
        protected override unsafe bool SocketIocpOk(RioConnectionOrientedSocket socket, byte status)
        {
            if (status == 1)
            {
                ThreadPool.QueueUserWorkItem(oo =>
                {
                    EndRecycle((RioConnectionOrientedSocket)oo, true);
                }, socket);
            }
            else if (status == 2)
            {
                TaskCompletionSource <RioSocket> r;
                activeSockets.TryAdd(socket.GetHashCode(), socket);
                socket.SetInUse(true);
                if (socket.SetSocketOption(SOL_SOCKET_SocketOptions.SO_UPDATE_CONNECT_CONTEXT, (void *)0, 0) != 0)
                {
                    WinSock.ThrowLastWSAError();
                }

                if (_ongoingConnections.TryRemove(socket, out r))
                {
                    ThreadPool.QueueUserWorkItem(oo =>
                    {
                        var rr = (Tuple <TaskCompletionSource <RioSocket>, RioConnectionOrientedSocket>)oo;
                        rr.Item1.SetResult(rr.Item2);
                    }, Tuple.Create(r, socket));
                }
            }

            return(false);
        }
Example #9
0
        internal void ResetSocket()
        {
            //Debug.Assert(!inUse);
            if (Socket != IntPtr.Zero)
            {
                WinSock.closesocket(Socket);
            }

            if ((Socket = WinSock.WSASocket(adressFam, sockType, protocol, IntPtr.Zero, 0, SOCKET_FLAGS.REGISTERED_IO | SOCKET_FLAGS.WSA_FLAG_OVERLAPPED)) == IntPtr.Zero)
            {
                WinSock.ThrowLastWSAError();
            }
            var error = 0;

            do
            {
                _requestQueue = RioStatic.CreateRequestQueue(Socket, maxOutstandingReceive / 2, 1, maxOutstandingSend / 2, 1, ReceiveCompletionQueue, SendCompletionQueue, GetHashCode());
                error         = WinSock.WSAGetLastError();
            } while (error == 10055);

            if (error != 0 && error != Kernel32.ERROR_IO_PENDING)
            {
                throw new Win32Exception(error);
            }
        }
Example #10
0
        public void Listen(IPEndPoint localEP, int backlog)
        {
            in_addr inAddress = new in_addr();

            inAddress.s_b1 = localEP.Address.GetAddressBytes()[0];
            inAddress.s_b2 = localEP.Address.GetAddressBytes()[1];
            inAddress.s_b3 = localEP.Address.GetAddressBytes()[2];
            inAddress.s_b4 = localEP.Address.GetAddressBytes()[3];

            sockaddr_in sa = new sockaddr_in();

            sa.sin_family = ADDRESS_FAMILIES.AF_INET;
            sa.sin_port   = WinSock.htons((ushort)localEP.Port);
            //Imports.ThrowLastWSAError();
            sa.sin_addr = inAddress;

            unsafe
            {
                if (WinSock.bind(_listenerSocket, ref sa, sizeof(sockaddr_in)) == WinSock.SOCKET_ERROR)
                {
                    WinSock.ThrowLastWSAError();
                }
            }

            if (WinSock.listen(_listenerSocket, backlog) == WinSock.SOCKET_ERROR)
            {
                WinSock.ThrowLastWSAError();
            }

            foreach (var s in allSockets)
            {
                BeginAccept(s);
            }
        }
Example #11
0
 internal unsafe void CommitSend()
 {
     if (!RioStatic.Send(_requestQueue, RIO_BUFSEGMENT.NullSegment, 0, RIO_SEND_FLAGS.COMMIT_ONLY, 0))
     {
         WinSock.ThrowLastWSAError();
     }
 }
Example #12
0
        protected override unsafe void SocketIocpComplete(object o)
        {
            IntPtr lpNumberOfBytes;
            IntPtr lpCompletionKey;
            RioNativeOverlapped *            lpOverlapped = stackalloc RioNativeOverlapped[1];
            TaskCompletionSource <RioSocket> r;
            RioConnectionOrientedSocket      res;
            int lpcbTransfer;
            int lpdwFlags;

            while (true)
            {
                if (Kernel32.GetQueuedCompletionStatusRio(socketIocp, out lpNumberOfBytes, out lpCompletionKey, out lpOverlapped, -1))
                {
                    if (lpOverlapped->Status == 1)
                    {
                        _freeSockets.Enqueue(allSockets[lpOverlapped->SocketIndex]);
                    }
                    else if (lpOverlapped->Status == 2)
                    {
                        if (WinSock.WSAGetOverlappedResult(allSockets[lpOverlapped->SocketIndex].Socket, lpOverlapped, out lpcbTransfer, false, out lpdwFlags))
                        {
                            res = allSockets[lpOverlapped->SocketIndex];
                            activeSockets.TryAdd(res.GetHashCode(), res);
                            if (_ongoingConnections.TryRemove(res, out r))
                            {
                                r.SetResult(res);
                            }
                        }
                        else
                        {
                            //recycle socket
                        }
                    }
                } //1225
                else
                {
                    var error = Marshal.GetLastWin32Error();

                    if (error == 735)
                    {
                        break;
                    }
                    else if (error != 0 && error != 64 && error != 1225 && error != 735) //connection no longer available
                    {
                        throw new Win32Exception(error);
                    }
                    else
                    {
                        res = allSockets[lpOverlapped->SocketIndex];
                        _freeSockets.Enqueue(allSockets[lpOverlapped->SocketIndex]);
                        if (_ongoingConnections.TryRemove(res, out r))
                        {
                            r.SetException(new Win32Exception(error));
                        }
                    }
                }
            }
        }
Example #13
0
        internal unsafe static RIO Initalize(IntPtr socket)
        {
            uint dwBytes = 0;
            RIO_EXTENSION_FUNCTION_TABLE rio = new RIO_EXTENSION_FUNCTION_TABLE();
            Guid RioFunctionsTableId         = new Guid("8509e081-96dd-4005-b165-9e2ee8c79e3f");

            int True   = -1;
            var result = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&True, 4);

            if (result != 0)
            {
                var error = WSAGetLastError();
                WinSock.WSACleanup();
                throw new Exception(String.Format("ERROR: setsockopt TCP_NODELAY returned {0}", error));
            }

            result = WSAIoctlGeneral(socket, SIO_LOOPBACK_FAST_PATH,
                                     &True, 4, null, 0,
                                     out dwBytes, IntPtr.Zero, IntPtr.Zero);

            if (result != 0)
            {
                var error = WSAGetLastError();
                WinSock.WSACleanup();
                throw new Exception(String.Format("ERROR: WSAIoctl SIO_LOOPBACK_FAST_PATH returned {0}", error));
            }

            result = WSAIoctl(socket, SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER,
                              ref RioFunctionsTableId, 16, ref rio,
                              sizeof(RIO_EXTENSION_FUNCTION_TABLE),
                              out dwBytes, IntPtr.Zero, IntPtr.Zero);

            if (result != 0)
            {
                var error = WSAGetLastError();
                WinSock.WSACleanup();
                throw new Exception(String.Format("ERROR: RIOInitalize returned {0}", error));
            }
            else
            {
                RIO rioFunctions = new RIO
                {
                    RegisterBuffer        = Marshal.GetDelegateForFunctionPointer <RIORegisterBuffer>(rio.RIORegisterBuffer),
                    CreateCompletionQueue = Marshal.GetDelegateForFunctionPointer <RIOCreateCompletionQueue>(rio.RIOCreateCompletionQueue),
                    CreateRequestQueue    = Marshal.GetDelegateForFunctionPointer <RIOCreateRequestQueue>(rio.RIOCreateRequestQueue),
                    Notify            = Marshal.GetDelegateForFunctionPointer <RIONotify>(rio.RIONotify),
                    DequeueCompletion = Marshal.GetDelegateForFunctionPointer <RIODequeueCompletion>(rio.RIODequeueCompletion),
                    Receive           = Marshal.GetDelegateForFunctionPointer <RIOReceive>(rio.RIOReceive),
                    ReceiveEx         = Marshal.GetDelegateForFunctionPointer <RIOReceiveEx>(rio.RIOReceiveEx),
                    Send   = Marshal.GetDelegateForFunctionPointer <RIOSend>(rio.RIOSend),
                    SendEx = Marshal.GetDelegateForFunctionPointer <RIOSendEx>(rio.RIOSendEx),
                    CloseCompletionQueue  = Marshal.GetDelegateForFunctionPointer <RIOCloseCompletionQueue>(rio.RIOCloseCompletionQueue),
                    DeregisterBuffer      = Marshal.GetDelegateForFunctionPointer <RIODeregisterBuffer>(rio.RIODeregisterBuffer),
                    ResizeCompletionQueue = Marshal.GetDelegateForFunctionPointer <RIOResizeCompletionQueue>(rio.RIOResizeCompletionQueue),
                    ResizeRequestQueue    = Marshal.GetDelegateForFunctionPointer <RIOResizeRequestQueue>(rio.RIOResizeRequestQueue)
                };
                return(rioFunctions);
            }
        }
Example #14
0
 public void SetLinger(int value)
 {
     //Debug.Assert(inUse);
     if (SetSocketOption(SOL_SOCKET_SocketOptions.SO_LINGER, &value, sizeof(int)) != 0)
     {
         WinSock.ThrowLastWSAError();
     }
 }
Example #15
0
 public unsafe void Flush()
 {
     Debug.Assert(inUse);
     if (!RioStatic.Send(_requestQueue, RIO_BUF.NullSegment, 0, RIO_SEND_FLAGS.COMMIT_ONLY, 0))
     {
         WinSock.ThrowLastWSAError();
     }
 }
Example #16
0
 internal virtual void Send(RioBufferSegment segment, RioBufferSegment remoteAdress, RIO_SEND_FLAGS flags)
 {
     Debug.Assert(inUse);
     if (!RioStatic.SendEx(_requestQueue, segment.SegmentPointer, 1, RIO_BUF.NullSegment, remoteAdress.SegmentPointer, RIO_BUF.NullSegment, RIO_BUF.NullSegment, flags, segment.Index))
     {
         WinSock.ThrowLastWSAError();
     }
 }
 internal void Close()
 {
     unchecked
     {
         currentId++;
     }
     WinSock.closesocket(Socket);
 }
Example #18
0
        public void SetTcpNoDelay(bool value)
        {
            int v = value ? 1 : 0;

            if (WinSock.setsockopt(Socket, WinSock.IPPROTO_TCP, WinSock.TCP_NODELAY, &v, 4) != 0)
            {
                WinSock.ThrowLastWSAError();
            }
        }
Example #19
0
 internal virtual void SendAndDispose(RioBufferSegment segment, RIO_SEND_FLAGS flags)
 {
     Debug.Assert(inUse);
     segment.DisposeOnComplete();
     if (!RioStatic.Send(_requestQueue, segment.SegmentPointer, 1, flags, segment.Index))
     {
         WinSock.ThrowLastWSAError();
     }
 }
Example #20
0
 public void WritePreAllocated(RioBufferSegment Segment)
 {
     unsafe
     {
         if (!RioStatic.Send(_requestQueue, Segment.SegmentPointer, 1, RIO_SEND_FLAGS.DEFER, Segment.Index))
         {
             WinSock.ThrowLastWSAError();
         }
     }
 }
Example #21
0
        public unsafe RioBufferSegment BeginReceive(RioBufferSegment segment)
        {
            segment.SetNotComplete();
            if (!RioStatic.Receive(_requestQueue, segment.SegmentPointer, 1, RIO_RECEIVE_FLAGS.NONE, segment.Index))
            {
                WinSock.ThrowLastWSAError();
            }

            return(segment);
        }
Example #22
0
        public void SetLoopbackFastPath(bool value)
        {
            //Debug.Assert(inUse);
            int  v       = value ? 1 : 0;
            uint dwBytes = 0;

            if (WinSock.WSAIoctlGeneral2(Socket, WinSock.SIO_LOOPBACK_FAST_PATH, &v, sizeof(int), (void *)0, 0, out dwBytes, IntPtr.Zero, IntPtr.Zero) != 0)
            {
                WinSock.ThrowLastWSAError();
            }
        }
Example #23
0
 public RioBufferSegment WritePreAllocated(RioBufferSegment Segment)
 {
     unsafe
     {
         Segment.SetNotComplete();
         if (!RioStatic.Send(_requestQueue, Segment.SegmentPointer, 1, RIO_SEND_FLAGS.DEFER, Segment.Index))
         {
             WinSock.ThrowLastWSAError();
         }
     }
     return(Segment);
 }
Example #24
0
        public virtual RioBufferSegment BeginReceive(RioBufferSegment segment)
        {
            Debug.Assert(inUse);
            segment.SegmentPointer->Length = segment.TotalLength;
            segment.SetNotComplete();
            if (!RioStatic.Receive(_requestQueue, segment.SegmentPointer, 1, RIO_RECEIVE_FLAGS.NONE, segment.Index))
            {
                WinSock.ThrowLastWSAError();
            }

            return(segment);
        }
Example #25
0
        internal static int ThrowLastWSAError()
        {
            var error = WinSock.WSAGetLastError();

            if (error != 0 && error != 997)
            {
                throw new Win32Exception(error);
            }
            else
            {
                return(error);
            }
        }
Example #26
0
        unsafe void ProcessReceiveCompletes(object o)
        {
            uint              maxResults = Math.Min(MaxOutstandingReceive, int.MaxValue);
            RIO_RESULT *      results    = stackalloc RIO_RESULT[(int)maxResults];
            uint              count;
            IntPtr            key, bytes;
            NativeOverlapped *overlapped = stackalloc NativeOverlapped[1];
            RIO_RESULT        result;
            RioBufferSegment  buf;

            while (true)
            {
                RioStatic.Notify(ReceiveCompletionQueue);

                if (Kernel32.GetQueuedCompletionStatus(ReceiveCompletionPort, out bytes, out key, out overlapped, -1) != 0)
                {
                    do
                    {
                        count = RioStatic.DequeueCompletion(ReceiveCompletionQueue, results, maxResults);
                        if (count == 0xFFFFFFFF)
                        {
                            WinSock.ThrowLastWSAError();
                        }

                        for (var i = 0; i < count; i++)
                        {
                            result = results[i];
                            buf    = ReceiveBufferPool.AllSegments[result.RequestCorrelation];
                            buf.SegmentPointer->Length = (int)result.BytesTransferred;
                            buf.Set();
                        }
                    } while (count > 0);
                }
                else
                {
                    var error = Marshal.GetLastWin32Error();
                    if (error == 0 || error == 735)
                    {
                        break;
                    }
                    else if (error == 126)
                    {
                        continue;
                    }
                    else
                    {
                        throw new Win32Exception(error);
                    }
                }
            }
        }
Example #27
0
        public virtual void Dispose()
        {
            RioStatic.DeregisterBuffer(_sendBufferId);
            RioStatic.DeregisterBuffer(_reciveBufferId);

            Kernel32.CloseHandle(SendCompletionPort);
            Kernel32.CloseHandle(ReceiveCompletionPort);
            RioStatic.CloseCompletionQueue(SendCompletionQueue);
            RioStatic.CloseCompletionQueue(ReceiveCompletionQueue);

            WinSock.WSACleanup();

            SendBufferPool.Dispose();
            ReceiveBufferPool.Dispose();
        }
Example #28
0
        unsafe void BeginAccept(RioConnectionOrientedSocket acceptSocket)
        {
            int recived = 0;

            acceptSocket.ResetOverlapped();
            if (!RioStatic.AcceptEx(_listenerSocket, acceptSocket.Socket, acceptSocket._adressBuffer, 0, sizeof(sockaddr_in) + 16, sizeof(sockaddr_in) + 16, out recived, acceptSocket._overlapped))
            {
                WinSock.ThrowLastWSAError();
            }
            else
            {
                acceptSocket.SetInUse(true);
                OnAccepted(acceptSocket);
            }
        }
Example #29
0
        internal RioSocket(RioFixedBufferPool sendBufferPool, RioFixedBufferPool receiveBufferPool,
                           uint maxOutstandingReceive, uint maxOutstandingSend, IntPtr SendCompletionQueue, IntPtr ReceiveCompletionQueue,
                           ADDRESS_FAMILIES adressFam, SOCKET_TYPE sockType, PROTOCOL protocol)
        {
            if ((Socket = WinSock.WSASocket(adressFam, sockType, protocol, IntPtr.Zero, 0, SOCKET_FLAGS.REGISTERED_IO | SOCKET_FLAGS.WSA_FLAG_OVERLAPPED)) == IntPtr.Zero)
            {
                WinSock.ThrowLastWSAError();
            }

            SendBufferPool    = sendBufferPool;
            ReceiveBufferPool = receiveBufferPool;

            _requestQueue = RioStatic.CreateRequestQueue(Socket, maxOutstandingReceive, 1, maxOutstandingSend, 1, ReceiveCompletionQueue, SendCompletionQueue, GetHashCode());
            WinSock.ThrowLastWSAError();
        }
Example #30
0
        unsafe void ProcessReceiveCompletes(object o)
        {
            uint              maxResults = Math.Min(MaxOutstandingReceive, int.MaxValue);
            RIO_RESULT *      results    = stackalloc RIO_RESULT[(int)maxResults];
            RioSocket         connection;
            uint              count;
            IntPtr            key, bytes;
            NativeOverlapped *overlapped = stackalloc NativeOverlapped[1];
            RIO_RESULT        result;
            RioBufferSegment  buf;

            while (true)
            {
                RioStatic.Notify(ReceiveCompletionQueue);
                WinSock.ThrowLastWSAError();

                if (Kernel32.GetQueuedCompletionStatus(ReceiveCompletionPort, out bytes, out key, out overlapped, -1) != 0)
                {
                    do
                    {
                        count = RioStatic.DequeueCompletion(ReceiveCompletionQueue, (IntPtr)results, maxResults);
                        if (count == 0xFFFFFFFF)
                        {
                            WinSock.ThrowLastWSAError();
                        }

                        for (var i = 0; i < count; i++)
                        {
                            result = results[i];
                            buf    = ReceiveBufferPool.AllSegments[result.RequestCorrelation];
                            if (activeSockets.TryGetValue(result.ConnectionCorrelation, out connection))
                            {
                                buf.SegmentPointer->Length = (int)result.BytesTransferred;
                                connection.onIncommingSegment(connection, buf);
                            }
                            else
                            {
                                buf.Dispose();
                            }
                        }
                    } while (count > 0);
                }
                else
                {
                    Kernel32.ThrowLastError();
                }
            }
        }