Using socket2 with hyper

632 Views Asked by At

I am writing a http server that works with it's host machine via a unix domain sockets. The server is written using hyper and I am connecting to UDS via socket2.

This is my code:

let socket = Socket::new(Domain::UNIX, Type::STREAM, None)?;
let socket_address = SockAddr::unix("unix://tmp/test.sock")?;
socket.bind(&socket_address)?;
socket.listen(128)?;
let server = hyper::server::Server::builder(socket.into()).serve(service);

What is the right way to do this? I am getting an error saying cannot infer type for type parameter I

error[E0698]: type inside `async fn` body must be known in this context
  --> src/server.rs:65:64
   |
65 |     let server = hyper::server::Server::builder(socket.into()).serve(service);
   |                                                                ^^^^^ cannot infer type for type parameter `I`
   |
note: the type is part of the `async fn` body because of this `await`
  --> src/server.rs:66:13
   |
66 |     let _ = server.await?;
   |             ^^^^^^^^^^^^

I is the generic parameter to hyper::server::Server. While I am aware what is causing the issue: compiler not able to determine what does socket.into() get cast to, I don't know to solve it.

Please correct if my understanding is wrong. Can I get some help in this?

1

There are 1 best solutions below

1
On BEST ANSWER

You need to convert the socket into a type such as tokio::net::UnixListener. Once you have done this, you need an implementation of the Accept trait. You can implement that trait in the following manner:

use hyper::server::accept::Accept;
use tokio::net::UnixListener;

use std::pin::Pin;
use std::task::{Context, Poll};

pub struct UDSAccept {
    inner: UnixListener,
}

impl Accept for UDSAccept {
    type Conn = tokio::net::UnixStream;
    type Error = std::io::Error;

    fn poll_accept(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<Result<Self::Conn, Self::Error>>> {
        match self.inner.poll_accept(cx) {
            Poll::Pending => Poll::Pending,
            Poll::Ready(Ok((socket, _addr))) => Poll::Ready(Some(Ok(socket))),
            Poll::Ready(Err(err)) => Poll::Ready(Some(Err(err))),
        }
    }
}

The above type will be usable as the argument to Server::builder.

If the constructor that comes with the Tokio type does not provide all the options you need and you still wish to use socket2 to construct it, you can do so by first converting it to the std UnixListener and then calling Tokio's from_std method. Be aware that you must set the socket in non-blocking mode yourself when doing this!