-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Provide a lower-level connection interface #1070
Comments
It would also be nice to support custom listeners. This would allow (among other things) custom TLS implementations using something other than Even if it's not exposed (yet), I think it's worth implementing one of these APIs internally, because it should make it somewhat easier to abstract over TLS and unix sockets which we definitely do want to support. I have come up with two main ideas for a design of this. "Rocket-driven":rocket::ignite().listen_on::<ListenerType>(executor)
trait Listener {
type Connection: Connection;
async fn bind(address, keepalive, read_timeout, options...) -> Result<Self, io::Error>;
fn local_addr(&self) -> Option<SocketAddr>;
async fn accept(&mut self) -> Result<Self::Connection, io::Error>;
} In this model, Rocket will call Note that User-driven:rocket::ignite().listen_on(listener, executor)
trait Listener {
type Connection: Connection;
fn local_addr(&self) -> Option<SocketAddr>;
fn set_keepalive(&mut self, keepalive);
async fn accept(&mut self) -> Self::Connection;
} In this model, it's assumed that the user will construct an instance of a ConnectionEither way, trait Connection: AysncRead + AsyncWrite {
fn remote_addr(&self) -> SocketAddr;
// This config could apply to the Listener trait
// in which case it would be set in accept() instead.
fn set_read_timeout(&mut self, timeout);
// Exists mainly for closing the read half early
fn close(&mut self, which);
} @SergioBenitez, are there any obvious flaws in this kind of extensibility or issues that should be resolved now? |
This is implemented in 8e103cb, but we will probably want to change some of the design before making any of the new types public. |
@carllerche I believe I have two concerns about upstreaming them. First, where would the traits go? I have this (maybe unfounded) idea that there will be users of Rocket who don't want to or can't use |
re: location, the idea is that HTTP related abstractions live in |
tower-http is very much in experimentation phase too. We can experiment together and figure out where things fall (hyper, rocket, or tower). Maybe start by listing the "user stories" around keep alive / idle timeout. |
There are a lot of layers to this problem surrounded by other irrelevant code, so I've written out a list of the steps performed that are relevant to connections. For reference, the /// A 'Listener' yields incoming connections
pub trait Listener {
type Connection: Connection;
/// Return the actual address this listener bound to.
fn local_addr(&self) -> Option<SocketAddr>;
/// Try to accept an incoming Connection if ready
fn poll_accept(&mut self, cx: &mut Context<'_>) -> Poll<Result<Self::Connection, io::Error>>;
}
/// A 'Connection' represents an open connection to a client
pub trait Connection: AsyncRead + AsyncWrite {
fn remote_addr(&self) -> Option<SocketAddr>;
} The current implementation:
Possible changes
Why do I keep bringing up keep-alive and idle timeouts?Because they were there in Rocket 0.4. I'm only partly joking. Rocket 0.4 needed a fairly short read timeout to prevent N_THREADS nonresponsive clients from blocking the server entirely. We don't need that in async Rocket because everything is asynchronous, but the other extreme of no timeout looks like a great way to run out of memory quickly so we should almost certainly have some configurable limit here. Rocket 0.4 also provided a mechanism to set the keep-alive timeout (https://docs.rs/hyper/0.10.16/hyper/server/struct.Server.html#method.keep_alive). hyper's API has changed a bit and different knobs are exposed, and I haven't yet looked at the semantics of the various options and what would best approximate the previous behavior, if it's still desirable. I actually hope that neither of these actually need to be part of the To upstream or not to upstreamI think the main question left is where to set idle timeouts, keep-alive, or other connection settings I haven't thought of. I see two main options:
|
FYI: I had a stab at |
This is awesome, one thought, the socket connection should be available so we can use |
@jcdickinson |
I'd really like to land something like this soon. From #1820 (comment):
This is effectively the "user-driven" approach with an answer for configuration. Rocket would give you a default listener, which at the moment only knows about TCP/TLS but can learn about unix domain sockets and so on. A user, however, can implement any kind of listener they want. |
Here are some more details for the kind of resolution of this issue that I'd like to see, copied from #2013 (comment):
|
Any news on this? |
Any news is appreciated, as I am eagerly awaiting UNIX socket support in some downstream projects (on Linux, not interested in Windows) |
I'll be tackling this later this week. |
Currently blocked on #2671, which I'm now prioritizing to make working on this possible. |
This is now in ROCKET_ADDRESS=unix:/tmp/rocket.sock cargo run Or in address="unix:path/to/some/socket |
Currently Rocket's public API only provides a way to listen on TCP sockets (and Unix sockets have also been proposed) with optional TLS. Rather than adding support for every possible I/O layer in Rocket itself, it might be nice to provide an API for custom I/O types. Such an API now exists in
http/src/listener.rs
, but it is private. This issue is about making this or a similar API public, or integrating with another existing crate that provides such an API.The original issue described here was implemented long ago without fanfare. Here's the original text:
The text was updated successfully, but these errors were encountered: