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 [CommonTransportKeys.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(ReadAsyncUnixMessage), sinkStack);
97 if (connection != null) connection.Release();
102 private void ReadAsyncUnixMessage(object data)
104 // This method is called by a new thread to asynchronously
105 // read the response to a request
107 // The stack was provided as state data in QueueUserWorkItem
108 IClientChannelSinkStack stack = (IClientChannelSinkStack)data;
110 // The first sink in the stack is this sink. Pop it and
111 // get the status data, which is the UnixConnection used to send
113 UnixConnection connection = (UnixConnection)stack.Pop(this);
117 ITransportHeaders responseHeaders;
119 // Read the response, blocking if necessary
120 MessageStatus status = UnixMessageIO.ReceiveMessageStatus (connection.Stream, connection.Buffer);
122 if (status != MessageStatus.MethodMessage)
123 throw new RemotingException ("Unknown response message from server");
125 Stream responseStream = UnixMessageIO.ReceiveMessageStream (connection.Stream, out responseHeaders, connection.Buffer);
127 // Free the connection, so it can be reused
128 connection.Release();
131 // Ok, proceed with the other sinks
132 stack.AsyncProcessResponse (responseHeaders, responseStream);
136 if (connection != null) connection.Release();
141 public void AsyncProcessResponse (IClientResponseChannelSinkStack sinkStack,
142 object state, ITransportHeaders headers,
145 // Should never be called
146 throw new NotSupportedException();
149 public Stream GetRequestStream (IMessage msg, ITransportHeaders headers)
154 public void ProcessMessage (IMessage msg,
155 ITransportHeaders requestHeaders,
156 Stream requestStream,
157 out ITransportHeaders responseHeaders,
158 out Stream responseStream)
160 UnixConnection connection = null;
163 if (requestHeaders == null) requestHeaders = new TransportHeaders();
164 requestHeaders [CommonTransportKeys.RequestUri] = ((IMethodMessage)msg).Uri;
167 connection = UnixConnectionPool.GetConnection (_path);
168 UnixMessageIO.SendMessageStream (connection.Stream, requestStream, requestHeaders, connection.Buffer);
169 connection.Stream.Flush ();
171 // Reads the response
172 MessageStatus status = UnixMessageIO.ReceiveMessageStatus (connection.Stream, connection.Buffer);
174 if (status != MessageStatus.MethodMessage)
175 throw new RemotingException ("Unknown response message from server");
177 responseStream = UnixMessageIO.ReceiveMessageStream (connection.Stream, out responseHeaders, connection.Buffer);
181 if (connection != null)
182 connection.Release();