* BinaryClientFormatterSink.cs, BinaryClientFormatterSinkProvider.cs,
[mono.git] / mcs / class / System.Runtime.Remoting / System.Runtime.Remoting.Channels / BinaryClientFormatterSink.cs
1 //
2 // System.Runtime.Remoting.Channels.BinaryClientFormatterSink.cs
3 //
4 // Author: Rodrigo Moya (rodrigo@ximian.com)
5 //         Dietmar Maurer (dietmar@ximian.com)
6 //         Lluis Sanchez Gual (lluis@ideary.com)
7 //
8 // 2002 (C) Copyright, Ximian, Inc.
9 //
10
11 using System.Collections;
12 using System.IO;
13 using System.Runtime.Remoting.Messaging;
14 using System.Runtime.Serialization;
15 using System.Runtime.Serialization.Formatters.Binary;
16
17 namespace System.Runtime.Remoting.Channels
18 {
19         public class BinaryClientFormatterSink : IClientFormatterSink,
20                 IMessageSink, IClientChannelSink, IChannelSinkBase
21         {
22                 BinaryCore _binaryCore = BinaryCore.DefaultInstance;
23                 IClientChannelSink _nextInChain;
24
25                 public BinaryClientFormatterSink (IClientChannelSink nextSink)
26                 {
27                         _nextInChain = nextSink;
28                 }
29
30                 internal BinaryCore BinaryCore
31                 {
32                         get { return _binaryCore; }
33                         set { _binaryCore = value; }
34                 }
35
36                 public IClientChannelSink NextChannelSink
37                 {
38                         get {
39                                 return _nextInChain;
40                         }
41                 }
42
43                 public IMessageSink NextSink
44                 {
45                         get {
46                                 // This is the last sink in the IMessageSink sink chain
47                                 return null;
48                         }
49                 }
50
51                 public IDictionary Properties
52                 {
53                         get {
54                                 return null;
55                         }
56                 }
57
58                 public void AsyncProcessRequest (IClientChannelSinkStack sinkStack,
59                                                  IMessage msg,
60                                                  ITransportHeaders headers,
61                                                  Stream stream)
62                 {
63                         // never called because the formatter sink is
64                         // always the first in the chain
65                         throw new NotSupportedException("BinaryClientFormatterSink must be the first sink in the IClientChannelSink chain");
66                 }
67
68                 public void AsyncProcessResponse (IClientResponseChannelSinkStack sinkStack,
69                                                   object state,
70                                                   ITransportHeaders headers,
71                                                   Stream stream)
72                 {
73                         IMessage replyMessage = (IMessage)_binaryCore.Deserializer.DeserializeMethodResponse (stream, null, (IMethodCallMessage)state);
74                         sinkStack.DispatchReplyMessage (replyMessage);
75                 }
76
77                 public Stream GetRequestStream (IMessage msg,
78                                                 ITransportHeaders headers)
79                 {
80                         // never called
81                         throw new NotSupportedException ();
82                 }
83
84                 public void ProcessMessage (IMessage msg,
85                                             ITransportHeaders requestHeaders,
86                                             Stream requestStream,
87                                             out ITransportHeaders responseHeaders,
88                                             out Stream responseStream)
89                 {
90                         // never called because the formatter sink is
91                         // always the first in the chain
92                         throw new NotSupportedException ();
93                 }
94
95                 public IMessageCtrl AsyncProcessMessage (IMessage msg,
96                         IMessageSink replySink)
97                 {
98                         ITransportHeaders transportHeaders = new TransportHeaders();
99                         transportHeaders[CommonTransportKeys.RequestUri] = ((IMethodCallMessage)msg).Uri;
100
101                         Stream stream = _nextInChain.GetRequestStream(msg, transportHeaders);
102                         if (stream == null) stream = new MemoryStream ();
103
104                         _binaryCore.Serializer.Serialize (stream, msg, null);
105                         if (stream is MemoryStream) stream.Position = 0;
106
107                         ClientChannelSinkStack stack = new ClientChannelSinkStack(replySink);
108                         stack.Push (this, msg);
109
110                         _nextInChain.AsyncProcessRequest (stack, msg, transportHeaders, stream);
111
112                         // FIXME: No idea about how to implement IMessageCtrl
113                         return null;    \r
114                 }
115
116                 public IMessage SyncProcessMessage (IMessage msg)
117                 {
118                         try {
119
120                                 ITransportHeaders call_headers = new TransportHeaders();
121                                 call_headers[CommonTransportKeys.RequestUri] = ((IMethodCallMessage)msg).Uri;
122                                 call_headers["Content-Type"] = "application/octet-stream";
123
124                                 Stream call_stream = _nextInChain.GetRequestStream(msg, call_headers);
125                                 if (call_stream == null) call_stream = new MemoryStream ();
126
127                                 // Serialize msg to the stream
128
129                                 _binaryCore.Serializer.Serialize (call_stream, msg, null);
130                                 if (call_stream is MemoryStream) call_stream.Position = 0;
131
132                                 Stream response_stream;
133                                 ITransportHeaders response_headers;
134
135                                 _nextInChain.ProcessMessage (msg, call_headers, call_stream, out response_headers,
136                                                             out response_stream);
137
138                                 // Deserialize response_stream
139
140                                 return (IMessage) _binaryCore.Deserializer.DeserializeMethodResponse (response_stream, null, (IMethodCallMessage)msg);
141                                 
142                         } catch (Exception e) {
143                                  return new ReturnMessage (e, (IMethodCallMessage)msg);
144                         }
145                 }
146         }
147 }