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(); } } }
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); } }
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(); } } } }
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(); }
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); } }
internal unsafe void SendInternal(RioBufferSegment segment, RIO_SEND_FLAGS flags) { if (!RioStatic.Send(_requestQueue, segment.SegmentPointer, 1, flags, segment.Index)) { WinSock.ThrowLastWSAError(); } }
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(); }; }
internal unsafe void CommitSend() { if (!RioStatic.Send(_requestQueue, RIO_BUFSEGMENT.NullSegment, 0, RIO_SEND_FLAGS.COMMIT_ONLY, 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(); } }
public void SetLinger(int value) { //Debug.Assert(inUse); if (SetSocketOption(SOL_SOCKET_SocketOptions.SO_LINGER, &value, sizeof(int)) != 0) { WinSock.ThrowLastWSAError(); } }
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 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 WritePreAllocated(RioBufferSegment Segment) { unsafe { if (!RioStatic.Send(_requestQueue, Segment.SegmentPointer, 1, RIO_SEND_FLAGS.DEFER, Segment.Index)) { WinSock.ThrowLastWSAError(); } } }
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 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); }
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); }
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); } } } }
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(); } } }
internal override void InitializeSocket(RioConnectionOrientedSocket socket) { socket.SetLoopbackFastPath(true); socket.SetTcpNoDelay(true); sockaddr_in sa = new sockaddr_in(); sa.sin_family = adressFam; unsafe { if (WinSock.bind(socket.Socket, ref sa, sizeof(sockaddr_in)) == WinSock.SOCKET_ERROR) { WinSock.ThrowLastWSAError(); } } }
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); }
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"))); } }
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; } } } }
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); }
unsafe void AcceptIocpComplete(object o) { IntPtr lpNumberOfBytes; IntPtr lpCompletionKey; RioNativeOverlapped *lpOverlapped = stackalloc RioNativeOverlapped[1]; while (true) { if (Kernel32.GetQueuedCompletionStatusRio(_listenIocp, out lpNumberOfBytes, out lpCompletionKey, out lpOverlapped, -1)) { var res = allSockets[lpOverlapped->SocketIndex]; activeSockets.TryAdd(res.GetHashCode(), res); void *apa = _listenerSocket.ToPointer(); if (res.SetSocketOption(SOL_SOCKET_SocketOptions.SO_UPDATE_ACCEPT_CONTEXT, &apa, IntPtr.Size) != 0) { WinSock.ThrowLastWSAError(); } res.SetInUse(true); OnAccepted(res); } else { var error = Marshal.GetLastWin32Error(); if (error == Kernel32.ERROR_ABANDONED_WAIT_0) { break; } else if (error == Kernel32.ERROR_NETNAME_DELETED) { BeginRecycle(allSockets[lpOverlapped->SocketIndex], false); } else { throw new Win32Exception(error); } } } }