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); } }
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(); } } }
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); } } } }
public RioTcpClientPool(RioFixedBufferPool sendPool, RioFixedBufferPool revicePool, uint socketCount, uint maxOutstandingReceive = 1024, uint maxOutstandingSend = 1024) : base(sendPool, revicePool, socketCount, 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 = ADDRESS_FAMILIES.AF_INET; 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(); } } } }
internal unsafe void CommitSend() { if (!RioStatic.Send(_requestQueue, RIO_BUFSEGMENT.NullSegment, 0, RIO_SEND_FLAGS.COMMIT_ONLY, 0)) { WinSock.ThrowLastWSAError(); } }
internal unsafe void SendInternal(RioBufferSegment segment, RIO_SEND_FLAGS flags) { if (!RioStatic.Send(_requestQueue, segment.SegmentPointer, 1, flags, segment.Index)) { WinSock.ThrowLastWSAError(); } }
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 = WinSock.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 = WinSock.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 = WinSock.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), Send = Marshal.GetDelegateForFunctionPointer <RIOSend>(rio.RIOSend), 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); } }
public void WritePreAllocated(RioBufferSegment Segment) { unsafe { if (!RioStatic.Send(_requestQueue, Segment.SegmentPointer, 1, RIO_SEND_FLAGS.DEFER, Segment.Index)) { WinSock.ThrowLastWSAError(); } } }
protected override unsafe void SocketIocpComplete(object o) { IntPtr lpNumberOfBytes; IntPtr lpCompletionKey; RioNativeOverlapped *lpOverlapped = stackalloc RioNativeOverlapped[1]; TaskCompletionSource <RioConnectionOrientedSocket> 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 != 0 && error != 64 & error != 1225) //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)); } } } } }
internal static int ThrowLastWSAError() { var error = WinSock.WSAGetLastError(); if (error != 0) { throw new Win32Exception(error); } else { return(error); } }
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(); }
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 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 RioTcpListener(RioFixedBufferPool sendPool, RioFixedBufferPool revicePool, uint socketCount, uint maxOutstandingReceive = 1024, uint maxOutstandingSend = 1024) : base(sendPool, revicePool, socketCount, maxOutstandingReceive, maxOutstandingSend, (maxOutstandingReceive + maxOutstandingSend) * socketCount) { if ((_listenerSocket = WinSock.WSASocket(ADDRESS_FAMILIES.AF_INET, SOCKET_TYPE.SOCK_STREAM, PROTOCOL.IPPROTO_TCP, IntPtr.Zero, 0, SOCKET_FLAGS.REGISTERED_IO | SOCKET_FLAGS.WSA_FLAG_OVERLAPPED)) == IntPtr.Zero) { WinSock.ThrowLastWSAError(); } int True = -1; UInt32 dwBytes = 0; WinSock.setsockopt(_listenerSocket, WinSock.IPPROTO_TCP, WinSock.TCP_NODELAY, (char *)&True, 4); WinSock.WSAIoctlGeneral(_listenerSocket, WinSock.SIO_LOOPBACK_FAST_PATH, &True, 4, null, 0, out dwBytes, IntPtr.Zero, IntPtr.Zero); if ((_listenIocp = Kernel32.CreateIoCompletionPort(_listenerSocket, _listenIocp, 0, 1)) == IntPtr.Zero) { Kernel32.ThrowLastError(); } Thread ListenIocpThread = new Thread(ListenIocpComplete); ListenIocpThread.IsBackground = true; ListenIocpThread.Start(); }
internal unsafe static void Initalize() { IntPtr tempSocket; tempSocket = WinSock.WSASocket(ADDRESS_FAMILIES.AF_INET, SOCKET_TYPE.SOCK_STREAM, PROTOCOL.IPPROTO_TCP, IntPtr.Zero, 0, SOCKET_FLAGS.REGISTERED_IO | SOCKET_FLAGS.WSA_FLAG_OVERLAPPED); WinSock.ThrowLastWSAError(); uint dwBytes = 0; Guid AcceptExId = new Guid("B5367DF1-CBAC-11CF-95CA-00805F48A192"); var acceptExptr = IntPtr.Zero; if (WinSock.WSAIoctl2(tempSocket, WinSock.SIO_GET_EXTENSION_FUNCTION_POINTER, ref AcceptExId, 16, ref acceptExptr, IntPtr.Size, out dwBytes, IntPtr.Zero, IntPtr.Zero) != 0) { WinSock.ThrowLastWSAError(); } else { AcceptEx = Marshal.GetDelegateForFunctionPointer <WinSock.AcceptEx>(acceptExptr); } Guid ConnectExId = new Guid("25A207B9-DDF3-4660-8EE9-76E58C74063E"); var ConnectExptr = IntPtr.Zero; if (WinSock.WSAIoctl2(tempSocket, WinSock.SIO_GET_EXTENSION_FUNCTION_POINTER, ref ConnectExId, 16, ref ConnectExptr, IntPtr.Size, out dwBytes, IntPtr.Zero, IntPtr.Zero) != 0) { WinSock.ThrowLastWSAError(); } else { ConnectEx = Marshal.GetDelegateForFunctionPointer <WinSock.ConnectEx>(ConnectExptr); } Guid DisconnectExId = new Guid("7FDA2E11-8630-436F-A031-F536A6EEC157"); var DisconnectExptr = IntPtr.Zero; if (WinSock.WSAIoctl2(tempSocket, WinSock.SIO_GET_EXTENSION_FUNCTION_POINTER, ref DisconnectExId, 16, ref DisconnectExptr, IntPtr.Size, out dwBytes, IntPtr.Zero, IntPtr.Zero) != 0) { WinSock.ThrowLastWSAError(); } else { DisconnectEx = Marshal.GetDelegateForFunctionPointer <WinSock.DisconnectEx>(DisconnectExptr); } var rio = new RIO_EXTENSION_FUNCTION_TABLE(); Guid RioFunctionsTableId = new Guid("8509e081-96dd-4005-b165-9e2ee8c79e3f"); if (WinSock.WSAIoctl(tempSocket, WinSock.SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER, ref RioFunctionsTableId, 16, ref rio, sizeof(RIO_EXTENSION_FUNCTION_TABLE), out dwBytes, IntPtr.Zero, IntPtr.Zero) != 0) { WinSock.ThrowLastWSAError(); } else { RegisterBuffer = Marshal.GetDelegateForFunctionPointer <WinSock.RIORegisterBuffer>(rio.RIORegisterBuffer); CreateCompletionQueue = Marshal.GetDelegateForFunctionPointer <WinSock.RIOCreateCompletionQueue>(rio.RIOCreateCompletionQueue); CreateRequestQueue = Marshal.GetDelegateForFunctionPointer <WinSock.RIOCreateRequestQueue>(rio.RIOCreateRequestQueue); Notify = Marshal.GetDelegateForFunctionPointer <WinSock.RIONotify>(rio.RIONotify); DequeueCompletion = Marshal.GetDelegateForFunctionPointer <WinSock.RIODequeueCompletion>(rio.RIODequeueCompletion); Receive = Marshal.GetDelegateForFunctionPointer <WinSock.RIOReceive>(rio.RIOReceive); Send = Marshal.GetDelegateForFunctionPointer <WinSock.RIOSend>(rio.RIOSend); CloseCompletionQueue = Marshal.GetDelegateForFunctionPointer <WinSock.RIOCloseCompletionQueue>(rio.RIOCloseCompletionQueue); DeregisterBuffer = Marshal.GetDelegateForFunctionPointer <WinSock.RIODeregisterBuffer>(rio.RIODeregisterBuffer); ResizeCompletionQueue = Marshal.GetDelegateForFunctionPointer <WinSock.RIOResizeCompletionQueue>(rio.RIOResizeCompletionQueue); ResizeRequestQueue = Marshal.GetDelegateForFunctionPointer <WinSock.RIOResizeRequestQueue>(rio.RIOResizeRequestQueue); } WinSock.closesocket(tempSocket); WinSock.ThrowLastWSAError(); }
public override void Dispose() { Kernel32.CloseHandle(_listenIocp); WinSock.closesocket(_listenerSocket); base.Dispose(); }
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(); }
public virtual void Dispose() { WinSock.closesocket(Socket); }