The Labs \ Source Viewer \ SSCLI \ System.Runtime.Remoting.Channels.Http \ HttpServerTransportSink

  1. // ==++==
  2. //
  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. //
  14. // ==--==
  15. //==========================================================================
  16. // File: HttpServerChannel.cs
  17. //
  18. // Summary: Implements a client channel that transmits method calls over HTTP.
  19. //
  20. // Classes: public HttpClientChannel
  21. // internal HttpClientTransportSink
  22. //
  23. //==========================================================================
  24. using System;
  25. using System.Collections;
  26. using System.IO;
  27. using System.Net;
  28. using System.Net.Sockets;
  29. using System.Reflection;
  30. using System.Runtime.Remoting;
  31. using System.Runtime.Remoting.Channels;
  32. using System.Runtime.Remoting.Messaging;
  33. using System.Runtime.Remoting.Metadata;
  34. using System.Runtime.Remoting.MetadataServices;
  35. using System.Security.Cryptography.X509Certificates;
  36. using System.Security.Principal;
  37. using System.Text;
  38. using System.Threading;
  39. using System.Runtime.InteropServices;
  40. using System.Globalization;
  41. using System.Security.Permissions;
  42. namespace System.Runtime.Remoting.Channels.Http
  43. {
  44.    
  45.     public class HttpServerChannel : BaseChannelWithProperties, IChannelReceiver, IChannelReceiverHook
  46.     {
  47.         private int _channelPriority = 1;
  48.         // priority of channel (default=1)
  49.         private string _channelName = "http server";
  50.         // channel name
  51.         private string _machineName = null;
  52.         // machine name
  53.         private int _port = -1;
  54.         // port to listen on
  55.         private ChannelDataStore _channelData = null;
  56.         // channel data
  57.         private string _forcedMachineName = null;
  58.         // an explicitly configured machine name
  59.         private bool _bUseIpAddress = true;
  60.         // by default, we'll use the ip address.
  61.         private IPAddress _bindToAddr = IPAddress.Any;
  62.         // address to bind to.
  63.         private bool _bSuppressChannelData = false;
  64.         // should we hand out null for our channel data
  65.         private IServerChannelSinkProvider _sinkProvider = null;
  66.         private HttpServerTransportSink _transportSink = null;
  67.         private IServerChannelSink _sinkChain = null;
  68.        
  69.         private bool _wantsToListen = true;
  70.         private bool _bHooked = false;
  71.         // has anyone hooked into the channel?
  72.        
  73.         private ExclusiveTcpListener _tcpListener;
  74.         private bool _bExclusiveAddressUse = true;
  75.         private Thread _listenerThread;
  76.         private bool _bListening = false;
  77.         // are we listening at the moment?
  78.         private Exception _startListeningException = null;
  79.         // if an exception happens on the listener thread when attempting
  80.         // to start listening, that will get set here.
  81.         private AutoResetEvent _waitForStartListening = new AutoResetEvent(false);
  82.        
  83.        
  84.         public HttpServerChannel() : base()
  85.         {
  86.             SetupMachineName();
  87.             SetupChannel();
  88.         }
  89.        
  90.         public HttpServerChannel(int port) : base()
  91.         {
  92.             _port = port;
  93.             SetupMachineName();
  94.             SetupChannel();
  95.         }
  96.         // HttpServerChannel()
  97.         public HttpServerChannel(string name, int port) : base()
  98.         {
  99.             _channelName = name;
  100.             _port = port;
  101.             SetupMachineName();
  102.             SetupChannel();
  103.         }
  104.         // HttpServerChannel()
  105.         public HttpServerChannel(string name, int port, IServerChannelSinkProvider sinkProvider) : base()
  106.         {
  107.             _channelName = name;
  108.             _port = port;
  109.             _sinkProvider = sinkProvider;
  110.             SetupMachineName();
  111.             SetupChannel();
  112.         }
  113.         // HttpServerChannel()
  114.        
  115.         public HttpServerChannel(IDictionary properties, IServerChannelSinkProvider sinkProvider) : base()
  116.         {
  117.             if (properties != null) {
  118.                 foreach (DictionaryEntry entry in properties) {
  119.                     switch ((string)entry.Key) {
  120.                         case "name":
  121.                             _channelName = (string)entry.Value;
  122.                             break;
  123.                         case "bindTo":
  124.                             _bindToAddr = IPAddress.Parse((string)entry.Value);
  125.                             break;
  126.                         case "listen":
  127.                             _wantsToListen = Convert.ToBoolean(entry.Value, CultureInfo.InvariantCulture);
  128.                             break;
  129.                         case "machineName":
  130.                             _forcedMachineName = (string)entry.Value;
  131.                             break;
  132.                         case "port":
  133.                             _port = Convert.ToInt32(entry.Value, CultureInfo.InvariantCulture);
  134.                             break;
  135.                         case "priority":
  136.                             _channelPriority = Convert.ToInt32(entry.Value, CultureInfo.InvariantCulture);
  137.                             break;
  138.                         case "suppressChannelData":
  139.                             _bSuppressChannelData = Convert.ToBoolean(entry.Value, CultureInfo.InvariantCulture);
  140.                             break;
  141.                         case "useIpAddress":
  142.                             _bUseIpAddress = Convert.ToBoolean(entry.Value, CultureInfo.InvariantCulture);
  143.                             break;
  144.                         case "exclusiveAddressUse":
  145.                             _bExclusiveAddressUse = Convert.ToBoolean(entry.Value, CultureInfo.InvariantCulture);
  146.                             break;
  147.                         default:
  148.                            
  149.                             break;
  150.                     }
  151.                 }
  152.             }
  153.            
  154.             _sinkProvider = sinkProvider;
  155.             SetupMachineName();
  156.             SetupChannel();
  157.         }
  158.         // HttpServerChannel
  159.        
  160.         internal bool IsSecured {
  161.             get { return false; }
  162.             set {
  163.                 if (_port >= 0 && value == true)
  164.                     throw new RemotingException(CoreChannel.GetResourceString("Remoting_Http_UseIISToSecureHttpServer"));
  165.             }
  166.         }
  167.        
  168.         private void SetupMachineName()
  169.         {
  170.             if (_forcedMachineName != null) {
  171.                 // an explicitly configured machine name was used
  172.                 _machineName = CoreChannel.DecodeMachineName(_forcedMachineName);
  173.             }
  174.             else {
  175.                 if (!_bUseIpAddress)
  176.                     _machineName = CoreChannel.GetMachineName();
  177.                 else {
  178.                     if (_bindToAddr == IPAddress.Any)
  179.                         _machineName = CoreChannel.GetMachineIp();
  180.                     else {
  181.                         _machineName = _bindToAddr.ToString();
  182.                         // Add [] around the ipadress for IPv6
  183.                         if (_bindToAddr.AddressFamily == AddressFamily.InterNetworkV6)
  184.                             _machineName = "[" + _machineName + "]";
  185.                     }
  186.                 }
  187.             }
  188.         }
  189.         // SetupMachineName
  190.        
  191.         private void SetupChannel()
  192.         {
  193.             // set channel data
  194.             // (These get changed inside of StartListening(), in the case where the listen
  195.             // port is 0, because we can't determine the port number until after the
  196.             // TcpListener starts.)
  197.            
  198.             _channelData = new ChannelDataStore(null);
  199.             if (_port > 0) {
  200.                 string channelUri = GetChannelUri();
  201.                 _channelData.ChannelUris = new string[1];
  202.                 _channelData.ChannelUris[0] = channelUri;
  203.                
  204.                 _wantsToListen = false;
  205.             }
  206.            
  207.             // set default provider (soap formatter) if no provider has been set
  208.             if (_sinkProvider == null)
  209.                 _sinkProvider = CreateDefaultServerProviderChain();
  210.            
  211.             CoreChannel.CollectChannelDataFromServerSinkProviders(_channelData, _sinkProvider);
  212.            
  213.             // construct sink chain
  214.             _sinkChain = ChannelServices.CreateServerChannelSinkChain(_sinkProvider, this);
  215.             _transportSink = new HttpServerTransportSink(_sinkChain);
  216.            
  217.             // set sink properties on base class, so that properties will be chained.
  218.             SinksWithProperties = _sinkChain;
  219.            
  220.             if (_port >= 0) {
  221.                 // Open a TCP port and create a thread to start listening
  222.                 _tcpListener = new ExclusiveTcpListener(_bindToAddr, _port);
  223.                 ThreadStart t = new ThreadStart(this.Listen);
  224.                 _listenerThread = new Thread(t);
  225.                 _listenerThread.IsBackground = true;
  226.                
  227.                 // Wait for thread to spin up
  228.                 StartListening(null);
  229.             }
  230.         }
  231.         // SetupChannel
  232.        
  233.         private IServerChannelSinkProvider CreateDefaultServerProviderChain()
  234.         {
  235.             IServerChannelSinkProvider chain = new SdlChannelSinkProvider();
  236.             IServerChannelSinkProvider sink = chain;
  237.            
  238.             sink.Next = new SoapServerFormatterSinkProvider();
  239.             sink = sink.Next;
  240.             sink.Next = new BinaryServerFormatterSinkProvider();
  241.            
  242.             return chain;
  243.         }
  244.         // CreateDefaultServerProviderChain
  245.        
  246.         //
  247.         // IChannel implementation
  248.         //
  249.        
  250.         public int ChannelPriority {
  251.             [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  252.             get { return _channelPriority; }
  253.         }
  254.        
  255.         public string ChannelName {
  256.             [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  257.             get { return _channelName; }
  258.         }
  259.        
  260.         // returns channelURI and places object uri into out parameter
  261.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  262.         public string Parse(string url, out string objectURI)
  263.         {
  264.             return HttpChannelHelper.ParseURL(url, out objectURI);
  265.         }
  266.         // Parse
  267.         //
  268.         // end of IChannel implementation
  269.         //
  270.        
  271.        
  272.         //
  273.         // IChannelReceiver implementation
  274.         //
  275.        
  276.         public object ChannelData {
  277.             [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  278.             get {
  279.                 if (!_bSuppressChannelData && (_bListening || _bHooked)) {
  280.                     return _channelData;
  281.                 }
  282.                 else {
  283.                     return null;
  284.                 }
  285.             }
  286.         }
  287.         // ChannelData
  288.        
  289.         public string GetChannelUri()
  290.         {
  291.             if ((_channelData != null) && (_channelData.ChannelUris != null)) {
  292.                 return _channelData.ChannelUris[0];
  293.             }
  294.             else {
  295.                 return "http://" + _machineName + ":" + _port;
  296.             }
  297.         }
  298.         // GetChannelURI
  299.        
  300.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  301.         public virtual string[] GetUrlsForUri(string objectUri)
  302.         {
  303.             string[] retVal = new string[1];
  304.            
  305.             if (!objectUri.StartsWith("/", StringComparison.Ordinal))
  306.                 objectUri = "/" + objectUri;
  307.             retVal[0] = GetChannelUri() + objectUri;
  308.            
  309.             return retVal;
  310.         }
  311.         // GetURLsforURI
  312.        
  313.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  314.         public void StartListening(object data)
  315.         {
  316.             InternalRemotingServices.RemotingTrace("HttpChannel.StartListening");
  317.            
  318.             if (_port >= 0) {
  319.                 if (_listenerThread.IsAlive == false) {
  320.                     _listenerThread.Start();
  321.                     _waitForStartListening.WaitOne();
  322.                     // listener thread will signal this after starting TcpListener
  323.                     if (_startListeningException != null) {
  324.                         // An exception happened when we tried to start listening (such as "socket already in use)
  325.                         Exception e = _startListeningException;
  326.                         _startListeningException = null;
  327.                         throw e;
  328.                     }
  329.                    
  330.                     _bListening = true;
  331.                    
  332.                     // get new port assignment if a port of 0 was used to auto-select a port
  333.                     if (_port == 0) {
  334.                         _port = ((IPEndPoint)_tcpListener.LocalEndpoint).Port;
  335.                        
  336.                         if (_channelData != null) {
  337.                             string channelUri = GetChannelUri();
  338.                             _channelData.ChannelUris = new string[1];
  339.                             _channelData.ChannelUris[0] = channelUri;
  340.                         }
  341.                     }
  342.                 }
  343.             }
  344.         }
  345.         // StartListening
  346.        
  347.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  348.         public void StopListening(object data)
  349.         {
  350.             InternalRemotingServices.RemotingTrace("HTTPChannel.StopListening");
  351.            
  352.             if (_port > 0) {
  353.                 _bListening = false;
  354.                
  355.                 // Ask the TCP listener to stop listening on the port
  356.                 if (null != _tcpListener) {
  357.                     _tcpListener.Stop();
  358.                 }
  359.             }
  360.         }
  361.         // StopListening
  362.         //
  363.         // end of IChannelReceiver implementation
  364.         //
  365.        
  366.         //
  367.         // IChannelReceiverHook implementation
  368.         //
  369.        
  370.         public string ChannelScheme {
  371.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  372.             get { return "http"; }
  373.         }
  374.        
  375.         public bool WantsToListen {
  376.             [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  377.             get { return _wantsToListen; }
  378.             set { _wantsToListen = value; }
  379.         }
  380.         // WantsToListen
  381.         public IServerChannelSink ChannelSinkChain {
  382.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  383.             get { return _sinkChain; }
  384.         }
  385.        
  386.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  387.         public void AddHookChannelUri(string channelUri)
  388.         {
  389.             if (_channelData.ChannelUris != null) {
  390.                 throw new RemotingException(CoreChannel.GetResourceString("Remoting_Http_LimitListenerOfOne"));
  391.             }
  392.             else {
  393.                 // replace machine name with explicitly configured
  394.                 // machine name or ip address if necessary
  395.                 if (_forcedMachineName != null) {
  396.                     channelUri = HttpChannelHelper.ReplaceMachineNameWithThisString(channelUri, _forcedMachineName);
  397.                 }
  398.                 else if (_bUseIpAddress) {
  399.                     channelUri = HttpChannelHelper.ReplaceMachineNameWithThisString(channelUri, CoreChannel.GetMachineIp());
  400.                 }
  401.                
  402.                 _channelData.ChannelUris = new string[] {channelUri};
  403.                 _wantsToListen = false;
  404.                 _bHooked = true;
  405.             }
  406.         }
  407.         // AddHookChannelUri
  408.        
  409.         //
  410.         // end of IChannelReceiverHook implementation
  411.         //
  412.        
  413.         // Thread for listening
  414.         void Listen()
  415.         {
  416.             bool bOkToListen = false;
  417.            
  418.             try {
  419.                 _tcpListener.Start(_bExclusiveAddressUse);
  420.                 bOkToListen = true;
  421.             }
  422.             catch (Exception e) {
  423.                 _startListeningException = e;
  424.             }
  425.             catch {
  426.                 _startListeningException = new Exception(CoreChannel.GetResourceString("Remoting_nonClsCompliantException"));
  427.             }
  428.            
  429.             _waitForStartListening.Set();
  430.             // allow main thread to continue now that we have tried to start the socket
  431.             InternalRemotingServices.RemotingTrace("Waiting to Accept the Socket on Port: " + _port);
  432.            
  433.             //
  434.             // Wait for an incoming socket
  435.             //
  436.             Socket socket;
  437.            
  438.             while (bOkToListen) {
  439.                 InternalRemotingServices.RemotingTrace("TCPChannel::Listen - tcpListen.Pending() == true");
  440.                
  441.                 try {
  442.                     socket = _tcpListener.AcceptSocket();
  443.                    
  444.                     if (socket == null) {
  445.                         throw new RemotingException(String.Format(CultureInfo.CurrentCulture, CoreChannel.GetResourceString("Remoting_Socket_Accept"), Marshal.GetLastWin32Error().ToString(CultureInfo.InvariantCulture)));
  446.                     }
  447.                     else {
  448.                         // disable nagle delay
  449.                         socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, 1);
  450.                         // Set keepalive flag, so that inactive sockets can be cleaned up
  451.                         socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1);
  452.                        
  453.                         // set linger option
  454.                         LingerOption lingerOption = new LingerOption(true, 3);
  455.                         socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lingerOption);
  456.                        
  457.                         Stream netStream = new SocketStream(socket);
  458.                         HttpServerSocketHandler streamManager = null;
  459.                        
  460.                         //Create the socket Handler
  461.                         streamManager = new HttpServerSocketHandler(socket, CoreChannel.RequestQueue, netStream);
  462.                        
  463.                         streamManager.DataArrivedCallback = new WaitCallback(_transportSink.ServiceRequest);
  464.                         streamManager.BeginReadMessage();
  465.                     }
  466.                 }
  467.                 catch (Exception e) {
  468.                     if (!_bListening) {
  469.                         // We called Stop() on the tcp listener, so gracefully exit.
  470.                         bOkToListen = false;
  471.                     }
  472.                     else {
  473.                         // we want the exception to show up as unhandled since this
  474.                         // is an unexpected failure.
  475.                         if (!(e is SocketException)) {
  476.                             //throw;
  477.                         }
  478.                     }
  479.                 }
  480.                 catch {
  481.                     if (!_bListening) {
  482.                         // We called Stop() on the tcp listener, so gracefully exit.
  483.                         bOkToListen = false;
  484.                     }
  485.                     else {
  486.                         // we want the exception to show up as unhandled since this
  487.                         // is an unexpected failure.
  488.                         {
  489.                             //throw;
  490.                         }
  491.                     }
  492.                 }
  493.             }
  494.             // while (bOkToListen)
  495.         }
  496.        
  497.         //
  498.         // Support for properties (through BaseChannelWithProperties)
  499.         //
  500.        
  501.         public override object this[object key]
  502.         {
  503.             get { return null; }
  504.            
  505.             set { }
  506.         }
  507.         // this[]
  508.         public override ICollection Keys {
  509.             get { return new ArrayList(); }
  510.         }
  511.        
  512.     }
  513.     // HttpServerChannel
  514.    
  515.    
  516.    
  517.     internal class HttpServerTransportSink : IServerChannelSink
  518.     {
  519.         private static string s_serverHeader = "MS .NET Remoting, MS .NET CLR " + System.Environment.Version.ToString();
  520.        
  521.         // sink state
  522.         private IServerChannelSink _nextSink;
  523.        
  524.        
  525.         public HttpServerTransportSink(IServerChannelSink nextSink)
  526.         {
  527.             _nextSink = nextSink;
  528.         }
  529.         // IServerChannelSink
  530.        
  531.         internal void ServiceRequest(object state)
  532.         {
  533.             HttpServerSocketHandler streamManager = (HttpServerSocketHandler)state;
  534.            
  535.             ITransportHeaders headers = streamManager.ReadHeaders();
  536.             Stream requestStream = streamManager.GetRequestStream();
  537.             headers["__CustomErrorsEnabled"] = streamManager.CustomErrorsEnabled();
  538.            
  539.             // process request
  540.             ServerChannelSinkStack sinkStack = new ServerChannelSinkStack();
  541.             sinkStack.Push(this, streamManager);
  542.            
  543.             IMessage responseMessage;
  544.             ITransportHeaders responseHeaders;
  545.             Stream responseStream;
  546.            
  547.             ServerProcessing processing = _nextSink.ProcessMessage(sinkStack, null, headers, requestStream, out responseMessage, out responseHeaders, out responseStream);
  548.            
  549.             // handle response
  550.             switch (processing) {
  551.                 case ServerProcessing.Complete:
  552.                    
  553.                    
  554.                     {
  555.                         // Send the response. Call completed synchronously.
  556.                         sinkStack.Pop(this);
  557.                         streamManager.SendResponse(responseStream, "200", "OK", responseHeaders);
  558.                         break;
  559.                     }
  560.                     break;
  561.                 case ServerProcessing.OneWay:
  562.                     // case ServerProcessing.Complete
  563.                    
  564.                     {
  565.                         // Just send back a 200 OK
  566.                         streamManager.SendResponse(null, "202", "Accepted", responseHeaders);
  567.                         break;
  568.                     }
  569.                     break;
  570.                 case ServerProcessing.Async:
  571.                     // case ServerProcessing.OneWay
  572.                    
  573.                     {
  574.                         sinkStack.StoreAndDispatch(this, streamManager);
  575.                         break;
  576.                     }
  577.                     break;
  578.                 // case ServerProcessing.Async
  579.             }
  580.             // switch (processing)
  581.            
  582.             // async processing will take care if handling this later
  583.             if (processing != ServerProcessing.Async) {
  584.                 if (streamManager.CanServiceAnotherRequest())
  585.                     streamManager.BeginReadMessage();
  586.                 else
  587.                     streamManager.Close();
  588.             }
  589.            
  590.         }
  591.         // ServiceRequest
  592.        
  593.        
  594.        
  595.         //
  596.         // IServerChannelSink implementation
  597.         //
  598.        
  599.         public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
  600.         {
  601.             // NOTE: This doesn't have to be implemented because the server transport
  602.             // sink is always first.
  603.             throw new NotSupportedException();
  604.         }
  605.         // ProcessMessage
  606.        
  607.         public void AsyncProcessResponse(IServerResponseChannelSinkStack sinkStack, object state, IMessage msg, ITransportHeaders headers, Stream stream)
  608.         {
  609.             HttpServerSocketHandler streamManager = null;
  610.            
  611.             streamManager = (HttpServerSocketHandler)state;
  612.            
  613.             // send the response
  614.             streamManager.SendResponse(stream, "200", "OK", headers);
  615.            
  616.             if (streamManager.CanServiceAnotherRequest())
  617.                 streamManager.BeginReadMessage();
  618.             else
  619.                 streamManager.Close();
  620.         }
  621.         // AsyncProcessResponse
  622.        
  623.         public Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack, object state, IMessage msg, ITransportHeaders headers)
  624.         {
  625.             HttpServerSocketHandler streamManager = (HttpServerSocketHandler)state;
  626.            
  627.             if (streamManager.AllowChunkedResponse)
  628.                 return streamManager.GetResponseStream("200", "OK", headers);
  629.             else
  630.                 return null;
  631.         }
  632.         // GetResponseStream
  633.        
  634.         public IServerChannelSink NextChannelSink {
  635.             get { return _nextSink; }
  636.         }
  637.        
  638.        
  639.         public IDictionary Properties {
  640.             get { return null; }
  641.         }
  642.         // Properties
  643.         //
  644.         // end of IServerChannelSink implementation
  645.         //
  646.        
  647.        
  648.         static internal string ServerHeader {
  649.             get { return s_serverHeader; }
  650.         }
  651.        
  652.        
  653.        
  654.     }
  655.     // HttpServerTransportSink
  656.    
  657.    
  658.     internal class ErrorMessage : IMethodCallMessage
  659.     {
  660.        
  661.         // IMessage
  662.         public IDictionary Properties {
  663.             get { return null; }
  664.         }
  665.        
  666.         // IMethodMessage
  667.         public string Uri {
  668.             get { return m_URI; }
  669.         }
  670.         public string MethodName {
  671.             get { return m_MethodName; }
  672.         }
  673.         public string TypeName {
  674.             get { return m_TypeName; }
  675.         }
  676.         public object MethodSignature {
  677.             get { return m_MethodSignature; }
  678.         }
  679.         public MethodBase MethodBase {
  680.             get { return null; }
  681.         }
  682.         public int ArgCount {
  683.             get { return m_ArgCount; }
  684.         }
  685.         public string GetArgName(int index)
  686.         {
  687.             return m_ArgName;
  688.         }
  689.         public object GetArg(int argNum)
  690.         {
  691.             return null;
  692.         }
  693.         public object[] Args {
  694.             get { return null; }
  695.         }
  696.        
  697.         public bool HasVarArgs {
  698.             get { return false; }
  699.         }
  700.         public LogicalCallContext LogicalCallContext {
  701.             get { return null; }
  702.         }
  703.        
  704.        
  705.         // IMethodCallMessage
  706.         public int InArgCount {
  707.             get { return m_ArgCount; }
  708.         }
  709.         public string GetInArgName(int index)
  710.         {
  711.             return null;
  712.         }
  713.         public object GetInArg(int argNum)
  714.         {
  715.             return null;
  716.         }
  717.         public object[] InArgs {
  718.             get { return null; }
  719.         }
  720.        
  721.         string m_URI = "Exception";
  722.         string m_MethodName = "Unknown";
  723.         string m_TypeName = "Unknown";
  724.         object m_MethodSignature = null;
  725.         int m_ArgCount = 0;
  726.         string m_ArgName = "Unknown";
  727.     }
  728.     // ErrorMessage
  729.    
  730.    
  731.    
  732. }
  733. // namespace System.Runtime.Remoting.Channels.Http

Developer Fusion