// Check the result of the overlapped operation. // Handle synchronous success by completing the asyncResult here. // Handle synchronous failure by cleaning up and returning a SocketError. internal SocketError ProcessOverlappedResult(bool success, int bytesTransferred) { if (success) { // Synchronous success. Socket socket = (Socket)AsyncObject; if (socket.SafeHandle.SkipCompletionPortOnSuccess) { // The socket handle is configured to skip completion on success, // so we can complete this asyncResult right now. CompletionCallback(bytesTransferred, SocketError.Success); return(SocketError.Success); } // Socket handle is going to post a completion to the completion port (may have done so already). // Return pending and we will continue in the completion port callback. return(SocketError.IOPending); } // Get the socket error (which may be IOPending) SocketError errorCode = SocketPal.GetLastSocketError(); if (errorCode == SocketError.IOPending) { // Operation is pending. // We will continue when the completion arrives (may have already at this point). return(SocketError.IOPending); } // Synchronous failure. // Release overlapped and pinned structures. ReleaseUnmanagedStructures(); return(errorCode); }
public static unsafe SocketError SendFile(SafeCloseSocket handle, SafeFileHandle fileHandle, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags) { fixed(byte *prePinnedBuffer = preBuffer) fixed(byte *postPinnedBuffer = postBuffer) { bool success = TransmitFileHelper(handle, fileHandle, SafeNativeOverlapped.Zero, preBuffer, postBuffer, flags); return(success ? SocketError.Success : SocketPal.GetLastSocketError()); } }
// This method is called by base.CompletionPortCallback base.OverlappedCallback as part of IO completion internal override object PostCompletion(int numBytes) { SocketError errorCode = (SocketError)ErrorCode; Socket socket = (Socket)AsyncObject; if (errorCode == SocketError.Success) { // Set the socket context. try { errorCode = Interop.Winsock.setsockopt( socket.SafeHandle, SocketOptionLevel.Socket, SocketOptionName.UpdateConnectContext, null, 0); if (errorCode == SocketError.SocketError) { errorCode = SocketPal.GetLastSocketError(); } } catch (ObjectDisposedException) { errorCode = SocketError.OperationAborted; } ErrorCode = (int)errorCode; } if (errorCode == SocketError.Success) { socket.SetToConnected(); return(socket); } return(null); }
private static unsafe void CompletionPortCallback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped) { #if DEBUG DebugThreadTracking.SetThreadSource(ThreadKinds.CompletionPort); using (DebugThreadTracking.SetThreadKind(ThreadKinds.System)) { #endif BaseOverlappedAsyncResult asyncResult = (BaseOverlappedAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(nativeOverlapped); if (asyncResult.InternalPeekCompleted) { NetEventSource.Fail(null, $"asyncResult.IsCompleted: {asyncResult}"); } if (NetEventSource.IsEnabled) { NetEventSource.Info(null, $"errorCode:{errorCode} numBytes:{numBytes} nativeOverlapped:{(IntPtr)nativeOverlapped}"); } // Complete the IO and invoke the user's callback. SocketError socketError = (SocketError)errorCode; if (socketError != SocketError.Success && socketError != SocketError.OperationAborted) { // There are cases where passed errorCode does not reflect the details of the underlined socket error. // "So as of today, the key is the difference between WSAECONNRESET and ConnectionAborted, // .e.g remote party or network causing the connection reset or something on the local host (e.g. closesocket // or receiving data after shutdown (SD_RECV)). With Winsock/TCP stack rewrite in longhorn, there may // be other differences as well." Socket socket = asyncResult.AsyncObject as Socket; if (socket == null) { socketError = SocketError.NotSocket; } else if (socket.CleanedUp) { socketError = SocketError.OperationAborted; } else { try { // The async IO completed with a failure. // Here we need to call WSAGetOverlappedResult() just so GetLastSocketError() will return the correct error. SocketFlags ignore; bool success = Interop.Winsock.WSAGetOverlappedResult( socket.SafeHandle, nativeOverlapped, out numBytes, false, out ignore); if (!success) { socketError = SocketPal.GetLastSocketError(); } if (success) { NetEventSource.Fail(asyncResult, $"Unexpectedly succeeded. errorCode:{errorCode} numBytes:{numBytes}"); } } catch (ObjectDisposedException) { // CleanedUp check above does not always work since this code is subject to race conditions socketError = SocketError.OperationAborted; } } } // Set results and invoke callback asyncResult.CompletionCallback((int)numBytes, socketError); #if DEBUG } #endif }
// This method will be called by us when the IO completes synchronously and // by the ThreadPool when the IO completes asynchronously. (only called on WinNT) internal override object?PostCompletion(int numBytes) { SocketError errorCode = (SocketError)ErrorCode; Internals.SocketAddress?remoteSocketAddress = null; if (errorCode == SocketError.Success) { _numBytes = numBytes; if (NetEventSource.IsEnabled) { LogBuffer(numBytes); } // get the endpoint remoteSocketAddress = IPEndPointExtensions.Serialize(_listenSocket._rightEndPoint !); IntPtr localAddr; int localAddrLength; IntPtr remoteAddr; // set the socket context bool refAdded = false; SafeHandle safeHandle = _listenSocket.SafeHandle; try { safeHandle.DangerousAddRef(ref refAdded); IntPtr handle = safeHandle.DangerousGetHandle(); Debug.Assert(_buffer != null); _listenSocket.GetAcceptExSockaddrs( Marshal.UnsafeAddrOfPinnedArrayElement(_buffer, 0), _buffer.Length - (_addressBufferLength * 2), _addressBufferLength, _addressBufferLength, out localAddr, out localAddrLength, out remoteAddr, out remoteSocketAddress.InternalSize); Marshal.Copy(remoteAddr, remoteSocketAddress.Buffer, 0, remoteSocketAddress.Size); errorCode = Interop.Winsock.setsockopt( _acceptSocket !.SafeHandle, SocketOptionLevel.Socket, SocketOptionName.UpdateAcceptContext, ref handle, IntPtr.Size); if (errorCode == SocketError.SocketError) { errorCode = SocketPal.GetLastSocketError(); } if (NetEventSource.IsEnabled) { NetEventSource.Info(this, $"setsockopt handle:{handle}, AcceptSocket:{_acceptSocket}, returns:{errorCode}"); } } catch (ObjectDisposedException) { errorCode = SocketError.OperationAborted; } finally { if (refAdded) { safeHandle.DangerousRelease(); } } ErrorCode = (int)errorCode; } if (errorCode != SocketError.Success) { return(null); } return(_listenSocket.UpdateAcceptSocket(_acceptSocket !, _listenSocket._rightEndPoint !.Create(remoteSocketAddress !))); }