private unsafe static 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);
object returnObject = null;
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 Marshal.GetLastWin32Error() will return the correct error.
SocketFlags ignore;
bool success = Interop.Winsock.WSAGetOverlappedResult(
socket.SafeHandle,
asyncResult.NativeOverlapped,
out numBytes,
false,
out ignore);
if (!success)
{
socketError = (SocketError)Marshal.GetLastWin32Error();
if (socketError == 0)
{
NetEventSource.Fail(asyncResult, $"socketError:0 numBytes:{numBytes}");
}
}
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;
}
}
}
asyncResult.ErrorCode = (int)socketError;
returnObject = asyncResult.PostCompletion((int)numBytes);
asyncResult.ReleaseUnmanagedStructures();
asyncResult.InvokeCallback(returnObject);
#if DEBUG
}
#endif
}