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

WIP: Support Unix Domain Sockets #4176

Merged
merged 48 commits into from
Mar 23, 2020
Merged

Conversation

jsouto18
Copy link
Contributor

@jsouto18 jsouto18 commented Feb 28, 2020

This Pull Request is meant to close #4115 by adding support for Unix Domain Sockets.

  • Add support to op_listen.
  • Add support to op_shutdown.
  • Add support to op_accept.
  • Add support to op_connect.
  • Add support to op_receive.
  • Add support to op_send.
  • Add tests.
  • Update documentation.

Mio v0.7 was recently released supporting poll events for the UDS protocol. That is necessary so that the state reference doesn't get stuck on the async function. As soon the tokio mio dependecy is updated I will change the implementation.

@jsouto18
Copy link
Contributor Author

jsouto18 commented Mar 2, 2020

@ry could you please review the implementation so far? The functional part is fully implemented, but before I finalize the PR with tests and documentation, I would like to get your approval on the direction this is heading. I made a lot of changes to the net.ts interfaces by adding generic types to them.

*
* In the future: `"tcp4"`, `"tcp6"`, `"udp4"`, `"udp6"`, `"ip"`, `"ip4"`,
* `"ip6"`, `"unix"`, `"unixgram"`, and `"unixpacket"`. */
transport: Transport;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My typescript isn't so good. Can this just be transport: "unix" ?

(cc @kitsonk - for expert TS advice)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is quite a bit of typing cleanup that can be done around the listen() code - it is not great right now imo - I don't see why we even need the type Transport. I can address that in a later PR once this one is merged.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think if we have overloads that express every "tagged" variant. When I went through and cleaned up the comments I noticed this and though ugh. I am not sure we need the seperate Options interfaces honestly. There is a whole load of duplication that isn't necessary, and some tagged unions "should" work fine and actually should eliminate the overloads.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kitsonk I understand that the tagged unions can replace the overloads, but won't that force the return type to also be a union and therefore force if branching on the user side?

/** The remote address of the connection. */
readonly remoteAddr: Addr;
readonly remoteAddr: T;
/** The resource ID of the connection. */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit weary of making Conn generic. Maybe it's okay but I wonder if it could be avoided...

Copy link
Contributor Author

@jsouto18 jsouto18 Mar 4, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A solution could be to replace T with Addr, where Addr is:

interface Addr {
  transport: Transport;
  hostname?: string;
  port?: number;
  address?: string;
}

I had it like this on an early stage, but I found it less strict than having a generic type. This way the addr of each Conn depends on the arguments used on connect.

(cc @kitsonk - for expert TS advice)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably why Go uses a string for hostname and port. It's nice to just have a single string for the address...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well Go has a single Addr type (https://golang.org/pkg/net/#Addr), this way I could replace all Transport specific Addr to:

interface Addr {
    transport: string;
    address: string;
}

But we would no longer be able to access hostname nor port without doing address.split(":"). Is this acceptable?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A compromise @bartek, @ry and yours truly came up with on our call:

export interface Conn extends Reader, Writer, Closer {
    /** The local address of the connection. */
    readonly localAddr: TCPAddr | UnixAddr;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A compromise @bartek, @ry and yours truly came up with on our call:

export interface Conn extends Reader, Writer, Closer {
    /** The local address of the connection. */
    readonly localAddr: TCPAddr | UnixAddr;

Alright! Pushing changes soon!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the way, why Addr needs a transport field? An address is an address, isn't it?

What if I wanted to use the same address between UDP and TCP and maybe QUIC?

@ry ry requested a review from piscisaureus March 6, 2020 13:39
@jsouto18 jsouto18 requested a review from ry March 6, 2020 20:27
cli/js/lib.deno.ns.d.ts Outdated Show resolved Hide resolved
cli/js/lib.deno.ns.d.ts Outdated Show resolved Hide resolved
}

/** A generic network listener for stream-oriented protocols. */
export interface Listener extends AsyncIterator<Conn> {
export interface Listener<T> extends AsyncIterator<Conn> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to make this not generic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I change to an interface union as suggested for the Conn interface?
IMO it should either be Generic or have a simple Addr interface like Go has for all its connections. This way the user would not have to conditionally branch in order to get the address properties.

Copy link
Member

@ry ry Mar 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’d prefer to go the Go route.. but I need to discuss this with @piscisaureus . We want to avoid having generics for relatively minor differences in interfaces because genetics tend to propagate outward to user interfaces making everything more complex...

Copy link
Contributor Author

@jsouto18 jsouto18 Mar 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd vouch for the Go route, it feels like the best alternative. After implementing the Generic Interfaces, I found that the outward propagation implied by this implementation could be just as bad for the end Deno user, as the conditional branching that is necessary using an interface union approach.
I'll wait for your discussion with @piscisaureus and implement what you guys decide on :)

@ry
Copy link
Member

ry commented Mar 19, 2020

@jsouto18 I'd like to get this in, even if the API isn't perfect, just so we don't lose this work. Could you can merge with master and get this green?

@jsouto18
Copy link
Contributor Author

@ry Will do! Was waiting on your decision, on the Addr deal

@ry
Copy link
Member

ry commented Mar 20, 2020

@jsouto18 Using union types and not generics would be best - but let me know if that proves very difficult. I could take a deeper look.

@jsouto18 jsouto18 requested a review from ry March 23, 2020 16:24
cli/js/tests/net_test.ts Outdated Show resolved Hide resolved
Copy link
Member

@ry ry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some unnecessary changes in third_party. Make sure you merge with master and do git submodule update

Copy link
Member

@ry ry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - thank for this massive contribution @jsouto18 !

I think we're going to need to iterate further on the network interfaces but let's do that on master branch.

(We're having some trouble with the windows release build in v0.37.0 - I'm going to wait a little bit to see if we can correct that and cut a new release before landing this..)

@ry ry merged commit 70a5034 into denoland:master Mar 23, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support unix domain sockets
7 participants