HTTP Hypertext Transfer Protocol HTTP/1.0 allows one outstanding request per TCP connection HTTP/1.1 adds request pipelining suffers from head-of-line blocking HeaderField can be repetitive and verbose HTTP/2 supports all core features of HTTP/1.1 can interleave requests and responses per TCP connection can prioritize requests can use fewer TCP connections HeaderField uses efficient coding uses binary message framing is an application-layer protocol runs on top of TCP uses same "http" and "https" URI schemes as HTTP/1.1 port 80 for "http" URIs 443 for "https" URIs Client initiates TCP connection ask if Server supports HTTP/2 VersionIdentifier negotiation implies use of HTTP/2 "h2c" means HTTP/2 over TCP without TLS reserved from ALPN identifier space "h2" means HTTP/2 over TLS used in TLS-ALPN extension field RFC7301 ALPN identifier = {0x68,0x32} StartSteps "h2c" noKnow Client does not know if Server supports HTTP/2 request "http" URI using HTTP/1.1 HeaderField Upgrade = "h2c" HTTP2-Settings only one if has payload body then Client sends payload body before sending HTTP/2 frames example GET / HTTP/1.1 Host: server.example.com Connection: Upgrade, HTTP2-Settings Upgrade: h2c HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload> stream StreamIdentifier = 1 state "half-closed (local)" to Client default priority may use OPTIONS request to upgrade HTTP/1.1 to HTTP/2 costing one more RTT Server receives Client request if does not support HTTP/2 then ignores Upgrade responds example HTTP/1.1 200 OK Content-Length: 243 Content-Type: text/html ... if supports HTTP/2 and accepts upgrade then ignore "h2" token in Upgrade HeaderField respods 101(Switching Protocols) HTTP/2 frames have ConnectionPreface response to client request example HTTP/1.1 101 Switching Protocols Connection: Upgrade Upgrade: h2c [ HTTP/2 connection ... Client receives 101 response sends ConnectionPreface yeKnow Client knows Server supports HTTP/2 may know using RFC7838 sends ConnectionPreface then may immediately send HTTP request Server receives ConnectionPreface identifies HTTP/2 by presence of ConnectionPreface sends ConnectionPreface "h2" Client may or not know if Server supports HTTP/2 request to an "https" URI using TLS-ALPN extension completes TLS handshake sends ConnectionPreface Server receives request sends ConnectionPreface HTTP2-Settings = token68 ABNF production RFC5234 RFC7230 Section 2.1 only sent by Client only for request to upgrade HTTP/1.1 to HTTP/2 only one per request if not in request then Server does not upgrade to HTTP/2 ConnectionPreface = strg || sttngsFrmC if sent by Client = sttngsFrmS if sent by Server strg = 0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" designed so that intermediaries do not attempt to process further frames sttngsFrameC Client SETTINGS frame may be empty sttngsFrameS Server SETTINGS frame may be empty if receive invalid ConnectionPreface then send Connection error PROTOCOL_ERROR may not send GOAWAY since peer may not be using HTTP/2 HTMLHeader SenderSteps put one or more HeaderField in HeaderList serialize HeaderList into HeaderBlock using HeaderCompression divided HeaderBlock into HeaderBlockFragments put HeaderBlockFragments in Payload of Frames Frames are transmitted to peer receiverSteps concatenate HeaderBlockFragments into HeaderBlock HeaderDeCompression reconstruct HeaderList read HeaderFields of HeaderList HeaderField same as in HTTP/1 HeaderBlock apply HeaderDeCompression even if data will be discarded is always processed to maintain correct connection state except if connection closes if server receives very large HeaderBlock then server may send HTTP 431 (Request Header Fields Too Large) status code RFC6585 HeaderBlockFragments made of one or more octet sequences put in Payload of one HEADERS Frame followed by zero or more CONTINUATION Frames one PUSH_PROMISE Frame followed by zero or more CONTINUATION Frames transmitted with no Frame of other Type interleaved stream interleaved HeaderCompression RFC7541 is statefull if abused by waste of processing then send stream error ENHANCE_YOUR_CALM Stream created and used unilaterally may be closed by Client or Server has Frames exchanged between Client and Server processed in receiving order with independent sequence bidirectional sequence States +--------+ send PP | | recv PP ,--------| idle |--------. / | | \ v +--------+ v +----------+ | +----------+ | | | send H / | | ,------| reserved | | recv H | reserved |------. | | (local) | | | (remote) | | | +----------+ v +----------+ | | | +--------+ | | | | recv ES | | send ES | | | send H | ,-------| open |-------. | recv H | | | / | | \ | | | v v +--------+ v v | | +----------+ | +----------+ | | | half | | | half | | | | closed | | send R / | closed | | | | (remote) | | recv R | (local) | | | +----------+ | +----------+ | | | | | | | | send ES / | recv ES / | | | | send R / v send R / | | | | recv R +--------+ recv R | | | send R / `----------->| |<-----------' send R / | | recv R | closed | recv R | `----------------------->| |<----------------------' +--------+ map shows stream state transitions frames and flags affecting only those transitions send endpoint sends this Frame recv endpoint receives this Frame H HEADERS Frame followed by zero or more CONTINUATION Frames PP PUSH_PROMISE Frame followed by zero or more CONTINUATION Frames R RST_STREAM Frame ES Frame with END_STREAM bit set processed as separate event to Frame that has it HEADERS frame with END_STREAM bit set causes two state transitions is interpreted as H and ES CONTINUATION frame does not result in state transitions PRIORITY frame may be sent and received in any state if receive Frame and this description doesnt say what to do then may send Connection error PROTOCOL_ERROR "idle" starting state if send or receive HEADERS Frame then "open" if send or receive HEADERS Frame with END_STREAM bit set then "half-closed" if send PUSH_PROMISE frame on another stream then "reserved (local)" for reserved stream if receive PUSH_PROMISE frame on another stream then "reserved (remote)" for reserved stream PUSH_PROMISE frame reserves "idle" stream identified in PromisedStreamID is not sent on "idle" stream if receive Frame with no HEADERS or PRIORITY then send connection error PROTOCOL_ERROR "reserved (local)" state after sending PUSH_PROMISE frame if send HEADERS frame then "half-closed (remote)" if send or receive RST_STREAM frame then "closed" and release stream reservation if send Frame with no HEADERS or RST_STREAM or PRIORITY then error if receive Frame with no RST_STREAM or PRIORITY or WINDOW_UPDATE then send connection error PROTOCOL_ERROR "reserved (remote)" stream reserved by peer if receive HEADERS Frame then "half-closed (local)" if send or receive RST_STREAM Frame then "closed" release stream reservation may send PRIORITY Frame to reprioritize reserved stream if send Frame with no RST_STREAM or WINDOW_UPDATE or PRIORITY then error if receive Frame with no HEADERS or RST_STREAM or PRIORITY then connection error PROTOCOL_ERROR "open" may send or receive Frames with any Type sender observes advertised stream-level FlowControl limits if send Frame END_STREAM bit set then "half-closed (local)" if receive Frame END_STREAM bit set then "half-closed (remote)" if send or receive RST_STREAM Frame then "closed" "half-closed (local)" may receive Frames with any Type if send Frames with no WINDOW_UPDATE or PRIORITY or RST_STREAM then error if receive Frame END_STREAM bit set then "closed" if send or receive RST_STREAM Frame then "closed" may send WINDOW_UPDATE Frame for FlowControl if receive Frame END_STREAM bit set then ignore the following WINDOW_UPDATE Frames "half-closed (remote)" do not maintain peer FlowControl window if receive Frames with no WINDOW_UPDATE or RST_STREAM or PRIORITY then send stream error STREAM_CLOSED may send frames of any type observe advertised stream-level FlowControl limits if send Frame END_STREAM bit set then "closed" if send or receive RST_STREAM Frame then "closed" "closed" terminal state if receive RST_STREAM Frame and receive Frame with no PRIORITY after then send stream error STREAM_CLOSED if receive Frame END_STREAM bit set and receive Frame with any Type after then stream error STREAM_CLOSED if send DATA or HEADERS with END_STREAM bit set then may receive WINDOW_UPDATE or RST_STREAM for a short period and must ignore Frames may send connection error PROTOCOL_ERROR if peer has not received and processed RST_STREAM or END_STREAM then peer may send WINDOW_UPDATE or RST_STREAM if receive PRIORITY Frame and stream has been removed from dependency tree then may ignore PRIORITY Frame if sent RST_STREAM in previous state and state became "closed" and receive any Frames after then ignore received Frames may send error if sent RST_STREAM and receive FlowControl Frame for example DATA then count FlowControl Frame toward FlowControl window if sent RST_STREAM and received PUSH_PROMISE after and PUSH_PROMISE is not wanted then send RST_STREAM StreamIdentifier = odd if stream initiated by Client even if stream initiated by Server 0 is used for connection control not used to establish new stream > any stream previously created by endpoint if = unexpected value then send connection error PROTOCOL_ERROR if send or receive Frame in new stream and other stream is "idle" and "idle" stream StreamIdentifier < new stream then "idle" stream becomes "closed" example if Client never sends Frame on stream 5 and sends HEADERS Frame on stream 7 then stream 5 becomes "closed" if Client wants to create new stream and StreamIdentifier value range is exhausted then Client creates new connection if Server wants to create new stream and StreamIdentifier value range is exhausted then Server sends GOAWAY Frame then Client opens new connection Priority set using HEADERS Frame PRIORITY Frame allows endpoint to express how peer may allocate resources when managing concurrent streams does not forces peer to process concurrent streams in a particular order depends on Dependency Weight for new Stream Dependency = 0 Weight = 16 Dependency used by marking Stream as dependent on other stream parent is a stream upon which stream is dependent children may get resources only if parents are "closed" or blocked 0 non-existent stream root of tree parent of parents if stream depends on itself then send stream error PROTOCOL_ERROR if stream has no parent then stream Dependency = 0 if stream is "idle" then stream is not in tree if stream is not in tree then children get Dependency = 0 Weight = 16 DefaultFlag StreamIdentifier is added as new child to StreamDependency chirdren sharing parent are not ordered with respect to each other example if B and C are the children of A then B and C and D become the children of A map A A / \ ==> /|\ B C B C D ExclusiveFlag children of StreamDependency become children of StreamIdentifier StreamIdentifier becomes the child of StreamDependency example if B and C are the children of A then B and C become the children of D D becomes the child of A map A A | / \ ==> D B C / \ B C if stream is reprioritized then children move with stream example stream is made dependent on own dependencies B and C depend on A D and E depend on C F depends on D if A is made dependent on D then D takes the place of A all other dependency relationships stay the same if reprioritization is exclusive then F becomes dependent on A map x x x x | / \ | | A D A D D / \ / / \ / \ | B C ==> F B C ==> F A OR A / \ | / \ /|\ D E E B C F B C | | | F E E (intermediate) (non-exclusive) (exclusive) if stream1 is the child of stream2 and stream1 is removed from tree then Weight of stream1 is distributed to children of stream1 children of stream1 become children of stream2 example map P / \ A B / \ C D streams A and B share parent and C and D depend on A if A and D are blocked then C receives all resources of A if A is removed from tree then A Weight is divided between C and D if C and D have same Weight and A is removed from tree and D is blocked then C receives 1/3 not 1/2 of resources if Stream becomes "closed" then endpoint may retain Stream Priority state for a period to avoid giving incorrect Priority to new dependent Streams if endpoint is under high load then endpoint may discard parts of Priority state Weight >= 1 <= 256 proportional to resources allocation bigger means more resources example if B has Weight 4 and parent A and C has Weight 12 and parent A and A is blocked then B should receive 1/3 of resources compared to C Frame = Header || Payload Header +-----------------------------------------------+ | Length (24) | +---------------+---------------+---------------+ | Type (8) | Flags (8) | +-+-------------+---------------+-------------------------------+ |R| StreamIdentifier (31) | +-+-------------------------------------------------------------+ Length of Payload unsigned integer <= SETTINGS_MAX_FRAME_SIZE size = 24bit Type determines Frame format and semantics if receive unknown then ignore and discard Frame size = 8bit Flags each bit has different use size = 8bit R = 0 ignored size = 1bit StreamIdentifier unsigned integer if = 0 then Frame is associated with whole Connection if != 0 then Frame is associated with individual stream size = 31bit DATA Header Type = 0 Flags PADDED bit 3 if set then PadLength and Padding are present if not set then PadLength and Padding are not present END_STREAM bit 0 if set then this is last Frame to send for stream Payload +---------------+ |PadLength? (8)| +---------------+-----------------------------------------------+ | Data (*) ... +---------------------------------------------------------------+ | Padding (*) ... +---------------------------------------------------------------+ PadLength in octets size = 8bit if >= Frame Header Length then receiver connection error PROTOCOL_ERROR may = 0 Data Application data may carry HTTP request or response payloads payload body RFC7230 Section 3.3 size = Frame Header Length - size of PadLength - PadLength octets Padding has no application semantic value may obscure size of messages = 0 if != 0 then receiver may connection error PROTOCOL_ERROR included in FlowControl only sent if stream is "open" or "half-closed (remote)" if StreamIdentifier = 0 then send connection error PROTOCOL_ERROR HEADERS Header Type = 1 Flags END_STREAM bit 0 if set then this is last HeaderBlock in Stream to send this Frame may be followed by CONTINUATION frame and still be last HeaderBlock in stream END_HEADERS bit 2 if set then this frame is not followed by CONTINUATION frame if not set then this frame is followed by CONTINUATION frame if set and receive frame in this or different stream then connection error PROTOCOL_ERROR allows HeaderBlock to be logically equivalent to one Frame PADDED bit 3 if set then PadLength and Padding are present if not set then PadLength and Padding are not present PRIORITY bit 5 if set then E and StreamDependency and Weight are present if not set then E and StreamDependency and Weight are not present enabled present data is equivalent to PRIORITY Frame reprioritizes Stream if bit set and in subsequent HEADERS to firt on Stream Payload +---------------+ |PadLength? (8)| +-+-------------+-----------------------------------------------+ |E| StreamDependency? (31) | +-+-------------+-----------------------------------------------+ | Weight? (8) | +-+-------------+-----------------------------------------------+ | HeaderBlockFragment (*) ... +---------------------------------------------------------------+ | Padding (*) ... +---------------------------------------------------------------+ PadLength length of Padding in octets size = 8bit if >= Frame Header Length then connection error PROTOCOL_ERROR E if set then StreamDependency is exclusive size = 1bit StreamDependency identifies the parent of this stream size = 31bit Weight unsigned integer Priority Weight of this stream add one to obtain value between 1 and 256 size = 8bit sent on stream in "idle" or "open" or "reserved (local)" or "half-closed (remote)" if HeaderBlock does not fit in one HEADERS then HeaderBlock is continued in one or more CONTINUATION Frames only appears at start or end of stream if StreamIdentifier = 0 then send connection error PROTOCOL_ERROR PRIORITY Header Type = 2 Flags none Payload +-+-------------------------------------------------------------+ |E| StreamDependency (31) | +-+-------------+-----------------------------------------------+ | Weight (8) | +-+-------------+ E indicates StreamDependency is exclusive size = 1bit StreamDependency identifies the parent of this stream size = 31bit Weight unsigned integer Priority Weight of this stream add one to obtain value between 1 and 256 size = 8bit if size != 5 octets then send stream error FRAME_SIZE_ERROR sent in any stream state not sent between consecutive Frames with single HeaderBlock if abused causing unnecessary waste of resources then send stream error ENHANCE_YOUR_CALM if StreamIdentifier = 0 then send connection error PROTOCOL_ERROR RST_STREAM Header Type = 3 Flags none Payload +---------------------------------------------------------------+ | ErrorCode (32) | +---------------------------------------------------------------+ unsigned integer indicates why stream is being terminated if size != 32bit then send connection error FRAME_SIZE_ERROR immediately terminates stream if received then send no additional Frame in stream except PRIORITY RST_STREAM Frame if sent then it takes time to arrive to peer sender may receive Frames must process received PUSH_PROMISE Frames FlowControl Frames HeaderCompression Frames if sent and receive Frame on "closed" stream after more than one RTT then may send again to deal with misbehaving implementations if received with ErrorCode = REFUSED_STREAM then stream is being closed prior to any processing having occurred request sent on this stream are safe to retry if StreamIdentifier = 0 then send connection error PROTOCOL_ERROR SETTINGS Header Type = 4 Flags ACK bit 0 if set then sender ACKnowledges receiving and applying this Frame Payload is empty else send connection error FRAME_SIZE_ERROR Payload has zero or more parameters each Parameter +-------------------------------+ | Identifier (16) | +-------------------------------+-------------------------------+ | Value (32) | +---------------------------------------------------------------+ Parameters defined here are all supported by implementations are not negotiated affects receiver last one received is applied all processed in appearing order with no other Frame processing in between different values for same Parameter can be advertised by each peer if receive unknown or unsupported then ignore SETTINGS_HEADER_TABLE_SIZE Identifier = 1 Value in octets = 4096 if initial value max size of HeaderCompression table used to decode HeaderBlock HeaderCompression encoder uses size <= Value SETTINGS_ENABLE_PUSH Identifier = 2 Value = 1 if initial value indicates server push is permitted if = 0 then do not send PUSH_PROMISE frame if != 0 or != 1 then send connection error PROTOCOL_ERROR if sent = 0 and ACKnowledged and receive PUSH_PROMISE then send connection error PROTOCOL_ERROR if Client receives SETTINGS_ENABLE_PUSH != 0 then send connection error PROTOCOL_ERROR SETTINGS_MAX_CONCURRENT_STREAMS Identifier = 3 Value number of streams sender permits receiver to create >= 100 is recomended 0 prevents creation of new streams does not prohibit sending PUSH_PROMISE initially there is no limit only counts Streams in "open" or "half-closed (local)" or "half-closed (remote)" if exceeded then send stream error PROTOCOL_ERROR or REFUSED_STREAM if endpoints wants Value < current concurrent streams then endpoint closes stream or waits for current concurrent streams to go down SETTINGS_INITIAL_WINDOW_SIZE Identifier = 4 Value receiver updates all streams WindowSizeS#s does not affect WindowSizeCs in octets = 2^16-1 if initial value < 2^31-1 else send connection error FLOW_CONTROL_ERROR SETTINGS_MAX_FRAME_SIZE Identifier = 5 Value size of largest Frame Payload sender is willing to receive in octets = 2^14 if initial value >= 2^14 else connection error PROTOCOL_ERROR < 2^24 else connection error PROTOCOL_ERROR SETTINGS_MAX_HEADER_LIST_SIZE Identifier = 6 Value max size of HeaderList sender accepts in octets initially there is no limit must be sent by both endpoints at start of connection may be sent by both endpoints at any other time of connection always apply to connection never apply to single stream if received and ACK not set then update received Parameters as soon as possible send immediately SETTINGS Frame with ACK set if sent and does not receive ACKnowledgement and reasonable amount of time passes then may send connection error SETTINGS_TIMEOUT if abused by pointlessly changing it or setting multiple undefined parameters then send stream error ENHANCE_YOUR_CALM if StreamIdentifier != 0 then send connection error PROTOCOL_ERROR if badly formed or incomplete then send connection error PROTOCOL_ERROR if Frame Length != multiple of 6 octets then send connection error FRAME_SIZE_ERROR PUSH_PROMISE Header Type = 5 Flags END_HEADERS bit 2 if set then this Frame has entire HeaderBlock is not followed by one or more CONTINUATION Frame if not set then this Frame is followed by one or more CONTINUATION Frame if not set and receive frame without CONTINUATION or frame on different stream then send connection error PROTOCOL_ERROR PADDED bit 3 if set then PadLength and Padding are present if not set then PadLength and Padding are not present Payload +---------------+ |PadLength? (8) | +-+-------------+-----------------------------------------------+ |R| PromisedStreamID (31) | +-+-----------------------------+-------------------------------+ | HeaderBlockFragment (*) ... +---------------------------------------------------------------+ | Padding (*) ... +---------------------------------------------------------------+ PadLength length of Padding in octets size = 8bit R reserved size = 1bit PromisedStreamID unsigned integer identifies stream that will be initiated by Server if received and stream PromisedStreamID is not "idle" then send connection error PROTOCOL_ERROR changes promised stream to "reserved" only reserves for later use size = 31bit HeaderBlockFragment provides additional context for promised stream may modify state of HeaderCompression has ":authority" if ":authority" is not authoritative then send stream error PROTOCOL_ERROR has ":method" that is safe and cacheable else send stream error PROTOCOL_ERROR is not sent by client only send on stream in "open" or "half-closed (remote)" promised streams may not be used in order promised if not cacheable or RFC7231 Section 4.2.3 not safe or RFC7231 Section 4.2.1 has request body then reset stream PromisedStreamID with stream error PROTOCOL_ERROR if received then may reject promised streams by returning RST_STREAM with promised StreamIdentifier if received and ignored then stream state becomes indeterminate if received in stream in neither "open" nor "half-closed (local)" then connection error PROTOCOL_ERROR if StreamIdentifier = 0 then send connection error PROTOCOL_ERROR PING Header Type = 6 Flags ACK bit 0 Payload +---------------------------------------------------------------+ | | | OpaqueData (64) | | | +---------------------------------------------------------------+ OpaqueData has any value sender wants used in any fashion by sender size = 64bit if received with ACK flag not set then send PING frame with ACK flag set identical Payload may higher priority than any other frame RTT round trip time = time it takes for PING with ACK not set to go + time it takes for PING with ACK set to come determines whether idle connection is functional sent from any endpoint if StreamIdentifier != 0 then send connection error PROTOCOL_ERROR if Frame Length != 8 then send connection error FRAME_SIZE_ERROR GOAWAY Header Type = 7 Flags none Payload +-+-------------------------------------------------------------+ |R| LastStreamID (31) | +-+-------------------------------------------------------------+ | ErrorCode (32) | +---------------------------------------------------------------+ | AdditionalDebugData (*) | +---------------------------------------------------------------+ LastStreamID unsigned integer highest stream sender might have taken some action on yet take action on initiated by receiver = 0 if no streams data was processed size = 31bit ErrorCode reason for closing connection size = 32bit AdditionalDebugData for diagnostic purposes only carries no semantic value may have security or private data if contains logged or otherwise persistently stored data then do adequate safeguards to prevent unauthorized access use to initiate shutdown of connection or signal serious error conditions gracefully stop accepting new streams while finishing processing established streams applies to connection does not apply to specific stream if StreamIdentifier != 0 then send connection error PROTOCOL_ERROR may send before closing connection so peer knows if stream is partially processed may not send before closing connection if peer is misbehaving if sent then ignore new streams initiated by receiver with StreamIdentifier > LastStreamID if sent GOAWAY and sent data on stream with StreamIdentifier > LastStreamID then that stream is ignored if received then do not open new streams on connection may do new connection for new streams if received and connection has no more uses then may send GOAWAY frame before terminating connection if GOAWAY was used and Connection closed and stream with StreamIdentifier <= LastStreamID was not closed then reattempting requests is not possible transactions is not possible any protocol activity is not possible idempotent actions is possible HTTP GET,PUT,DELETE is possible if GOAWAY was used and Connection closed and stream with StreamIdentifier > LastStreamID was not closed then any protocol activity may be safely retried using new connection if sent then may maintaining connection "open" until all streams complete if endpoint wants to do gracefull connection shut down then send GOAWAY with ErrorCode = NO_ERROR LastStreamID = 2^31-1 wait at least one RTT if no error hapens then send GOAWAY with ErrorCode = NO_ERROR LastStreamID = real stream if sent GOAWAY with ErrorCode NO_ERROR and new ErrorCode happens then may send GOAWAY with new ErrorCode LastStreamID <= LastStreamID of first GOAWAY indicating which streams could have been acted upon if connection terminates without GOAWAY frame then LastStreamID = 2^31-1 WINDOW_UPDATE Header Type = 8 Flags none Payload +-+-------------------------------------------------------------+ |R| WindowSizeIncrement (31) | +-+-------------------------------------------------------------+ R reserved size = 1bit WindowSizeIncrement unsigned integer in octets > 0 < 2^31 if = 0 then stream error PROTOCOL_ERROR size = 31bit if size != 4 then send connection error FRAME_SIZE_ERROR FlowControl Frames are of Type DATA future Extensions may add new Types does not apply to AllHops example Server to midlebox1 to midlebox2 to Client applies to each OneHop example Client to midlebox2 or midlebox1 to midlebox2 uses WindowSize integer can be negative in octets = 65535 if new connection or stream each enpoint has for each Connection WindowSizeCs for sending WindowSizeCr for receiving Stream WindowSizeS#s for sending WindowSizeS#r for receiving if receive FlowControl Frame with StreamIdentifier = 3 Length > WindowSizeS3r then either 1 process Frame update WindowSizeS3r = WindowSizeS3r - Frame Length WindowSizeCr = WindowSizeCr - Frame Length receiving Frame Length > WindowSizeS3r may happen after sending small SETTINGS_INITIAL_WINDOW_SIZE 2 send connection error FLOW_CONTROL_ERROR if receive FlowControl Frame with StreamIdentifier = 2 Length <= WindowSizeS2r then process Frame update WindowSizeS2r = WindowSizeS2r - Frame Length WindowSizeCr = WindowSizeCr - Frame Length FlowControl Frame can not have StreamIdentifier = 0 if want to send FlowControl Frame with StreamIdentifier = 5 Length > WindowSizeS5s then do not send Frame if want to send FlowControl Frame with StreamIdentifier = 4 Length <= WindowSizeS4s then send Frame update WindowSizeS4s = WindowSizeS4s - Frame Length WindowSizeCs = WindowSizeCs - Frame Length if receive FlowControl Frame and detect connection error then do not apply FlowControl if receive FlowControl Frame and detect stream error then apply FlowControl if receive WINDOW_UPDATE with StreamIdentifier = 0 then update WindowSizeCr = WindowSizeCr + WindowSizeIncrement if receive WINDOW_UPDATE with StreamIdentifier = 1 then update WindowSizeS1r = WindowSizeS1r + WindowSizeIncrement if any WindowSize >= 2^31 then send either GOAWAY with FLOW_CONTROL_ERROR RST_STREAM with FLOW_CONTROL_ERROR if connection is new and client sends 60000 octets and server sends SETTINGS_INITIAL_WINDOW_SIZE = 16000 octets then client calcualtes WindowSizeS1s = 65535 when connection is new WindowSizeS1s = 65535-60000 = 5535 when client sends 60000 octets WindowSizeS1s = 5535 + (16000-65535) =-44000 when server sends SETTINGS_INITIAL_WINDOW_SIZE implementations manage how to avoid head-of-line blocking large bandwidth*delay problems RFC7323 SETTINGS can change WindowSize for streams in "open" or "half-closed (remote)" if abused causing unnecessary waste of resources then send stream error ENHANCE_YOUR_CALM CONTINUATION Header Type = 9 Flags END_HEADERS bit 2 if set then this Frame ends HeaderBlock if not set and next received Frame Type != CONTINUATION or is from another stream then send connection error PROTOCOL_ERROR Payload +---------------------------------------------------------------+ | HeaderBlockFragment (*) ... +---------------------------------------------------------------+ continues sequence of HeaderBlock fragments any number of CONTINUATION frames can be sent if received and previous Frame had no HEADERS or PUSH_PROMISE or CONTINUATION with END_HEADERS not set then send connection error PROTOCOL_ERROR if StreamIdentifier = 0 then send connection error PROTOCOL_ERROR if size > SETTINGS_MAX_FRAME_SIZE or size > max limit for Frame type or size < min limit for Frame type then send error FRAME_SIZE_ERROR if FRAME_SIZE_ERROR for Frame with HEADERS or PUSH_PROMISE or CONTINUATION or SETTINGS or StreamIdentifier = 0 then Connection error sending big Frame may delay sending time-sensitive Frames example RST_STREAM or WINDOW_UPDATE or PRIORITY if endpoints do not maintain synchronized view of connection state then communication will fail if abused by receiving many small or empty then send stream error ENHANCE_YOUR_CALM Error class ConnectionError if entire connection becomes unusable StreamError if one stream becomes unusable ConnectionError for error preventing further processing of frame layer or corrupting any connection state if encountered then may send Frame Type GOAWAY StreamIdentifier of last successful Stream received ErrorCode indicating why connection is terminating close TCP connection endpoint may end connection at any time treat StreamError as ConnectionError StreamError does not affect other Streams if detected then send Frame Type RST_STREAM StreamIdentifier where error occurred ErrorCode ErrorCode size = 32bit if unknown or unsupported then trigger no special behavior may treate as INTERNAL_ERROR = 0 NO_ERROR associated condition is not a result of error = may be in GOAWAY indicating graceful shutdown of connection = 1 PROTOCOL_ERROR endpoint detected unspecific protocol error = use if specific ErrorCode is not available = 2 INTERNAL_ERROR sender encountered unexpected internal error = 3 FLOW_CONTROL_ERROR sender detected peer violated flow-control protocol = 4 SETTINGS_TIMEOUT sender sent SETTINGS frame and received no response in time = 5 STREAM_CLOSED sender received frame on "half-closed" stream = 6 FRAME_SIZE_ERROR sender received frame with invalid size = 7 REFUSED_STREAM sender refused stream prior to performing application processing = 8 CANCEL sender indicates stream is no longer needed = 9 COMPRESSION_ERROR sender is unable to maintain HeaderCompression context for connection = 10 CONNECT_ERROR connection established in response to CONNECT was reset or abnormally closed = 11 ENHANCE_YOUR_CALM sender detected peer might be generating excessive load = 12 INADEQUATE_SECURITY underlying transport properties do not meet minimum security requirements = 13 HTTP_1_1_REQUIRED sender requires HTTP/1.1 instead of HTTP/2 all request and response semantics are preserved from HTTP/1.1 into HTTP/2 specification and requirements of HTTP/1.1 Semantics and Content RFC7231 Conditional Requests RFC7232 Range Requests RFC7233 Caching RFC7234 Authentication RFC7235 portions of Message Syntax and Routing RFC7230 such as HTTP and HTTPS URI schemes are applicable in HTTP/2 HTTP exchange consumes single stream Client request on new stream starts with HEADERS "open" ends with Frame with END_STREAM set "half-closed (local)" for Client "half-closed (remote)" for Server Server response on same stream starts with HEADERS ends with Frame END_STREAM set "closed" completes after Server sends or client receives Frame END_STREAM set and any CONTINUATION frames if client has not finished sending full request and server response does not depend on the rest to receive then server may send complete response for example Frame with END_STREAM set RST_STREAM with error NO_ERROR then Client does not discard responses because NO_ERROR may discard responses because other reasons does not support upgrade to another protocol message . one HEADERS followed by zero or more CONTINUATION with HeadeFields RFC7230 Section 3.2 . zero or more DATA with payload body . only for HTML response zero or more HEADERS each followed by zero or more CONTINUATION with informational (1xx) HTTP responses RFC7230 Section 3.2 RFC7231 Section 6.2 . one HEADERS followed by zero or more CONTINUATION with Trailer RFC7230 Section 4.1.2 if receive final (non-informational) status code and HEADERS END_STREAM is not set then treat as malformed do not use "chunked" transfer encoding RFC7230 Section 4.1 101 (Switching Protocols) status code RFC7231 Section 6.2.2 HeaderField series of key-value pairs list at https://www.iana.org/assignments/message-headers Name strings of ASCII characters compared in case-insensitive fashion if uppercase in HTTP request or response then treat as malformed TE HeaderField may be present in request only with value "trailers" do not use Connection HeaderField to indicate connection-specific HeaderFields if message has connection-specific HeaderFields then treat as malformed if transforming HTTP/1.x message to HTTP/2 then remove HeaderFields nominated by Connection HeaderField Connection HeaderField may remove even if not nominated by Connection HeaderField Keep-Alive Proxy-Connection Transfer-Encoding Upgrade Cookie uses ";" to delimit cookie-pairs or "crumbs" does not follow list construction rules in HTTP RFC7230 Section 3.2.2 may be split into separate HeaderField each with one or more cookie-pairs if finish HeaderDeCompression and there are multiple Cookie then concatenate all Cookie into single octet string using 0x3B 0x20 = "; " then pass to non-HTTP/2 context like HTTP/1.1 connection or generic HTTP server application example cookie: a=b cookie: c=d cookie: e=f concatenates into cookie: a=b; c=d; e=f if HTTP request or response has payload body then content-length HeaderField may be used if response has no payload RFC7230 Section 3.3.2 and no content in all DATA Frames then response can have non-zero content-length HeaderField if content-length HeaderField value != sum of DATA frame payload lengths forming body then treat as malformed PseudoHeaderField != HeaderField begins with ':' character (ASCII 0x3a) has target URI method of request status code for response are not in trailing HeaderFields if defined for HTTP requests then do not put in HTTP responses if defined for HTTP responses then do not put in HTTP requests if in request or response and is undefined or invalid then treat as malformed if in request or response and is after HeaderField then treat as malformed only use the ones defined here all HTTP requests have at least one valid ":method" and ":scheme" and ":path" else treat as malformed responses have one ":status" else treat as malformed request ":method" has HTTP method RFC7231 Section 4 ":scheme" has scheme portion of target URI RFC3986 Section 3.1 not restricted to "http" and "https" schemed URIs proxy or gateway can translate non-HTTP schemes use HTTP to interact with non-HTTP services ":authority" has authority portion of target URI RFC3986 Section 3.2 no "userinfo" subcomponent for "http" or "https" schemed URIs if translating HTTP/1.1 request with target in origin form asterisk form RFC7230 Section 5.3 then ":authority" is omitted if Client generates HTTP/2 requests directly then should use ":authority" instead of Host HeaderField if intermediary converts HTTP/2 request to HTTP/1.1 and request has no Host HeaderField then create Host HeaderField by copying ":authority" value ":path" has path and query parts of target URI "path-absolute" production optionally '?' character followed by "query" production RFC3986 Sections 3.3 and 3.4 '*' for request in asterisk form if "http" or "https" URI has no path component then ":path" = '/' if "http" or "https" URI has no path component and is an OPTIONS request then ":path" = '*' RFC7230 Section 5.3.4 HTTP/2 has no way to carry version identifier of HTTP/1.1 request line response ":status" has HTTP status code field RFC7231 Section 6 HTTP/2 has no way to carry version or reason phrase of HTTP/1.1 status line Malformed if detected then send stream error PROTOCOL_ERROR if detected by intermediary then intermediary does not forward message for example any intermediary not acting as tunnel if detected in requests by server then server may send response before closing or resetting stream if detected in response by Client then Client does not accept response Padding does not replace TLS padding only slows attacker by increasing number of frames to observe provides little protection if using random padding with predictable distribution if plaintext is padded to fixed size and attacker makes payload cross the fixed size then plaintext information will be exposed intermediaries may retain padding of DATA remove padding of HEADERS PUSH_PROMISE to improve data protection HTTP/1.1equivalentHTTP/2 HTTP GET request has request HeaderFields no payload body example HEADERS frame has END_HEADERS and END_STREAM flags set no CONTINUATION frames sent equivalence GET /resource HTTP/1.1 HEADERS Host: example.org ==> + END_STREAM Accept: image/jpeg + END_HEADERS :method = GET :scheme = https :path = /resource host = example.org accept = image/jpeg example HTTP response has only response HeaderFields sent as HEADERS frame followed by zero or more CONTINUATION frames equivalence HTTP/1.1 304 Not Modified HEADERS ETag: "xyzzy" ==> + END_STREAM Expires: Thu, 23 Jan ... + END_HEADERS :status = 304 etag = "xyzzy" expires = Thu, 23 Jan ... example HTTP POST request has HeaderFields and payload data sent as one HEADERS frame followed by zero or more CONTINUATION frames with request header fields followed by one or more DATA frames last CONTINUATION or HEADERS END_HEADERS set and last DATA END_STREAM set equivalence POST /resource HTTP/1.1 HEADERS Host: example.org ==> - END_STREAM Content-Type: image/jpeg - END_HEADERS Content-Length: 123 :method = POST :path = /resource {binary data} :scheme = https CONTINUATION + END_HEADERS content-type = image/jpeg host = example.org content-length = 123 DATA + END_STREAM {binary data} example HTTP response has HeaderFields and payload data sent as one HEADERS frame followed by zero or more CONTINUATION frames followed by one or more DATA frames last DATA END_STREAM set equivalence HTTP/1.1 200 OK HEADERS Content-Type: image/jpeg ==> - END_STREAM Content-Length: 123 + END_HEADERS :status = 200 {binary data} content-type = image/jpeg content-length = 123 DATA + END_STREAM {binary data} informational response 1xx status code other than 101 is sent as HEADERS frame followed by zero or more CONTINUATION frames trailing HeaderFields are sent as HEADERS frame with END_STREAM set after sending request or response HeaderBlock all DATA frames example 100 (Continue) status code is sent for request with "100-continue" token Expect HeaderField trailing HeaderField is sent after equivalence HTTP/1.1 100 Continue HEADERS Extension-Field: bar ==> - END_STREAM + END_HEADERS :status = 100 extension-field = bar HTTP/1.1 200 OK HEADERS Content-Type: image/jpeg ==> - END_STREAM Transfer-Encoding: chunked + END_HEADERS Trailer: Foo :status = 200 content-length = 123 123 content-type = image/jpeg {binary data} trailer = Foo 0 Foo: bar DATA - END_STREAM {binary data} HEADERS + END_STREAM + END_HEADERS foo = bar ServerPush used by server by sending PUSH_PROMISE steps unoptimized Client initiates request1 Server sends response1 Client sends request2 Server sends response2 Client sends request3 Server sends response3 optimized1 Client initiates request1 Server sends response1 PUSH_PROMISE response2 response3 optimized2 Client initiates request1 Server sends PUSH_PROMISE response1 response2 response3 response1 has data making Client request again for example links to images optimized1 PUSH_PROMISE may stop Client from sending request2 and request3 optimized2 PUSH_PROMISE stops Client from sending request2 and request3 negotiated independently for each hop between Server and Client Request is PUSH_PROMISE Frame followed by zero or more CONTINUATION Frames always associated with explicit request from client sent on stream where explicit request from client happened frames are interspersed with response frames Response uses stream promised by PUSH_PROMISE transmits HTTP response client may not requests for the promised response until promised stream has closed if client does not want or server takes too long to begin sending then client sends RST_STREAM with StreamIdentifier = PromisedStreamID and either CANCEL REFUSED_STREAM if received by Client then Client validates either server is authoritative proxy is configured for corresponding request example if server has certificate "example.com" DNS-ID or Common Name then server is not permitted to respond for "https://www.example.org/doc" if client accepts PUSH_PROMISE and limits number of streams in "reserved (remote)" and limit it reached then client sends stream error ENHANCE_YOUR_CALM stream begins with HEADERS changing stream into "half-closed (remote)" for server "half-closed (local)" for client ends with END_STREAM set changing stream into "closed" client never sends frame with END_STREAM set if is cacheable and RFC7234 Section 3 client implements HTTP cache then client may store response if "no-cache" cache response directive is present and response stream PromisedStreamID is still open then response is successfully validated on Server if not cacheable then HTTP cache does not store response may be made available to application separately if received by intermediary then intermediary chosses independently of actions taken by server to forward it or not to client to make additional pushes to client if server receives then connection error PROTOCOL_ERROR Cacheability is possible depends on Cache-Control HeaderField has issues if single server hosts multiple clients example server offers parts of URI space to multiple users if clients have no authority over representations of resources then clients cant push representations of resources not used if server is not authoritative CONNECT in HTTP/1.x RFC7231 Section 4.3.6 converts connection into tunnel to remote host used with HTTP proxies to establish TLS session with origin server to interact with "https" resources in HTTP/2 establishes tunnel over one stream to remote host ":method" = "CONNECT" ":scheme" omitted ":path" omitted ":authority" has host and port to connect to authority-form of request-target of CONNECT requests RFC7230 Section 5.3 if not following definition then treat as malformed proxy steps establishes TCP connection with server in ":authority" sends client HEADERS with 2xx series status code RFC7231 Section 4.3.6 each peer sends initial HEADERS all subsecuent DATA frames correspond to data sent on TCP transmits client Payload DATA to TCP server assembles server TCP data into DATA for client if receives DATA with END_STREAM set then proxy sends last TCP segment with FIN set if receives TCP segment with FIN set then proxy sends DATA frame with END_STREAM set if receives Frames other than DATA RST_STREAM WINDOW_UPDATE PRIORITY then sends stream error RST_STREAM if detects TCP connection error or receives TCP segment with RST set then sends stream error CONNECT_ERROR if detects HTTP/2 stream or connection error then sends TCP segment with RST set if close stream of peer then TCP connection may remain in TIME_WAIT state maintain resources does not rely only on SETTINGS_MAX_CONCURRENT_STREAMS to limit resources consumed may be abused to create disproportionate load on proxy peer stream creation is less expensive than proxy TCP connection creation and maintenance if client receives END_STREAM set then client sends DATA with END_STREAM set DATA frame with END_STREAM set is equivalent to TCP FIN bit final TCP segment may be empty final DATA frame may be empty TCP connection may be closed by either peer TCP connection error is signaled with RST_STREAM Connection is persistent Servers may maintain open for as long as possible terminate if idle clients may open multiple to same IP and port using different SNI to provide different TLS client certificates avoid multiple with same configuration avoid multiple to same host and port pair derived from URI or configured proxy or alternative service RFC7838 not close until no further communication necessary user navigates away from web page server closes connection replace Connection near exhaustion of streamidentifier Connection with errors to refresh TLS key may have multiple concurrently open Streams either endpoint interleaving Frames from multiple Streams has HeaderCompression context HeaderDeCompression context if HeaderDeCompression error then send connection error COMPRESSION_ERROR Reuse if requests have multiple different URI authority components if origin server is authoritative if IP addresses resolve to same host in URI and using TCP without TLS if host in URI has valid certificate and using TCP with TLS if origin server certificate has multiple "subjectAltName" or names with wildcards one of which is valid for authority in URI example server has certificate with "subjectAltName" of "*.example.com" may Reuse Connection for requests to "https://a.example.com/" and "https://b.example.com/" for multiple origin servers requests may go to wrong origin server example if middlebox uses SNI extension to select origin server and does TLS termination then clients may send confidential data to wrong server even when server is authoritative if not wanted by server and server receives request then server sends 421 (Misdirected Request) status code for all client requests sent via proxy 421 (Misdirected Request) Status Code indicates that request to server has no response may be sent by server not configured to respond to request with specific scheme and authority in URI is not generated by proxies cacheable by default may be disabled by method definition or explicit cache controls RFC7234 Section 4.2.2 if client sends request and receives 421 Status Code then client may retry request on different connection usingTLS may follow general guidance RFC7525 version >= 1.2 support SNI clients indicate target domain name disable TLS 1.2 compression disable TLS 1.2 renegotiation if server wants to change to other protocol that supports renegotiation then server sends error HTTP_1_1_REQUIRED support key size >= 224bit for ECDHE else send connection error INADEQUATE_SECURITY >= 2048bit for DHE else send connection error INADEQUATE_SECURITY <= 4096bit for DHE for client support TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 with P-256 endpoint may do connection error INADEQUATE_SECURITY if ciphersuite in BlackList is negotiated endpoint must not do connection error INADEQUATE_SECURITY if ciphersuite not in BlackList is negotiated if client supports HTTP/1.1 and HTTP/2 then client may advertise ciphersuites in BlackList BlackList RFC7540 Appendix A if attacker can control confidential data transported over TLS then do not compress confidential data if separate compression dictionaries are not used for each source of confidential data then do not compressed confidential data ServerAuthority determine if server is authoritative of response uses definition in RFC7230 Section 9.1 local name resolution for "http" URI scheme authenticated server identity RFC2818 Section 3 for "https" scheme Extensions are within the scope of one HTTP/2 connection applies to protocol elements defined here does not affect existing options for extending HTTP may use new Frame Type or new SETTINGS Parameter or new ErrorCode without prior arrangement or negotiation implementations ignore unknown or unsupported values in all extensible protocol elements discard frames with unknown or unsupported types if Extension Frames appear in middle of HeaderBlock then send connection error PROTOCOL_ERROR if Extension changes semantics of existing protocol components then negotiate Extension before use for negotiating use of Extension there is no specific method SETTINGS Parameter may be used defaults to disabled CrossProtocolAttack attacker makes client start transaction in one protocol toward server using different protocol transaction valid in second protocol avoided by using TLS handshake with ALPN identifier may happen if not using TLS and server ignores parts of HTTP/1.1 request with Upgrade header client connection preface IntermediaryEncapsulationAttack if carriage return CR ASCII 0xd or line feed LF ASCII 0xa or zero character NUL ASCII 0x0 are translated verbatim then attacker may exploit them if request or response has invalid HeaderField name then treat as malformed intermediary does no translation from HTTP/2 to HTTP/1.1 if request or response has invalid character in HeaderField value then treat as malformed valid characters are defined by "field-content" ABNF rule RFC7230 Section 3.2 Privacy observer may locate enpoint using PING response latency fingerprinting endpoints correlate actions of endpoints over time handling of settings values FlowControl managment priorities allocation to streams timing of reactions reusing connections for different origins