The Labs \ Source Viewer \ SSCLI \ System.Runtime.Remoting.Channels \ SoapClientFormatterSink

  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: SoapFormatterSinks.cs
  17. //
  18. // Summary: Soap formatter client and server sinks.
  19. //
  20. //==========================================================================
  21. using System;
  22. using System.Collections;
  23. using System.IO;
  24. using System.Reflection;
  25. using System.Runtime.Remoting;
  26. using System.Runtime.Remoting.Channels;
  27. using System.Runtime.Remoting.Channels.Http;
  28. using System.Runtime.Remoting.Messaging;
  29. using System.Runtime.Remoting.Metadata;
  30. using System.Runtime.Serialization;
  31. using System.Security;
  32. using System.Security.Permissions;
  33. using System.Runtime.Serialization.Formatters;
  34. using System.Runtime.Serialization.Formatters.Soap;
  35. using System.Text;
  36. using System.Globalization;
  37. namespace System.Runtime.Remoting.Channels
  38. {
  39.    
  40.     //
  41.     // CLIENT-SIDE SOAP FORMATTER SINKS
  42.     //
  43.    
  44.     public class SoapClientFormatterSinkProvider : IClientFormatterSinkProvider
  45.     {
  46.         private IClientChannelSinkProvider _next = null;
  47.        
  48.         // settings from config
  49.         private bool _includeVersioning = true;
  50.         private bool _strictBinding = false;
  51.        
  52.        
  53.         public SoapClientFormatterSinkProvider()
  54.         {
  55.         }
  56.        
  57.         public SoapClientFormatterSinkProvider(IDictionary properties, ICollection providerData)
  58.         {
  59.             // look at properties
  60.             if (properties != null) {
  61.                 foreach (DictionaryEntry entry in properties) {
  62.                     string keyStr = entry.Key.ToString();
  63.                     switch (keyStr) {
  64.                         case "includeVersions":
  65.                             _includeVersioning = Convert.ToBoolean(entry.Value, CultureInfo.InvariantCulture);
  66.                             break;
  67.                         case "strictBinding":
  68.                             _strictBinding = Convert.ToBoolean(entry.Value, CultureInfo.InvariantCulture);
  69.                             break;
  70.                         default:
  71.                            
  72.                             break;
  73.                     }
  74.                 }
  75.             }
  76.            
  77.             // not expecting any provider data
  78.             CoreChannel.VerifyNoProviderData(this.GetType().Name, providerData);
  79.         }
  80.        
  81.        
  82.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  83.         public IClientChannelSink CreateSink(IChannelSender channel, string url, object remoteChannelData)
  84.         {
  85.             IClientChannelSink nextSink = null;
  86.             if (_next != null) {
  87.                 nextSink = _next.CreateSink(channel, url, remoteChannelData);
  88.                 if (nextSink == null)
  89.                     return null;
  90.             }
  91.            
  92.             SinkChannelProtocol protocol = CoreChannel.DetermineChannelProtocol(channel);
  93.            
  94.             SoapClientFormatterSink sink = new SoapClientFormatterSink(nextSink);
  95.             sink.IncludeVersioning = _includeVersioning;
  96.             sink.StrictBinding = _strictBinding;
  97.             sink.ChannelProtocol = protocol;
  98.             return sink;
  99.         }
  100.        
  101.         public IClientChannelSinkProvider Next {
  102.             [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  103.             get { return _next; }
  104.             [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  105.             set { _next = value; }
  106.         }
  107.     }
  108.     // class SoapClientFormatterSinkProvider
  109.    
  110.     public class SoapClientFormatterSink : IClientFormatterSink
  111.     {
  112.         private IClientChannelSink _nextSink = null;
  113.        
  114.         private bool _includeVersioning = true;
  115.         // should versioning be used
  116.         private bool _strictBinding = false;
  117.         // strict binding should be used
  118.         private SinkChannelProtocol _channelProtocol = SinkChannelProtocol.Other;
  119.        
  120.        
  121.         public SoapClientFormatterSink(IClientChannelSink nextSink)
  122.         {
  123.             _nextSink = nextSink;
  124.         }
  125.         // SoapClientFormatterSink
  126.        
  127.         internal bool IncludeVersioning {
  128.             set { _includeVersioning = value; }
  129.         }
  130.         // IncludeVersioning
  131.         internal bool StrictBinding {
  132.             set { _strictBinding = value; }
  133.         }
  134.         // StrictBinding
  135.         internal SinkChannelProtocol ChannelProtocol {
  136.             set { _channelProtocol = value; }
  137.         }
  138.         // ChannelProtocol
  139.        
  140.         //
  141.         // IMessageSink implementation
  142.         //
  143.        
  144.         // formatter sender sink is always last "IMessageSink"
  145.         public IMessageSink NextSink {
  146.             [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  147.             get {
  148.                 throw new NotSupportedException();
  149.             }
  150.         }
  151.        
  152.        
  153.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  154.         public IMessage SyncProcessMessage(IMessage msg)
  155.         {
  156.             IMethodCallMessage mcm = (IMethodCallMessage)msg;
  157.             IMessage retMsg;
  158.            
  159.             try {
  160.                 // serialize message
  161.                 ITransportHeaders headers;
  162.                 Stream requestStream;
  163.                 SerializeMessage(mcm, out headers, out requestStream);
  164.                
  165.                 // process message
  166.                 Stream returnStream;
  167.                 ITransportHeaders returnHeaders;
  168.                 _nextSink.ProcessMessage(msg, headers, requestStream, out returnHeaders, out returnStream);
  169.                 if (returnHeaders == null)
  170.                     throw new ArgumentNullException("returnHeaders");
  171.                
  172.                 // deserialize stream
  173.                 retMsg = DeserializeMessage(mcm, returnHeaders, returnStream);
  174.             }
  175.             catch (Exception e) {
  176.                 retMsg = new ReturnMessage(e, mcm);
  177.             }
  178.             catch {
  179.                 retMsg = new ReturnMessage(new Exception(CoreChannel.GetResourceString("Remoting_nonClsCompliantException")), mcm);
  180.             }
  181.            
  182.             return retMsg;
  183.         }
  184.         // SyncProcessMessage
  185.        
  186.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  187.         public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
  188.         {
  189.             IMethodCallMessage mcm = (IMethodCallMessage)msg;
  190.             IMessage retMsg;
  191.            
  192.             try {
  193.                 // serialize message
  194.                 ITransportHeaders headers;
  195.                 Stream requestStream;
  196.                 SerializeMessage(mcm, out headers, out requestStream);
  197.                
  198.                 // process message
  199.                 ClientChannelSinkStack sinkStack = new ClientChannelSinkStack(replySink);
  200.                 sinkStack.Push(this, mcm);
  201.                 _nextSink.AsyncProcessRequest(sinkStack, msg, headers, requestStream);
  202.             }
  203.             catch (Exception e) {
  204.                 retMsg = new ReturnMessage(e, mcm);
  205.                 if (replySink != null)
  206.                     replySink.SyncProcessMessage(retMsg);
  207.             }
  208.             catch {
  209.                 retMsg = new ReturnMessage(new Exception(CoreChannel.GetResourceString("Remoting_nonClsCompliantException")), mcm);
  210.                 if (replySink != null)
  211.                     replySink.SyncProcessMessage(retMsg);
  212.             }
  213.            
  214.             return null;
  215.         }
  216.         // AsyncProcessMessage
  217.        
  218.         //
  219.         // end of IMessageSink implementation
  220.         //
  221.        
  222.        
  223.         // helper function to serialize the message
  224.         private void SerializeMessage(IMethodCallMessage mcm, out ITransportHeaders headers, out Stream stream)
  225.         {
  226.             BaseTransportHeaders requestHeaders = new BaseTransportHeaders();
  227.             headers = requestHeaders;
  228.            
  229.             // add SOAPAction header
  230.             MethodBase mb = mcm.MethodBase;
  231.             headers["SOAPAction"] = '"' + HttpEncodingHelper.EncodeUriAsXLinkHref(SoapServices.GetSoapActionFromMethodBase(mb)) + '"';
  232.            
  233.             // add other http soap headers
  234.             requestHeaders.ContentType = CoreChannel.SOAPContentType;
  235.             if (_channelProtocol == SinkChannelProtocol.Http)
  236.                 headers["__RequestVerb"] = "POST";
  237.            
  238.             bool bMemStream = false;
  239.             stream = _nextSink.GetRequestStream(mcm, headers);
  240.             if (stream == null) {
  241.                 stream = new ChunkedMemoryStream(CoreChannel.BufferPool);
  242.                 bMemStream = true;
  243.             }
  244.             CoreChannel.SerializeSoapMessage(mcm, stream, _includeVersioning);
  245.             if (bMemStream)
  246.                 stream.Position = 0;
  247.         }
  248.         // SerializeMessage
  249.        
  250.         // helper function to deserialize the message
  251.         private IMessage DeserializeMessage(IMethodCallMessage mcm, ITransportHeaders headers, Stream stream)
  252.         {
  253.             IMessage retMsg;
  254.            
  255.             Header[] h = new Header[3];
  256.             h[0] = new Header("__TypeName", mcm.TypeName);
  257.             h[1] = new Header("__MethodName", mcm.MethodName);
  258.             h[2] = new Header("__MethodSignature", mcm.MethodSignature);
  259.            
  260.             string contentTypeHeader = headers["Content-Type"] as string;
  261.             string contentTypeValue;
  262.             string charsetValue;
  263.             HttpChannelHelper.ParseContentType(contentTypeHeader, out contentTypeValue, out charsetValue);
  264.            
  265.             if (String.Compare(contentTypeValue, CoreChannel.SOAPMimeType, StringComparison.Ordinal) == 0) {
  266.                 // deserialize the message
  267.                 retMsg = CoreChannel.DeserializeSoapResponseMessage(stream, mcm, h, _strictBinding);
  268.             }
  269.             else {
  270.                 // an error has occurred
  271.                 int bufferSize = 1024;
  272.                 byte[] buffer = new byte[bufferSize];
  273.                 StringBuilder sb = new StringBuilder();
  274.                
  275.                 int readCount = stream.Read(buffer, 0, bufferSize);
  276.                 while (readCount > 0) {
  277.                     sb.Append(Encoding.ASCII.GetString(buffer, 0, readCount));
  278.                     readCount = stream.Read(buffer, 0, bufferSize);
  279.                 }
  280.                
  281.                 retMsg = new ReturnMessage(new RemotingException(sb.ToString()), mcm);
  282.             }
  283.            
  284.             // Close the stream since we're done with it (especially important if this
  285.             // happened to be a network stream)
  286.             stream.Close();
  287.            
  288.             return retMsg;
  289.         }
  290.         // DeserializeMessage
  291.        
  292.         //
  293.         // IClientChannelSink implementation
  294.         //
  295.        
  296.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  297.         public void ProcessMessage(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream, out ITransportHeaders responseHeaders, out Stream responseStream)
  298.         {
  299.             // never gets called, this sink is always first
  300.             throw new NotSupportedException();
  301.         }
  302.         // ProcessMessage
  303.        
  304.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  305.         public void AsyncProcessRequest(IClientChannelSinkStack sinkStack, IMessage msg, ITransportHeaders headers, Stream stream)
  306.         {
  307.             // never gets called, this sink is always first
  308.             throw new NotSupportedException();
  309.         }
  310.         // AsyncProcessRequest
  311.        
  312.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  313.         public void AsyncProcessResponse(IClientResponseChannelSinkStack sinkStack, object state, ITransportHeaders headers, Stream stream)
  314.         {
  315.             // previously we stored the outgoing message in state
  316.             IMethodCallMessage mcm = (IMethodCallMessage)state;
  317.             IMessage retMsg = DeserializeMessage(mcm, headers, stream);
  318.             sinkStack.DispatchReplyMessage(retMsg);
  319.         }
  320.         // AsyncProcessRequest
  321.        
  322.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  323.         public Stream GetRequestStream(IMessage msg, ITransportHeaders headers)
  324.         {
  325.             // should never be called on formatter sender sink
  326.             throw new NotSupportedException();
  327.         }
  328.         // GetRequestStream
  329.        
  330.         public IClientChannelSink NextChannelSink {
  331.             [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  332.             get { return _nextSink; }
  333.         }
  334.         // Next
  335.        
  336.         public IDictionary Properties {
  337.             [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  338.             get { return null; }
  339.         }
  340.         // Properties
  341.         //
  342.         // end of IClientChannelSink implementation
  343.         //
  344.        
  345.     }
  346.     // class SoapClientFormatterSink
  347.    
  348.    
  349.     //
  350.     // SERVER-SIDE SOAP FORMATTER SINKS
  351.     //
  352.    
  353.     public class SoapServerFormatterSinkProvider : IServerFormatterSinkProvider
  354.     {
  355.         private IServerChannelSinkProvider _next = null;
  356.        
  357.         // settings from config
  358.         private bool _includeVersioning = true;
  359.         private bool _strictBinding = false;
  360.         private TypeFilterLevel _formatterSecurityLevel = TypeFilterLevel.Low;
  361.        
  362.         public SoapServerFormatterSinkProvider()
  363.         {
  364.         }
  365.         // SoapServerFormatterSinkProvider
  366.         public SoapServerFormatterSinkProvider(IDictionary properties, ICollection providerData)
  367.         {
  368.             // look at properties
  369.             if (properties != null) {
  370.                 foreach (DictionaryEntry entry in properties) {
  371.                     string keyStr = entry.Key.ToString();
  372.                     switch (keyStr) {
  373.                         case "includeVersions":
  374.                             _includeVersioning = Convert.ToBoolean(entry.Value, CultureInfo.InvariantCulture);
  375.                             break;
  376.                         case "strictBinding":
  377.                             _strictBinding = Convert.ToBoolean(entry.Value, CultureInfo.InvariantCulture);
  378.                             break;
  379.                         case "typeFilterLevel":
  380.                             _formatterSecurityLevel = (TypeFilterLevel)Enum.Parse(typeof(TypeFilterLevel), (string)entry.Value);
  381.                             break;
  382.                         default:
  383.                             break;
  384.                     }
  385.                 }
  386.             }
  387.            
  388.             // not expecting any provider data
  389.             CoreChannel.VerifyNoProviderData(this.GetType().Name, providerData);
  390.         }
  391.         // SoapServerFormatterSinkProvider
  392.        
  393.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  394.         public void GetChannelData(IChannelDataStore channelData)
  395.         {
  396.         }
  397.         // GetChannelData
  398.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  399.         public IServerChannelSink CreateSink(IChannelReceiver channel)
  400.         {
  401.             if (null == channel) {
  402.                 throw new ArgumentNullException("channel");
  403.             }
  404.            
  405.             IServerChannelSink nextSink = null;
  406.             if (_next != null)
  407.                 nextSink = _next.CreateSink(channel);
  408.            
  409.             SoapServerFormatterSink.Protocol protocol = SoapServerFormatterSink.Protocol.Other;
  410.            
  411.             // see if this is an http channel
  412.             string uri = channel.GetUrlsForUri("")[0];
  413.             if (String.Compare("http", 0, uri, 0, 4, StringComparison.OrdinalIgnoreCase) == 0)
  414.                 protocol = SoapServerFormatterSink.Protocol.Http;
  415.            
  416.             SoapServerFormatterSink sink = new SoapServerFormatterSink(protocol, nextSink, channel);
  417.             sink.IncludeVersioning = _includeVersioning;
  418.             sink.StrictBinding = _strictBinding;
  419.             sink.TypeFilterLevel = _formatterSecurityLevel;
  420.             return sink;
  421.         }
  422.        
  423.         public IServerChannelSinkProvider Next {
  424.             [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  425.             get { return _next; }
  426.             [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  427.             set { _next = value; }
  428.         }
  429.        
  430.         [System.Runtime.InteropServices.ComVisible(false)]
  431.         public TypeFilterLevel TypeFilterLevel {
  432.             get { return _formatterSecurityLevel; }
  433.            
  434.             set { _formatterSecurityLevel = value; }
  435.         }
  436.     }
  437.     // class SoapServerFormatterSinkProvider
  438.    
  439.     public class SoapServerFormatterSink : IServerChannelSink
  440.     {
  441.         [Serializable()]
  442.         public enum Protocol
  443.         {
  444.             Http,
  445.             // special processing needed for http
  446.             Other
  447.         }
  448.        
  449.        
  450.         private IServerChannelSink _nextSink;
  451.         // If this sink doesn't recognize, the incoming
  452.         // format then he should call the next
  453.         // sink if there is one.
  454.         private Protocol _protocol;
  455.         // transport protocol being used
  456.         private IChannelReceiver _receiver;
  457.         // transport sink used to parse url
  458.         private bool _includeVersioning = true;
  459.         // should versioning be used
  460.         private bool _strictBinding = false;
  461.         // should strict binding be used
  462.         private TypeFilterLevel _formatterSecurityLevel = TypeFilterLevel.Full;
  463.        
  464.        
  465.         public SoapServerFormatterSink(Protocol protocol, IServerChannelSink nextSink, IChannelReceiver receiver)
  466.         {
  467.             if (receiver == null)
  468.                 throw new ArgumentNullException("receiver");
  469.            
  470.             _nextSink = nextSink;
  471.             _protocol = protocol;
  472.             _receiver = receiver;
  473.         }
  474.         // SoapServerFormatterSinkProvider
  475.        
  476.         internal bool IncludeVersioning {
  477.             set { _includeVersioning = value; }
  478.         }
  479.         // IncludeVersioning
  480.         internal bool StrictBinding {
  481.             set { _strictBinding = value; }
  482.         }
  483.         // StrictBinding
  484.         [System.Runtime.InteropServices.ComVisible(false)]
  485.         public TypeFilterLevel TypeFilterLevel {
  486.             get { return _formatterSecurityLevel; }
  487.            
  488.             set { _formatterSecurityLevel = value; }
  489.         }
  490.        
  491.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  492.         public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
  493.         {
  494.             if (requestMsg != null) {
  495.                 // The message has already been deserialized so delegate to the next sink.
  496.                 return _nextSink.ProcessMessage(sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);
  497.             }
  498.            
  499.             if (requestHeaders == null)
  500.                 throw new ArgumentNullException("requestHeaders");
  501.             BaseTransportHeaders wkRequestHeaders = requestHeaders as BaseTransportHeaders;
  502.            
  503.             ServerProcessing processing;
  504.            
  505.             responseHeaders = null;
  506.             responseStream = null;
  507.            
  508.             string verb = null;
  509.             string contentType = null;
  510.            
  511.             bool bCanServiceRequest = true;
  512.            
  513.             // determine the content type
  514.             string contentTypeHeader = null;
  515.             if (wkRequestHeaders != null)
  516.                 contentTypeHeader = wkRequestHeaders.ContentType;
  517.             else
  518.                 contentTypeHeader = requestHeaders["Content-Type"] as string;
  519.             if (contentTypeHeader != null) {
  520.                 string charsetValue;
  521.                 HttpChannelHelper.ParseContentType(contentTypeHeader, out contentType, out charsetValue);
  522.             }
  523.            
  524.             // check to see if Content-Type matches
  525.             if ((contentType != null) && (String.Compare(contentType, CoreChannel.SOAPMimeType, StringComparison.Ordinal) != 0)) {
  526.                 bCanServiceRequest = false;
  527.             }
  528.            
  529.             // check for http specific verbs
  530.             if (_protocol == Protocol.Http) {
  531.                 verb = (string)requestHeaders["__RequestVerb"];
  532.                 if (!verb.Equals("POST") && !verb.Equals("M-POST"))
  533.                     bCanServiceRequest = false;
  534.             }
  535.            
  536.             // either delegate or return an error message if we can't service the request
  537.             if (!bCanServiceRequest) {
  538.                 // delegate to next sink if available
  539.                 if (_nextSink != null) {
  540.                     return _nextSink.ProcessMessage(sinkStack, null, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);
  541.                 }
  542.                 else {
  543.                     // send back an error message
  544.                     if (_protocol == Protocol.Http) {
  545.                         // return a client bad request error
  546.                         responseHeaders = new TransportHeaders();
  547.                         responseHeaders["__HttpStatusCode"] = "400";
  548.                         responseHeaders["__HttpReasonPhrase"] = "Bad Request";
  549.                         responseStream = null;
  550.                         responseMsg = null;
  551.                         return ServerProcessing.Complete;
  552.                     }
  553.                     else {
  554.                         // The transport sink will catch this and do something here.
  555.                         throw new RemotingException(CoreChannel.GetResourceString("Remoting_Channels_InvalidRequestFormat"));
  556.                     }
  557.                 }
  558.             }
  559.            
  560.             bool bClientIsClr = true;
  561.             try {
  562.                 string objectUri = null;
  563.                 if (wkRequestHeaders != null)
  564.                     objectUri = wkRequestHeaders.RequestUri;
  565.                 else
  566.                     objectUri = (string)requestHeaders[CommonTransportKeys.RequestUri];
  567.                
  568.                 if (RemotingServices.GetServerTypeForUri(objectUri) == null)
  569.                     throw new RemotingException(CoreChannel.GetResourceString("Remoting_ChnlSink_UriNotPublished"));
  570.                
  571.                 if (_protocol == Protocol.Http) {
  572.                     string userAgent = (string)requestHeaders["User-Agent"];
  573.                     if (userAgent != null) {
  574.                         if (userAgent.IndexOf("MS .NET Remoting") == -1) {
  575.                             // user agent string did not contain ".NET Remoting", so it is someone else
  576.                             bClientIsClr = false;
  577.                         }
  578.                     }
  579.                     else {
  580.                         bClientIsClr = false;
  581.                     }
  582.                 }
  583.                
  584.                 bool bIsCustomErrorEnabled = true;
  585.                 object oIsCustomErrorEnabled = requestHeaders["__CustomErrorsEnabled"];
  586.                 if (oIsCustomErrorEnabled != null && oIsCustomErrorEnabled is bool) {
  587.                     bIsCustomErrorEnabled = (bool)oIsCustomErrorEnabled;
  588.                 }
  589.                 CallContext.SetData("__CustomErrorsEnabled", bIsCustomErrorEnabled);
  590.                
  591.                 string soapActionToVerify;
  592.                 Header[] h = GetChannelHeaders(requestHeaders, out soapActionToVerify);
  593.                
  594.                 PermissionSet currentPermissionSet = null;
  595.                 if (this.TypeFilterLevel != TypeFilterLevel.Full) {
  596.                     currentPermissionSet = new PermissionSet(PermissionState.None);
  597.                     currentPermissionSet.SetPermission(new SecurityPermission(SecurityPermissionFlag.SerializationFormatter));
  598.                 }
  599.                
  600.                 try {
  601.                     if (currentPermissionSet != null)
  602.                         currentPermissionSet.PermitOnly();
  603.                    
  604.                     // Deserialize Request - Stream to IMessage
  605.                     requestMsg = CoreChannel.DeserializeSoapRequestMessage(requestStream, h, _strictBinding, this.TypeFilterLevel);
  606.                 }
  607.                 finally {
  608.                     if (currentPermissionSet != null)
  609.                         CodeAccessPermission.RevertPermitOnly();
  610.                 }
  611.                
  612.                 requestStream.Close();
  613.                
  614.                 if (requestMsg == null) {
  615.                     throw new RemotingException(CoreChannel.GetResourceString("Remoting_DeserializeMessage"));
  616.                 }
  617.                
  618.                 // verify soap action if necessary
  619.                 if ((soapActionToVerify != null) && (!SoapServices.IsSoapActionValidForMethodBase(soapActionToVerify, ((IMethodMessage)requestMsg).MethodBase))) {
  620.                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, CoreChannel.GetResourceString("Remoting_Soap_InvalidSoapAction"), soapActionToVerify));
  621.                 }
  622.                
  623.                 // Dispatch Call
  624.                 sinkStack.Push(this, null);
  625.                 processing = _nextSink.ProcessMessage(sinkStack, requestMsg, requestHeaders, null, out responseMsg, out responseHeaders, out responseStream);
  626.                 // make sure that responseStream is null
  627.                 if (responseStream != null) {
  628.                     throw new RemotingException(CoreChannel.GetResourceString("Remoting_ChnlSink_WantNullResponseStream"));
  629.                 }
  630.                
  631.                 switch (processing) {
  632.                     case ServerProcessing.Complete:
  633.                        
  634.                        
  635.                         {
  636.                             if (responseMsg == null)
  637.                                 throw new RemotingException(CoreChannel.GetResourceString("Remoting_DispatchMessage"));
  638.                            
  639.                             sinkStack.Pop(this);
  640.                            
  641.                             SerializeResponse(sinkStack, responseMsg, bClientIsClr, ref responseHeaders, out responseStream);
  642.                             break;
  643.                         }
  644.                         break;
  645.                     case ServerProcessing.OneWay:
  646.                         // case ServerProcessing.Complete
  647.                        
  648.                         {
  649.                             sinkStack.Pop(this);
  650.                             break;
  651.                         }
  652.                         break;
  653.                     case ServerProcessing.Async:
  654.                         // case ServerProcessing.OneWay:
  655.                        
  656.                         {
  657.                             sinkStack.Store(this, null);
  658.                             break;
  659.                         }
  660.                         break;
  661.                     // case ServerProcessing.Async
  662.                 }
  663.                 // switch (processing)
  664.             }
  665.             catch (Exception e) {
  666.                 processing = ServerProcessing.Complete;
  667.                 responseMsg = new ReturnMessage(e, (IMethodCallMessage)(requestMsg == null ? new ErrorMessage() : requestMsg));
  668.                 //TODO, sowmys: See if we could call SerializeResponse here
  669.                 CallContext.SetData("__ClientIsClr", bClientIsClr);
  670.                 responseStream = (MemoryStream)CoreChannel.SerializeSoapMessage(responseMsg, _includeVersioning);
  671.                 CallContext.FreeNamedDataSlot("__ClientIsClr");
  672.                 responseStream.Position = 0;
  673.                 responseHeaders = new TransportHeaders();
  674.                
  675.                 if (_protocol == Protocol.Http) {
  676.                     responseHeaders["__HttpStatusCode"] = "500";
  677.                     responseHeaders["__HttpReasonPhrase"] = "Internal Server Error";
  678.                     responseHeaders["Content-Type"] = CoreChannel.SOAPContentType;
  679.                 }
  680.             }
  681.             catch {
  682.                 processing = ServerProcessing.Complete;
  683.                 responseMsg = new ReturnMessage(new Exception(CoreChannel.GetResourceString("Remoting_nonClsCompliantException")), (IMethodCallMessage)(requestMsg == null ? new ErrorMessage() : requestMsg));
  684.                 //TODO, sowmys: See if we could call SerializeResponse here
  685.                 CallContext.SetData("__ClientIsClr", bClientIsClr);
  686.                 responseStream = (MemoryStream)CoreChannel.SerializeSoapMessage(responseMsg, _includeVersioning);
  687.                 CallContext.FreeNamedDataSlot("__ClientIsClr");
  688.                 responseStream.Position = 0;
  689.                 responseHeaders = new TransportHeaders();
  690.                
  691.                 if (_protocol == Protocol.Http) {
  692.                     responseHeaders["__HttpStatusCode"] = "500";
  693.                     responseHeaders["__HttpReasonPhrase"] = "Internal Server Error";
  694.                     responseHeaders["Content-Type"] = CoreChannel.SOAPContentType;
  695.                 }
  696.             }
  697.             finally {
  698.                 CallContext.FreeNamedDataSlot("__CustomErrorsEnabled");
  699.             }
  700.            
  701.             return processing;
  702.         }
  703.         // ProcessMessage
  704.        
  705.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  706.         public void AsyncProcessResponse(IServerResponseChannelSinkStack sinkStack, object state, IMessage msg, ITransportHeaders headers, Stream stream)
  707.         {
  708.             SerializeResponse(sinkStack, msg, true, ref headers, out stream);
  709.             sinkStack.AsyncProcessResponse(msg, headers, stream);
  710.         }
  711.         // AsyncProcessResponse
  712.        
  713.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  714.         private void SerializeResponse(IServerResponseChannelSinkStack sinkStack, IMessage msg, bool bClientIsClr, ref ITransportHeaders headers, out Stream stream)
  715.         {
  716.             BaseTransportHeaders responseHeaders = new BaseTransportHeaders();
  717.             if (headers != null) {
  718.                 // copy old headers into new headers
  719.                 foreach (DictionaryEntry entry in headers) {
  720.                     responseHeaders[entry.Key] = entry.Value;
  721.                 }
  722.             }
  723.             headers = responseHeaders;
  724.             responseHeaders.ContentType = CoreChannel.SOAPContentType;
  725.            
  726.             if (_protocol == Protocol.Http) {
  727.                 // check to see if an exception occurred (requires special status code for HTTP)
  728.                 IMethodReturnMessage mrm = msg as IMethodReturnMessage;
  729.                 if ((mrm != null) && (mrm.Exception != null)) {
  730.                     headers["__HttpStatusCode"] = "500";
  731.                     headers["__HttpReasonPhrase"] = "Internal Server Error";
  732.                 }
  733.             }
  734.            
  735.             bool bMemStream = false;
  736.             stream = sinkStack.GetResponseStream(msg, headers);
  737.             if (stream == null) {
  738.                 stream = new ChunkedMemoryStream(CoreChannel.BufferPool);
  739.                 bMemStream = true;
  740.             }
  741.            
  742.            
  743.             bool bBashUrl = CoreChannel.SetupUrlBashingForIisSslIfNecessary();
  744.             CallContext.SetData("__ClientIsClr", bClientIsClr);
  745.             try {
  746.                 CoreChannel.SerializeSoapMessage(msg, stream, _includeVersioning);
  747.             }
  748.             finally {
  749.                 CallContext.FreeNamedDataSlot("__ClientIsClr");
  750.                 CoreChannel.CleanupUrlBashingForIisSslIfNecessary(bBashUrl);
  751.             }
  752.            
  753.             if (bMemStream)
  754.                 stream.Position = 0;
  755.         }
  756.         // SerializeResponse
  757.        
  758.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  759.         public Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack, object state, IMessage msg, ITransportHeaders headers)
  760.         {
  761.             // We don't need to implement this because it will never be called.
  762.             throw new NotSupportedException();
  763.         }
  764.         // GetResponseStream
  765.        
  766.         public IServerChannelSink NextChannelSink {
  767.             [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  768.             get { return _nextSink; }
  769.         }
  770.        
  771.        
  772.         public IDictionary Properties {
  773.             [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure, Infrastructure = true)]
  774.             get { return null; }
  775.         }
  776.         // Properties
  777.        
  778.         // Helper method for analyzing headers
  779.         private Header[] GetChannelHeaders(ITransportHeaders requestHeaders, out string soapActionToVerify)
  780.         {
  781.             soapActionToVerify = null;
  782.            
  783.             // transport sink removes any channel specific information
  784.             string objectURI = (string)requestHeaders[CommonTransportKeys.RequestUri];
  785.            
  786.             string soapAction = (string)requestHeaders["SOAPAction"];
  787.             if (soapAction == null)
  788.                 throw new RemotingException(CoreChannel.GetResourceString("Remoting_SoapActionMissing"));
  789.             soapAction = HttpEncodingHelper.DecodeUri(soapAction);
  790.            
  791.             soapActionToVerify = soapAction;
  792.            
  793.             string typeName;
  794.             string methodName;
  795.             if (!SoapServices.GetTypeAndMethodNameFromSoapAction(soapAction, out typeName, out methodName)) {
  796.                 // This means there are multiple methods for this soap action, so we will have to
  797.                 // settle for the type based off of the uri.
  798.                 Type type = RemotingServices.GetServerTypeForUri(objectURI);
  799.                 if (type == null) {
  800.                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, CoreChannel.GetResourceString("Remoting_TypeNotFoundFromUri"), objectURI));
  801.                 }
  802.                
  803.                 typeName = "clr:" + type.FullName + ", " + type.Assembly.GetName().Name;
  804.             }
  805.             else {
  806.                 typeName = "clr:" + typeName;
  807.             }
  808.            
  809.             // Create a new header array and pass it back.
  810.             int headerLen = 2;
  811.             Header[] h = new Header[headerLen];
  812.             h[0] = new Header("__Uri", objectURI);
  813.             h[1] = new Header("__TypeName", typeName);
  814.            
  815.             return h;
  816.         }
  817.         // GetChannelHeaders
  818.        
  819.     }
  820.     // class SoapServerFormatterSink
  821.    
  822.    
  823. }
  824. // namespace System.Runtime.Remoting.Channnels

Developer Fusion