The Labs \ Source Viewer \ SSCLI \ System.Net.Sockets \ ReceiveMessageOverlappedAsyncResult

  1. //------------------------------------------------------------------------------
  2. // <copyright file="_OverlappedAsyncResult.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Net.Sockets
  16. {
  17.     using System;
  18.     using System.Net;
  19.     using System.Runtime.InteropServices;
  20.     using System.Threading;
  21.     using Microsoft.Win32;
  22.     using System.Collections.Generic;
  23.    
  24.     //
  25.     // OverlappedAsyncResult - used to take care of storage for async Socket operation
  26.     // from the BeginSend, BeginSendTo, BeginReceive, BeginReceiveFrom calls.
  27.     //
  28.     unsafe internal class ReceiveMessageOverlappedAsyncResult : BaseOverlappedAsyncResult
  29.     {
  30.        
  31.         //
  32.         // internal class members
  33.         //
  34.         private UnsafeNclNativeMethods.OSSOCK.WSAMsg* m_Message;
  35.         internal SocketAddress SocketAddressOriginal;
  36.         internal SocketAddress m_SocketAddress;
  37.         private WSABuffer* m_WSABuffer;
  38.         private byte[] m_WSABufferArray;
  39.         private byte[] m_ControlBuffer;
  40.         internal byte[] m_MessageBuffer;
  41.         internal SocketFlags m_flags;
  42.        
  43.         private static readonly int s_ControlDataSize = Marshal.SizeOf(typeof(UnsafeNclNativeMethods.OSSOCK.ControlData));
  44.         private static readonly int s_ControlDataIPv6Size = Marshal.SizeOf(typeof(UnsafeNclNativeMethods.OSSOCK.ControlDataIPv6));
  45.         private static readonly int s_WSABufferSize = Marshal.SizeOf(typeof(WSABuffer));
  46.         private static readonly int s_WSAMsgSize = Marshal.SizeOf(typeof(UnsafeNclNativeMethods.OSSOCK.WSAMsg));
  47.        
  48.         internal IPPacketInformation m_IPPacketInformation;
  49.        
  50.         //
  51.         // the following two will be used only on WinNT to enable completion ports
  52.         //
  53.         //
  54.         // Constructor. We take in the socket that's creating us, the caller's
  55.         // state object, and the buffer on which the I/O will be performed.
  56.         // We save the socket and state, pin the callers's buffer, and allocate
  57.         // an event for the WaitHandle.
  58.         //
  59.         internal ReceiveMessageOverlappedAsyncResult(Socket socket, object asyncState, AsyncCallback asyncCallback) : base(socket, asyncState, asyncCallback)
  60.         {
  61.         }
  62.        
  63.         internal IntPtr GetSocketAddressSizePtr()
  64.         {
  65.             return Marshal.UnsafeAddrOfPinnedArrayElement(m_SocketAddress.m_Buffer, m_SocketAddress.GetAddressSizeOffset());
  66.         }
  67.        
  68.         internal SocketAddress SocketAddress {
  69.             get { return m_SocketAddress; }
  70.         }
  71.        
  72.        
  73.         //
  74.         // SetUnmanagedStructures -
  75.         // Fills in Overlapped Structures used in an Async Overlapped Winsock call
  76.         // these calls are outside the runtime and are unmanaged code, so we need
  77.         // to prepare specific structures and ints that lie in unmanaged memory
  78.         // since the Overlapped calls can be Async
  79.         //
  80.        
  81.         internal void SetUnmanagedStructures(byte[] buffer, int offset, int size, SocketAddress socketAddress, SocketFlags socketFlags)
  82.         {
  83.             //ipv4 or ipv6?
  84.             bool ipv4 = ((Socket)(AsyncObject)).AddressFamily == AddressFamily.InterNetwork;
  85.             bool ipv6 = ((Socket)(AsyncObject)).AddressFamily == AddressFamily.InterNetworkV6;
  86.            
  87.             m_MessageBuffer = new byte[s_WSAMsgSize];
  88.             m_WSABufferArray = new byte[s_WSABufferSize];
  89.            
  90.             //prepare control buffer
  91.             if (ipv4) {
  92.                 m_ControlBuffer = new byte[s_ControlDataSize];
  93.             }
  94.             else if (ipv6) {
  95.                 m_ControlBuffer = new byte[s_ControlDataIPv6Size];
  96.             }
  97.            
  98.             //pin buffers
  99.             object[] objectsToPin = new object[(m_ControlBuffer != null) ? 5 : 4];
  100.             objectsToPin[0] = buffer;
  101.             objectsToPin[1] = m_MessageBuffer;
  102.             objectsToPin[2] = m_WSABufferArray;
  103.            
  104.             //prepare socketaddress buffer
  105.             m_SocketAddress = socketAddress;
  106.             m_SocketAddress.CopyAddressSizeIntoBuffer();
  107.             objectsToPin[3] = m_SocketAddress.m_Buffer;
  108.            
  109.             if (m_ControlBuffer != null) {
  110.                 objectsToPin[4] = m_ControlBuffer;
  111.             }
  112.            
  113.             base.SetUnmanagedStructures(objectsToPin);
  114.            
  115.             //prepare data buffer
  116.             m_WSABuffer = (WSABuffer*)Marshal.UnsafeAddrOfPinnedArrayElement(m_WSABufferArray, 0);
  117.             m_WSABuffer->Length = size;
  118.             m_WSABuffer->Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset);
  119.            
  120.            
  121.             //setup structure
  122.             m_Message = (UnsafeNclNativeMethods.OSSOCK.WSAMsg*)Marshal.UnsafeAddrOfPinnedArrayElement(m_MessageBuffer, 0);
  123.             m_Message->socketAddress = Marshal.UnsafeAddrOfPinnedArrayElement(m_SocketAddress.m_Buffer, 0);
  124.             m_Message->addressLength = (uint)m_SocketAddress.Size;
  125.             m_Message->buffers = Marshal.UnsafeAddrOfPinnedArrayElement(m_WSABufferArray, 0);
  126.             m_Message->count = 1;
  127.            
  128.             if (m_ControlBuffer != null) {
  129.                 m_Message->controlBuffer.Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(m_ControlBuffer, 0);
  130.                 m_Message->controlBuffer.Length = m_ControlBuffer.Length;
  131.             }
  132.            
  133.             m_Message->flags = socketFlags;
  134.         }
  135.        
  136.         internal void SetUnmanagedStructures(byte[] buffer, int offset, int size, SocketAddress socketAddress, SocketFlags socketFlags, ref OverlappedCache overlappedCache)
  137.         {
  138.             SetupCache(ref overlappedCache);
  139.             SetUnmanagedStructures(buffer, offset, size, socketAddress, socketFlags);
  140.         }
  141.        
  142.         unsafe private void InitIPPacketInformation()
  143.         {
  144.            
  145.             IPAddress address = null;
  146.            
  147.             //ipv4
  148.             if (m_ControlBuffer.Length == s_ControlDataSize) {
  149.                 UnsafeNclNativeMethods.OSSOCK.ControlData controlData = (UnsafeNclNativeMethods.OSSOCK.ControlData)Marshal.PtrToStructure(m_Message->controlBuffer.Pointer, typeof(UnsafeNclNativeMethods.OSSOCK.ControlData));
  150.                 if (controlData.length != UIntPtr.Zero) {
  151.                     address = new IPAddress((long)controlData.address);
  152.                 }
  153.                 m_IPPacketInformation = new IPPacketInformation(((address != null) ? address : IPAddress.None), (int)controlData.index);
  154.             }
  155.             //ipv6
  156.             else if (m_ControlBuffer.Length == s_ControlDataIPv6Size) {
  157.                 UnsafeNclNativeMethods.OSSOCK.ControlDataIPv6 controlData = (UnsafeNclNativeMethods.OSSOCK.ControlDataIPv6)Marshal.PtrToStructure(m_Message->controlBuffer.Pointer, typeof(UnsafeNclNativeMethods.OSSOCK.ControlDataIPv6));
  158.                 if (controlData.length != UIntPtr.Zero) {
  159.                     address = new IPAddress(controlData.address);
  160.                 }
  161.                 m_IPPacketInformation = new IPPacketInformation(((address != null) ? address : IPAddress.IPv6None), (int)controlData.index);
  162.             }
  163.             //other
  164.             else {
  165.                 m_IPPacketInformation = new IPPacketInformation();
  166.             }
  167.         }
  168.        
  169.        
  170.         //
  171.         // This method is called after an asynchronous call is made for the user,
  172.         // it checks and acts accordingly if the IO:
  173.         // 1) completed synchronously.
  174.         // 2) was pended.
  175.         // 3) failed.
  176.         //
  177.        
  178.         internal void SyncReleaseUnmanagedStructures()
  179.         {
  180.             InitIPPacketInformation();
  181.             ForceReleaseUnmanagedStructures();
  182.         }
  183.        
  184.        
  185.         protected override void ForceReleaseUnmanagedStructures()
  186.         {
  187.             m_flags = m_Message->flags;
  188.             base.ForceReleaseUnmanagedStructures();
  189.         }
  190.        
  191.         internal override object PostCompletion(int numBytes)
  192.         {
  193.             InitIPPacketInformation();
  194.             if (ErrorCode == 0) {
  195.                 if (Logging.On)
  196.                     LogBuffer(numBytes);
  197.             }
  198.             return (int)numBytes;
  199.         }
  200.        
  201.         void LogBuffer(int size)
  202.         {
  203.             GlobalLog.Assert(Logging.On, "ReceiveMessageOverlappedAsyncResult#{0}::LogBuffer()|Logging is off!", ValidationHelper.HashString(this));
  204.             Logging.Dump(Logging.Sockets, AsyncObject, "PostCompletion", m_WSABuffer->Pointer, Math.Min(m_WSABuffer->Length, size));
  205.         }
  206.        
  207.     }
  208.     // class OverlappedAsyncResult
  209.    
  210.    
  211.    
  212. }
  213. // namespace System.Net.Sockets

Developer Fusion