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

Any interest in implementing tonic::transport::server::Connected for tokio::net::UnixStream? #856

Closed
agreen17 opened this issue Dec 2, 2021 · 6 comments

Comments

@agreen17
Copy link
Contributor

agreen17 commented Dec 2, 2021

Feature Request

I started using tonic recently and it has been awesome to work with so far! I saw an opportunity for a small contribution that I believe would make tonic a little easier to use so I wanted to see if there was interest in accepting such a feature - implementing tonic::transport::server::Connected for tokio::net::UnixStream to allow client code to use a UnixStream on the server side more easily.

Crates

tonic

Motivation

At first glance I thought there was no Unix socket support for tonic clients/servers, but I stumbled upon the uds client/server example soon thereafter and I was able to get my server listening on a unix socket easily.

That said, I think it would be nice if consumers could use a tokio::net::UnixStream on the server side without needing to provide the following (which are currently required):

  • impl tonic::transport::server::Connected for tokio::net::UnixStream
  • newtype wrapper (or similar) around tokio::net::UnixStream, implement AsyncRead/AsyncWrite (only needed since client code can't implement an external trait for an external type)

Proposal

I've looked around the repo a bit and I think the main piece of getting this working would be something like this:

// in `transport/server/conn.rs` - copied from the current UDS example

#[cfg(unix)]
#[cfg_attr(docsrs, doc(cfg(unix)))]
#[derive(Clone, Debug)]
pub struct UdsConnectInfo {
    /// Peer address. This will be "unnamed" for client unix sockets.
    pub peer_addr: Option<Arc<tokio::net::unix::SocketAddr>>,
    /// Process credentials for the unix socket.
    pub peer_cred: Option<tokio::net::unix::UCred>,
}

#[cfg(unix)]
impl Connected for tokio::net::UnixStream {
    type ConnectInfo = UdsConnectInfo;

    fn connect_info(&self) -> Self::ConnectInfo {
        UdsConnectInfo {
            peer_addr: self.peer_addr().ok().map(Arc::new),
            peer_cred: self.peer_cred().ok(),
        }
    }
}

To me, the win here is that since tonic itself would be implementing Connected, client code would no longer have to define a newtype wrapper around UnixStream and hand-implement Connected/AsyncRead/AsyncWrite on it - tokio-streams UnixListenerStream would then be usable out the box at this point:

let greeter = MyGreeter::default();

let uds = tokio::net::UnixListener::bind(path)?;
let uds_stream = tokio_stream::wrappers::UnixListenerStream::new(uds);

Server::builder()
    .add_service(GreeterServer::new(greeter))
    .serve_with_incoming(uds_stream)
    .await?;

This could possibly require some other work in server/mod.rs but I'm unsure about this part...just wanted to check in on interest level before digging in too far! Thanks for looking!

Alternatives

Current solution is to copy the approach from the uds/server.rs example, which works right now as-is.

@LucioFranco
Copy link
Member

Yeah, I think this makes sense, I would totally accept a PR for this.

@agreen17
Copy link
Contributor Author

agreen17 commented Dec 7, 2021

Yeah, I think this makes sense, I would totally accept a PR for this.

Awesome. I'll submit a PR for this in the next few days.

agreen17 added a commit to StarryInternet/tonic that referenced this issue Dec 8, 2021
This impl is needed in order to use a tokio UnixStream as the
`incoming` argument in methods like
`tonic::transport::server::Router::serve_with_incoming_shutdown`

Fixes: hyperium#856

Signed-off-by: Anthony Green <agreen@starry.com>
agreen17 added a commit to StarryInternet/tonic that referenced this issue Dec 8, 2021
tokio-stream packages a UnixListenerStream that implements
futures_core::Stream. Using this cuts down on consumer boilerplate
when using UnixStreams with a tonic server.

Refs: hyperium#856

Signed-off-by: Anthony Green <agreen@starry.com>
agreen17 added a commit to StarryInternet/tonic that referenced this issue Dec 8, 2021
Refs: hyperium#856

Signed-off-by: Anthony Green <agreen@starry.com>
agreen17 added a commit to StarryInternet/tonic that referenced this issue Dec 8, 2021
Refs: hyperium#856

Signed-off-by: Anthony Green <agreen@starry.com>
@agreen17
Copy link
Contributor Author

agreen17 commented Dec 10, 2021

@LucioFranco (or someone else - not really sure who to ask 😁 ) could you check out this PR I put out for the fix and allow me to run workflows? Looks like I need a maintainer to approve running CI

@LucioFranco
Copy link
Member

Yes just took a look, sorry for the delay. Holidays are crazy :D

@agreen17
Copy link
Contributor Author

@LucioFranco Haha no worries, thanks for taking a look 👍🏽

agreen17 added a commit to StarryInternet/tonic that referenced this issue Feb 14, 2022
This impl is needed in order to use a tokio UnixStream as the
`incoming` argument in methods like
`tonic::transport::server::Router::serve_with_incoming_shutdown`

Fixes: hyperium#856

Signed-off-by: Anthony Green <agreen@starry.com>
agreen17 added a commit to StarryInternet/tonic that referenced this issue Feb 14, 2022
tokio-stream packages a UnixListenerStream that implements
futures_core::Stream. Using this cuts down on consumer boilerplate
when using UnixStreams with a tonic server.

Refs: hyperium#856

Signed-off-by: Anthony Green <agreen@starry.com>
agreen17 added a commit to StarryInternet/tonic that referenced this issue Feb 14, 2022
Refs: hyperium#856

Signed-off-by: Anthony Green <agreen@starry.com>
@agreen17
Copy link
Contributor Author

Closing this issue as the the relevant PR has been merged 🎉

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

No branches or pull requests

2 participants