Welcome to mirror list, hosted at ThFree Co, Russian Federation.

TcpClientTransportSink.cs « System.Runtime.Remoting.Channels.Tcp « System.Runtime.Remoting « class « mcs - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: ad26ec4371f31da2b5610ba1f97acd55a69b097f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//
// System.Runtime.Remoting.Channels.Tcp.TcpClientTransportSink.cs
//
// Author: Dietmar Maurer (dietmar@ximian.com)
//         Lluis Sanchez (lsg@ctv.es)
//
// 2002 (C) Copyright, Ximian, Inc.
//

using System;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Messaging;
using System.Collections;
using System.IO;
using System.Threading;

namespace System.Runtime.Remoting.Channels.Tcp
{
	public class TcpClientTransportSink : IClientChannelSink
	{
		string _host;
		string _objectUri;
		int _port;
		
		public TcpClientTransportSink (string url)
		{
			_host = TcpChannel.ParseTcpURL (url, out _objectUri, out _port);
		}

		public IDictionary Properties
		{
			get 
			{
				return null;
			}
		}

		public IClientChannelSink NextChannelSink
		{
			get 
			{
				// we are the last one
				return null;
			}
		}

		public void AsyncProcessRequest (IClientChannelSinkStack sinkStack, IMessage msg,
			ITransportHeaders headers, Stream requestStream)
		{
			TcpConnection connection = null;
			try
			{
				// Sends the stream using a connection from the pool
				// and creates a WorkItem that will wait for the
				// response of the server

				connection = TcpConnectionPool.GetConnection (_host, _port);
				TcpMessageIO.SendMessageStream (connection.Stream, requestStream, headers, connection.Buffer);
				sinkStack.Push (this, connection);
				ThreadPool.QueueUserWorkItem (new WaitCallback(ReadAsyncTcpMessage), sinkStack);
			}
			catch
			{
				if (connection != null) connection.Release();
				throw;
			}
		}

		private void ReadAsyncTcpMessage(object data)
		{
			// This method is called by a new thread to asynchronously
			// read the response to a request

			// The stack was provided as state data in QueueUserWorkItem
			IClientChannelSinkStack stack = (IClientChannelSinkStack)data;

			// The first sink in the stack is this sink. Pop it and
			// get the status data, which is the TcpConnection used to send
			// the request
			TcpConnection connection = (TcpConnection)stack.Pop(this);

			try
			{
				ITransportHeaders responseHeaders;

				// Read the response, blocking if necessary
				MessageType type = TcpMessageIO.ReceiveMessageType (connection.Stream);

				if (type != MessageType.MethodMessage)
					throw new RemotingException ("Unknown response message from server");

				Stream responseStream = TcpMessageIO.ReceiveMessageStream (connection.Stream, out responseHeaders, connection.Buffer);

				// Free the connection, so it can be reused
				connection.Release();
				connection = null;

				// Ok, proceed with the other sinks
				stack.AsyncProcessResponse (responseHeaders, responseStream);
			}
			catch
			{
				if (connection != null) connection.Release();
				throw;
			}
		}
	
		public void AsyncProcessResponse (IClientResponseChannelSinkStack sinkStack,
			object state, ITransportHeaders headers,
			Stream stream)
		{
			// Should never be called
			throw new NotSupportedException();
		}

		public Stream GetRequestStream (IMessage msg, ITransportHeaders headers)
		{
			return null;
		}
		
		public void ProcessMessage (IMessage msg,
			ITransportHeaders requestHeaders,
			Stream requestStream,
			out ITransportHeaders responseHeaders,
			out Stream responseStream)
		{
			TcpConnection connection = null;
			try
			{
				// Sends the message
				connection = TcpConnectionPool.GetConnection (_host, _port);
				TcpMessageIO.SendMessageStream (connection.Stream, requestStream, requestHeaders, connection.Buffer);

				// Reads the response
				MessageType type = TcpMessageIO.ReceiveMessageType (connection.Stream);

				if (type != MessageType.MethodMessage)
					throw new RemotingException ("Unknown response message from server");

				responseStream = TcpMessageIO.ReceiveMessageStream (connection.Stream, out responseHeaders, connection.Buffer);
			}
			finally
			{
				if (connection != null) 
					connection.Release();
			}
		}

	}


}