2 // Mono.Remoting.Channels.Unix.UnixClientTransportSink.cs
4 // Author: Dietmar Maurer (dietmar@ximian.com)
5 // Lluis Sanchez Gual (lluis@novell.com)
7 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
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.
32 using System.Runtime.Remoting.Channels;
33 using System.Runtime.Remoting.Messaging;
34 using System.Collections;
36 using System.Threading;
37 using System.Runtime.Remoting;
39 namespace Mono.Remoting.Channels.Unix
41 internal class UnixClientTransportSink : IClientChannelSink
45 public UnixClientTransportSink (string url)
48 _path = UnixChannel.ParseUnixURL (url, out objectUri);
51 public IDictionary Properties
59 public IClientChannelSink NextChannelSink
63 // we are the last one
68 public void AsyncProcessRequest (IClientChannelSinkStack sinkStack, IMessage msg,
69 ITransportHeaders headers, Stream requestStream)
71 UnixConnection connection = null;
72 bool isOneWay = RemotingServices.IsOneWay (((IMethodMessage)msg).MethodBase);
76 if (headers == null) headers = new TransportHeaders();
77 headers ["__RequestUri"] = ((IMethodMessage)msg).Uri;
79 // Sends the stream using a connection from the pool
80 // and creates a WorkItem that will wait for the
81 // response of the server
83 connection = UnixConnectionPool.GetConnection (_path);
84 UnixMessageIO.SendMessageStream (connection.Stream, requestStream, headers, connection.Buffer);
85 connection.Stream.Flush ();
89 sinkStack.Push (this, connection);
90 ThreadPool.QueueUserWorkItem (new WaitCallback(data => {
92 ReadAsyncUnixMessage (data);
101 if (connection != null) connection.Release();
102 if (!isOneWay) throw;
106 private void ReadAsyncUnixMessage(object data)
108 // This method is called by a new thread to asynchronously
109 // read the response to a request
111 // The stack was provided as state data in QueueUserWorkItem
112 IClientChannelSinkStack stack = (IClientChannelSinkStack)data;
114 // The first sink in the stack is this sink. Pop it and
115 // get the status data, which is the UnixConnection used to send
117 UnixConnection connection = (UnixConnection)stack.Pop(this);
121 ITransportHeaders responseHeaders;
123 // Read the response, blocking if necessary
124 MessageStatus status = UnixMessageIO.ReceiveMessageStatus (connection.Stream, connection.Buffer);
126 if (status != MessageStatus.MethodMessage)
127 throw new RemotingException ("Unknown response message from server");
129 Stream responseStream = UnixMessageIO.ReceiveMessageStream (connection.Stream, out responseHeaders, connection.Buffer);
131 // Free the connection, so it can be reused
132 connection.Release();
135 // Ok, proceed with the other sinks
136 stack.AsyncProcessResponse (responseHeaders, responseStream);
140 if (connection != null) connection.Release();
145 public void AsyncProcessResponse (IClientResponseChannelSinkStack sinkStack,
146 object state, ITransportHeaders headers,
149 // Should never be called
150 throw new NotSupportedException();
153 public Stream GetRequestStream (IMessage msg, ITransportHeaders headers)
158 public void ProcessMessage (IMessage msg,
159 ITransportHeaders requestHeaders,
160 Stream requestStream,
161 out ITransportHeaders responseHeaders,
162 out Stream responseStream)
164 UnixConnection connection = null;
167 if (requestHeaders == null) requestHeaders = new TransportHeaders();
168 requestHeaders ["__RequestUri"] = ((IMethodMessage)msg).Uri;
171 connection = UnixConnectionPool.GetConnection (_path);
172 UnixMessageIO.SendMessageStream (connection.Stream, requestStream, requestHeaders, connection.Buffer);
173 connection.Stream.Flush ();
175 // Reads the response
176 MessageStatus status = UnixMessageIO.ReceiveMessageStatus (connection.Stream, connection.Buffer);
178 if (status != MessageStatus.MethodMessage)
179 throw new RemotingException ("Unknown response message from server");
181 responseStream = UnixMessageIO.ReceiveMessageStream (connection.Stream, out responseHeaders, connection.Buffer);
185 if (connection != null)
186 connection.Release();