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

  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.     internal class OverlappedAsyncResult : BaseOverlappedAsyncResult
  29.     {
  30.        
  31.         //
  32.         // internal class members
  33.         //
  34.        
  35.         private SocketAddress m_SocketAddress;
  36.         private SocketAddress m_SocketAddressOriginal;
  37.         // needed for partial BeginReceiveFrom/EndReceiveFrom completion
  38.         // These two are used only as alternatives
  39.         internal WSABuffer m_SingleBuffer;
  40.         internal WSABuffer[] m_WSABuffers;
  41.        
  42.         //
  43.         // the following two will be used only on WinNT to enable completion ports
  44.         //
  45.         //
  46.         // Constructor. We take in the socket that's creating us, the caller's
  47.         // state object, and the buffer on which the I/O will be performed.
  48.         // We save the socket and state, pin the callers's buffer, and allocate
  49.         // an event for the WaitHandle.
  50.         //
  51.         internal OverlappedAsyncResult(Socket socket, object asyncState, AsyncCallback asyncCallback) : base(socket, asyncState, asyncCallback)
  52.         {
  53.         }
  54.        
  55.         //
  56.         internal IntPtr GetSocketAddressPtr()
  57.         {
  58.             return Marshal.UnsafeAddrOfPinnedArrayElement(m_SocketAddress.m_Buffer, 0);
  59.         }
  60.         //
  61.         internal IntPtr GetSocketAddressSizePtr()
  62.         {
  63.             return Marshal.UnsafeAddrOfPinnedArrayElement(m_SocketAddress.m_Buffer, m_SocketAddress.GetAddressSizeOffset());
  64.         }
  65.         //
  66.         internal SocketAddress SocketAddress {
  67.             get { return m_SocketAddress; }
  68.         }
  69.         //
  70.         internal SocketAddress SocketAddressOriginal {
  71.             get { return m_SocketAddressOriginal; }
  72.             set { m_SocketAddressOriginal = value; }
  73.         }
  74.        
  75.         //
  76.         // SetUnmanagedStructures -
  77.         // Fills in Overlapped Structures used in an Async Overlapped Winsock call
  78.         // these calls are outside the runtime and are unmanaged code, so we need
  79.         // to prepare specific structures and ints that lie in unmanaged memory
  80.         // since the Overlapped calls can be Async
  81.         //
  82.        
  83.         internal void SetUnmanagedStructures(byte[] buffer, int offset, int size, SocketAddress socketAddress, bool pinSocketAddress)
  84.         {
  85.             //
  86.             // Fill in Buffer Array structure that will be used for our send/recv Buffer
  87.             //
  88.             m_SocketAddress = socketAddress;
  89.             if (pinSocketAddress && m_SocketAddress != null) {
  90.                 object[] objectsToPin = null;
  91.                 objectsToPin = new object[2];
  92.                 objectsToPin[0] = buffer;
  93.                
  94.                 m_SocketAddress.CopyAddressSizeIntoBuffer();
  95.                 objectsToPin[1] = m_SocketAddress.m_Buffer;
  96.                
  97.                 base.SetUnmanagedStructures(objectsToPin);
  98.             }
  99.             else {
  100.                 base.SetUnmanagedStructures(buffer);
  101.             }
  102.            
  103.             m_SingleBuffer.Length = size;
  104.             m_SingleBuffer.Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset);
  105.         }
  106.        
  107.         internal void SetUnmanagedStructures(byte[] buffer, int offset, int size, SocketAddress socketAddress, bool pinSocketAddress, ref OverlappedCache overlappedCache)
  108.         {
  109.             SetupCache(ref overlappedCache);
  110.             SetUnmanagedStructures(buffer, offset, size, socketAddress, pinSocketAddress);
  111.         }
  112.        
  113.         internal void SetUnmanagedStructures(BufferOffsetSize[] buffers)
  114.         {
  115.            
  116.             //
  117.             // Fill in Buffer Array structure that will be used for our send/recv Buffer
  118.             //
  119.             m_WSABuffers = new WSABuffer[buffers.Length];
  120.            
  121.             object[] objectsToPin = new object[buffers.Length];
  122.             for (int i = 0; i < buffers.Length; i++)
  123.                 objectsToPin[i] = buffers[i].Buffer;
  124.            
  125.             // has to be called now to pin memory
  126.             base.SetUnmanagedStructures(objectsToPin);
  127.            
  128.             for (int i = 0; i < buffers.Length; i++) {
  129.                 m_WSABuffers[i].Length = buffers[i].Size;
  130.                 m_WSABuffers[i].Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(buffers[i].Buffer, buffers[i].Offset);
  131.             }
  132.         }
  133.        
  134.         internal void SetUnmanagedStructures(BufferOffsetSize[] buffers, ref OverlappedCache overlappedCache)
  135.         {
  136.             SetupCache(ref overlappedCache);
  137.             SetUnmanagedStructures(buffers);
  138.         }
  139.        
  140.         internal void SetUnmanagedStructures(IList<ArraySegment<byte>> buffers)
  141.         {
  142.            
  143.             // Fill in Buffer Array structure that will be used for our send/recv Buffer
  144.             //
  145.            
  146.             //make sure we don't let the app mess up the buffer array enough to cause
  147.             //corruption.
  148.             int count = buffers.Count;
  149.             ArraySegment<byte>[] buffersCopy = new ArraySegment<byte>[count];
  150.            
  151.             for (int i = 0; i < count; i++) {
  152.                 buffersCopy[i] = buffers[i];
  153.             }
  154.            
  155.             m_WSABuffers = new WSABuffer[count];
  156.            
  157.             object[] objectsToPin = new object[count];
  158.             for (int i = 0; i < count; i++)
  159.                 objectsToPin[i] = buffersCopy[i].Array;
  160.            
  161.             base.SetUnmanagedStructures(objectsToPin);
  162.            
  163.             for (int i = 0; i < count; i++) {
  164.                 m_WSABuffers[i].Length = buffersCopy[i].Count;
  165.                 m_WSABuffers[i].Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(buffersCopy[i].Array, buffersCopy[i].Offset);
  166.             }
  167.         }
  168.        
  169.         internal void SetUnmanagedStructures(IList<ArraySegment<byte>> buffers, ref OverlappedCache overlappedCache)
  170.         {
  171.             SetupCache(ref overlappedCache);
  172.             SetUnmanagedStructures(buffers);
  173.         }
  174.        
  175.         //
  176.         // This method is called after an asynchronous call is made for the user,
  177.         // it checks and acts accordingly if the IO:
  178.         // 1) completed synchronously.
  179.         // 2) was pended.
  180.         // 3) failed.
  181.         //
  182.         internal override object PostCompletion(int numBytes)
  183.         {
  184.             if (ErrorCode == 0) {
  185.                 if (Logging.On)
  186.                     LogBuffer(numBytes);
  187.             }
  188.             return (int)numBytes;
  189.         }
  190.        
  191.         void LogBuffer(int size)
  192.         {
  193.             GlobalLog.Assert(Logging.On, "OverlappedAsyncResult#{0}::LogBuffer()|Logging is off!", ValidationHelper.HashString(this));
  194.             if (size > -1) {
  195.                 if (m_WSABuffers != null) {
  196.                     foreach (WSABuffer wsaBuffer in m_WSABuffers) {
  197.                         Logging.Dump(Logging.Sockets, AsyncObject, "PostCompletion", wsaBuffer.Pointer, Math.Min(wsaBuffer.Length, size));
  198.                         if ((size -= wsaBuffer.Length) <= 0)
  199.                             break;
  200.                     }
  201.                 }
  202.                 else {
  203.                     Logging.Dump(Logging.Sockets, AsyncObject, "PostCompletion", m_SingleBuffer.Pointer, Math.Min(m_SingleBuffer.Length, size));
  204.                 }
  205.             }
  206.         }
  207.        
  208.     }
  209.     // class OverlappedAsyncResult
  210.    
  211.    
  212.    
  213. }
  214. // namespace System.Net.Sockets

Developer Fusion