| File: System\IO\Pipes\NamedPipeClientStream.Unix.cs | Web Access |
| Project: src\runtime\src\libraries\System.IO.Pipes\src\System.IO.Pipes.csproj (System.IO.Pipes) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Principal; using System.Threading; using Microsoft.Win32.SafeHandles; namespace System.IO.Pipes { /// <summary> /// Named pipe client. Use this to open the client end of a named pipes created with /// NamedPipeServerStream. /// </summary> public sealed partial class NamedPipeClientStream : PipeStream { [System.Runtime.Versioning.SupportedOSPlatform("windows")] public NamedPipeClientStream(string serverName, string pipeName, PipeAccessRights desiredAccessRights, PipeOptions options, TokenImpersonationLevel impersonationLevel, HandleInheritability inheritability) : base(PipeDirection.InOut, 0) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_PipeAccessRights); } private static int AccessRightsFromDirection(PipeDirection _) => 0; private bool TryConnect(int _ /* timeout */) { // timeout isn't used as Connect will be very fast, // either succeeding immediately if the server is listening or failing // immediately if it isn't. The only delay will be between the time the server // has called Bind and Listen, with the latter immediately following the former. var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified); SafePipeHandle? clientHandle = null; try { socket.Connect(new UnixDomainSocketEndPoint(_normalizedPipePath!)); clientHandle = new SafePipeHandle(socket); ConfigureSocket(socket, clientHandle, _direction, 0, 0, _inheritability); } catch (SocketException e) { clientHandle?.Dispose(); socket.Dispose(); switch (e.SocketErrorCode) { // Retryable errors case SocketError.AddressAlreadyInUse: case SocketError.AddressNotAvailable: case SocketError.ConnectionRefused: return false; // Non-retryable errors default: throw; } } try { ValidateRemotePipeUser(clientHandle); } catch (Exception) { clientHandle.Dispose(); socket.Dispose(); throw; } InitializeHandle(clientHandle, isExposed: false, isAsync: (_pipeOptions & PipeOptions.Asynchronous) != 0); State = PipeState.Connected; return true; } [SupportedOSPlatform("windows")] public int NumberOfServerInstances { get { CheckPipePropertyOperations(); throw new PlatformNotSupportedException(); // no way to determine this accurately } } public override int InBufferSize { get { CheckPipePropertyOperations(); if (!CanRead) throw new NotSupportedException(SR.NotSupported_UnreadableStream); return InternalHandle?.PipeSocket.ReceiveBufferSize ?? 0; } } public override int OutBufferSize { get { CheckPipePropertyOperations(); if (!CanWrite) throw new NotSupportedException(SR.NotSupported_UnwritableStream); return InternalHandle?.PipeSocket.SendBufferSize ?? 0; } } private void ValidateRemotePipeUser(SafePipeHandle handle) { if (!IsCurrentUserOnly) return; uint userId = Interop.Sys.GetEUid(); if (Interop.Sys.GetPeerID(handle, out uint serverOwner) == -1) { throw CreateExceptionForLastError(); } if (userId != serverOwner) { throw new UnauthorizedAccessException(SR.UnauthorizedAccess_NotOwnedByCurrentUser); } } } }