2 // System.Runtime.Remoting.Channels.BinaryServerFormatterSink.cs
4 // Author: Duncan Mak (duncan@ximian.com)
5 // Lluis Sanchez Gual (lluis@ideary.com)
7 // 2002 (C) Copyright, Ximian, Inc.
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Collections;
33 using System.Runtime.Remoting.Messaging;
34 using System.Runtime.Serialization;
35 using System.Runtime.Serialization.Formatters;
36 using System.Runtime.Serialization.Formatters.Binary;
37 using System.Runtime.InteropServices;
39 namespace System.Runtime.Remoting.Channels {
41 public class BinaryServerFormatterSink : IServerChannelSink, IChannelSinkBase
50 BinaryCore _binaryCore = BinaryCore.DefaultInstance;
52 IServerChannelSink next_sink;
54 IChannelReceiver receiver;
56 public BinaryServerFormatterSink (BinaryServerFormatterSink.Protocol protocol,
57 IServerChannelSink nextSink,
58 IChannelReceiver receiver)
60 this.protocol = protocol;
61 this.next_sink = nextSink;
62 this.receiver = receiver;
65 internal BinaryCore BinaryCore
67 get { return _binaryCore; }
68 set { _binaryCore = value; }
71 public IServerChannelSink NextChannelSink {
77 public IDictionary Properties {
84 public TypeFilterLevel TypeFilterLevel
86 get { return _binaryCore.TypeFilterLevel; }
89 IDictionary props = (IDictionary) ((ICloneable)_binaryCore.Properties).Clone ();
90 props ["typeFilterLevel"] = value;
91 _binaryCore = new BinaryCore (this, props, BinaryServerFormatterSinkProvider.AllowedProperties);
95 public void AsyncProcessResponse (IServerResponseChannelSinkStack sinkStack, object state,
96 IMessage msg, ITransportHeaders headers, Stream stream)
98 ITransportHeaders responseHeaders = new TransportHeaders();
100 if (sinkStack != null) stream = sinkStack.GetResponseStream (msg, responseHeaders);
101 if (stream == null) stream = new MemoryStream();
103 _binaryCore.Serializer.Serialize (stream, msg, null);
104 if (stream is MemoryStream) stream.Position = 0;
106 sinkStack.AsyncProcessResponse (msg, responseHeaders, stream);
109 public Stream GetResponseStream (IServerResponseChannelSinkStack sinkStack, object state,
110 IMessage msg, ITransportHeaders headers)
115 public ServerProcessing ProcessMessage (IServerChannelSinkStack sinkStack,
116 IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream,
117 out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
119 // Check whether the request was already processed by another
120 // formatter sink and pass the request to the next sink if so.
121 if (requestMsg != null)
122 return next_sink.ProcessMessage (sinkStack,
130 // Check whether the request is suitable for this formatter
131 // and pass the request to the next sink if not.
132 // Note that a null content-type is handled as suitable,
133 // otherwise no other sink will be able to handle the request.
134 string contentType = requestHeaders["Content-Type"] as string;
135 if (contentType != null && contentType != "application/octet-stream") {
137 return next_sink.ProcessMessage (sinkStack,
145 // Let this formatter handle the exception.
149 sinkStack.Push (this, null);
150 ServerProcessing res;
154 string url = (string)requestHeaders[CommonTransportKeys.RequestUri];
156 receiver.Parse (url, out uri);
157 if (uri == null) uri = url;
159 MethodCallHeaderHandler mhh = new MethodCallHeaderHandler(uri);
160 requestMsg = (IMessage) _binaryCore.Deserializer.Deserialize (requestStream, new HeaderHandler(mhh.HandleHeaders));
162 res = next_sink.ProcessMessage (sinkStack, requestMsg, requestHeaders, null, out responseMsg, out responseHeaders, out responseStream);
166 responseMsg = new ReturnMessage (ex, (IMethodCallMessage)requestMsg);
167 res = ServerProcessing.Complete;
168 responseHeaders = null;
169 responseStream = null;
172 if (res == ServerProcessing.Complete)
174 for (int n=0; n<3; n++) {
175 responseStream = null;
176 responseHeaders = new TransportHeaders();
178 if (sinkStack != null) responseStream = sinkStack.GetResponseStream (responseMsg, responseHeaders);
179 if (responseStream == null) responseStream = new MemoryStream();
182 _binaryCore.Serializer.Serialize (responseStream, responseMsg);
184 } catch (Exception ex) {
185 if (n == 2) throw ex;
186 else responseMsg = new ReturnMessage (ex, (IMethodCallMessage)requestMsg);
190 if (responseStream is MemoryStream) responseStream.Position = 0;
193 sinkStack.Pop (this);
200 internal class MethodCallHeaderHandler
204 public MethodCallHeaderHandler (string uri)
209 public object HandleHeaders (Header[] headers)