/mcs/class/referencesource/System/net/System/Net/Sockets/_AcceptOverlappedAsyncResult.cs

https://github.com/pruiz/mono · C# · 171 lines · 100 code · 30 blank · 41 comment · 9 complexity · 1892e2e5b105ab8406b062c3e631ca70 MD5 · raw file

  1. //------------------------------------------------------------------------------
  2. // <copyright file="_AcceptOverlappedAsyncResult.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. //------------------------------------------------------------------------------
  6. namespace System.Net.Sockets {
  7. using System;
  8. using System.Net;
  9. using System.Runtime.InteropServices;
  10. using System.Threading;
  11. using Microsoft.Win32;
  12. //
  13. // AcceptOverlappedAsyncResult - used to take care of storage for async Socket BeginAccept call.
  14. //
  15. internal class AcceptOverlappedAsyncResult : BaseOverlappedAsyncResult {
  16. //
  17. // internal class members
  18. //
  19. private int m_LocalBytesTransferred;
  20. private Socket m_ListenSocket;
  21. private Socket m_AcceptSocket;
  22. private int m_AddressBufferLength;
  23. private byte[] m_Buffer;
  24. // Constructor. We take in the socket that's creating us, the caller's
  25. // state object, and the buffer on which the I/O will be performed.
  26. // We save the socket and state, pin the callers's buffer, and allocate
  27. // an event for the WaitHandle.
  28. //
  29. internal AcceptOverlappedAsyncResult(Socket listenSocket, Object asyncState, AsyncCallback asyncCallback) :
  30. base(listenSocket, asyncState, asyncCallback)
  31. {
  32. m_ListenSocket = listenSocket;
  33. }
  34. #if !FEATURE_PAL
  35. //
  36. // This method will be called by us when the IO completes synchronously and
  37. // by the ThreadPool when the IO completes asynchronously. (only called on WinNT)
  38. //
  39. internal override object PostCompletion(int numBytes) {
  40. SocketError errorCode = (SocketError)ErrorCode;
  41. SocketAddress remoteSocketAddress = null;
  42. if (errorCode==SocketError.Success) {
  43. m_LocalBytesTransferred = numBytes;
  44. if(Logging.On)LogBuffer((long)numBytes);
  45. //get the endpoint
  46. remoteSocketAddress = m_ListenSocket.m_RightEndPoint.Serialize();
  47. IntPtr localAddr;
  48. int localAddrLength;
  49. IntPtr remoteAddr;
  50. //set the socket context
  51. try
  52. {
  53. m_ListenSocket.GetAcceptExSockaddrs(
  54. Marshal.UnsafeAddrOfPinnedArrayElement(m_Buffer, 0),
  55. m_Buffer.Length - (m_AddressBufferLength * 2),
  56. m_AddressBufferLength,
  57. m_AddressBufferLength,
  58. out localAddr,
  59. out localAddrLength,
  60. out remoteAddr,
  61. out remoteSocketAddress.m_Size
  62. );
  63. Marshal.Copy(remoteAddr, remoteSocketAddress.m_Buffer, 0, remoteSocketAddress.m_Size);
  64. IntPtr handle = m_ListenSocket.SafeHandle.DangerousGetHandle();
  65. errorCode = UnsafeNclNativeMethods.OSSOCK.setsockopt(
  66. m_AcceptSocket.SafeHandle,
  67. SocketOptionLevel.Socket,
  68. SocketOptionName.UpdateAcceptContext,
  69. ref handle,
  70. Marshal.SizeOf(handle));
  71. if (errorCode == SocketError.SocketError) errorCode = (SocketError) Marshal.GetLastWin32Error();
  72. GlobalLog.Print("AcceptOverlappedAsyncResult#" + ValidationHelper.HashString(this) + "::PostCallback() setsockopt handle:" + handle.ToString() + " AcceptSocket:" + ValidationHelper.HashString(m_AcceptSocket) + " itsHandle:" + m_AcceptSocket.SafeHandle.DangerousGetHandle().ToString() + " returns:" + errorCode.ToString());
  73. }
  74. catch (ObjectDisposedException)
  75. {
  76. errorCode = SocketError.OperationAborted;
  77. }
  78. ErrorCode = (int)errorCode;
  79. }
  80. if (errorCode==SocketError.Success) {
  81. return m_ListenSocket.UpdateAcceptSocket(m_AcceptSocket, m_ListenSocket.m_RightEndPoint.Create(remoteSocketAddress), false);
  82. }
  83. else
  84. return null;
  85. }
  86. #endif // !FEATURE_PAL
  87. //
  88. // SetUnmanagedStructures -
  89. // Fills in Overlapped Structures used in an Async Overlapped Winsock call
  90. // these calls are outside the runtime and are unmanaged code, so we need
  91. // to prepare specific structures and ints that lie in unmanaged memory
  92. // since the Overlapped calls can be Async
  93. //
  94. internal void SetUnmanagedStructures(byte[] buffer, int addressBufferLength) {
  95. // has to be called first to pin memory
  96. base.SetUnmanagedStructures(buffer);
  97. //
  98. // Fill in Buffer Array structure that will be used for our send/recv Buffer
  99. //
  100. m_AddressBufferLength = addressBufferLength;
  101. m_Buffer = buffer;
  102. }
  103. /*
  104. // Consider removing.
  105. internal void SetUnmanagedStructures(byte[] buffer, int addressBufferLength, ref OverlappedCache overlappedCache)
  106. {
  107. SetupCache(ref overlappedCache);
  108. SetUnmanagedStructures(buffer, addressBufferLength);
  109. }
  110. */
  111. void LogBuffer(long size) {
  112. GlobalLog.Assert(Logging.On, "AcceptOverlappedAsyncResult#{0}::LogBuffer()|Logging is off!", ValidationHelper.HashString(this));
  113. IntPtr pinnedBuffer = Marshal.UnsafeAddrOfPinnedArrayElement(m_Buffer, 0);
  114. if (pinnedBuffer != IntPtr.Zero) {
  115. if (size > -1) {
  116. Logging.Dump(Logging.Sockets, m_ListenSocket, "PostCompletion", pinnedBuffer, (int)Math.Min(size, (long)m_Buffer.Length));
  117. }
  118. else {
  119. Logging.Dump(Logging.Sockets, m_ListenSocket, "PostCompletion", pinnedBuffer, (int)m_Buffer.Length);
  120. }
  121. }
  122. }
  123. internal byte[] Buffer {
  124. get {
  125. return m_Buffer;
  126. }
  127. }
  128. internal int BytesTransferred {
  129. get {
  130. return m_LocalBytesTransferred;
  131. }
  132. }
  133. internal Socket AcceptSocket
  134. {
  135. set
  136. {
  137. m_AcceptSocket = value;
  138. }
  139. }
  140. }
  141. }