System.Runtime.Remoting.Channels

来源:互联网 发布:堡垒机网络部署案例 编辑:程序博客网 时间:2024/05/18 02:37
  1. // ==++==
  2. // 
  3. //   
  4. //    Copyright (c) 2002 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. // 
  14. // ==--==
  15. /*============================================================
  16. **
  17. ** File:    IChannel.cs
  18. **
  19. ** Author:                                     
  20. **                                             
  21. **
  22. ** Purpose: Defines the interfaces implemented by channels
  23. **
  24. ** Date:    May 27, 1999
  25. **
  26. ===========================================================*/
  27. namespace System.Runtime.Remoting.Channels {
  28.     using System.Collections;
  29.     using System.IO;
  30.     using System.Runtime.Remoting;
  31.     using System.Runtime.Remoting.Messaging;
  32.     using System.Runtime.Remoting.Metadata;
  33.     using System.Security.Permissions;
  34.     using System;
  35.     using System.Globalization;
  36.     
  37.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannel"]/*' />
  38.     public interface IChannel
  39.     {
  40.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannel.ChannelPriority"]/*' />
  41.         int ChannelPriority 
  42.     {
  43.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)] 
  44.             get
  45.     }
  46.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannel.ChannelName"]/*' />
  47.         String ChannelName
  48.         {
  49.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)] 
  50.         get
  51.         }
  52.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannel.Parse"]/*' />
  53.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)] 
  54.         String Parse(String url, out String objectURI);
  55.     }
  56.     
  57.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannelSender"]/*' />
  58.     public interface IChannelSender : IChannel
  59.     {
  60.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannelSender.CreateMessageSink"]/*' />
  61.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)] 
  62.         IMessageSink CreateMessageSink(String url, Object remoteChannelData, out String objectURI);
  63.     } // interface IChannelSender
  64.     
  65.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannelReceiver"]/*' />
  66.     public interface IChannelReceiver : IChannel
  67.     {
  68.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannelReceiver.ChannelData"]/*' />
  69.         Object ChannelData 
  70.         {
  71.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)] 
  72.         get;
  73.     }
  74.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannelReceiver.GetUrlsForUri"]/*' />
  75.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)] 
  76.         String[] GetUrlsForUri(String objectURI);
  77.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannelReceiver.StartListening"]/*' />
  78.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)] 
  79.         void StartListening(Object data);
  80.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannelReceiver.StopListening"]/*' />
  81.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)] 
  82.         void StopListening(Object data);
  83.     } // interface IChannelReceiver 
  84.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannelReceiverHook"]/*' />
  85.     public interface IChannelReceiverHook
  86.     {
  87.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannelReceiverHook.ChannelScheme"]/*' />
  88.         String ChannelScheme
  89.     {
  90.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)] 
  91.             get;
  92.     }
  93.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannelReceiverHook.WantsToListen"]/*' />
  94.         bool WantsToListen
  95.         { 
  96.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)] 
  97.         get;
  98.         }
  99.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannelReceiverHook.ChannelSinkChain"]/*' />
  100.         IServerChannelSink ChannelSinkChain
  101.         {
  102.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]     
  103.          get;
  104.         }
  105.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannelReceiverHook.AddHookChannelUri"]/*' />
  106.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)] 
  107.         void AddHookChannelUri(String channelUri);
  108.         
  109.     } // interface IChannelReceiverHook
  110.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="IClientChannelSinkProvider"]/*' />
  111.     public interface IClientChannelSinkProvider
  112.     {
  113.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IClientChannelSinkProvider.CreateSink"]/*' />
  114.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)] 
  115.         IClientChannelSink CreateSink(IChannelSender channel, String url, Object remoteChannelData);
  116.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IClientChannelSinkProvider.Next"]/*' />
  117.         IClientChannelSinkProvider Next 
  118.         {
  119.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)] 
  120.          get;
  121.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  122.           set
  123.         }
  124.     } // interface IClientChannelSinkProvider
  125.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="IServerChannelSinkProvider"]/*' />
  126.     public interface IServerChannelSinkProvider
  127.     {
  128.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IServerChannelSinkProvider.GetChannelData"]/*' />
  129.         // The sink provider should also chain this call to the next provider in the chain.
  130.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  131.         void GetChannelData(IChannelDataStore channelData);
  132.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IServerChannelSinkProvider.CreateSink"]/*' />
  133.         
  134.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  135.         IServerChannelSink CreateSink(IChannelReceiver channel);
  136.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IServerChannelSinkProvider.Next"]/*' />
  137.         IServerChannelSinkProvider Next
  138.     { 
  139.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  140.         get;
  141.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  142.             set;
  143.     }
  144.     } // interface IServerChannelSinkProvider
  145.     // This has the same exact functionality as IClientChannelSinkProvider.
  146.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="IClientFormatterSinkProvider"]/*' />
  147.     public interface IClientFormatterSinkProvider : IClientChannelSinkProvider
  148.     {
  149.     } // interface IClientFormatterSinkProvider
  150.     // This has the same exact functionality as IServerChannelSinkProvider.
  151.     // There may be multiple formatter sinks. If there are more than one, then one
  152.     // formatter sink may decide to delegate the formatting responsibilities to the next
  153.     // one.
  154.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="IServerFormatterSinkProvider"]/*' />
  155.     public interface IServerFormatterSinkProvider : IServerChannelSinkProvider
  156.     {
  157.     } // interface IServerFormatterSinkProvider
  158.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="IClientChannelSink"]/*' />
  159.     public interface IClientChannelSink : IChannelSinkBase
  160.     {
  161.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IClientChannelSink.ProcessMessage"]/*' />
  162.         // Parameters:
  163.         //   msg - it's the "IMethodCallMessage"
  164.         //   requestHeaders - headers to add to the outgoing message heading to server
  165.         //   requestStream - stream headed towards the transport sink
  166.         //   responseHeaders - headers that server returned
  167.         //   responseStream - stream coming back from the transport sink
  168.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  169.         void ProcessMessage(IMessage msg,
  170.                             ITransportHeaders requestHeaders, Stream requestStream,
  171.                             out ITransportHeaders responseHeaders, out Stream responseStream);
  172.                             
  173.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IClientChannelSink.AsyncProcessRequest"]/*' />
  174.         // Parameters: (for async calls, the transport sink is responsible for doing the write
  175.         //     and read asynchronously)
  176.         //   sinkStack - channel sinks who called this one
  177.         //   msg - it's the "IMessage" msg
  178.         //   headers - headers to add to the outgoing message heading to server
  179.         //   stream - stream headed towards the transport sink
  180.         // Returns:
  181.         //   IAsyncResult for this call.
  182.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  183.         void AsyncProcessRequest(IClientChannelSinkStack sinkStack, IMessage msg,
  184.                                  ITransportHeaders headers, Stream stream);
  185.                                  
  186.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IClientChannelSink.AsyncProcessResponse"]/*' />
  187.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  188.         void AsyncProcessResponse(IClientResponseChannelSinkStack sinkStack, Object state,
  189.                                   ITransportHeaders headers, Stream stream);
  190.                                   
  191.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IClientChannelSink.GetRequestStream"]/*' />
  192.         // Parameters:
  193.         //   msg - it's the "IMethodCallMessage"
  194.         //   headers - headers to add to the outgoing message heading to server
  195.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  196.         Stream GetRequestStream(IMessage msg, ITransportHeaders headers);
  197.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IClientChannelSink.NextChannelSink"]/*' />
  198.         // the next channel sink in the chain
  199.         IClientChannelSink NextChannelSink
  200.         { 
  201.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  202.         get;
  203.     }
  204.         
  205.     } // IClientChannelSink
  206.     
  207.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="ServerProcessing"]/*' />
  208.     [Serializable]
  209.     public enum ServerProcessing
  210.     {
  211.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="ServerProcessing.Complete"]/*' />
  212.         Complete, // server synchronously processed message
  213.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="ServerProcessing.OneWay"]/*' />
  214.         OneWay,   // message dispatched and no response should be sent
  215.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="ServerProcessing.Async"]/*' />
  216.         Async     // the call was dispatched asynchronously
  217.                   //   (sink should store data on stack for later processing)
  218.     } // ServerProcessing
  219.     // Used for security sink and transport sinks.
  220.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="IServerChannelSink"]/*' />
  221.     public interface IServerChannelSink : IChannelSinkBase
  222.     {
  223.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IServerChannelSink.ProcessMessage"]/*' />
  224.         // Parameters:
  225.         //   sinkStack - channel sinks who called this one
  226.         //   requestMsg - deserialized request message or null if the stream hasn't been deserialized
  227.         //   requestHeaders - headers retrieved from the incoming message from client
  228.         //   requestStream - stream to process and pass onto towards the deserialization sink.
  229.         //   responseMsg - response message
  230.         //   responseHeaders - headers to add to return message heading to client
  231.         //   responseStream - stream heading back towards the transport sink
  232.         // Returns:
  233.         //   Provides information about how message was processed.
  234.     [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  235.         ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack,
  236.                                         IMessage requestMsg,
  237.                                         ITransportHeaders requestHeaders, Stream requestStream,
  238.                                         out IMessage responseMsg, out ITransportHeaders responseHeaders,
  239.                                         out Stream responseStream);
  240.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IServerChannelSink.AsyncProcessResponse"]/*' />
  241.         // Parameters: (for async calls)
  242.         //   sinkStack - sink stack (leading back to the server transport sink)
  243.         //   headers - headers to add to return message heading to client
  244.         //   stream - stream heading back towards the transport sink
  245.     [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  246.         void AsyncProcessResponse(IServerResponseChannelSinkStack sinkStack, Object state,
  247.                                   IMessage msg, ITransportHeaders headers, Stream stream);                   
  248.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IServerChannelSink.GetResponseStream"]/*' />
  249.         // Parameters:
  250.         //   sinkStack - sink stack (leading back to the server transport sink)  
  251.         //   state - state that had been pushed to the stack by this sink
  252.         //   msg - it's the "IMethodCallMessage"
  253.         //   headers - headers to put in response message to client 
  254.     [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  255.         Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack, Object state,
  256.                                  IMessage msg, ITransportHeaders headers);                               
  257.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IServerChannelSink.NextChannelSink"]/*' />
  258.         // the next channel sink in the chain
  259.         IServerChannelSink NextChannelSink 
  260.         {
  261.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  262.          get;
  263.         }
  264.     } // interface IServerChannelSink
  265.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannelSinkBase"]/*' />
  266.     public interface IChannelSinkBase
  267.     {
  268.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannelSinkBase.Properties"]/*' />
  269.         // This returns a dictionary through which properties on the sink may be retrieved
  270.         // or configured. If a property is not present in this sink, it should delegate the
  271.         // the property get or set to the next sink in the chain.
  272.         IDictionary Properties 
  273.     {
  274.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  275.          get;
  276.     }  
  277.     }
  278.     // Client formatter sinks are both a message sink and a channel sink.
  279.     // They initially transform the message into a stream.
  280.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="IClientFormatterSink"]/*' />
  281.     public interface IClientFormatterSink : IMessageSink, IClientChannelSink
  282.     {
  283.     } // interface IClientFormatterSink
  284.     // Channels wishing to use the channel sink architecture must implement this interface
  285.     //   on their ChannelData object.
  286.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannelDataStore"]/*' />
  287.     public interface IChannelDataStore
  288.     {
  289.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannelDataStore.ChannelUris"]/*' />
  290.         String[] ChannelUris 
  291.     {
  292.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]             
  293.          get;
  294.     }
  295.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="IChannelDataStore.this"]/*' />
  296.     
  297.         Object this[Object key] 
  298.         {
  299.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  300.          get;
  301.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  302.          set;
  303.     }
  304.     } // interface IChannelDataStore
  305.     // Used to store channel data for our remoting channels
  306.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="ChannelDataStore"]/*' />
  307.     [Serializable]
  308.     public class ChannelDataStore : IChannelDataStore
  309.     {
  310.         String[]           _channelURIs;  // list of channel uri's that map to this channel
  311.         
  312.         DictionaryEntry[]  _extraData;    // sink data
  313.         // private constructor for shallow clone    
  314.         private ChannelDataStore(String[] channelUrls, DictionaryEntry[] extraData)
  315.         {
  316.             _channelURIs = channelUrls;
  317.             _extraData = extraData;
  318.         }
  319.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="ChannelDataStore.ChannelDataStore"]/*' />
  320.         public ChannelDataStore(String[] channelURIs)
  321.         {
  322.             _channelURIs = channelURIs;
  323.             _extraData = null;
  324.         }
  325.         internal ChannelDataStore InternalShallowCopy()
  326.         {
  327.             return new ChannelDataStore(_channelURIs, _extraData);
  328.         }
  329.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="ChannelDataStore.ChannelUris"]/*' />
  330.         public String[] ChannelUris
  331.         {
  332.             get { return _channelURIs; }
  333.             set { _channelURIs = value; }
  334.         }
  335.         // implementation of IChannelDataStore
  336.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="ChannelDataStore.this"]/*' />
  337.         public Object this[Object key]
  338.         {
  339.             get 
  340.             {
  341.                 // look for matching key in extra data list
  342.                 foreach (DictionaryEntry entry in _extraData)
  343.                 {
  344.                     if (entry.Key.Equals(key))
  345.                         return entry.Value;                    
  346.                 }
  347.                 // entry not found
  348.                 return null;
  349.             } // get
  350.             set
  351.             {
  352.                 if (_extraData == null)
  353.                 {
  354.                     _extraData = new DictionaryEntry[1];
  355.                     _extraData[0] = new DictionaryEntry(key, value);
  356.                 }
  357.                 else
  358.                 {
  359.                     int length =_extraData.Length;
  360.                     DictionaryEntry[] newList = new DictionaryEntry[length + 1];
  361.                     int co = 0;
  362.                     for (; co < length; co++)
  363.                         newList[co] = _extraData[co];
  364.                     newList[co] = new DictionaryEntry(key, value); // set last value
  365.                     _extraData = newList;
  366.                 }
  367.             } // set
  368.         } // Object this[Object key]
  369.         
  370.     } // class ChannelDataStore
  371.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="ITransportHeaders"]/*' />
  372.     public interface ITransportHeaders
  373.     {
  374.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="ITransportHeaders.this"]/*' />
  375.         // Should add headers in order, and remove them if somebody tries to set
  376.         //   it to null.
  377.         Object this[Object key]
  378.     { 
  379.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  380.         get;
  381.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  382.         set;
  383.     }
  384.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="ITransportHeaders.GetEnumerator"]/*' />
  385.         // This is required to handback an enumerator which iterates over all entries
  386.         //   in the headers.
  387.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]         
  388.         IEnumerator GetEnumerator();
  389.     } // interface ITransportHeaders
  390.     // TransportHeaders is used to store a collection of headers that is used in the channel sinks.
  391.     // The header list preserves order, and keeps headers in the order that they were originally
  392.     // added. You can use the foreach statement to iterate over the contents of the header list 
  393.     // which contains objects of type DictionaryEntry. Keys are required to be strings, and
  394.     // comparisons are done on a case-insensitive basis.
  395.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="TransportHeaders"]/*' />
  396.     [Serializable]
  397.     public class TransportHeaders : ITransportHeaders
  398.     {
  399.         private ArrayList _headerList; // array of type DictionaryEntry
  400.     
  401.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="TransportHeaders.TransportHeaders"]/*' />
  402.         public TransportHeaders()
  403.         {
  404.             // The default capacity is larger than we'll typically need so start off at 6.
  405.             _headerList = new ArrayList(6);
  406.         } // TransportHeaders
  407.         // dictionary like interface
  408.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="TransportHeaders.this"]/*' />
  409.         public Object this[Object key]
  410.         {
  411.             get 
  412.             {
  413.                 String strKey = (String)key;
  414.                 
  415.                 // look for matching key in header list
  416.                 foreach (DictionaryEntry entry in _headerList)
  417.                 {
  418.                     if (String.Compare((String)entry.Key, strKey, true, CultureInfo.InvariantCulture) == 0)
  419.                         return entry.Value;                    
  420.                 }
  421.                 // entry not found
  422.                 return null;
  423.             } // get
  424.             set
  425.             {
  426.                 if (key == null)
  427.                     return;
  428.                 String strKey = (String)key;
  429.                 // remove this entry if it's already in the list
  430.                 int co = _headerList.Count - 1;
  431.                 while (co >= 0)
  432.                 {                
  433.                     String headerKey = (String)((DictionaryEntry)_headerList[co]).Key;
  434.                     if (String.Compare(headerKey, strKey, true, CultureInfo.InvariantCulture) == 0)
  435.                     {
  436.                         _headerList.RemoveAt(co);
  437.                         break;
  438.                     }
  439.                     co--;
  440.                 }
  441.                 // otherwise, add this entry
  442.                 if (value != null)
  443.                 {
  444.                     _headerList.Add(new DictionaryEntry(key, value));
  445.                 }
  446.             } // set
  447.         } // Object this[Object key]
  448.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="TransportHeaders.GetEnumerator"]/*' />
  449.         public IEnumerator GetEnumerator() 
  450.         {
  451.             return _headerList.GetEnumerator(); 
  452.         } // GetEnumerator
  453.         
  454.     } // TransportHeaders
  455.     // All sink providers must have a constructor that accepts a hashtable and 
  456.     //   an ArrayList of these structures if they want to be used from a config file.
  457.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="SinkProviderData"]/*' />
  458.     public class SinkProviderData
  459.     {
  460.         private String _name;
  461.         private Hashtable _properties = new Hashtable(new CaseInsensitiveHashCodeProvider(CultureInfo.InvariantCulture), new CaseInsensitiveComparer(CultureInfo.InvariantCulture));
  462.         private ArrayList _children = new ArrayList();
  463.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="SinkProviderData.SinkProviderData"]/*' />
  464.         public SinkProviderData(String name) 
  465.         {
  466.             _name = name;
  467.         }
  468.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="SinkProviderData.Name"]/*' />
  469.         public String Name { get { return _name; } }
  470.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="SinkProviderData.Properties"]/*' />
  471.         public IDictionary Properties { get { return _properties; } }
  472.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="SinkProviderData.Children"]/*' />
  473.         public IList Children { get { return _children; } }
  474.     } // class SinkProviderData
  475.     // Base implementation for channel sinks that want to supply properties.
  476.     // The derived class only needs to implement the Keys property and this[].
  477.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelSinkWithProperties"]/*' />
  478.     public abstract class BaseChannelSinkWithProperties : BaseChannelObjectWithProperties
  479.     {       
  480.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelSinkWithProperties.BaseChannelSinkWithProperties"]/*' />
  481.         protected BaseChannelSinkWithProperties() : base()
  482.         {
  483.         }    
  484.     } // class BaseChannelSinkWithProperties
  485.     // This provides a base implementation of a channel that wants
  486.     // to provide a dictionary interface. It handles the complexity
  487.     // of asking a channel sink chain for their properties.
  488.     // Once the channel constructs its sink chain (usually only applicable
  489.     // for server channels) it should set the SinksWithProperties property.
  490.     // The properties only get chained for channel sinks when the users asks
  491.     // for the "Properties" dictionary. If you just go through the dictionary interface
  492.     // you'll only get the channel specific properties.
  493.     // The derived class only needs to implement the Keys property and this[].
  494.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelWithProperties"]/*' />
  495.     public abstract class BaseChannelWithProperties : BaseChannelObjectWithProperties
  496.     {    
  497.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelWithProperties.SinksWithProperties"]/*' />
  498.         protected IChannelSinkBase SinksWithProperties = null;
  499.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelWithProperties.BaseChannelWithProperties"]/*' />
  500.         protected BaseChannelWithProperties() : base()
  501.         {
  502.         }
  503.         // This is overridden so that server channels can expose the properties
  504.         //   of their channel sinks through a flat dictionary interface.
  505.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelWithProperties.Properties"]/*' />
  506.         public override IDictionary Properties 
  507.         {
  508.             get
  509.             {
  510.                 // collect dictionaries for all channel sinks and return
  511.                 //   aggregate dictionary
  512.                 ArrayList dictionaries = new ArrayList();
  513.                 // add the channel itself
  514.                 dictionaries.Add(this);
  515.                 if (SinksWithProperties != null)
  516.                 {
  517.                     IServerChannelSink srvSink = SinksWithProperties as IServerChannelSink;
  518.                     if (srvSink != null)
  519.                     {
  520.                         while (srvSink != null)
  521.                         {
  522.                             IDictionary dict = srvSink.Properties;
  523.                             if (dict != null)
  524.                                 dictionaries.Add(dict);
  525.                             srvSink = srvSink.NextChannelSink;
  526.                         }
  527.                     }
  528.                     else
  529.                     {
  530.                         // we know it's a client channel sink
  531.                         IClientChannelSink chnlSink = (IClientChannelSink)SinksWithProperties;                        
  532.                         
  533.                         while (chnlSink != null)
  534.                         {
  535.                             IDictionary dict = chnlSink.Properties;
  536.                             if (dict != null)
  537.                                 dictionaries.Add(dict);
  538.                             chnlSink = chnlSink.NextChannelSink;
  539.                         }
  540.                     }                    
  541.                 }
  542.                 // return a dictionary that spans all dictionaries provided
  543.                 return new AggregateDictionary(dictionaries);
  544.             }
  545.         } 
  546.     } // class BaseChannelWithProperties
  547.     
  548.     // Base implementation for channel sinks that want to supply properties.
  549.     // The derived class only needs to implement the Keys property and this[].
  550.     /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelObjectWithProperties"]/*' />
  551.     public abstract class BaseChannelObjectWithProperties : IDictionary
  552.     {
  553.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelObjectWithProperties.BaseChannelObjectWithProperties"]/*' />
  554.         public BaseChannelObjectWithProperties()
  555.         {
  556.         }   
  557.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelObjectWithProperties.Properties"]/*' />
  558.         public virtual IDictionary Properties { get { return this; } }
  559.         // 
  560.         // IDictionary implementation        
  561.         //
  562.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelObjectWithProperties.this"]/*' />
  563.         public virtual Object this[Object key]
  564.         {
  565.             get { return null; }            
  566.             set { throw new NotImplementedException(); } 
  567.         } // Object this[Object key]
  568.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelObjectWithProperties.Keys"]/*' />
  569.         public virtual ICollection Keys { get { return null; } }
  570.         
  571.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelObjectWithProperties.Values"]/*' />
  572.         public virtual ICollection Values
  573.         {
  574.             get
  575.             {
  576.                 ICollection keys = Keys;
  577.                 if (keys == null)
  578.                     return null;
  579.                 ArrayList values = new ArrayList();
  580.                 foreach (Object key in keys)
  581.                 {
  582.                     values.Add(this[key]);
  583.                 }                
  584.                 return values;
  585.             }
  586.         }       
  587.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelObjectWithProperties.Contains"]/*' />
  588.         public virtual bool Contains(Object key) 
  589.         {
  590.             if (key == null)
  591.                 return false;
  592.             ICollection keySet = Keys;
  593.             if (keySet == null)
  594.                 return false;
  595.             String keyStr = key as String;
  596.         
  597.             foreach (Object someKey in keySet)
  598.             {
  599.                 if (keyStr != null)
  600.                 {
  601.                     String someKeyStr = someKey as String;
  602.                     if (someKeyStr != null)
  603.                     {
  604.                         // compare the key strings case-insensitively
  605.                         if (String.Compare(keyStr, someKeyStr, true, CultureInfo.InvariantCulture) == 0)
  606.                             return true;
  607.                         continue;
  608.                     }
  609.                 }                
  610.             
  611.                 if (key.Equals(someKey))
  612.                     return true;
  613.             }
  614.             return false;
  615.         } // Contains
  616.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelObjectWithProperties.IsReadOnly"]/*' />
  617.         public virtual bool IsReadOnly { get { return false; } }
  618.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelObjectWithProperties.IsFixedSize"]/*' />
  619.         public virtual bool IsFixedSize { get { return true; } } 
  620.         // The following three methods should never be implemented because
  621.         // they don't apply to the way IDictionary is being used in this case
  622.         // (plus, IsFixedSize returns true.)
  623.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelObjectWithProperties.Add"]/*' />
  624.         public virtual void Add(Object key, Object value) { throw new NotSupportedException(); }
  625.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelObjectWithProperties.Clear"]/*' />
  626.         public virtual void Clear() { throw new NotSupportedException(); }
  627.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelObjectWithProperties.Remove"]/*' />
  628.         public virtual void Remove(Object key) { throw new NotSupportedException(); }
  629.         
  630.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelObjectWithProperties.GetEnumerator"]/*' />
  631.         public virtual IDictionaryEnumerator GetEnumerator()
  632.         {
  633.             return new DictionaryEnumeratorByKeys(this);
  634.         } // GetEnumerator
  635.                             
  636.         //
  637.         // end of IDictionary implementation 
  638.         //
  639.         //
  640.         // ICollection implementation 
  641.         //
  642.          //ICollection
  643.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelObjectWithProperties.CopyTo"]/*' />
  644.         public virtual void CopyTo(Array array, int index) { throw new NotSupportedException(); }
  645.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelObjectWithProperties.Count"]/*' />
  646.         public virtual int Count 
  647.         {
  648.             get 
  649.             {
  650.                 ICollection keySet = Keys;
  651.                 if (keySet == null)
  652.                     return 0;
  653.                     
  654.                 return keySet.Count; 
  655.             }
  656.         } // Count
  657.         
  658.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelObjectWithProperties.SyncRoot"]/*' />
  659.         public virtual Object SyncRoot { get { return this; } }
  660.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelObjectWithProperties.IsSynchronized"]/*' />
  661.         public virtual bool IsSynchronized { get { return false; } }
  662.         //
  663.         // end of ICollection implementation
  664.         //
  665.         //IEnumerable
  666.         /// <include file='doc/IChannel.uex' path='docs/doc[@for="BaseChannelObjectWithProperties.IEnumerable.GetEnumerator"]/*' />
  667.         /// <internalonly/>
  668.         IEnumerator IEnumerable.GetEnumerator()
  669.         {
  670.             return new DictionaryEnumeratorByKeys(this);
  671.         }
  672.     
  673.     } // class BaseChannelObjectWithProperties
  674.     // an enumerator based off of a key set
  675.     internal class DictionaryEnumeratorByKeys : IDictionaryEnumerator
  676.     {
  677.         IDictionary _properties;
  678.         IEnumerator _keyEnum;
  679.     
  680.         public DictionaryEnumeratorByKeys(IDictionary properties)
  681.         {
  682.             _properties = properties;
  683.             _keyEnum = properties.Keys.GetEnumerator();
  684.         } // PropertyEnumeratorByKeys
  685.         public bool MoveNext() { return _keyEnum.MoveNext(); }        
  686.         public void Reset() { _keyEnum.Reset(); }        
  687.         public Object Current { get { return Entry; } }
  688.         public DictionaryEntry Entry { get { return new DictionaryEntry(Key, Value); } }
  689.         
  690.         public Object Key { get { return _keyEnum.Current; } }
  691.         public Object Value { get { return _properties[Key]; } }       
  692.         
  693.     } // DictionaryEnumeratorByKeys
  694.     // combines multiple dictionaries into one
  695.     //   (used for channel sink properties
  696.     internal class AggregateDictionary : IDictionary
  697.     {
  698.         private ICollection _dictionaries;
  699.             
  700.         public AggregateDictionary(ICollection dictionaries)
  701.         { 
  702.             _dictionaries = dictionaries;
  703.         } // AggregateDictionary  
  704.         // 
  705.         // IDictionary implementation        
  706.         //
  707.         public virtual Object this[Object key]
  708.         {
  709.             get 
  710.             {
  711.                 foreach (IDictionary dict in _dictionaries)
  712.                 {
  713.                     if (dict.Contains(key))
  714.                         return dict[key];
  715.                 }
  716.             
  717.                 return null
  718.             }
  719.                 
  720.             set
  721.             {
  722.                 foreach (IDictionary dict in _dictionaries)
  723.                 {
  724.                     if (dict.Contains(key))
  725.                         dict[key] = value;
  726.                 }
  727.             } 
  728.         } // Object this[Object key]
  729.         public virtual ICollection Keys 
  730.         {
  731.             get
  732.             {
  733.                 ArrayList keys = new ArrayList();
  734.                 // add keys from every dictionary
  735.                 foreach (IDictionary dict in _dictionaries)
  736.                 {
  737.                     ICollection dictKeys = dict.Keys;
  738.                     if (dictKeys != null)
  739.                     {
  740.                         foreach (Object key in dictKeys)
  741.                         {
  742.                             keys.Add(key);
  743.                         }
  744.                     }
  745.                 }
  746.                 return keys;
  747.             }
  748.         } // Keys
  749.         
  750.         public virtual ICollection Values
  751.         {
  752.             get
  753.             {
  754.                 ArrayList values = new ArrayList();
  755.                 // add values from every dictionary
  756.                 foreach (IDictionary dict in _dictionaries)
  757.                 {
  758.                     ICollection dictValues = dict.Values;
  759.                     if (dictValues != null)
  760.                     {
  761.                         foreach (Object value in dictValues)
  762.                         {
  763.                             values.Add(value);
  764.                         }
  765.                     }
  766.                 }
  767.                 return values;
  768.             }
  769.         } // Values
  770.         public virtual bool Contains(Object key) 
  771.         {
  772.             foreach (IDictionary dict in _dictionaries)
  773.             {
  774.                 if (dict.Contains(key))
  775.                     return true;
  776.             }
  777.             
  778.             return false
  779.         } // Contains
  780.         public virtual bool IsReadOnly { get { return false; } }
  781.         public virtual bool IsFixedSize { get { return true; } } 
  782.         // The following three methods should never be implemented because
  783.         // they don't apply to the way IDictionary is being used in this case
  784.         // (plus, IsFixedSize returns true.)
  785.         public virtual void Add(Object key, Object value) { throw new NotSupportedException(); }
  786.         public virtual void Clear() { throw new NotSupportedException(); }
  787.         public virtual void Remove(Object key) { throw new NotSupportedException(); }
  788.         
  789.         public virtual IDictionaryEnumerator GetEnumerator()
  790.         {
  791.             return new DictionaryEnumeratorByKeys(this);
  792.         } // GetEnumerator
  793.                             
  794.         //
  795.         // end of IDictionary implementation 
  796.         //
  797.         //
  798.         // ICollection implementation 
  799.         //
  800.         //ICollection
  801.         public virtual void CopyTo(Array array, int index) { throw new NotSupportedException(); }
  802.         public virtual int Count 
  803.         {
  804.             get 
  805.             {
  806.                 int count = 0;
  807.             
  808.                 foreach (IDictionary dict in _dictionaries)
  809.                 {
  810.                     count += dict.Count;
  811.                 }
  812.                 return count;
  813.             }
  814.         } // Count
  815.         
  816.         public virtual Object SyncRoot { get { return this; } }
  817.         public virtual bool IsSynchronized { get { return false; } }
  818.         //
  819.         // end of ICollection implementation
  820.         //
  821.         //IEnumerable
  822.         IEnumerator IEnumerable.GetEnumerator()
  823.         {
  824.             return new DictionaryEnumeratorByKeys(this);
  825.         }
  826.     
  827.     } // class AggregateDictionary
  828.     
  829. // namespace System.Runtime.Remoting