Skip to content

Support setting NamedPipeClientStream.ReadMode with PipeAccessRights ctor overload#100001

Merged
jeffhandley merged 7 commits intodotnet:mainfrom
jeffhandley:jeffhandley/namedpipe-readmode
Mar 27, 2024
Merged

Support setting NamedPipeClientStream.ReadMode with PipeAccessRights ctor overload#100001
jeffhandley merged 7 commits intodotnet:mainfrom
jeffhandley:jeffhandley/namedpipe-readmode

Conversation

@jeffhandley
Copy link
Copy Markdown
Member

Fixes #83072 (Cannot set ReadMode after creating a NamedPipeClientStream instance).

Per the API Review notes and video:

  1. Add the missing constructor to NamedPipeClientStream that accepts PipeAccessRights
  2. Promote PipeAccessRights from System.IO.Pipes.AccessRights to System.IO.Pipes, and add the necessary type-forward
  3. Mark the constructor as being only supported on Windows, but leave the enum available on all platforms
  4. Review for nullability annotations -- no arguments allow null

The .NET Framework implementation was referenced from Pipe.cs, but the behavior was improved slightly.

  • Argument validation logic is reused rather than being duplicated into the new constructor
  • The direction argument is given a valid value when the desiredAccessRights value is invalid, ensuring that the correct desiredAccessRights argument exception is thrown
    • In netfx, any desiredAccessRights value missing both the ReadData (1) and WriteData (2) bits would throw an argument exception for direction, which is not an argument to the constructor
  • Argument validation for desiredAccessRights also throws for a 0 value, which netfx didn't do

The functionality was tested using the following server / client apps:

server.cs

using System.IO.Pipes;

var pipeOut = new NamedPipeServerStream("SomeNamedPipe",
                                        PipeDirection.Out,
                                        1,
                                        PipeTransmissionMode.Message);

Console.WriteLine("Waiting for a connection...");
pipeOut.WaitForConnection();

Console.WriteLine("Connected. Sending messages...");

while (true) {
    pipeOut.Write("Hello "u8);
    pipeOut.Write("from "u8);
    pipeOut.Write("the "u8);
    pipeOut.Write("server!"u8);

    Console.WriteLine("Messages sent. Sleeping for 10 seconds.");
    System.Threading.Thread.Sleep(10_000);
}

client.cs

using System.IO.Pipes;

var pipeIn = new NamedPipeClientStream(".",
                             "SomeNamedPipe",
                             PipeAccessRights.ReadData | PipeAccessRights.WriteAttributes,
                             PipeOptions.None,
                             System.Security.Principal.TokenImpersonationLevel.None,
                             System.IO.HandleInheritability.None);

pipeIn.Connect();
pipeIn.ReadMode = PipeTransmissionMode.Message;

while (pipeIn.IsConnected)
{
    var buffer = new byte[2];
    var bytesRead = pipeIn.Read(buffer, 0, buffer.Length);

    if (bytesRead > 0) {
        var message = System.Text.Encoding.UTF8.GetString(buffer, 0, bytesRead);
        Console.Write(message);

        System.Threading.Thread.Sleep(1000);

        if (pipeIn.IsMessageComplete) {
            Console.WriteLine();
        }
    }
}

With this PR, that application works as expected, with the client detecting completed messages after each word and rendering newlines.

Loading
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cannot set ReadMode after creating a NamedPipeClientStream instance

3 participants