Exemple #1
0
        unsafe void ProcessSendCompletes(object o)
        {
            const int         maxResults = 1024;
            RIO_RESULT *      results    = stackalloc RIO_RESULT[maxResults];
            uint              count;
            IntPtr            key, bytes;
            NativeOverlapped *overlapped = stackalloc NativeOverlapped[1];

            while (true)
            {
                RioStatic.Notify(SendCompletionQueue);
                if (Kernel32.GetQueuedCompletionStatus(SendCompletionPort, out bytes, out key, out overlapped, -1) != 0)
                {
                    do
                    {
                        count = RioStatic.DequeueCompletion(SendCompletionQueue, (IntPtr)results, maxResults);
                        WinSock.ThrowLastWSAError();
                        for (var i = 0; i < count; i++)
                        {
                            var buf = SendBufferPool.AllSegments[results[i].RequestCorrelation];
                            if (buf.AutoFree)
                            {
                                buf.Dispose();
                            }
                        }
                    } while (count > 0);
                }
                else
                {
                    Kernel32.ThrowLastError();
                }
            }
        }
Exemple #2
0
 internal unsafe void SendInternal(RioBufferSegment segment, RIO_SEND_FLAGS flags)
 {
     if (!RioStatic.Send(_requestQueue, segment.SegmentPointer, 1, flags, segment.Index))
     {
         WinSock.ThrowLastWSAError();
     }
 }
Exemple #3
0
 internal unsafe void CommitSend()
 {
     if (!RioStatic.Send(_requestQueue, RIO_BUFSEGMENT.NullSegment, 0, RIO_SEND_FLAGS.COMMIT_ONLY, 0))
     {
         WinSock.ThrowLastWSAError();
     }
 }
Exemple #4
0
 public void WritePreAllocated(RioBufferSegment Segment)
 {
     unsafe
     {
         if (!RioStatic.Send(_requestQueue, Segment.SegmentPointer, 1, RIO_SEND_FLAGS.DEFER, Segment.Index))
         {
             WinSock.ThrowLastWSAError();
         }
     }
 }
Exemple #5
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();
        }
Exemple #6
0
        internal RioSocketBase(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();
        }
        internal unsafe virtual void Recycle(RioConnectionOrientedSocket socket)
        {
            RioSocketBase c;

            activeSockets.TryRemove(socket.GetHashCode(), out c);
            socket.ResetOverlapped();
            socket._overlapped->Status = 1;
            if (!RioStatic.DisconnectEx(c.Socket, socket._overlapped, 0x02, 0)) //TF_REUSE_SOCKET
            {
                if (WinSock.WSAGetLastError() != 997)                           // error_io_pending
                {
                    WinSock.ThrowLastWSAError();
                }
            }
            //else
            //    AcceptEx(socket);
        }
        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))
            {
                if (WinSock.WSAGetLastError() != 997) // error_io_pending
                {
                    WinSock.ThrowLastWSAError();
                }
            }
            else
            {
                OnAccepted(acceptSocket);
            }
        }
Exemple #9
0
        unsafe void ProcessReceiveCompletes(object o)
        {
            const int         maxResults = 1024;
            RIO_RESULT *      results    = stackalloc RIO_RESULT[maxResults];
            RioSocketBase     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);
                        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(buf);
                            }
                            else
                            {
                                buf.Dispose();
                            }
                        }
                    } while (count > 0);
                }
                else
                {
                    Kernel32.ThrowLastError();
                }
            }
        }
        public unsafe Task <RioConnectionOrientedSocket> Connect(Uri adress)
        {
            var adr = Dns.GetHostAddressesAsync(adress.Host).Result.First(i => i.AddressFamily == AddressFamily.InterNetwork);

            in_addr inAddress = new in_addr();

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

            sockaddr_in sa = new sockaddr_in();

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

            RioConnectionOrientedSocket s;

            _freeSockets.TryDequeue(out s);
            var tcs = new TaskCompletionSource <RioConnectionOrientedSocket>();

            _ongoingConnections.TryAdd(s, tcs);

            uint gurka;

            unsafe
            {
                s.ResetOverlapped();
                s._overlapped->Status = 2;
                if (!RioStatic.ConnectEx(s.Socket, sa, sizeof(sockaddr_in), IntPtr.Zero, 0, out gurka, s._overlapped))
                {
                    if (WinSock.WSAGetLastError() != 997) // error_io_pending
                    {
                        WinSock.ThrowLastWSAError();
                    }
                }
            }

            return(tcs.Task);
        }
