PageRenderTime 109ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs

https://gitlab.com/0072016/0072016-corefx-
C# | 936 lines | 760 code | 129 blank | 47 comment | 104 complexity | ee37cabded79d6d5b493d54c2c804983 MD5 | raw file
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. using System.Collections.Generic;
  5. using System.Collections;
  6. using System.ComponentModel;
  7. using System.Diagnostics;
  8. using System.Globalization;
  9. using System.IO;
  10. using System.Net;
  11. using System.Runtime.InteropServices;
  12. using System.Threading.Tasks;
  13. using System.Threading;
  14. namespace System.Net.Sockets
  15. {
  16. internal static class SocketPal
  17. {
  18. public const bool SupportsMultipleConnectAttempts = true;
  19. private readonly static int s_protocolInformationSize = Marshal.SizeOf<Interop.Winsock.WSAPROTOCOL_INFO>();
  20. public static int ProtocolInformationSize { get { return s_protocolInformationSize; } }
  21. private static void MicrosecondsToTimeValue(long microseconds, ref Interop.Winsock.TimeValue socketTime)
  22. {
  23. const int microcnv = 1000000;
  24. socketTime.Seconds = (int)(microseconds / microcnv);
  25. socketTime.Microseconds = (int)(microseconds % microcnv);
  26. }
  27. public static SocketError GetLastSocketError()
  28. {
  29. return (SocketError)Marshal.GetLastWin32Error();
  30. }
  31. public static SocketError CreateSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType, out SafeCloseSocket socket)
  32. {
  33. socket = SafeCloseSocket.CreateWSASocket(addressFamily, socketType, protocolType);
  34. return socket.IsInvalid ? GetLastSocketError() : SocketError.Success;
  35. }
  36. public static SocketError SetBlocking(SafeCloseSocket handle, bool shouldBlock, out bool willBlock)
  37. {
  38. int intBlocking = shouldBlock ? 0 : -1;
  39. SocketError errorCode;
  40. errorCode = Interop.Winsock.ioctlsocket(
  41. handle,
  42. Interop.Winsock.IoctlSocketConstants.FIONBIO,
  43. ref intBlocking);
  44. if (errorCode == SocketError.SocketError)
  45. {
  46. errorCode = (SocketError)Marshal.GetLastWin32Error();
  47. }
  48. willBlock = intBlocking == 0;
  49. return errorCode;
  50. }
  51. public static SocketError GetSockName(SafeCloseSocket handle, byte[] buffer, ref int nameLen)
  52. {
  53. SocketError errorCode = Interop.Winsock.getsockname(handle, buffer, ref nameLen);
  54. return errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success;
  55. }
  56. public static SocketError GetAvailable(SafeCloseSocket handle, out int available)
  57. {
  58. int value = 0;
  59. SocketError errorCode = Interop.Winsock.ioctlsocket(
  60. handle,
  61. Interop.Winsock.IoctlSocketConstants.FIONREAD,
  62. ref value);
  63. available = value;
  64. return errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success;
  65. }
  66. public static SocketError GetPeerName(SafeCloseSocket handle, byte[] buffer, ref int nameLen)
  67. {
  68. SocketError errorCode = Interop.Winsock.getpeername(handle, buffer, ref nameLen);
  69. return errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success;
  70. }
  71. public static SocketError Bind(SafeCloseSocket handle, byte[] buffer, int nameLen)
  72. {
  73. SocketError errorCode = Interop.Winsock.bind(handle, buffer, nameLen);
  74. return errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success;
  75. }
  76. public static SocketError Listen(SafeCloseSocket handle, int backlog)
  77. {
  78. SocketError errorCode = Interop.Winsock.listen(handle, backlog);
  79. return errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success;
  80. }
  81. public static SocketError Accept(SafeCloseSocket handle, byte[] buffer, ref int nameLen, out SafeCloseSocket socket)
  82. {
  83. socket = SafeCloseSocket.Accept(handle, buffer, ref nameLen);
  84. return socket.IsInvalid ? GetLastSocketError() : SocketError.Success;
  85. }
  86. public static SocketError Connect(SafeCloseSocket handle, byte[] peerAddress, int peerAddressLen)
  87. {
  88. SocketError errorCode = Interop.Winsock.WSAConnect(
  89. handle.DangerousGetHandle(),
  90. peerAddress,
  91. peerAddressLen,
  92. IntPtr.Zero,
  93. IntPtr.Zero,
  94. IntPtr.Zero,
  95. IntPtr.Zero);
  96. return errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success;
  97. }
  98. public static SocketError Send(SafeCloseSocket handle, IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out int bytesTransferred)
  99. {
  100. int count = buffers.Count;
  101. WSABuffer[] WSABuffers = new WSABuffer[count];
  102. GCHandle[] objectsToPin = null;
  103. try
  104. {
  105. objectsToPin = new GCHandle[count];
  106. for (int i = 0; i < count; ++i)
  107. {
  108. ArraySegment<byte> buffer = buffers[i];
  109. RangeValidationHelpers.ValidateSegment(buffer);
  110. objectsToPin[i] = GCHandle.Alloc(buffer.Array, GCHandleType.Pinned);
  111. WSABuffers[i].Length = buffer.Count;
  112. WSABuffers[i].Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Array, buffer.Offset);
  113. }
  114. // This may throw ObjectDisposedException.
  115. SocketError errorCode = Interop.Winsock.WSASend_Blocking(
  116. handle.DangerousGetHandle(),
  117. WSABuffers,
  118. count,
  119. out bytesTransferred,
  120. socketFlags,
  121. SafeNativeOverlapped.Zero,
  122. IntPtr.Zero);
  123. if ((SocketError)errorCode == SocketError.SocketError)
  124. {
  125. errorCode = (SocketError)Marshal.GetLastWin32Error();
  126. }
  127. return errorCode;
  128. }
  129. finally
  130. {
  131. if (objectsToPin != null)
  132. {
  133. for (int i = 0; i < objectsToPin.Length; ++i)
  134. {
  135. if (objectsToPin[i].IsAllocated)
  136. {
  137. objectsToPin[i].Free();
  138. }
  139. }
  140. }
  141. }
  142. }
  143. public static unsafe SocketError Send(SafeCloseSocket handle, byte[] buffer, int offset, int size, SocketFlags socketFlags, out int bytesTransferred)
  144. {
  145. int bytesSent;
  146. if (buffer.Length == 0)
  147. {
  148. bytesSent = Interop.Winsock.send(handle.DangerousGetHandle(), null, 0, socketFlags);
  149. }
  150. else
  151. {
  152. fixed (byte* pinnedBuffer = buffer)
  153. {
  154. bytesSent = Interop.Winsock.send(
  155. handle.DangerousGetHandle(),
  156. pinnedBuffer + offset,
  157. size,
  158. socketFlags);
  159. }
  160. }
  161. if (bytesSent == (int)SocketError.SocketError)
  162. {
  163. bytesTransferred = 0;
  164. return GetLastSocketError();
  165. }
  166. bytesTransferred = bytesSent;
  167. return SocketError.Success;
  168. }
  169. public static unsafe SocketError SendTo(SafeCloseSocket handle, byte[] buffer, int offset, int size, SocketFlags socketFlags, byte[] peerAddress, int peerAddressSize, out int bytesTransferred)
  170. {
  171. int bytesSent;
  172. if (buffer.Length == 0)
  173. {
  174. bytesSent = Interop.Winsock.sendto(
  175. handle.DangerousGetHandle(),
  176. null,
  177. 0,
  178. socketFlags,
  179. peerAddress,
  180. peerAddressSize);
  181. }
  182. else
  183. {
  184. fixed (byte* pinnedBuffer = buffer)
  185. {
  186. bytesSent = Interop.Winsock.sendto(
  187. handle.DangerousGetHandle(),
  188. pinnedBuffer + offset,
  189. size,
  190. socketFlags,
  191. peerAddress,
  192. peerAddressSize);
  193. }
  194. }
  195. if (bytesSent == (int)SocketError.SocketError)
  196. {
  197. bytesTransferred = 0;
  198. return GetLastSocketError();
  199. }
  200. bytesTransferred = bytesSent;
  201. return SocketError.Success;
  202. }
  203. public static SocketError Receive(SafeCloseSocket handle, IList<ArraySegment<byte>> buffers, ref SocketFlags socketFlags, out int bytesTransferred)
  204. {
  205. int count = buffers.Count;
  206. WSABuffer[] WSABuffers = new WSABuffer[count];
  207. GCHandle[] objectsToPin = null;
  208. try
  209. {
  210. objectsToPin = new GCHandle[count];
  211. for (int i = 0; i < count; ++i)
  212. {
  213. ArraySegment<byte> buffer = buffers[i];
  214. RangeValidationHelpers.ValidateSegment(buffer);
  215. objectsToPin[i] = GCHandle.Alloc(buffer.Array, GCHandleType.Pinned);
  216. WSABuffers[i].Length = buffer.Count;
  217. WSABuffers[i].Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Array, buffer.Offset);
  218. }
  219. // This can throw ObjectDisposedException.
  220. SocketError errorCode = Interop.Winsock.WSARecv_Blocking(
  221. handle.DangerousGetHandle(),
  222. WSABuffers,
  223. count,
  224. out bytesTransferred,
  225. ref socketFlags,
  226. SafeNativeOverlapped.Zero,
  227. IntPtr.Zero);
  228. if ((SocketError)errorCode == SocketError.SocketError)
  229. {
  230. errorCode = (SocketError)Marshal.GetLastWin32Error();
  231. }
  232. return errorCode;
  233. }
  234. finally
  235. {
  236. if (objectsToPin != null)
  237. {
  238. for (int i = 0; i < objectsToPin.Length; ++i)
  239. {
  240. if (objectsToPin[i].IsAllocated)
  241. {
  242. objectsToPin[i].Free();
  243. }
  244. }
  245. }
  246. }
  247. }
  248. public static unsafe SocketError Receive(SafeCloseSocket handle, byte[] buffer, int offset, int size, SocketFlags socketFlags, out int bytesTransferred)
  249. {
  250. int bytesReceived;
  251. if (buffer.Length == 0)
  252. {
  253. bytesReceived = Interop.Winsock.recv(handle.DangerousGetHandle(), null, 0, socketFlags);
  254. }
  255. else
  256. {
  257. fixed (byte* pinnedBuffer = buffer)
  258. {
  259. bytesReceived = Interop.Winsock.recv(handle.DangerousGetHandle(), pinnedBuffer + offset, size, socketFlags);
  260. }
  261. }
  262. if (bytesReceived == (int)SocketError.SocketError)
  263. {
  264. bytesTransferred = 0;
  265. return GetLastSocketError();
  266. }
  267. bytesTransferred = bytesReceived;
  268. return SocketError.Success;
  269. }
  270. public static SocketError ReceiveMessageFrom(Socket socket, SafeCloseSocket handle, byte[] buffer, int offset, int size, ref SocketFlags socketFlags, Internals.SocketAddress socketAddress, out Internals.SocketAddress receiveAddress, out IPPacketInformation ipPacketInformation, out int bytesTransferred)
  271. {
  272. ReceiveMessageOverlappedAsyncResult asyncResult = new ReceiveMessageOverlappedAsyncResult(socket, null, null);
  273. asyncResult.SetUnmanagedStructures(buffer, offset, size, socketAddress, socketFlags);
  274. SocketError errorCode = SocketError.Success;
  275. bytesTransferred = 0;
  276. try
  277. {
  278. // This can throw ObjectDisposedException (retrieving the delegate AND resolving the handle).
  279. if (socket.WSARecvMsgBlocking(
  280. handle.DangerousGetHandle(),
  281. Marshal.UnsafeAddrOfPinnedArrayElement(asyncResult._messageBuffer, 0),
  282. out bytesTransferred,
  283. IntPtr.Zero,
  284. IntPtr.Zero) == SocketError.SocketError)
  285. {
  286. errorCode = (SocketError)Marshal.GetLastWin32Error();
  287. }
  288. }
  289. finally
  290. {
  291. asyncResult.SyncReleaseUnmanagedStructures();
  292. }
  293. socketFlags = asyncResult.SocketFlags;
  294. receiveAddress = asyncResult.SocketAddress;
  295. ipPacketInformation = asyncResult.IPPacketInformation;
  296. return errorCode;
  297. }
  298. public static unsafe SocketError ReceiveFrom(SafeCloseSocket handle, byte[] buffer, int offset, int size, SocketFlags socketFlags, byte[] socketAddress, ref int addressLength, out int bytesTransferred)
  299. {
  300. int bytesReceived;
  301. if (buffer.Length == 0)
  302. {
  303. bytesReceived = Interop.Winsock.recvfrom(handle.DangerousGetHandle(), null, 0, socketFlags, socketAddress, ref addressLength);
  304. }
  305. else
  306. {
  307. fixed (byte* pinnedBuffer = buffer)
  308. {
  309. bytesReceived = Interop.Winsock.recvfrom(handle.DangerousGetHandle(), pinnedBuffer + offset, size, socketFlags, socketAddress, ref addressLength);
  310. }
  311. }
  312. if (bytesReceived == (int)SocketError.SocketError)
  313. {
  314. bytesTransferred = 0;
  315. return GetLastSocketError();
  316. }
  317. bytesTransferred = bytesReceived;
  318. return SocketError.Success;
  319. }
  320. public static SocketError WindowsIoctl(SafeCloseSocket handle, int ioControlCode, byte[] optionInValue, byte[] optionOutValue, out int optionLength)
  321. {
  322. if (ioControlCode == Interop.Winsock.IoctlSocketConstants.FIONBIO)
  323. {
  324. throw new InvalidOperationException(SR.net_sockets_useblocking);
  325. }
  326. SocketError errorCode = Interop.Winsock.WSAIoctl_Blocking(
  327. handle.DangerousGetHandle(),
  328. ioControlCode,
  329. optionInValue,
  330. optionInValue != null ? optionInValue.Length : 0,
  331. optionOutValue,
  332. optionOutValue != null ? optionOutValue.Length : 0,
  333. out optionLength,
  334. SafeNativeOverlapped.Zero,
  335. IntPtr.Zero);
  336. return errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success;
  337. }
  338. public static unsafe SocketError SetSockOpt(SafeCloseSocket handle, SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue)
  339. {
  340. SocketError errorCode = Interop.Winsock.setsockopt(
  341. handle,
  342. optionLevel,
  343. optionName,
  344. ref optionValue,
  345. sizeof(int));
  346. return errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success;
  347. }
  348. public static SocketError SetSockOpt(SafeCloseSocket handle, SocketOptionLevel optionLevel, SocketOptionName optionName, byte[] optionValue)
  349. {
  350. SocketError errorCode = Interop.Winsock.setsockopt(
  351. handle,
  352. optionLevel,
  353. optionName,
  354. optionValue,
  355. optionValue != null ? optionValue.Length : 0);
  356. return errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success;
  357. }
  358. public static void SetReceivingDualModeIPv4PacketInformation(Socket socket)
  359. {
  360. socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true);
  361. }
  362. public static SocketError SetMulticastOption(SafeCloseSocket handle, SocketOptionName optionName, MulticastOption optionValue)
  363. {
  364. Interop.Winsock.IPMulticastRequest ipmr = new Interop.Winsock.IPMulticastRequest();
  365. ipmr.MulticastAddress = unchecked((int)optionValue.Group.GetAddress());
  366. if (optionValue.LocalAddress != null)
  367. {
  368. ipmr.InterfaceAddress = unchecked((int)optionValue.LocalAddress.GetAddress());
  369. }
  370. else
  371. { //this structure works w/ interfaces as well
  372. int ifIndex = IPAddress.HostToNetworkOrder(optionValue.InterfaceIndex);
  373. ipmr.InterfaceAddress = unchecked((int)ifIndex);
  374. }
  375. #if BIGENDIAN
  376. ipmr.MulticastAddress = (int) (((uint) ipmr.MulticastAddress << 24) |
  377. (((uint) ipmr.MulticastAddress & 0x0000FF00) << 8) |
  378. (((uint) ipmr.MulticastAddress >> 8) & 0x0000FF00) |
  379. ((uint) ipmr.MulticastAddress >> 24));
  380. if (optionValue.LocalAddress != null)
  381. {
  382. ipmr.InterfaceAddress = (int) (((uint) ipmr.InterfaceAddress << 24) |
  383. (((uint) ipmr.InterfaceAddress & 0x0000FF00) << 8) |
  384. (((uint) ipmr.InterfaceAddress >> 8) & 0x0000FF00) |
  385. ((uint) ipmr.InterfaceAddress >> 24));
  386. }
  387. #endif
  388. // This can throw ObjectDisposedException.
  389. SocketError errorCode = Interop.Winsock.setsockopt(
  390. handle,
  391. SocketOptionLevel.IP,
  392. optionName,
  393. ref ipmr,
  394. Interop.Winsock.IPMulticastRequest.Size);
  395. return errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success;
  396. }
  397. public static SocketError SetIPv6MulticastOption(SafeCloseSocket handle, SocketOptionName optionName, IPv6MulticastOption optionValue)
  398. {
  399. Interop.Winsock.IPv6MulticastRequest ipmr = new Interop.Winsock.IPv6MulticastRequest();
  400. ipmr.MulticastAddress = optionValue.Group.GetAddressBytes();
  401. ipmr.InterfaceIndex = unchecked((int)optionValue.InterfaceIndex);
  402. // This can throw ObjectDisposedException.
  403. SocketError errorCode = Interop.Winsock.setsockopt(
  404. handle,
  405. SocketOptionLevel.IPv6,
  406. optionName,
  407. ref ipmr,
  408. Interop.Winsock.IPv6MulticastRequest.Size);
  409. return errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success;
  410. }
  411. public static SocketError SetLingerOption(SafeCloseSocket handle, LingerOption optionValue)
  412. {
  413. Interop.Winsock.Linger lngopt = new Interop.Winsock.Linger();
  414. lngopt.OnOff = optionValue.Enabled ? (ushort)1 : (ushort)0;
  415. lngopt.Time = (ushort)optionValue.LingerTime;
  416. // This can throw ObjectDisposedException.
  417. SocketError errorCode = Interop.Winsock.setsockopt(
  418. handle,
  419. SocketOptionLevel.Socket,
  420. SocketOptionName.Linger,
  421. ref lngopt,
  422. 4);
  423. return errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success;
  424. }
  425. public static SocketError GetSockOpt(SafeCloseSocket handle, SocketOptionLevel optionLevel, SocketOptionName optionName, out int optionValue)
  426. {
  427. int optionLength = 4; // sizeof(int)
  428. SocketError errorCode = Interop.Winsock.getsockopt(
  429. handle,
  430. optionLevel,
  431. optionName,
  432. out optionValue,
  433. ref optionLength);
  434. return errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success;
  435. }
  436. public static SocketError GetSockOpt(SafeCloseSocket handle, SocketOptionLevel optionLevel, SocketOptionName optionName, byte[] optionValue, ref int optionLength)
  437. {
  438. SocketError errorCode = Interop.Winsock.getsockopt(
  439. handle,
  440. optionLevel,
  441. optionName,
  442. optionValue,
  443. ref optionLength);
  444. return errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success;
  445. }
  446. public static SocketError GetMulticastOption(SafeCloseSocket handle, SocketOptionName optionName, out MulticastOption optionValue)
  447. {
  448. Interop.Winsock.IPMulticastRequest ipmr = new Interop.Winsock.IPMulticastRequest();
  449. int optlen = Interop.Winsock.IPMulticastRequest.Size;
  450. // This can throw ObjectDisposedException.
  451. SocketError errorCode = Interop.Winsock.getsockopt(
  452. handle,
  453. SocketOptionLevel.IP,
  454. optionName,
  455. out ipmr,
  456. ref optlen);
  457. if (errorCode == SocketError.SocketError)
  458. {
  459. optionValue = default(MulticastOption);
  460. return GetLastSocketError();
  461. }
  462. #if BIGENDIAN
  463. ipmr.MulticastAddress = (int) (((uint) ipmr.MulticastAddress << 24) |
  464. (((uint) ipmr.MulticastAddress & 0x0000FF00) << 8) |
  465. (((uint) ipmr.MulticastAddress >> 8) & 0x0000FF00) |
  466. ((uint) ipmr.MulticastAddress >> 24));
  467. ipmr.InterfaceAddress = (int) (((uint) ipmr.InterfaceAddress << 24) |
  468. (((uint) ipmr.InterfaceAddress & 0x0000FF00) << 8) |
  469. (((uint) ipmr.InterfaceAddress >> 8) & 0x0000FF00) |
  470. ((uint) ipmr.InterfaceAddress >> 24));
  471. #endif // BIGENDIAN
  472. IPAddress multicastAddr = new IPAddress(ipmr.MulticastAddress);
  473. IPAddress multicastIntr = new IPAddress(ipmr.InterfaceAddress);
  474. optionValue = new MulticastOption(multicastAddr, multicastIntr);
  475. return SocketError.Success;
  476. }
  477. public static SocketError GetIPv6MulticastOption(SafeCloseSocket handle, SocketOptionName optionName, out IPv6MulticastOption optionValue)
  478. {
  479. Interop.Winsock.IPv6MulticastRequest ipmr = new Interop.Winsock.IPv6MulticastRequest();
  480. int optlen = Interop.Winsock.IPv6MulticastRequest.Size;
  481. // This can throw ObjectDisposedException.
  482. SocketError errorCode = Interop.Winsock.getsockopt(
  483. handle,
  484. SocketOptionLevel.IP,
  485. optionName,
  486. out ipmr,
  487. ref optlen);
  488. if (errorCode == SocketError.SocketError)
  489. {
  490. optionValue = default(IPv6MulticastOption);
  491. return GetLastSocketError();
  492. }
  493. optionValue = new IPv6MulticastOption(new IPAddress(ipmr.MulticastAddress), ipmr.InterfaceIndex);
  494. return SocketError.Success;
  495. }
  496. public static SocketError GetLingerOption(SafeCloseSocket handle, out LingerOption optionValue)
  497. {
  498. Interop.Winsock.Linger lngopt = new Interop.Winsock.Linger();
  499. int optlen = 4;
  500. // This can throw ObjectDisposedException.
  501. SocketError errorCode = Interop.Winsock.getsockopt(
  502. handle,
  503. SocketOptionLevel.Socket,
  504. SocketOptionName.Linger,
  505. out lngopt,
  506. ref optlen);
  507. if (errorCode == SocketError.SocketError)
  508. {
  509. optionValue = default(LingerOption);
  510. return GetLastSocketError();
  511. }
  512. optionValue = new LingerOption(lngopt.OnOff != 0, (int)lngopt.Time);
  513. return SocketError.Success;
  514. }
  515. public static SocketError Poll(SafeCloseSocket handle, int microseconds, SelectMode mode, out bool status)
  516. {
  517. IntPtr rawHandle = handle.DangerousGetHandle();
  518. IntPtr[] fileDescriptorSet = new IntPtr[2] { (IntPtr)1, rawHandle };
  519. Interop.Winsock.TimeValue IOwait = new Interop.Winsock.TimeValue();
  520. // A negative timeout value implies an indefinite wait.
  521. int socketCount;
  522. if (microseconds != -1)
  523. {
  524. MicrosecondsToTimeValue((long)(uint)microseconds, ref IOwait);
  525. socketCount =
  526. Interop.Winsock.select(
  527. 0,
  528. mode == SelectMode.SelectRead ? fileDescriptorSet : null,
  529. mode == SelectMode.SelectWrite ? fileDescriptorSet : null,
  530. mode == SelectMode.SelectError ? fileDescriptorSet : null,
  531. ref IOwait);
  532. }
  533. else
  534. {
  535. socketCount =
  536. Interop.Winsock.select(
  537. 0,
  538. mode == SelectMode.SelectRead ? fileDescriptorSet : null,
  539. mode == SelectMode.SelectWrite ? fileDescriptorSet : null,
  540. mode == SelectMode.SelectError ? fileDescriptorSet : null,
  541. IntPtr.Zero);
  542. }
  543. if ((SocketError)socketCount == SocketError.SocketError)
  544. {
  545. status = false;
  546. return GetLastSocketError();
  547. }
  548. status = (int)fileDescriptorSet[0] != 0 && fileDescriptorSet[1] == rawHandle;
  549. return SocketError.Success;
  550. }
  551. public static SocketError Select(IList checkRead, IList checkWrite, IList checkError, int microseconds)
  552. {
  553. IntPtr[] readfileDescriptorSet = Socket.SocketListToFileDescriptorSet(checkRead);
  554. IntPtr[] writefileDescriptorSet = Socket.SocketListToFileDescriptorSet(checkWrite);
  555. IntPtr[] errfileDescriptorSet = Socket.SocketListToFileDescriptorSet(checkError);
  556. // This code used to erroneously pass a non-null timeval structure containing zeroes
  557. // to select() when the caller specified (-1) for the microseconds parameter. That
  558. // caused select to actually have a *zero* timeout instead of an infinite timeout
  559. // turning the operation into a non-blocking poll.
  560. //
  561. // Now we pass a null timeval struct when microseconds is (-1).
  562. //
  563. // Negative microsecond values that weren't exactly (-1) were originally successfully
  564. // converted to a timeval struct containing unsigned non-zero integers. This code
  565. // retains that behavior so that any app working around the original bug with,
  566. // for example, (-2) specified for microseconds, will continue to get the same behavior.
  567. int socketCount;
  568. if (microseconds != -1)
  569. {
  570. Interop.Winsock.TimeValue IOwait = new Interop.Winsock.TimeValue();
  571. MicrosecondsToTimeValue((long)(uint)microseconds, ref IOwait);
  572. socketCount =
  573. Interop.Winsock.select(
  574. 0, // ignored value
  575. readfileDescriptorSet,
  576. writefileDescriptorSet,
  577. errfileDescriptorSet,
  578. ref IOwait);
  579. }
  580. else
  581. {
  582. socketCount =
  583. Interop.Winsock.select(
  584. 0, // ignored value
  585. readfileDescriptorSet,
  586. writefileDescriptorSet,
  587. errfileDescriptorSet,
  588. IntPtr.Zero);
  589. }
  590. if (GlobalLog.IsEnabled)
  591. {
  592. GlobalLog.Print("Socket::Select() Interop.Winsock.select returns socketCount:" + socketCount);
  593. }
  594. if ((SocketError)socketCount == SocketError.SocketError)
  595. {
  596. return GetLastSocketError();
  597. }
  598. Socket.SelectFileDescriptor(checkRead, readfileDescriptorSet);
  599. Socket.SelectFileDescriptor(checkWrite, writefileDescriptorSet);
  600. Socket.SelectFileDescriptor(checkError, errfileDescriptorSet);
  601. return SocketError.Success;
  602. }
  603. public static SocketError Shutdown(SafeCloseSocket handle, bool isConnected, bool isDisconnected, SocketShutdown how)
  604. {
  605. SocketError err = Interop.Winsock.shutdown(handle, (int)how);
  606. if (err != SocketError.SocketError)
  607. {
  608. return SocketError.Success;
  609. }
  610. err = GetLastSocketError();
  611. Debug.Assert(err != SocketError.NotConnected || (!isConnected && !isDisconnected));
  612. return err;
  613. }
  614. public static unsafe SocketError ConnectAsync(Socket socket, SafeCloseSocket handle, byte[] socketAddress, int socketAddressLen, ConnectOverlappedAsyncResult asyncResult)
  615. {
  616. // This will pin the socketAddress buffer.
  617. asyncResult.SetUnmanagedStructures(socketAddress);
  618. int ignoreBytesSent;
  619. if (!socket.ConnectEx(
  620. handle,
  621. Marshal.UnsafeAddrOfPinnedArrayElement(socketAddress, 0),
  622. socketAddressLen,
  623. IntPtr.Zero,
  624. 0,
  625. out ignoreBytesSent,
  626. asyncResult.OverlappedHandle))
  627. {
  628. return GetLastSocketError();
  629. }
  630. return SocketError.Success;
  631. }
  632. public static unsafe SocketError SendAsync(SafeCloseSocket handle, byte[] buffer, int offset, int count, SocketFlags socketFlags, OverlappedAsyncResult asyncResult)
  633. {
  634. // Set up asyncResult for overlapped WSASend.
  635. // This call will use completion ports.
  636. asyncResult.SetUnmanagedStructures(buffer, offset, count, null, false /*don't pin null remoteEP*/);
  637. // This can throw ObjectDisposedException.
  638. int bytesTransferred;
  639. SocketError errorCode = Interop.Winsock.WSASend(
  640. handle,
  641. ref asyncResult._singleBuffer,
  642. 1, // There is only ever 1 buffer being sent.
  643. out bytesTransferred,
  644. socketFlags,
  645. asyncResult.OverlappedHandle,
  646. IntPtr.Zero);
  647. if (errorCode != SocketError.Success)
  648. {
  649. errorCode = GetLastSocketError();
  650. }
  651. return errorCode;
  652. }
  653. public static unsafe SocketError SendAsync(SafeCloseSocket handle, IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, OverlappedAsyncResult asyncResult)
  654. {
  655. // Set up asyncResult for overlapped WSASend.
  656. // This call will use completion ports.
  657. asyncResult.SetUnmanagedStructures(buffers);
  658. // This can throw ObjectDisposedException.
  659. int bytesTransferred;
  660. SocketError errorCode = Interop.Winsock.WSASend(
  661. handle,
  662. asyncResult._wsaBuffers,
  663. asyncResult._wsaBuffers.Length,
  664. out bytesTransferred,
  665. socketFlags,
  666. asyncResult.OverlappedHandle,
  667. IntPtr.Zero);
  668. if (errorCode != SocketError.Success)
  669. {
  670. errorCode = GetLastSocketError();
  671. }
  672. return errorCode;
  673. }
  674. public static unsafe SocketError SendToAsync(SafeCloseSocket handle, byte[] buffer, int offset, int count, SocketFlags socketFlags, Internals.SocketAddress socketAddress, OverlappedAsyncResult asyncResult)
  675. {
  676. // Set up asyncResult for overlapped WSASendTo.
  677. // This call will use completion ports.
  678. asyncResult.SetUnmanagedStructures(buffer, offset, count, socketAddress, false /* don't pin RemoteEP*/);
  679. int bytesTransferred;
  680. SocketError errorCode = Interop.Winsock.WSASendTo(
  681. handle,
  682. ref asyncResult._singleBuffer,
  683. 1, // There is only ever 1 buffer being sent.
  684. out bytesTransferred,
  685. socketFlags,
  686. asyncResult.GetSocketAddressPtr(),
  687. asyncResult.SocketAddress.Size,
  688. asyncResult.OverlappedHandle,
  689. IntPtr.Zero);
  690. if (errorCode != SocketError.Success)
  691. {
  692. errorCode = GetLastSocketError();
  693. }
  694. return errorCode;
  695. }
  696. public static unsafe SocketError ReceiveAsync(SafeCloseSocket handle, byte[] buffer, int offset, int count, SocketFlags socketFlags, OverlappedAsyncResult asyncResult)
  697. {
  698. // Set up asyncResult for overlapped WSARecv.
  699. // This call will use completion ports.
  700. asyncResult.SetUnmanagedStructures(buffer, offset, count, null, false /* don't pin null RemoteEP*/);
  701. // This can throw ObjectDisposedException.
  702. int bytesTransferred;
  703. SocketError errorCode = Interop.Winsock.WSARecv(
  704. handle,
  705. ref asyncResult._singleBuffer,
  706. 1,
  707. out bytesTransferred,
  708. ref socketFlags,
  709. asyncResult.OverlappedHandle,
  710. IntPtr.Zero);
  711. if (errorCode != SocketError.Success)
  712. {
  713. errorCode = GetLastSocketError();
  714. }
  715. return errorCode;
  716. }
  717. public static unsafe SocketError ReceiveAsync(SafeCloseSocket handle, IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, OverlappedAsyncResult asyncResult)
  718. {
  719. // Set up asyncResult for overlapped WSASend.
  720. // This call will use completion ports.
  721. asyncResult.SetUnmanagedStructures(buffers);
  722. // This can throw ObjectDisposedException.
  723. int bytesTransferred;
  724. SocketError errorCode = Interop.Winsock.WSARecv(
  725. handle,
  726. asyncResult._wsaBuffers,
  727. asyncResult._wsaBuffers.Length,
  728. out bytesTransferred,
  729. ref socketFlags,
  730. asyncResult.OverlappedHandle,
  731. IntPtr.Zero);
  732. if (errorCode != SocketError.Success)
  733. {
  734. errorCode = GetLastSocketError();
  735. }
  736. return errorCode;
  737. }
  738. public static unsafe SocketError ReceiveFromAsync(SafeCloseSocket handle, byte[] buffer, int offset, int count, SocketFlags socketFlags, Internals.SocketAddress socketAddress, OverlappedAsyncResult asyncResult)
  739. {
  740. // Set up asyncResult for overlapped WSARecvFrom.
  741. // This call will use completion ports on WinNT and Overlapped IO on Win9x.
  742. asyncResult.SetUnmanagedStructures(buffer, offset, count, socketAddress, true);
  743. int bytesTransferred;
  744. SocketError errorCode = Interop.Winsock.WSARecvFrom(
  745. handle,
  746. ref asyncResult._singleBuffer,
  747. 1,
  748. out bytesTransferred,
  749. ref socketFlags,
  750. asyncResult.GetSocketAddressPtr(),
  751. asyncResult.GetSocketAddressSizePtr(),
  752. asyncResult.OverlappedHandle,
  753. IntPtr.Zero);
  754. if (errorCode != SocketError.Success)
  755. {
  756. errorCode = GetLastSocketError();
  757. }
  758. return errorCode;
  759. }
  760. public static unsafe SocketError ReceiveMessageFromAsync(Socket socket, SafeCloseSocket handle, byte[] buffer, int offset, int count, SocketFlags socketFlags, Internals.SocketAddress socketAddress, ReceiveMessageOverlappedAsyncResult asyncResult)
  761. {
  762. asyncResult.SetUnmanagedStructures(buffer, offset, count, socketAddress, socketFlags);
  763. int bytesTransfered;
  764. SocketError errorCode = (SocketError)socket.WSARecvMsg(
  765. handle,
  766. Marshal.UnsafeAddrOfPinnedArrayElement(asyncResult._messageBuffer, 0),
  767. out bytesTransfered,
  768. asyncResult.OverlappedHandle,
  769. IntPtr.Zero);
  770. if (errorCode != SocketError.Success)
  771. {
  772. errorCode = GetLastSocketError();
  773. }
  774. return errorCode;
  775. }
  776. public static unsafe SocketError AcceptAsync(Socket socket, SafeCloseSocket handle, SafeCloseSocket acceptHandle, int receiveSize, int socketAddressSize, AcceptOverlappedAsyncResult asyncResult)
  777. {
  778. // The buffer needs to contain the requested data plus room for two sockaddrs and 16 bytes
  779. // of associated data for each.
  780. int addressBufferSize = socketAddressSize + 16;
  781. byte[] buffer = new byte[receiveSize + ((addressBufferSize) * 2)];
  782. // Set up asyncResult for overlapped AcceptEx.
  783. // This call will use completion ports on WinNT.
  784. asyncResult.SetUnmanagedStructures(buffer, addressBufferSize);
  785. // This can throw ObjectDisposedException.
  786. int bytesTransferred;
  787. SocketError errorCode = SocketError.Success;
  788. if (!socket.AcceptEx(
  789. handle,
  790. acceptHandle,
  791. Marshal.UnsafeAddrOfPinnedArrayElement(asyncResult.Buffer, 0),
  792. receiveSize,
  793. addressBufferSize,
  794. addressBufferSize,
  795. out bytesTransferred,
  796. asyncResult.OverlappedHandle))
  797. {
  798. errorCode = GetLastSocketError();
  799. }
  800. return errorCode;
  801. }
  802. public static void CheckDualModeReceiveSupport(Socket socket)
  803. {
  804. // Dual-mode sockets support received packet info on Windows.
  805. }
  806. }
  807. }