internal SocketError DoOperationSendPackets(Socket socket, SafeCloseSocket handle) { Debug.Assert(_sendPacketsElements != null); SendPacketsElement[] elements = (SendPacketsElement[])_sendPacketsElements.Clone(); FileStream[] files = new FileStream[elements.Length]; // Open all files synchronously ahead of time so that any exceptions are propagated // to the caller, to match Windows behavior. try { for (int i = 0; i < elements.Length; i++) { string path = elements[i]?.FilePath; if (path != null) { files[i] = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 0x1000, useAsync: true); } } } catch (Exception exc) { // Clean up any files that were already opened. foreach (FileStream s in files) { s?.Dispose(); } // Windows differentiates the directory not being found from the file not being found. // Approximate this by checking to see if the directory exists; this is only best-effort, // as there are various things that could affect this, e.g. directory creation racing with // this check, but it's good enough for most situations. if (exc is FileNotFoundException fnfe) { string dirname = Path.GetDirectoryName(fnfe.FileName); if (!string.IsNullOrEmpty(dirname) && !Directory.Exists(dirname)) { throw new DirectoryNotFoundException(fnfe.Message); } } // Otherwise propagate the original error. throw; } SocketPal.SendPacketsAsync(socket, SendPacketsFlags, elements, files, (bytesTransferred, error) => { if (error == SocketError.Success) { FinishOperationAsyncSuccess((int)bytesTransferred, SocketFlags.None); } else { FinishOperationAsyncFailure(error, (int)bytesTransferred, SocketFlags.None); } }); return(SocketError.IOPending); }