flush
[mcs.git] / class / System.Core / System.IO.Pipes / PipeUnix.cs
bloba9f19967f859435f9c7642668f5da9f2bf3e055e
1 //
2 // PipeUnix.cs
3 //
4 // Author:
5 // Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2009 Novell, Inc. http://www.novell.com
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 #if !BOOTSTRAP_BASIC
31 using System;
32 using System.ComponentModel;
33 using System.IO;
34 using System.Linq;
35 using System.Net;
36 using System.Runtime.InteropServices;
37 using System.Security.AccessControl;
38 using System.Security.Permissions;
39 using System.Security.Principal;
40 using System.Text;
41 using System.Threading;
42 using Microsoft.Win32;
43 using Microsoft.Win32.SafeHandles;
44 using Mono.Unix.Native;
46 namespace System.IO.Pipes
48 abstract class UnixAnonymousPipe : IPipe
50 protected UnixAnonymousPipe ()
54 public abstract SafePipeHandle Handle { get; }
56 public void WaitForPipeDrain ()
58 throw new NotImplementedException ();
62 class UnixAnonymousPipeClient : UnixAnonymousPipe, IAnonymousPipeClient
64 // AnonymousPipeClientStream owner;
66 public UnixAnonymousPipeClient (AnonymousPipeClientStream owner, SafePipeHandle handle)
68 // this.owner = owner;
70 this.handle = handle;
73 SafePipeHandle handle;
75 public override SafePipeHandle Handle {
76 get { return handle; }
80 class UnixAnonymousPipeServer : UnixAnonymousPipe, IAnonymousPipeServer
82 // AnonymousPipeServerStream owner;
84 public UnixAnonymousPipeServer (AnonymousPipeServerStream owner, PipeDirection direction, HandleInheritability inheritability, int bufferSize)
86 // this.owner = owner;
88 throw new NotImplementedException ();
91 public UnixAnonymousPipeServer (AnonymousPipeServerStream owner, SafePipeHandle serverHandle, SafePipeHandle clientHandle)
93 // this.owner = owner;
95 this.server_handle = serverHandle;
96 this.client_handle = clientHandle;
98 throw new NotImplementedException ();
101 SafePipeHandle server_handle, client_handle;
103 public override SafePipeHandle Handle {
104 get { return server_handle; }
107 public SafePipeHandle ClientHandle {
108 get { return client_handle; }
111 public void DisposeLocalCopyOfClientHandle ()
113 throw new NotImplementedException ();
117 abstract class UnixNamedPipe : IPipe
119 public abstract SafePipeHandle Handle { get; }
121 public void WaitForPipeDrain ()
123 throw new NotImplementedException ();
126 public void EnsureTargetFile (string name)
128 if (!File.Exists (name)) {
129 var error = Syscall.mknod (name, FilePermissions.S_IFIFO | FilePermissions.ALLPERMS, 0);
130 if (error != 0)
131 throw new IOException (String.Format ("Error on creating named pipe: error code {0}", error));
135 protected void ValidateOptions (PipeOptions options, PipeTransmissionMode mode)
137 if ((options & PipeOptions.WriteThrough) != 0)
138 throw new NotImplementedException ("WriteThrough is not supported");
140 if ((mode & PipeTransmissionMode.Message) != 0)
141 throw new NotImplementedException ("Message transmission mode is not supported");
142 if ((options & PipeOptions.Asynchronous) != 0) // FIXME: use O_NONBLOCK?
143 throw new NotImplementedException ("Asynchronous pipe mode is not supported");
146 protected string RightsToAccess (PipeAccessRights rights)
148 string access = null;
149 if ((rights & PipeAccessRights.ReadData) != 0) {
150 if ((rights & PipeAccessRights.WriteData) != 0)
151 access = "r+";
152 else
153 access = "r";
155 else if ((rights & PipeAccessRights.WriteData) != 0)
156 access = "w";
157 else
158 throw new InvalidOperationException ("The pipe must be opened to either read or write");
160 return access;
163 protected FileAccess RightsToFileAccess (PipeAccessRights rights)
165 string access = null;
166 if ((rights & PipeAccessRights.ReadData) != 0) {
167 if ((rights & PipeAccessRights.WriteData) != 0)
168 return FileAccess.ReadWrite;
169 else
170 return FileAccess.Read;
172 else if ((rights & PipeAccessRights.WriteData) != 0)
173 return FileAccess.Write;
174 else
175 throw new InvalidOperationException ("The pipe must be opened to either read or write");
179 class UnixNamedPipeClient : UnixNamedPipe, INamedPipeClient
181 // .ctor with existing handle
182 public UnixNamedPipeClient (NamedPipeClientStream owner, SafePipeHandle safePipeHandle)
184 this.owner = owner;
185 this.handle = safePipeHandle;
186 // FIXME: dunno how is_async could be filled.
189 // .ctor without handle - create new
190 public UnixNamedPipeClient (NamedPipeClientStream owner, string serverName, string pipeName,
191 PipeAccessRights desiredAccessRights, PipeOptions options, HandleInheritability inheritability)
193 this.owner = owner;
195 if (serverName != "." && !Dns.GetHostEntry (serverName).AddressList.Contains (IPAddress.Loopback))
196 throw new NotImplementedException ("Unix fifo does not support remote server connection");
197 var name = Path.Combine ("/var/tmp/", pipeName);
198 EnsureTargetFile (name);
200 string access = RightsToAccess (desiredAccessRights);
202 ValidateOptions (options, owner.TransmissionMode);
204 // FIXME: handle inheritability
206 opener = delegate {
207 var fs = new FileStream (name, FileMode.Open, RightsToFileAccess (desiredAccessRights), FileShare.ReadWrite);
208 owner.Stream = fs;
209 handle = new SafePipeHandle (fs.Handle, false);
213 NamedPipeClientStream owner;
214 bool is_async;
215 SafePipeHandle handle;
216 Action opener;
218 public override SafePipeHandle Handle {
219 get { return handle; }
222 public void Connect ()
224 if (owner.IsConnected)
225 throw new InvalidOperationException ("The named pipe is already connected");
227 opener ();
230 public void Connect (int timeout)
232 AutoResetEvent waitHandle = new AutoResetEvent (false);
233 opener.BeginInvoke (delegate (IAsyncResult result) {
234 opener.EndInvoke (result);
235 waitHandle.Set ();
236 }, null);
237 if (!waitHandle.WaitOne (TimeSpan.FromMilliseconds (timeout)))
238 throw new TimeoutException ();
241 public bool IsAsync {
242 get { return is_async; }
245 public int NumberOfServerInstances {
246 get { throw new NotImplementedException (); }
250 class UnixNamedPipeServer : UnixNamedPipe, INamedPipeServer
252 //NamedPipeServerStream owner;
254 // .ctor with existing handle
255 public UnixNamedPipeServer (NamedPipeServerStream owner, SafePipeHandle safePipeHandle)
257 this.handle = safePipeHandle;
258 //this.owner = owner;
261 // .ctor without handle - create new
262 public UnixNamedPipeServer (NamedPipeServerStream owner, string pipeName, int maxNumberOfServerInstances,
263 PipeTransmissionMode transmissionMode, PipeAccessRights rights, PipeOptions options,
264 int inBufferSize, int outBufferSize, HandleInheritability inheritability)
266 string name = Path.Combine ("/var/tmp/", pipeName);
267 EnsureTargetFile (name);
269 string access = RightsToAccess (rights);
271 ValidateOptions (options, owner.TransmissionMode);
273 // FIXME: maxNumberOfServerInstances, modes, sizes, handle inheritability
275 var fs = new FileStream (name, FileMode.Open, RightsToFileAccess (rights), FileShare.ReadWrite);
276 handle = new SafePipeHandle (fs.Handle, false);
277 owner.Stream = fs;
278 should_close_handle = true;
281 SafePipeHandle handle;
282 bool should_close_handle;
284 public override SafePipeHandle Handle {
285 get { return handle; }
288 public void Disconnect ()
290 if (should_close_handle)
291 Syscall.fclose (handle.DangerousGetHandle ());
294 public void WaitForConnection ()
296 // FIXME: what can I do here?
301 #endif