5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2009 Novell, Inc. http://www.novell.com
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
32 using System
.ComponentModel
;
36 using System
.Runtime
.InteropServices
;
37 using System
.Security
.AccessControl
;
38 using System
.Security
.Permissions
;
39 using System
.Security
.Principal
;
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;
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);
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)
155 else if ((rights
& PipeAccessRights
.WriteData
) != 0)
158 throw new InvalidOperationException ("The pipe must be opened to either read or write");
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
;
170 return FileAccess
.Read
;
172 else if ((rights
& PipeAccessRights
.WriteData
) != 0)
173 return FileAccess
.Write
;
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
)
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
)
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
207 var fs
= new FileStream (name
, FileMode
.Open
, RightsToFileAccess (desiredAccessRights
), FileShare
.ReadWrite
);
209 handle
= new SafePipeHandle (fs
.Handle
, false);
213 NamedPipeClientStream owner
;
215 SafePipeHandle handle
;
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");
230 public void Connect (int timeout
)
232 AutoResetEvent waitHandle
= new AutoResetEvent (false);
233 opener
.BeginInvoke (delegate (IAsyncResult result
) {
234 opener
.EndInvoke (result
);
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);
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?