Exemple #11
0
        internal unsafe void ReciveInternal()
        {
            RioBufferSegment buf;

            if (ReceiveBufferPool.TryGetBuffer(out buf))
            {
                if (!RioStatic.Receive(_requestQueue, buf.SegmentPointer, 1, RIO_RECEIVE_FLAGS.NONE, buf.Index))
                {
                    WinSock.ThrowLastWSAError();
                }
            }
            else
            {
                ThreadPool.QueueUserWorkItem(o =>
                {
                    var b = ReceiveBufferPool.GetBuffer();
                    if (!RioStatic.Receive(_requestQueue, ReceiveBufferPool.GetBuffer().SegmentPointer, 1, RIO_RECEIVE_FLAGS.NONE, b.Index))
                    {
                        WinSock.ThrowLastWSAError();
                    }
                }, null);
            }
        }
Exemple #12
0
        public unsafe RioSocketPool(RioFixedBufferPool sendPool, RioFixedBufferPool receivePool,
                                    uint maxOutstandingReceive = 1024, uint maxOutstandingSend = 1024, uint maxOutsandingCompletions = 2048)
        {
            MaxOutstandingReceive    = maxOutstandingReceive;
            MaxOutstandingSend       = maxOutstandingSend;
            MaxOutsandingCompletions = maxOutsandingCompletions;
            SendBufferPool           = sendPool;
            ReceiveBufferPool        = receivePool;

            var     version = new Version(2, 2);
            WSAData data;
            var     result = WinSock.WSAStartup((short)version.Raw, out data);

            if (result != 0)
            {
                WinSock.ThrowLastWSAError();
            }

            RioStatic.Initalize();

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

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


            _sendBufferId = RioStatic.RegisterBuffer(SendBufferPool.BufferPointer, (uint)SendBufferPool.TotalLength);
            WinSock.ThrowLastWSAError();
            SendBufferPool.SetBufferId(_sendBufferId);

            _reciveBufferId = RioStatic.RegisterBuffer(ReceiveBufferPool.BufferPointer, (uint)ReceiveBufferPool.TotalLength);
            WinSock.ThrowLastWSAError();
            ReceiveBufferPool.SetBufferId(_reciveBufferId);

            var sendCompletionMethod = new RIO_NOTIFICATION_COMPLETION()
            {
                Type = RIO_NOTIFICATION_COMPLETION_TYPE.IOCP_COMPLETION,
                Iocp = new RIO_NOTIFICATION_COMPLETION_IOCP()
                {
                    IocpHandle       = SendCompletionPort,
                    QueueCorrelation = 0,
                    Overlapped       = (NativeOverlapped *)-1
                }
            };

            if ((SendCompletionQueue = RioStatic.CreateCompletionQueue(MaxOutsandingCompletions, sendCompletionMethod)) == IntPtr.Zero)
            {
                WinSock.ThrowLastWSAError();
            }

            var receiveCompletionMethod = new RIO_NOTIFICATION_COMPLETION()
            {
                Type = RIO_NOTIFICATION_COMPLETION_TYPE.IOCP_COMPLETION,
                Iocp = new RIO_NOTIFICATION_COMPLETION_IOCP()
                {
                    IocpHandle       = ReceiveCompletionPort,
                    QueueCorrelation = 0,
                    Overlapped       = (NativeOverlapped *)-1
                }
            };

            if ((ReceiveCompletionQueue = RioStatic.CreateCompletionQueue(MaxOutsandingCompletions, receiveCompletionMethod)) == IntPtr.Zero)
            {
                WinSock.ThrowLastWSAError();
            }


            Thread receiveThread = new Thread(ProcessReceiveCompletes);

            receiveThread.IsBackground = true;
            receiveThread.Start();
            Thread sendThread = new Thread(ProcessSendCompletes);

            sendThread.IsBackground = true;
            sendThread.Start();
        }