Make a copy of the old ZipLib
[mono.git] / mcs / class / System.Runtime.Remoting / System.Runtime.Remoting.Channels.Ipc.Win32 / IpcClientChannel.cs
1 //
2 // System.Runtime.Remoting.Channels.Ipc.Win32.IpcClientChannel.cs
3 //
4 // Author: Robert Jordan (robertj@gmx.net)
5 //
6 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
7 //
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 #if NET_2_0
30
31 using System;
32 using System.Collections;
33 using System.IO;
34 using System.Runtime.Remoting;
35 using System.Runtime.Remoting.Channels;
36 using System.Runtime.Remoting.Messaging;
37
38 namespace System.Runtime.Remoting.Channels.Ipc.Win32
39 {
40     internal class IpcClientChannel : IChannelSender, IChannel
41     {
42         readonly string channelName = IpcChannelHelper.Scheme;
43         readonly int channelPriority = 1;
44         readonly IClientChannelSinkProvider clientProvider;
45
46         /// <summary>
47         /// Creates a default client channel.
48         /// </summary>
49         public IpcClientChannel()
50             : this ((IDictionary)null, null)
51         {
52         }
53
54         /// <summary>
55         /// Creates a default client channel.
56         /// </summary>
57         /// <param name="name">The channel name.</param>
58         /// <param name="sinkProvider">The provider</param>
59         public IpcClientChannel(string name, IClientChannelSinkProvider provider)
60             : this (IpcServerChannel.BuildDefaultProperties (name), provider)
61         {
62         }
63
64         /// <summary>
65         /// Creates a client channel.
66         /// </summary>
67         /// <param name="properties">The properties.</param>
68         /// <param name="sinkProvider">The provider</param>
69         public IpcClientChannel(IDictionary properties, IClientChannelSinkProvider provider)
70         {
71             if (properties != null) 
72             {
73                 foreach (DictionaryEntry e in properties) 
74                 {
75                     switch ((string)e.Key) 
76                     {
77                         case "name":
78                             channelName = (string)e.Value;
79                             break;
80                         case "priority":
81                             channelPriority = Convert.ToInt32(e.Value);
82                             break;
83                     }
84                 }
85             }
86
87             if (provider == null) 
88             {
89                 clientProvider = new BinaryClientFormatterSinkProvider();
90                 clientProvider.Next = new IpcClientChannelSinkProvider();
91             }
92             else 
93             {
94                 // add us to the sink chain.
95                 clientProvider = provider;
96                 IClientChannelSinkProvider p;
97                 for (p = clientProvider; p.Next != null; p = p.Next) {}
98                 p.Next = new IpcClientChannelSinkProvider();
99             }
100                                         
101         }
102
103         #region IChannelSender Members
104
105         public IMessageSink CreateMessageSink(string url, object remoteChannelData, out string objectURI)
106         {
107             objectURI = null;
108             string channelUri = null;
109
110             if (url != null) 
111             {
112                 channelUri = Parse(url, out objectURI);
113             }
114
115             if (channelUri == null) 
116             {
117                 // get url from the channel data
118                 IChannelDataStore ds = remoteChannelData as IChannelDataStore;
119                 if (ds != null) 
120                 {
121                     channelUri = Parse(ds.ChannelUris[0], out objectURI);
122                     if (channelUri != null)
123                         url = ds.ChannelUris[0];
124                 }
125             }
126
127             if (channelUri != null) 
128             {
129                 return (IMessageSink) clientProvider.CreateSink(this, url, remoteChannelData);
130             }
131             else 
132             {
133                 return null;
134             }
135         }
136
137         #endregion
138
139         #region IChannel Members
140
141         public string ChannelName
142         {
143             get
144             {
145                 return channelName;
146             }
147         }
148
149         public int ChannelPriority
150         {
151             get
152             {
153                 return channelPriority;
154             }
155         }
156
157         public string Parse(string url, out string objectURI)
158         {
159             return IpcChannelHelper.Parse(url, out objectURI);
160         }
161
162         #endregion
163     }
164
165     internal class IpcClientChannelSinkProvider : IClientChannelSinkProvider
166     {
167         #region IClientChannelSinkProvider Members
168
169         public IClientChannelSink CreateSink(IChannelSender channel, string url, object remoteChannelData)
170         {
171             return new IpcClientChannelSink(url);
172         }
173
174         public IClientChannelSinkProvider Next
175         {
176             get
177             {
178                 return null;
179             }
180             set
181             {
182                 throw new NotSupportedException();
183             }
184         }
185
186         #endregion
187     }
188
189     internal class IpcClientChannelSink : IClientChannelSink
190     {
191         readonly string pipeName;
192
193         public IpcClientChannelSink(string url) 
194         {
195             string unused;
196             IpcChannelHelper.Parse(url, out pipeName, out unused);
197         }
198
199         #region IClientChannelSink Members
200
201         delegate void AsyncResponse(IClientChannelSinkStack sinkStack, IpcTransport transport);
202
203         public void AsyncProcessRequest(IClientChannelSinkStack sinkStack, IMessage msg, ITransportHeaders headers, Stream stream)
204         {
205             headers[CommonTransportKeys.RequestUri] = ((IMethodCallMessage)msg).Uri;
206
207             // connect
208             NamedPipeClient client = new NamedPipeClient(pipeName);
209             NamedPipeSocket socket = client.Connect();
210             IpcTransport t = new IpcTransport(socket);
211             t.Write(headers, stream);
212
213             // schedule an async call
214             if (!RemotingServices.IsOneWay(((IMethodCallMessage)msg).MethodBase)) 
215             {
216                 new AsyncResponse(AsyncHandler).BeginInvoke(sinkStack, t, null, null);
217             }
218         }
219
220         void AsyncHandler(IClientChannelSinkStack sinkStack, IpcTransport transport) 
221         {
222             try 
223             {
224                 // get the response headers and the response stream from the server
225                 ITransportHeaders responseHeaders;
226                 Stream responseStream;
227                 transport.Read(out responseHeaders, out responseStream);
228                 transport.Close();
229                 sinkStack.AsyncProcessResponse(responseHeaders, responseStream);
230             }
231             catch (Exception ex) 
232             {
233                 sinkStack.DispatchException(ex);
234             }
235         }
236
237         public void ProcessMessage(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream, out ITransportHeaders responseHeaders, out Stream responseStream)
238         {
239             responseHeaders = null;
240             responseStream = null;
241
242             requestHeaders[CommonTransportKeys.RequestUri] = ((IMethodCallMessage)msg).Uri;
243
244             // connect
245             NamedPipeClient client = new NamedPipeClient(pipeName);
246             NamedPipeSocket socket = client.Connect();
247             IpcTransport t = new IpcTransport(socket);
248             t.Write(requestHeaders, requestStream);
249             t.Read(out responseHeaders, out responseStream);
250             t.Close();
251         }
252
253         public void AsyncProcessResponse(IClientResponseChannelSinkStack sinkStack, object state, ITransportHeaders headers, Stream stream)
254         {
255             throw new NotSupportedException();
256         }
257
258         public Stream GetRequestStream(IMessage msg, ITransportHeaders headers)
259         {
260             return null;
261         }
262
263         public IClientChannelSink NextChannelSink
264         {
265             get { return null; }
266         }
267
268         #endregion
269
270         #region IChannelSinkBase Members
271
272         public IDictionary Properties
273         {
274             get { return null; }
275         }
276
277         #endregion
278
279     }
280
281 }
282
283 #endif