2 // System.Runtime.Remoting.Channels.Tcp.TcpClientTransportSink.cs
4 // Author: Dietmar Maurer (dietmar@ximian.com)
5 // Lluis Sanchez Gual (lluis@ideary.com)
7 // 2002 (C) Copyright, Ximian, Inc.
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;
\r
33 using System.Runtime.Remoting.Messaging;
\r
34 using System.Collections;
\r
36 using System.Threading;
\r
38 namespace System.Runtime.Remoting.Channels.Tcp
\r
40 internal class TcpClientTransportSink : IClientChannelSink
46 public TcpClientTransportSink (string url)
49 _host = TcpChannel.ParseTcpURL (url, out objectUri, out _port);
53 public IDictionary Properties
61 public IClientChannelSink NextChannelSink
65 // we are the last one
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);
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);
87 connection.Stream.Flush ();
91 sinkStack.Push (this, connection);
92 ThreadPool.QueueUserWorkItem (new WaitCallback(ReadAsyncTcpMessage), sinkStack);
99 if (connection != null) connection.Release();
100 if (!isOneWay) throw;
104 private void ReadAsyncTcpMessage(object data)
106 // This method is called by a new thread to asynchronously
107 // read the response to a request
109 // The stack was provided as state data in QueueUserWorkItem
110 IClientChannelSinkStack stack = (IClientChannelSinkStack)data;
112 // The first sink in the stack is this sink. Pop it and
113 // get the status data, which is the TcpConnection used to send
115 TcpConnection connection = (TcpConnection)stack.Pop(this);
119 ITransportHeaders responseHeaders;
121 // Read the response, blocking if necessary
122 MessageStatus status = TcpMessageIO.ReceiveMessageStatus (connection.Stream, connection.Buffer);
124 if (status != MessageStatus.MethodMessage)
125 throw new RemotingException ("Unknown response message from server");
127 Stream responseStream = TcpMessageIO.ReceiveMessageStream (connection.Stream, out responseHeaders, connection.Buffer);
129 // Free the connection, so it can be reused
130 connection.Release();
133 // Ok, proceed with the other sinks
134 stack.AsyncProcessResponse (responseHeaders, responseStream);
138 if (connection != null) connection.Release();
143 public void AsyncProcessResponse (IClientResponseChannelSinkStack sinkStack,
144 object state, ITransportHeaders headers,
147 // Should never be called
148 throw new NotSupportedException();
151 public Stream GetRequestStream (IMessage msg, ITransportHeaders headers)
156 public void ProcessMessage (IMessage msg,
157 ITransportHeaders requestHeaders,
158 Stream requestStream,
159 out ITransportHeaders responseHeaders,
160 out Stream responseStream)
162 TcpConnection connection = null;
165 if (requestHeaders == null) requestHeaders = new TransportHeaders();
166 requestHeaders [CommonTransportKeys.RequestUri] = ((IMethodMessage)msg).Uri;
169 connection = TcpConnectionPool.GetConnection (_host, _port);
170 TcpMessageIO.SendMessageStream (connection.Stream, requestStream, requestHeaders, connection.Buffer);
171 connection.Stream.Flush ();
173 // Reads the response
174 MessageStatus status = TcpMessageIO.ReceiveMessageStatus (connection.Stream, connection.Buffer);
176 if (status != MessageStatus.MethodMessage)
177 throw new RemotingException ("Unknown response message from server");
179 responseStream = TcpMessageIO.ReceiveMessageStream (connection.Stream, out responseHeaders, connection.Buffer);
183 if (connection != null)
184 connection.Release();