PipeUnix.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  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. string access = null;
  138. if ((rights & PipeAccessRights.ReadData) != 0) {
  139. if ((rights & PipeAccessRights.WriteData) != 0)
  140. return FileAccess.ReadWrite;
  141. else
  142. return FileAccess.Read;
  143. }
  144. else if ((rights & PipeAccessRights.WriteData) != 0)
  145. return FileAccess.Write;
  146. else
  147. throw new InvalidOperationException ("The pipe must be opened to either read or write");
  148. }
  149. }
  150. class UnixNamedPipeClient : UnixNamedPipe, INamedPipeClient
  151. {
  152. // .ctor with existing handle
  153. public UnixNamedPipeClient (NamedPipeClientStream owner, SafePipeHandle safePipeHandle)
  154. {
  155. this.owner = owner;
  156. this.handle = safePipeHandle;
  157. // FIXME: dunno how is_async could be filled.
  158. }
  159. // .ctor without handle - create new
  160. public UnixNamedPipeClient (NamedPipeClientStream owner, string serverName, string pipeName,
  161. PipeAccessRights desiredAccessRights, PipeOptions options, HandleInheritability inheritability)
  162. {
  163. this.owner = owner;
  164. if (serverName != "." && !Dns.GetHostEntry (serverName).AddressList.Contains (IPAddress.Loopback))
  165. throw new NotImplementedException ("Unix fifo does not support remote server connection");
  166. var name = Path.Combine ("/var/tmp/", pipeName);
  167. EnsureTargetFile (name);
  168. string access = RightsToAccess (desiredAccessRights);
  169. ValidateOptions (options, owner.TransmissionMode);
  170. // FIXME: handle inheritability
  171. opener = delegate {
  172. var fs = new FileStream (name, FileMode.Open, RightsToFileAccess (desiredAccessRights), FileShare.ReadWrite);
  173. owner.Stream = fs;
  174. handle = new SafePipeHandle (fs.Handle, false);
  175. };
  176. }
  177. NamedPipeClientStream owner;
  178. bool is_async;
  179. SafePipeHandle handle;
  180. Action opener;
  181. public override SafePipeHandle Handle {
  182. get { return handle; }
  183. }
  184. public void Connect ()
  185. {
  186. if (owner.IsConnected)
  187. throw new InvalidOperationException ("The named pipe is already connected");
  188. opener ();
  189. }
  190. public void Connect (int timeout)
  191. {
  192. AutoResetEvent waitHandle = new AutoResetEvent (false);
  193. opener.BeginInvoke (delegate (IAsyncResult result) {
  194. opener.EndInvoke (result);
  195. waitHandle.Set ();
  196. }, null);
  197. if (!waitHandle.WaitOne (TimeSpan.FromMilliseconds (timeout)))
  198. throw new TimeoutException ();
  199. }
  200. public bool IsAsync {
  201. get { return is_async; }
  202. }
  203. public int NumberOfServerInstances {
  204. get { throw new NotImplementedException (); }
  205. }
  206. }
  207. class UnixNamedPipeServer : UnixNamedPipe, INamedPipeServer
  208. {
  209. //NamedPipeServerStream owner;
  210. // .ctor with existing handle
  211. public UnixNamedPipeServer (NamedPipeServerStream owner, SafePipeHandle safePipeHandle)
  212. {
  213. this.handle = safePipeHandle;
  214. //this.owner = owner;
  215. }
  216. // .ctor without handle - create new
  217. public UnixNamedPipeServer (NamedPipeServerStream owner, string pipeName, int maxNumberOfServerInstances,
  218. PipeTransmissionMode transmissionMode, PipeAccessRights rights, PipeOptions options,
  219. int inBufferSize, int outBufferSize, HandleInheritability inheritability)
  220. {
  221. string name = Path.Combine ("/var/tmp/", pipeName);
  222. EnsureTargetFile (name);
  223. string access = RightsToAccess (rights);
  224. ValidateOptions (options, owner.TransmissionMode);
  225. // FIXME: maxNumberOfServerInstances, modes, sizes, handle inheritability
  226. var fs = new FileStream (name, FileMode.Open, RightsToFileAccess (rights), FileShare.ReadWrite);
  227. handle = new SafePipeHandle (fs.Handle, false);
  228. owner.Stream = fs;
  229. should_close_handle = true;
  230. }
  231. SafePipeHandle handle;
  232. bool should_close_handle;
  233. public override SafePipeHandle Handle {
  234. get { return handle; }
  235. }
  236. public void Disconnect ()
  237. {
  238. if (should_close_handle)
  239. Syscall.fclose (handle.DangerousGetHandle ());
  240. }
  241. public void WaitForConnection ()
  242. {
  243. // FIXME: what can I do here?
  244. }
  245. }
  246. }
  247. #endif