GenericParameter.cs: override Module properly
[mcs.git] / class / Mono.Posix / Mono.Remoting.Channels.Unix / UnixServerChannel.cs
blob3162d86506f7a05d1cee1392564c850ff7cc6ae7
1 //
2 // Mono.Remoting.Channels.Unix.UnixServerChannel.cs
3 //
4 // Author: Rodrigo Moya (rodrigo@ximian.com)
5 // Lluis Sanchez Gual (lluis@ideary.com)
6 //
7 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
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.Collections;
33 using System.Runtime.Remoting.Messaging;
34 using System.Text.RegularExpressions;
35 using System.Net.Sockets;
36 using System.Net;
37 using System.Threading;
38 using System.IO;
39 using System.Runtime.Remoting.Channels;
40 using Mono.Unix;
42 namespace Mono.Remoting.Channels.Unix
44 public class UnixServerChannel : IChannelReceiver, IChannel
46 string path = null;
47 string name = "unix";
49 int priority = 1;
50 bool supressChannelData = false;
52 Thread server_thread = null;
53 UnixListener listener;
54 UnixServerTransportSink sink;
55 ChannelDataStore channel_data;
56 int _maxConcurrentConnections = 100;
57 ArrayList _activeConnections = new ArrayList();
60 void Init (IServerChannelSinkProvider serverSinkProvider)
62 if (serverSinkProvider == null)
64 serverSinkProvider = new UnixBinaryServerFormatterSinkProvider ();
67 // Gets channel data from the chain of channel providers
69 channel_data = new ChannelDataStore (null);
70 IServerChannelSinkProvider provider = serverSinkProvider;
71 while (provider != null)
73 provider.GetChannelData(channel_data);
74 provider = provider.Next;
77 // Creates the sink chain that will process all incoming messages
79 IServerChannelSink next_sink = ChannelServices.CreateServerChannelSinkChain (serverSinkProvider, this);
80 sink = new UnixServerTransportSink (next_sink);
82 StartListening (null);
85 public UnixServerChannel (string path)
87 this.path = path;
88 Init (null);
91 public UnixServerChannel (IDictionary properties,
92 IServerChannelSinkProvider serverSinkProvider)
94 foreach(DictionaryEntry property in properties)
96 switch((string)property.Key)
98 case "path":
99 path = property.Value as string;
100 break;
101 case "priority":
102 priority = Convert.ToInt32(property.Value);
103 break;
104 case "supressChannelData":
105 supressChannelData = Convert.ToBoolean (property.Value);
106 break;
109 Init (serverSinkProvider);
112 public UnixServerChannel (string name, string path,
113 IServerChannelSinkProvider serverSinkProvider)
115 this.name = name;
116 this.path = path;
117 Init (serverSinkProvider);
120 public UnixServerChannel (string name, string path)
122 this.name = name;
123 this.path = path;
124 Init (null);
127 public object ChannelData
129 get {
130 if (supressChannelData) return null;
131 else return channel_data;
135 public string ChannelName
137 get {
138 return name;
142 public int ChannelPriority
144 get {
145 return priority;
149 public string GetChannelUri ()
151 return "unix://" + path;
154 public string[] GetUrlsForUri (string uri)
156 if (!uri.StartsWith ("/")) uri = "/" + uri;
158 string [] chnl_uris = channel_data.ChannelUris;
159 string [] result = new String [chnl_uris.Length];
161 for (int i = 0; i < chnl_uris.Length; i++)
162 result [i] = chnl_uris [i] + "?" + uri;
164 return result;
167 public string Parse (string url, out string objectURI)
169 return UnixChannel.ParseUnixURL (url, out objectURI);
172 void WaitForConnections ()
176 while (true)
178 Socket client = listener.AcceptSocket ();
179 CreateListenerConnection (client);
182 catch
186 internal void CreateListenerConnection (Socket client)
188 lock (_activeConnections)
190 if (_activeConnections.Count >= _maxConcurrentConnections)
191 Monitor.Wait (_activeConnections);
193 if (server_thread == null) return; // Server was stopped while waiting
195 ClientConnection reader = new ClientConnection (this, client, sink);
196 Thread thread = new Thread (new ThreadStart (reader.ProcessMessages));
197 thread.Start();
198 thread.IsBackground = true;
199 _activeConnections.Add (thread);
203 internal void ReleaseConnection (Thread thread)
205 lock (_activeConnections)
207 _activeConnections.Remove (thread);
208 Monitor.Pulse (_activeConnections);
212 public void StartListening (object data)
214 listener = new UnixListener (path);
215 Mono.Unix.Native.Syscall.chmod (path,
216 Mono.Unix.Native.FilePermissions.S_IRUSR |
217 Mono.Unix.Native.FilePermissions.S_IWUSR |
218 Mono.Unix.Native.FilePermissions.S_IRGRP |
219 Mono.Unix.Native.FilePermissions.S_IWGRP |
220 Mono.Unix.Native.FilePermissions.S_IROTH |
221 Mono.Unix.Native.FilePermissions.S_IWOTH);
223 if (server_thread == null)
225 listener.Start ();
227 string[] uris = new String [1];
228 uris = new String [1];
229 uris [0] = GetChannelUri ();
230 channel_data.ChannelUris = uris;
232 server_thread = new Thread (new ThreadStart (WaitForConnections));
233 server_thread.IsBackground = true;
234 server_thread.Start ();
238 public void StopListening (object data)
240 if (server_thread == null) return;
242 lock (_activeConnections)
244 server_thread.Abort ();
245 server_thread = null;
246 listener.Stop ();
248 foreach (Thread thread in _activeConnections)
249 thread.Abort();
251 _activeConnections.Clear();
252 Monitor.PulseAll (_activeConnections);
257 class ClientConnection
259 Socket _client;
260 UnixServerTransportSink _sink;
261 Stream _stream;
262 UnixServerChannel _serverChannel;
264 byte[] _buffer = new byte[UnixMessageIO.DefaultStreamBufferSize];
266 public ClientConnection (UnixServerChannel serverChannel, Socket client, UnixServerTransportSink sink)
268 _serverChannel = serverChannel;
269 _client = client;
270 _sink = sink;
273 public Socket Client {
274 get { return _client; }
277 public byte[] Buffer
279 get { return _buffer; }
282 public void ProcessMessages()
284 byte[] buffer = new byte[256];
285 _stream = new BufferedStream (new NetworkStream (_client));
289 bool end = false;
290 while (!end)
292 MessageStatus type = UnixMessageIO.ReceiveMessageStatus (_stream, buffer);
294 switch (type)
296 case MessageStatus.MethodMessage:
297 _sink.InternalProcessMessage (this, _stream);
298 break;
300 case MessageStatus.Unknown:
301 case MessageStatus.CancelSignal:
302 end = true;
303 break;
307 catch (Exception)
309 // Console.WriteLine (ex);
311 finally
313 _stream.Close();
314 _client.Close ();
315 _serverChannel.ReleaseConnection (Thread.CurrentThread);
319 public bool IsLocal
323 return true;