Skip to content

Instantly share code, notes, and snippets.

@stepancheg
Last active September 13, 2016 03:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stepancheg/6b3f02b0e534d53420522ba677ae251d to your computer and use it in GitHub Desktop.
Save stepancheg/6b3f02b0e534d53420522ba677ae251d to your computer and use it in GitHub Desktop.
// HTTP/2 request of response stream is a sequence of frames.
// Header frames can be interleaves with data frames.
enum HttpStreamPart {
Headers(Vec<Header>),
Body(Vec<u8>),
}
// To be implemented by user.
//
// Server may start sending response before
// reading while request from the network.
//
// Several requests/stream could be executed
// in parallel over the same HTTP/2 connection.
trait Http2Service {
fn start_request(req: Stream<HttpStreamPart>) -> Stream<HttpStreamPart>;
}
// HTTP/2 stream, not futures Stream
struct Http2Stream {
// channel to send requests to the request handler
req_tx: Sender<HttpStreamPart>,
}
// Get or create HTTP/2 stream.
fn get_or_create_stream(stream_id, to_write_tx) -> {
if stream exists {
return it;
} else {
// channel to send HTTP response to write loop
let (req_tx, req_rx) = channel();
// Instantiate a fresh request handler.
let resp = service.start_request(rx);
// Spawn a task that drives request future
// and sends frames to write loop
spawn(|| {
loop {
let frame = await resp.recv();
to_write_tx.send(frame);
}
})
Http2Stream {
req_tx: req_tx,
}
}
}
// read frames from the network
// and supply them to user provided request handler
fn read_loop(reader, to_write_tx) {
loop {
let frame = await read.read_frame();
let http_stream = get_or_create_frame(frame.id, to_write_tx);
http_stream.req_tx.send(frame);
}
}
// write loop simply drains a queue into a socket
fn write_loop(writer, to_write_rx) {
loop {
let frame = await to_write_rx.recv();
await writer.write_frame(frame);
}
}
// run HTTP/2 connection loop
fn run_conn(conn) {
// channel to supply data to writer
let (to_write_tx, to_write_rx) = channel();
// split connection into reader and writer parts
let (reader, writer) = conn.split();
// run two loops in single task
read_loop(reader, to_write_tx).join(write_loop(writer, to_write_rx))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment