Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use fd with net.Socket? #8297

Closed
cookiengineer opened this issue Aug 27, 2016 · 5 comments
Closed

How to use fd with net.Socket? #8297

cookiengineer opened this issue Aug 27, 2016 · 5 comments
Labels
net Issues and PRs related to the net subsystem. question Issues that look for answers.

Comments

@cookiengineer
Copy link

cookiengineer commented Aug 27, 2016

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.

@bnoordhuis
Copy link
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?

@bnoordhuis bnoordhuis added question Issues that look for answers. net Issues and PRs related to the net subsystem. labels Aug 27, 2016
@cookiengineer
Copy link
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.

@bnoordhuis
Copy link
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.

@cookiengineer
Copy link
Author

cookiengineer commented Aug 27, 2016

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.

@joyeecheung
Copy link
Member

joyeecheung commented Mar 20, 2017

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
Labels
net Issues and PRs related to the net subsystem. question Issues that look for answers.
Projects
None yet
Development

No branches or pull requests

3 participants