**** Merged from MCS ****
[mono-project.git] / mcs / class / System.Runtime.Remoting / System.Runtime.Remoting.Channels.Tcp / TcpClientTransportSink.cs
blobdff1a2ce5286653153a88076c0d9a8d0e58ed132
1 //
2 // System.Runtime.Remoting.Channels.Tcp.TcpClientTransportSink.cs
3 //
4 // Author: Dietmar Maurer (dietmar@ximian.com)
5 // Lluis Sanchez Gual (lluis@ideary.com)
6 //
7 // 2002 (C) Copyright, Ximian, Inc.
8 //
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:
18 //
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 //
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;
32 using System.Runtime.Remoting.Channels;
33 using System.Runtime.Remoting.Messaging;
34 using System.Collections;
35 using System.IO;
36 using System.Threading;
38 namespace System.Runtime.Remoting.Channels.Tcp
40 internal class TcpClientTransportSink : IClientChannelSink
42 string _host;
43 string _url;
44 int _port;
46 public TcpClientTransportSink (string url)
48 string objectUri;
49 _host = TcpChannel.ParseTcpURL (url, out objectUri, out _port);
50 _url = url;
53 public IDictionary Properties
55 get
57 return null;
61 public IClientChannelSink NextChannelSink
63 get
65 // we are the last one
66 return null;
70 public void AsyncProcessRequest (IClientChannelSinkStack sinkStack, IMessage msg,
71 ITransportHeaders headers, Stream requestStream)
73 TcpConnection connection = null;
74 bool isOneWay = RemotingServices.IsOneWay (((IMethodMessage)msg).MethodBase);
76 try
78 if (headers == null) headers = new TransportHeaders();
79 headers [CommonTransportKeys.RequestUri] = ((IMethodMessage)msg).Uri;
81 // Sends the stream using a connection from the pool
82 // and creates a WorkItem that will wait for the
83 // response of the server
85 connection = TcpConnectionPool.GetConnection (_host, _port);
86 TcpMessageIO.SendMessageStream (connection.Stream, requestStream, headers, connection.Buffer);
88 if (!isOneWay)
90 sinkStack.Push (this, connection);
91 ThreadPool.QueueUserWorkItem (new WaitCallback(ReadAsyncTcpMessage), sinkStack);
93 else
94 connection.Release();
96 catch
98 if (connection != null) connection.Release();
99 if (!isOneWay) throw;
103 private void ReadAsyncTcpMessage(object data)
105 // This method is called by a new thread to asynchronously
106 // read the response to a request
108 // The stack was provided as state data in QueueUserWorkItem
109 IClientChannelSinkStack stack = (IClientChannelSinkStack)data;
111 // The first sink in the stack is this sink. Pop it and
112 // get the status data, which is the TcpConnection used to send
113 // the request
114 TcpConnection connection = (TcpConnection)stack.Pop(this);
118 ITransportHeaders responseHeaders;
120 // Read the response, blocking if necessary
121 MessageStatus status = TcpMessageIO.ReceiveMessageStatus (connection.Stream);
123 if (status != MessageStatus.MethodMessage)
124 throw new RemotingException ("Unknown response message from server");
126 Stream responseStream = TcpMessageIO.ReceiveMessageStream (connection.Stream, out responseHeaders, connection.Buffer);
128 // Free the connection, so it can be reused
129 connection.Release();
130 connection = null;
132 // Ok, proceed with the other sinks
133 stack.AsyncProcessResponse (responseHeaders, responseStream);
135 catch
137 if (connection != null) connection.Release();
138 throw;
142 public void AsyncProcessResponse (IClientResponseChannelSinkStack sinkStack,
143 object state, ITransportHeaders headers,
144 Stream stream)
146 // Should never be called
147 throw new NotSupportedException();
150 public Stream GetRequestStream (IMessage msg, ITransportHeaders headers)
152 return null;
155 public void ProcessMessage (IMessage msg,
156 ITransportHeaders requestHeaders,
157 Stream requestStream,
158 out ITransportHeaders responseHeaders,
159 out Stream responseStream)
161 TcpConnection connection = null;
164 if (requestHeaders == null) requestHeaders = new TransportHeaders();
165 requestHeaders [CommonTransportKeys.RequestUri] = ((IMethodMessage)msg).Uri;
167 // Sends the message
168 connection = TcpConnectionPool.GetConnection (_host, _port);
169 TcpMessageIO.SendMessageStream (connection.Stream, requestStream, requestHeaders, connection.Buffer);
171 // Reads the response
172 MessageStatus status = TcpMessageIO.ReceiveMessageStatus (connection.Stream);
174 if (status != MessageStatus.MethodMessage)
175 throw new RemotingException ("Unknown response message from server");
177 responseStream = TcpMessageIO.ReceiveMessageStream (connection.Stream, out responseHeaders, connection.Buffer);
179 finally
181 if (connection != null)
182 connection.Release();