PipeUnix.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. //
  2. // PipeUnix.cs
  3. //
  4. // Author:
  5. // Atsushi Enomoto <[email protected]>
  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.
  27. //
  28. #if !BOOTSTRAP_BASIC
  29. using System;
  30. using System.ComponentModel;
  31. using System.IO;
  32. using System.Linq;
  33. using System.Net;
  34. using System.Runtime.InteropServices;
  35. using System.Security.AccessControl;
  36. using System.Security.Permissions;
  37. using System.Security.Principal;
  38. using System.Text;
  39. using System.Threading;
  40. using Microsoft.Win32;
  41. using Microsoft.Win32.SafeHandles;
  42. using Mono.Unix.Native;
  43. namespace System.IO.Pipes
  44. {
  45. abstract class UnixAnonymousPipe : IPipe
  46. {
  47. protected UnixAnonymousPipe ()
  48. {
  49. }
  50. public abstract SafePipeHandle Handle { get; }
  51. public void WaitForPipeDrain ()
  52. {
  53. throw new NotImplementedException ();
  54. }
  55. }
  56. class UnixAnonymousPipeClient : UnixAnonymousPipe, IAnonymousPipeClient
  57. {
  58. // AnonymousPipeClientStream owner;
  59. public UnixAnonymousPipeClient (AnonymousPipeClientStream owner, SafePipeHandle handle)
  60. {
  61. // this.owner = owner;
  62. this.handle = handle;
  63. }
  64. SafePipeHandle handle;
  65. public override SafePipeHandle Handle {
  66. get { return handle; }
  67. }
  68. }
  69. class UnixAnonymousPipeServer : UnixAnonymousPipe, IAnonymousPipeServer
  70. {
  71. // AnonymousPipeServerStream owner;
  72. public UnixAnonymousPipeServer (AnonymousPipeServerStream owner, PipeDirection direction, HandleInheritability inheritability, int bufferSize)
  73. {
  74. // this.owner = owner;
  75. throw new NotImplementedException ();
  76. }
  77. public UnixAnonymousPipeServer (AnonymousPipeServerStream owner, SafePipeHandle serverHandle, SafePipeHandle clientHandle)
  78. {
  79. // this.owner = owner;
  80. this.server_handle = serverHandle;
  81. this.client_handle = clientHandle;
  82. throw new NotImplementedException ();
  83. }
  84. SafePipeHandle server_handle, client_handle;
  85. public override SafePipeHandle Handle {
  86. get { return server_handle; }
  87. }
  88. public SafePipeHandle ClientHandle {
  89. get { return client_handle; }
  90. }
  91. public void DisposeLocalCopyOfClientHandle ()
  92. {
  93. throw new NotImplementedException ();
  94. }
  95. }
  96. abstract class UnixNamedPipe : IPipe
  97. {
  98. public abstract SafePipeHandle Handle { get; }
  99. public void WaitForPipeDrain ()
  100. {
  101. throw new NotImplementedException ();
  102. }
  103. public void EnsureTargetFile (string name)
  104. {
  105. if (!File.Exists (name)) {
  106. var error = Syscall.mknod (name, FilePermissions.S_IFIFO | FilePermissions.ALLPERMS, 0);
  107. if (error != 0)
  108. throw new IOException (String.Format ("Error on creating named pipe: error code {0}", error));
  109. }
  110. }
  111. protected void ValidateOptions (PipeOptions options, PipeTransmissionMode mode)
  112. {
  113. if ((options & PipeOptions.WriteThrough) != 0)
  114. throw new NotImplementedException ("WriteThrough is not supported");
  115. if ((mode & PipeTransmissionMode.Message) != 0)
  116. throw new NotImplementedException ("Message transmission mode is not supported");
  117. if ((options & PipeOptions.Asynchronous) != 0) // FIXME: use O_NONBLOCK?
  118. throw new NotImplementedException ("Asynchronous pipe mode is not supported");
  119. }
  120. protected string RightsToAccess (PipeAccessRights rights)
  121. {
  122. string access = null;
  123. if ((rights & PipeAccessRights.ReadData) != 0) {
  124. if ((rights & PipeAccessRights.WriteData) != 0)
  125. access = "r+";
  126. else
  127. access = "r";
  128. }
  129. else if ((rights & PipeAccessRights.WriteData) != 0)
  130. access = "w";
  131. else
  132. throw new InvalidOperationException ("The pipe must be opened to either read or write");
  133. return access;
  134. }
  135. protected FileAccess RightsToFileAccess (PipeAccessRights rights)
  136. {
  137. if ((rights & PipeAccessRights.ReadData) != 0) {
  138. if ((rights & PipeAccessRights.WriteData) != 0)
  139. return FileAccess.ReadWrite;
  140. else
  141. return FileAccess.Read;
  142. }
  143. else if ((rights & PipeAccessRights.WriteData) != 0)
  144. return FileAccess.Write;
  145. else
  146. throw new InvalidOperationException ("The pipe must be opened to either read or write");
  147. }
  148. }
  149. class UnixNamedPipeClient : UnixNamedPipe, INamedPipeClient
  150. {
  151. // .ctor with existing handle
  152. public UnixNamedPipeClient (NamedPipeClientStream owner, SafePipeHandle safePipeHandle)
  153. {
  154. this.owner = owner;
  155. this.handle = safePipeHandle;
  156. // FIXME: dunno how is_async could be filled.
  157. }
  158. // .ctor without handle - create new
  159. public UnixNamedPipeClient (NamedPipeClientStream owner, string serverName, string pipeName,
  160. PipeAccessRights desiredAccessRights, PipeOptions options, HandleInheritability inheritability)
  161. {
  162. this.owner = owner;
  163. if (serverName != "." && !Dns.GetHostEntry (serverName).AddressList.Contains (IPAddress.Loopback))
  164. throw new NotImplementedException ("Unix fifo does not support remote server connection");
  165. var name = Path.Combine ("/var/tmp/", pipeName);
  166. EnsureTargetFile (name);
  167. RightsToAccess (desiredAccessRights);
  168. ValidateOptions (options, owner.TransmissionMode);
  169. // FIXME: handle inheritability
  170. opener = delegate {
  171. var fs = new FileStream (name, FileMode.Open, RightsToFileAccess (desiredAccessRights), FileShare.ReadWrite);
  172. owner.Stream = fs;
  173. handle = new SafePipeHandle (fs.Handle, false);
  174. };
  175. }
  176. NamedPipeClientStream owner;
  177. SafePipeHandle handle;
  178. Action opener;
  179. public override SafePipeHandle Handle {
  180. get { return handle; }
  181. }
  182. public void Connect ()
  183. {
  184. if (owner.IsConnected)
  185. throw new InvalidOperationException ("The named pipe is already connected");
  186. opener ();
  187. }
  188. public void Connect (int timeout)
  189. {
  190. AutoResetEvent waitHandle = new AutoResetEvent (false);
  191. opener.BeginInvoke (delegate (IAsyncResult result) {
  192. opener.EndInvoke (result);
  193. waitHandle.Set ();
  194. }, null);
  195. if (!waitHandle.WaitOne (TimeSpan.FromMilliseconds (timeout)))
  196. throw new TimeoutException ();
  197. }
  198. public bool IsAsync {
  199. get { return false; }
  200. }
  201. public int NumberOfServerInstances {
  202. get { throw new NotImplementedException (); }
  203. }
  204. }
  205. class UnixNamedPipeServer : UnixNamedPipe, INamedPipeServer
  206. {
  207. //NamedPipeServerStream owner;
  208. // .ctor with existing handle
  209. public UnixNamedPipeServer (NamedPipeServerStream owner, SafePipeHandle safePipeHandle)
  210. {
  211. this.handle = safePipeHandle;
  212. //this.owner = owner;
  213. }
  214. // .ctor without handle - create new
  215. public UnixNamedPipeServer (NamedPipeServerStream owner, string pipeName, int maxNumberOfServerInstances,
  216. PipeTransmissionMode transmissionMode, PipeAccessRights rights, PipeOptions options,
  217. int inBufferSize, int outBufferSize, HandleInheritability inheritability)
  218. {
  219. string name = Path.Combine ("/var/tmp/", pipeName);
  220. EnsureTargetFile (name);
  221. RightsToAccess (rights);
  222. ValidateOptions (options, owner.TransmissionMode);
  223. // FIXME: maxNumberOfServerInstances, modes, sizes, handle inheritability
  224. var fs = new FileStream (name, FileMode.Open, RightsToFileAccess (rights), FileShare.ReadWrite);
  225. handle = new SafePipeHandle (fs.Handle, false);
  226. owner.Stream = fs;
  227. should_close_handle = true;
  228. }
  229. SafePipeHandle handle;
  230. bool should_close_handle;
  231. public override SafePipeHandle Handle {
  232. get { return handle; }
  233. }
  234. public void Disconnect ()
  235. {
  236. if (should_close_handle)
  237. Syscall.fclose (handle.DangerousGetHandle ());
  238. }
  239. public void WaitForConnection ()
  240. {
  241. // FIXME: what can I do here?
  242. }
  243. }
  244. }
  245. #endif