private void DoBeginReceiveFrom(byte[] buffer, int offset, int size, SocketFlags socketFlags, EndPoint endPointSnapshot, Internals.SocketAddress socketAddress, OriginalAddressOverlappedAsyncResult asyncResult) { EndPoint oldEndPoint = _rightEndPoint; if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"size:{size}"); // Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to // avoid a Socket leak in case of error. SocketError errorCode = SocketError.SocketError; try { // Save a copy of the original EndPoint in the asyncResult. asyncResult.SocketAddressOriginal = IPEndPointExtensions.Serialize(endPointSnapshot); if (_rightEndPoint == null) { _rightEndPoint = endPointSnapshot; } errorCode = SocketPal.ReceiveFromAsync(_handle, buffer, offset, size, socketFlags, socketAddress, asyncResult); if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Interop.Winsock.WSARecvFrom returns:{errorCode} size:{size} returning AsyncResult:{asyncResult}"); } catch (ObjectDisposedException) { _rightEndPoint = oldEndPoint; throw; } finally { errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode); } // Throw an appropriate SocketException if the native call fails synchronously. if (errorCode != SocketError.Success) { // Update the internal state of this socket according to the error before throwing. _rightEndPoint = oldEndPoint; SocketException socketException = new SocketException((int)errorCode); UpdateStatusAfterSocketError(socketException); if (NetEventSource.IsEnabled) NetEventSource.Error(this, socketException); throw socketException; } if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"size:{size} return AsyncResult:{asyncResult}"); }
// Routine Description: // // BeginReceiveFrom - Async implementation of RecvFrom call, // // Called when we want to start an async receive. // We kick off the receive, and if it completes synchronously we'll // call the callback. Otherwise we'll return an IASyncResult, which // the caller can use to wait on or retrieve the final status, as needed. // // Uses Winsock 2 overlapped I/O. // // Arguments: // // ReadBuffer - status line that we wish to parse // Index - Offset into ReadBuffer to begin reading from // Request - Size of Buffer to recv // Flags - Additional Flags that may be passed to the underlying winsock call // remoteEP - EndPoint that are to receive from // Callback - Delegate function that holds callback, called on completion of I/O // State - State used to track callback, set by caller, not required // // Return Value: // // IAsyncResult - Async result used to retrieve result public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP, AsyncCallback callback, object state) { if (NetEventSource.IsEnabled) NetEventSource.Enter(this); if (CleanedUp) { throw new ObjectDisposedException(this.GetType().FullName); } // Validate input parameters. if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } if (remoteEP == null) { throw new ArgumentNullException(nameof(remoteEP)); } if (!CanTryAddressFamily(remoteEP.AddressFamily)) { throw new ArgumentException(SR.Format(SR.net_InvalidEndPointAddressFamily, remoteEP.AddressFamily, _addressFamily), nameof(remoteEP)); } if (offset < 0 || offset > buffer.Length) { throw new ArgumentOutOfRangeException(nameof(offset)); } if (size < 0 || size > buffer.Length - offset) { throw new ArgumentOutOfRangeException(nameof(size)); } if (_rightEndPoint == null) { throw new InvalidOperationException(SR.net_sockets_mustbind); } SocketPal.CheckDualModeReceiveSupport(this); // We don't do a CAS demand here because the contents of remoteEP aren't used by // WSARecvFrom; all that matters is that we generate a unique-to-this-call SocketAddress // with the right address family Internals.SocketAddress socketAddress = SnapshotAndSerialize(ref remoteEP); // Set up the result and set it to collect the context. var asyncResult = new OriginalAddressOverlappedAsyncResult(this, state, callback); asyncResult.StartPostingAsyncOp(false); // Start the ReceiveFrom. DoBeginReceiveFrom(buffer, offset, size, socketFlags, remoteEP, socketAddress, asyncResult); // Capture the context, maybe call the callback, and return. asyncResult.FinishPostingAsyncOp(ref Caches.ReceiveClosureCache); if (asyncResult.CompletedSynchronously && !asyncResult.SocketAddressOriginal.Equals(asyncResult.SocketAddress)) { try { remoteEP = remoteEP.Create(asyncResult.SocketAddress); } catch { } } if (NetEventSource.IsEnabled) NetEventSource.Exit(this, asyncResult); return asyncResult; }