Last active
September 13, 2016 03:22
-
-
Save stepancheg/6b3f02b0e534d53420522ba677ae251d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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