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(); } } }
internal unsafe void SendInternal(RioBufferSegment segment, RIO_SEND_FLAGS flags) { if (!RioStatic.Send(_requestQueue, segment.SegmentPointer, 1, flags, segment.Index)) { WinSock.ThrowLastWSAError(); } }
internal unsafe void CommitSend() { if (!RioStatic.Send(_requestQueue, RIO_BUFSEGMENT.NullSegment, 0, RIO_SEND_FLAGS.COMMIT_ONLY, 0)) { WinSock.ThrowLastWSAError(); } }
public void WritePreAllocated(RioBufferSegment Segment) { unsafe { if (!RioStatic.Send(_requestQueue, Segment.SegmentPointer, 1, RIO_SEND_FLAGS.DEFER, Segment.Index)) { WinSock.ThrowLastWSAError(); } } }
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(); }
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); } }
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); }
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); } }
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(); }