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