Пример #1
0
 internal unsafe void CommitSend()
 {
     if (!RioStatic.Send(_requestQueue, RIO_BUFSEGMENT.NullSegment, 0, RIO_SEND_FLAGS.COMMIT_ONLY, 0))
     {
         WinSock.ThrowLastWSAError();
     }
 }
Пример #2
0
 internal unsafe void SendInternal(RioBufferSegment segment, RIO_SEND_FLAGS flags)
 {
     if (!RioStatic.Send(_requestQueue, segment.SegmentPointer, 1, flags, segment.Index))
     {
         WinSock.ThrowLastWSAError();
     }
 }
Пример #3
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();
            };
        }
Пример #4
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);
            }
        }
Пример #5
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();
     }
 }
Пример #6
0
 public unsafe void Flush()
 {
     Debug.Assert(inUse);
     if (!RioStatic.Send(_requestQueue, RIO_BUF.NullSegment, 0, RIO_SEND_FLAGS.COMMIT_ONLY, 0))
     {
         WinSock.ThrowLastWSAError();
     }
 }
Пример #7
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();
     }
 }
Пример #8
0
 public void WritePreAllocated(RioBufferSegment Segment)
 {
     unsafe
     {
         if (!RioStatic.Send(_requestQueue, Segment.SegmentPointer, 1, RIO_SEND_FLAGS.DEFER, Segment.Index))
         {
             WinSock.ThrowLastWSAError();
         }
     }
 }
Пример #9
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);
        }
Пример #10
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);
 }
Пример #11
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);
        }
Пример #12
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);
                    }
                }
            }
        }
Пример #13
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();
        }
Пример #14
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);
            }
        }
Пример #15
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();
        }
Пример #16
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();
                }
            }
        }
Пример #17
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))
            {
                if (WinSock.WSAGetLastError() != 997) // error_io_pending
                {
                    WinSock.ThrowLastWSAError();
                }
            }
            else
            {
                OnAccepted(acceptSocket);
            }
        }
        internal unsafe virtual void Recycle(RioConnectionOrientedSocket socket)
        {
            RioSocket c;

            activeSockets.TryRemove(socket.GetHashCode(), out c);
            socket.ResetOverlapped();
            socket._overlapped->Status = 1;
            if (!RioStatic.DisconnectEx(socket.Socket, socket._overlapped, disconnectexflag, 0)) //TF_REUSE_SOCKET
            {
                if (WinSock.WSAGetLastError() != 997)                                            // error_io_pending
                {
                    WinSock.ThrowLastWSAError();
                }
            }
            //else
            //    AcceptEx(socket);
        }
Пример #19
0
        public async Task <RioSocket> Connect(Uri adress)
        {
            var ip = (await Dns.GetHostAddressesAsync(adress.Host)).First(i => i.AddressFamily == AddressFamily.InterNetwork);

            sockaddr_in sa = new sockaddr_in();

            sa.sin_family = adressFam;
            sa.sin_port   = WinSock.htons((ushort)adress.Port);

            var ipBytes = ip.GetAddressBytes();

            unsafe
            {
                fixed(byte *a = ipBytes)
                Unsafe.CopyBlock(sa.sin_addr.Address, a, (uint)ipBytes.Length);
            }

            RioConnectionOrientedSocket s;

            if (_freeSockets.TryDequeue(out s))
            {
                s.SetInUse(true);
                var tcs = new TaskCompletionSource <RioSocket>();
                _ongoingConnections.TryAdd(s, tcs);
                uint bytesSent;
                unsafe
                {
                    s.ResetOverlapped();
                    s._overlapped->Status = 2;
                    if (!RioStatic.ConnectEx(s.Socket, sa, sizeof(sockaddr_in), IntPtr.Zero, 0, out bytesSent, s._overlapped))
                    {
                        WinSock.ThrowLastWSAError();
                    }
                }

                return(await tcs.Task);
            }
            else
            {
                return(await Task.FromException <RioConnectionOrientedSocket>(new ArgumentException("No sockets available in pool")));
            }
        }
Пример #20
0
        unsafe void ProcessSendCompletes(object o)
        {
            uint              maxResults = Math.Min(MaxOutstandingSend, int.MaxValue);
            RIO_RESULT *      results    = stackalloc RIO_RESULT[(int)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, results, maxResults);
                        if (count == 0xFFFFFFFF)
                        {
                            WinSock.ThrowLastWSAError();
                        }
                        for (var i = 0; i < count; i++)
                        {
                            var buf = SendBufferPool.AllSegments[results[i].RequestCorrelation];
                            buf.Set();
                        }
                    } while (count > 0);
                }
                else
                {
                    var error = Marshal.GetLastWin32Error();

                    if (error != 0 && error != 735)
                    {
                        throw new Win32Exception(error);
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
Пример #21
0
        public unsafe Task <RioSocket> 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 = adressFam;
            sa.sin_port   = WinSock.htons((ushort)adress.Port);
            //Imports.ThrowLastWSAError();
            sa.sin_addr = inAddress;

            RioConnectionOrientedSocket s;

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

            _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);
        }
Пример #22
0
        public unsafe void BeginReceive()
        {
            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);
            }
        }
Пример #23
0
        internal unsafe virtual void BeginRecycle(RioConnectionOrientedSocket socket, bool force)
        {
            RioConnectionOrientedSocket c;

            activeSockets.TryRemove(socket.GetHashCode(), out c);

            if (force || socket.Socket == IntPtr.Zero || socket.pendingRecives > 0 || socket.pendingSends > 0)
            {
                socket.ResetSocket();
                if ((Kernel32.CreateIoCompletionPort(socket.Socket, socketIocp, 0, 1)) == IntPtr.Zero)
                {
                    Kernel32.ThrowLastError();
                }
                InitializeSocket(socket);
                EndRecycle(socket, false);
            }
            else
            {
                disconnectingSockets.TryAdd(socket.GetHashCode(), socket);
                socket.disconnectStartTime = CurrentTime;

                socket._overlapped->Status = 1;
                if (!RioStatic.DisconnectEx(socket.Socket, socket._overlapped, WinSock.TF_REUSE_SOCKET, 0))
                {
                    var error = WinSock.WSAGetLastError();
                    if (error == WinSock.WSAENOTCONN || error == 10038)
                    {
                        BeginRecycle(socket, true);
                    }

                    else
                    {
                        WinSock.ThrowLastWSAError();
                    }
                }
            }
        }
Пример #24
0
        public unsafe RioSocketPool(RioFixedBufferPool sendPool, RioFixedBufferPool receivePool, ADDRESS_FAMILIES adressFam, SOCKET_TYPE sockType, PROTOCOL protocol,
                                    uint maxOutstandingReceive = 1024, uint maxOutstandingSend = 1024, uint maxOutsandingCompletions = 2048)
        {
            MaxOutstandingReceive    = maxOutstandingReceive;
            MaxOutstandingSend       = maxOutstandingSend;
            MaxOutsandingCompletions = maxOutsandingCompletions;
            SendBufferPool           = sendPool;
            ReceiveBufferPool        = receivePool;

            this.adressFam = adressFam;
            this.sockType  = sockType;
            this.protocol  = protocol;

            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();
        }