Skip to content

How to use fd with net.Socket? #8297

Description

@cookiengineer

This code will cause problems with an error:

let connector = new _net.Socket({
  fd: null,
// fd: new _stream.Duplex() won't work either
  readable: true,
  writable: true
});

// some time later
connector.connect({ host: host, port: port });

Randomly, depending on how stdout and stderr are repiped of the process, it will give this error:

TypeError: Unsupported fd type: FILE

What the heck does that mean? Everything on stackoverflow is 100% unrelated where people try to create sockets to files. Here I want to create a Socket to a TCP remote port (client-side socket implementation), but the pipe itself is later created using connector.connect({host: host, port: port}).

So at the constructor point in time there can't be such a thing as an already existing TCP Pipe(!?!?!?!).

Debugging

I figured out that the TCP type file descriptor is necessary lib/net.js#L31.

The tty_wrap.guessHandleType(fd) uses internal representations to return type TCP tty_wrap.cc#L66.

Solution?

How to solve this and create a file descriptor for net.Socket?

Having a FILE fd does not help obviously, but there is literally zero documentation on how to create a file descriptor for TCP. I tried to read all the TCP relevant code, but UV_TCP is pretty much everywhere in code related to streams, files, handles and uv ... seems as this is a if/else construct in the whole codebase.

OS Information

Debian, Ubuntu, Archlinux. All amd64 and verified the identical problem.

Activity

  1. bnoordhuis commented on Aug 27, 2016

    @bnoordhuis
    Member

    TypeError: Unsupported fd type: FILE

    null is coerced to zero in your example and apparently file descriptor zero refers to a file. If you use the .fd option, it must refer to a valid TCP or pipe file descriptor.

    Having a FILE fd does not help obviously, but there is literally zero documentation on how to create a file descriptor for TCP.

    What exactly are you trying to do? If you want to connect to a remote host over TCP, hy do you want to create the file descriptor explicitly instead of letting node.js / libuv handle that for you?

  2. added
    questionIssues asking questions about Node.js.
    netIssues and PRs related to the net subsystem.
    on Aug 27, 2016
  3. cookiengineer commented on Aug 27, 2016

    @cookiengineer
    Author

    Does that mean a valid TCP pipe is only being created by net.Server and not create-able directly? Just in case: How to create a valid TCP pipe yourself?

    I had to add fd: null in a previous node version because of TTY bugs when listening to stdout/stdin. I guess that has changed somewhere in the last three(?) months. I was assuming that this is wanted, but I removed it now from the code.

  4. bnoordhuis commented on Aug 27, 2016

    @bnoordhuis
    Member

    'TCP pipe' is a bit of an oxymoron - TCP sockets and pipes are different things. The .fd property is for creating net.Socket instances out of existing file descriptors that refer to a TCP socket or a pipe.

    I guess that has changed somewhere in the last three(?) months.

    I'm not aware of any such changes, I don't think the logic around .fd changed much since v0.10.

  5. cookiengineer commented on Aug 27, 2016

    @cookiengineer
    Author

    net.Socket instances out of existing file descriptors that refer to a TCP socket or a pipe

    How to do so in the code? Let's say I want to create and reuse such a socket/pipe.

  6. joyeecheung commented on Mar 20, 2017

    @joyeecheung
    Member

    So at the constructor point in time there can't be such a thing as an already existing TCP Pipe(!?!?!?!).

    Put it in man pages terms, if only the public net API are used, socket(2), bind(2), listen(2)/connect(2) all happen in server.listen() or socket.connect() calls, new Socket() doesn't do any of these. So yea, when doing new Socket() nothing is actually allocated. On the other hand, after it starts connecting/listening, the fd can be accessed via socket._handle.fd, though it's not recommended to use a underscore-prefixed property...(it's possible to add a new socket.getFD() though)

    I guess at the moment there is no way to get a fd of a fresh unbound socket purely with the existing public net API..you can get a fd from somewhere else (e.g. outside Node.js) though.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    netIssues and PRs related to the net subsystem.questionIssues asking questions about Node.js.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions