(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / class / System.Runtime.Remoting / System.Runtime.Remoting.Channels.Tcp / TcpServerChannel.cs
blob6e3aba6f960a90457a50ac99bfeebdac6f264acb
1 //
2 // System.Runtime.Remoting.Channels.Tcp.TcpServerChannel.cs
3 //
4 // Author: Rodrigo Moya (rodrigo@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.Collections;
32 using System.Runtime.Remoting.Messaging;
33 using System.Text.RegularExpressions;
34 using System.Net.Sockets;
35 using System.Net;
36 using System.Threading;
37 using System.IO;
39 namespace System.Runtime.Remoting.Channels.Tcp
41 public class TcpServerChannel : IChannelReceiver, IChannel
43 int port = 0;
44 string name = "tcp";
45 string host = null;
46 int priority = 1;
47 bool supressChannelData = false;
48 bool useIpAddress = false;
50 IPAddress bindAddress = IPAddress.Any;
51 Thread server_thread = null;
52 TcpListener listener;
53 TcpServerTransportSink sink;
54 ChannelDataStore channel_data;
55 int _maxConcurrentConnections = 100;
56 ArrayList _activeConnections = new ArrayList();
59 void Init (IServerChannelSinkProvider serverSinkProvider)
61 if (serverSinkProvider == null)
63 serverSinkProvider = new BinaryServerFormatterSinkProvider ();
66 if (host == null)
68 if (useIpAddress) {
69 if (!bindAddress.Equals(IPAddress.Any)) host = bindAddress.ToString ();
70 else {
71 IPHostEntry he = Dns.Resolve (Dns.GetHostName());
72 if (he.AddressList.Length == 0) throw new RemotingException ("IP address could not be determined for this host");
73 host = he.AddressList [0].ToString ();
76 else
77 host = Dns.GetHostByName(Dns.GetHostName()).HostName;
80 // Gets channel data from the chain of channel providers
82 channel_data = new ChannelDataStore (null);
83 IServerChannelSinkProvider provider = serverSinkProvider;
84 while (provider != null)
86 provider.GetChannelData(channel_data);
87 provider = provider.Next;
90 // Creates the sink chain that will process all incoming messages
92 IServerChannelSink next_sink = ChannelServices.CreateServerChannelSinkChain (serverSinkProvider, this);
93 sink = new TcpServerTransportSink (next_sink);
96 public TcpServerChannel (int port)
98 this.port = port;
99 Init (null);
102 public TcpServerChannel (IDictionary properties,
103 IServerChannelSinkProvider serverSinkProvider)
105 foreach(DictionaryEntry property in properties)
107 switch((string)property.Key)
109 case "name":
110 name = property.Value.ToString();
111 break;
112 case "port":
113 port = Convert.ToInt32(property.Value);
114 break;
115 case "priority":
116 priority = Convert.ToInt32(property.Value);
117 break;
118 case "bindTo":
119 bindAddress = IPAddress.Parse((string)property.Value);
120 break;
121 case "rejectRemoteRequests":
122 if(Convert.ToBoolean(properties["rejectRemoteRequests"]))
123 bindAddress = IPAddress.Loopback;
124 break;
125 case "supressChannelData":
126 supressChannelData = Convert.ToBoolean (property.Value);
127 break;
128 case "useIpAddress":
129 useIpAddress = Convert.ToBoolean (property.Value);
130 break;
131 case "machineName":
132 host = property.Value as string;
133 break;
136 Init (serverSinkProvider);
139 public TcpServerChannel (string name, int port,
140 IServerChannelSinkProvider serverSinkProvider)
142 this.name = name;
143 this.port = port;
144 Init (serverSinkProvider);
147 public TcpServerChannel (string name, int port)
149 this.name = name;
150 this.port = port;
151 Init (null);
154 public object ChannelData
156 get {
157 if (supressChannelData) return null;
158 else return channel_data;
162 public string ChannelName
164 get {
165 return name;
169 public int ChannelPriority
171 get {
172 return priority;
176 public string GetChannelUri ()
178 return "tcp://" + host + ":" + port;
181 public string[] GetUrlsForUri (string uri)
183 if (!uri.StartsWith ("/")) uri = "/" + uri;
185 string [] chnl_uris = channel_data.ChannelUris;
186 string [] result = new String [chnl_uris.Length];
188 for (int i = 0; i < chnl_uris.Length; i++)
189 result [i] = chnl_uris [i] + uri;
191 return result;
194 public string Parse (string url, out string objectURI)
196 return TcpChannel.ParseChannelUrl (url, out objectURI);
199 void WaitForConnections ()
203 while (true)
205 TcpClient client = listener.AcceptTcpClient ();
206 CreateListenerConnection (client);
209 catch
213 internal void CreateListenerConnection (TcpClient client)
215 lock (_activeConnections)
217 if (_activeConnections.Count >= _maxConcurrentConnections)
218 Monitor.Wait (_activeConnections);
220 if (server_thread == null) return; // Server was stopped while waiting
222 ClientConnection reader = new ClientConnection (this, client, sink);
223 Thread thread = new Thread (new ThreadStart (reader.ProcessMessages));
224 thread.Start();
225 thread.IsBackground = true;
226 _activeConnections.Add (thread);
230 internal void ReleaseConnection (Thread thread)
232 lock (_activeConnections)
234 _activeConnections.Remove (thread);
235 Monitor.Pulse (_activeConnections);
239 public void StartListening (object data)
241 listener = new TcpListener (bindAddress, port);
242 if (server_thread == null)
244 listener.Start ();
246 if (port == 0)
247 port = ((IPEndPoint)listener.LocalEndpoint).Port;
249 string[] uris = new String [1];
250 uris = new String [1];
251 uris [0] = GetChannelUri ();
252 channel_data.ChannelUris = uris;
254 server_thread = new Thread (new ThreadStart (WaitForConnections));
255 server_thread.IsBackground = true;
256 server_thread.Start ();
260 public void StopListening (object data)
262 if (server_thread == null) return;
264 lock (_activeConnections)
266 server_thread.Abort ();
267 server_thread = null;
268 listener.Stop ();
270 foreach (Thread thread in _activeConnections)
271 thread.Abort();
273 _activeConnections.Clear();
274 Monitor.PulseAll (_activeConnections);
279 class ClientConnection
281 TcpClient _client;
282 TcpServerTransportSink _sink;
283 Stream _stream;
284 TcpServerChannel _serverChannel;
286 byte[] _buffer = new byte[TcpMessageIO.DefaultStreamBufferSize];
288 public ClientConnection (TcpServerChannel serverChannel, TcpClient client, TcpServerTransportSink sink)
290 _serverChannel = serverChannel;
291 _client = client;
292 _sink = sink;
295 public Stream Stream
297 get { return _stream; }
300 public byte[] Buffer
302 get { return _buffer; }
305 public void ProcessMessages()
307 _stream = _client.GetStream();
311 bool end = false;
312 while (!end)
314 MessageStatus type = TcpMessageIO.ReceiveMessageStatus (_stream);
316 switch (type)
318 case MessageStatus.MethodMessage:
319 _sink.InternalProcessMessage (this);
320 break;
322 case MessageStatus.CancelSignal:
323 end = true;
324 break;
328 catch (Exception ex)
330 // Console.WriteLine (ex);
332 finally
334 _stream.Close();
335 _serverChannel.ReleaseConnection (Thread.CurrentThread);
339 public bool IsLocal
343 return true;