Search code examples
node.jswinapinamed-pipes

Node.js named pipe causes ERROR_INVALID_PARAMETER


This is primarily Node.js question but it likely requires to be familiar with Win32 API and named pipes.

Node.js supports Windows named pipes for IPC connections. Here's an example:

// server.js
const server = require('net').createServer((socket) => {
    socket.write('test\n');
    socket.on('end', () => {
        server.close();
    });
});

server.listen('\\\\.\\\pipe\\\WinUAE');

It doesn't work when named pipe is connected by third-party client written in C++, this results in ERROR_INVALID_PARAMETER (code 87) error:

Connected to '\.\pipe\WinUAE'

SetNamedPipeHandleState failed err=87

And the snippet that causes the problem:

mode = PIPE_READMODE_MESSAGE;
if (!SetNamedPipeHandleState(p, &mode, NULL, NULL)) {
printf("SetNamedPipeHandleState failed err=%d\n", GetLastError());
return 0;
}

Client binary can be downloaded here, and the mirror in case of hosting problems.

I assume the problem is that Node.js doesn't fully support Windows named pipes and cannot be used for IPC in cases that demand first-class support like this one.

Is Node.js not suitable for IPC with such process? What is going on here under the hood?


Solution

  • This is primarily Node.js question

    No, I can reproduce it with C++, creating namepipe with PIPE_TYPE_BYTE type(this is the default type).

    As @RbMm pointed out, according to the SetNamedPipeHandleState:

    PIPE_READMODE_MESSAGE: Data is read from the pipe as a stream of messages. The function fails if this flag is specified for a byte-type pipe.

    This is because the type modes must be the same for all instances of a pipe, but PIPE_TYPE_BYTE do not support PIPE_READMODE_MESSAGE mode. CreateNamedPipe:

    dwPipeMode

    The same type mode must be specified for each instance of the pipe.

    PIPE_TYPE_BYTE: Data is written to the pipe as a stream of bytes. This mode cannot be used with PIPE_READMODE_MESSAGE. The pipe does not distinguish bytes written during different write operations.

    PIPE_READMODE_MESSAGE: Data is read from the pipe as a stream of messages. This mode can be only used if PIPE_TYPE_MESSAGE is also specified.

    As the document Named Pipe Type, Read, and Wait Modes:

    To create a byte-type pipe, specify PIPE_TYPE_BYTE or use the default value. The data is written to the pipe as a stream of bytes, and the system does not differentiate between the bytes written in different write operations.

    To create a message-type pipe, specify PIPE_TYPE_MESSAGE. The system treats the bytes written in each write operation to the pipe as a message unit. The system always performs write operations on message-type pipes as if write-through mode were enabled.

    When specified as PIPE_TYPE_BYTE, the system does not differentiate between the bytes written in different write operations, so the message unit in each write operation is also not able to be differentiated.