Skip to content

Instantly share code, notes, and snippets.

@vinipsmaker
Last active August 29, 2015 14:23
Show Gist options
  • Save vinipsmaker/ebf703dffbf50caad228 to your computer and use it in GitHub Desktop.
Save vinipsmaker/ebf703dffbf50caad228 to your computer and use it in GitHub Desktop.

HTTP/2.0

Intro

From RFC 7540:

Flow control and prioritization ensure that it is possible to efficiently use multiplexed streams.

TODO:

  • Compare our design with.
    • Proxygen's.
    • libnghttp2_asio's.
    • curl's.

Fundamental problems

Where does tcp::async_read_some is called? basic_http2_server should not buffer structured messages, because object/memory pools whatsoever, but a new "transaction" can be requested at any moment. So, the only appropriate place to tcp::async_read_some is within basic_http2_server's async_accept, which opens a channel to a new stream.

It happens we might issue concurrent write requests (e.g. multiple handlers on different streams). How to prevent concurrent writes? Nothing needs to be done. User can already implement correct synchronization infering the readness status from whether completion handler from the last write operation was called or not. It's too complex, but the user can always use an underlying basic_queue_socket.

Is the server cleanly stoppable? Yes, just stop accepting new streams/transactions and the asio's executor will exit as soon as the remaining operations are complete.

Stateless push? HTTP/1.1 is stateless, but this is not so true for HTTP/2.0. HTTP/2.0 adds a new interaction mode whereby a server can push responses to a client. Server push allows a server to speculatively send data to a client that the server anticipates the client will need. This state is tied to an HTTP/2.0 connection, so the connection object will add the interface which can be used to do a server push.

So, the interaction will be like:

The HTTP/2.0 connection object will:

  • Act as the "acceptor" for new streams within the underlying connection.
  • Buffer bytes, structure messages and dispatch them to the correct ServerSocket's objects.
  • Handle server push.

To make the code simpler, the concept of multiple streams will not be used. Instead, after the response is delivered for each ServerSocket object, their "connection" will be closed. Therefore, they're closer to the concept of a transaction. The "done" objects can be reused in new async_accept calls.

Display the source blob
Display the rendered blob
Raw
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
<svg width="19cm" height="18cm" viewBox="258 -55 369 359" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<rect style="fill: #ffffff" x="319" y="-54" width="243.6" height="36"/>
<rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="319" y="-54" width="243.6" height="36"/>
<text font-size="12.7998" style="fill: #000000;text-anchor:middle;font-family:monospace;font-style:normal;font-weight:normal" x="440.8" y="-32">boost::asio::ip::tcp::socket</text>
</g>
<g>
<rect style="fill: #ffffff" x="356" y="128" width="174.3" height="36"/>
<rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="356" y="128" width="174.3" height="36"/>
<text font-size="12.7998" style="fill: #000000;text-anchor:middle;font-family:monospace;font-style:normal;font-weight:normal" x="443.15" y="150">HTTP/2.0 connection</text>
</g>
<g>
<rect style="fill: #ffffff" x="259.024" y="266.761" width="366.8" height="36"/>
<rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="259.024" y="266.761" width="366.8" height="36"/>
<text font-size="12.7998" style="fill: #000000;text-anchor:middle;font-family:monospace;font-style:normal;font-weight:normal" x="442.424" y="288.761">object whose type is a model of ServerSocket</text>
</g>
<g>
<polygon style="fill: #ffffff" points="409.903,58.5323 441.453,39.6023 473.003,58.5323 441.453,77.4623 "/>
<polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="409.903,58.5323 441.453,39.6023 473.003,58.5323 441.453,77.4623 "/>
<text font-size="12.7998" style="fill: #000000;text-anchor:end;font-family:monospace;font-style:normal;font-weight:normal" x="403.903" y="52.5323"/>
<text font-size="12.7998" style="fill: #000000;text-anchor:start;font-family:monospace;font-style:normal;font-weight:normal" x="479.003" y="52.5323"/>
<text font-size="12.7998" style="fill: #000000;text-anchor:middle;font-family:monospace;font-style:normal;font-weight:normal" x="441.453" y="62.5323">has</text>
</g>
<line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="440.931" y1="-17.0751" x2="441.318" y2="38.9611"/>
<line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="441.84" y1="78.456" x2="442.782" y2="127.016"/>
<text font-size="12.7998" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="441.124" y="10.943">
<tspan x="441.124" y="10.943">1</tspan>
</text>
<text font-size="12.7998" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="442.311" y="102.736">
<tspan x="442.311" y="102.736">1</tspan>
</text>
<g>
<polygon style="fill: #ffffff" points="406.092,220.328 437.642,201.398 469.192,220.328 437.642,239.258 "/>
<polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="406.092,220.328 437.642,201.398 469.192,220.328 437.642,239.258 "/>
<text font-size="12.7998" style="fill: #000000;text-anchor:end;font-family:monospace;font-style:normal;font-weight:normal" x="400.092" y="214.328"/>
<text font-size="12.7998" style="fill: #000000;text-anchor:start;font-family:monospace;font-style:normal;font-weight:normal" x="475.192" y="214.328"/>
<text font-size="12.7998" style="fill: #000000;text-anchor:middle;font-family:monospace;font-style:normal;font-weight:normal" x="437.642" y="224.328">has</text>
</g>
<line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="439.119" y1="200.394" x2="441.746" y2="164.945"/>
<line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="441.018" y1="265.821" x2="439.12" y2="240.243"/>
<text font-size="12.7998" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="440.432" y="182.669">
<tspan x="440.432" y="182.669">1</tspan>
</text>
<text font-size="12.7998" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="440.069" y="253.032">
<tspan x="440.069" y="253.032">N</tspan>
</text>
</svg>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment