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(); } } }
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, 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(); } } } }
internal unsafe void SendInternal(RioBufferSegment segment, RIO_SEND_FLAGS flags) { if (!RioStatic.Send(_requestQueue, segment.SegmentPointer, 1, flags, segment.Index)) { WinSock.ThrowLastWSAError(); } }
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(); }
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(); }; }
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); }
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); } }
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); } }
internal unsafe void CommitSend() { if (!RioStatic.Send(_requestQueue, RIO_BUFSEGMENT.NullSegment, 0, RIO_SEND_FLAGS.COMMIT_ONLY, 0)) { WinSock.ThrowLastWSAError(); } }
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)); } } } } }
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); } }
public void SetLinger(int value) { //Debug.Assert(inUse); if (SetSocketOption(SOL_SOCKET_SocketOptions.SO_LINGER, &value, sizeof(int)) != 0) { WinSock.ThrowLastWSAError(); } }
public unsafe void Flush() { Debug.Assert(inUse); if (!RioStatic.Send(_requestQueue, RIO_BUF.NullSegment, 0, RIO_SEND_FLAGS.COMMIT_ONLY, 0)) { WinSock.ThrowLastWSAError(); } }
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); }
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(); } }
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(); } }
public void WritePreAllocated(RioBufferSegment Segment) { unsafe { if (!RioStatic.Send(_requestQueue, Segment.SegmentPointer, 1, RIO_SEND_FLAGS.DEFER, Segment.Index)) { WinSock.ThrowLastWSAError(); } } }
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); }
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(); } }
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); }
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); }
internal static int ThrowLastWSAError() { var error = WinSock.WSAGetLastError(); if (error != 0 && error != 997) { throw new Win32Exception(error); } else { return(error); } }
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); } } } }
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(); }
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); } }
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(); }
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(); } } }