Network Working Group M. Belshe
Internet-Draft Twist
Intended status: Standards Track R. Peon
Expires: February 2, 2013 Google, Inc
August 2012
SPDY Protocol
draft-mbelshe-httpbis-spdy-00
Abstract
This document describes SPDY, a protocol designed for low-latency
transport of content over the World Wide Web. SPDY introduces two
layers of protocol. The lower layer is a general purpose framing
layer which can be used atop a reliable transport (likely TCP) for
multiplexed, prioritized, and compressed data communication of many
concurrent streams. The upper layer of the protocol provides HTTP-
like semantics for compatibility with existing HTTP application
servers.
Status of This Memo
This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet-
Drafts is at http://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."
This Internet-Draft will expire on February 2, 2013.
Copyright Notice
Copyright (c) 2012 IETF Trust and the persons identified as the
document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents
(http://trustee.ietf.org/license-info) in effect on the date of
publication of this document. Please review these documents
carefully, as they describe your rights and restrictions with respect
Belshe & Peon Expires February 2, 2013 [Page 1]
Internet-Draft SPDY August 2012
to this document. Code Components extracted from this document must
include Simplified BSD License text as described in Section 4.e of
the Trust Legal Provisions and are provided without warranty as
described in the Simplified BSD License.
Table of Contents
1. Overview . . . . . . . . . . . . . . . . . . . . . . . . . intro
1.1. Document Organization . . . . . . . . . . . . . . . . . ancho
1.2. Definitions . . . . . . . . . . . . . . . . . . . . . . ancho
2. SPDY Framing Layer . . . . . . . . . . . . . . . . . . . . Frami
2.1. Connection . . . . . . . . . . . . . . . . . . . . . . ancho
2.2. Connection Header . . . . . . . . . . . . . . . . . . . Conne
2.3. Framing . . . . . . . . . . . . . . . . . . . . . . . . ancho
2.3.1. Frame Header . . . . . . . . . . . . . . . . . . . Frame
2.3.2. Frame Size . . . . . . . . . . . . . . . . . . . . Frame
2.4. Streams . . . . . . . . . . . . . . . . . . . . . . . . ancho
2.4.1. Stream Creation . . . . . . . . . . . . . . . . . . Strea
2.4.2. Stream priority . . . . . . . . . . . . . . . . . . Strea
2.4.3. Stream half-close . . . . . . . . . . . . . . . . . Strea
2.4.4. Stream close . . . . . . . . . . . . . . . . . . . Strea
2.5. Error Handling . . . . . . . . . . . . . . . . . . . . ancho
2.5.1. Connection Error Handling . . . . . . . . . . . . . Conne
2.5.2. Stream Error Handling . . . . . . . . . . . . . . . Strea
2.5.3. Error Codes . . . . . . . . . . . . . . . . . . . . Error
2.6. Name/Value Header Block . . . . . . . . . . . . . . . . Heade
2.6.1. Compression . . . . . . . . . . . . . . . . . . . . Compr
2.7. Frame Types . . . . . . . . . . . . . . . . . . . . . . frame
2.7.1. DATA Frames . . . . . . . . . . . . . . . . . . . . DataF
2.7.2. HEADERS+PRIORITY . . . . . . . . . . . . . . . . . HEADE
2.7.3. RST_STREAM . . . . . . . . . . . . . . . . . . . . RST_S
2.7.4. SETTINGS . . . . . . . . . . . . . . . . . . . . . SETTI
2.7.5. PUSH_PROMISE . . . . . . . . . . . . . . . . . . . PUSH_
2.7.6. PING . . . . . . . . . . . . . . . . . . . . . . . PING
2.7.7. GOAWAY . . . . . . . . . . . . . . . . . . . . . . GOAWA
2.7.8. HEADERS . . . . . . . . . . . . . . . . . . . . . . HEADE
2.7.9. WINDOW_UPDATE . . . . . . . . . . . . . . . . . . . WINDO
2.7.10. CREDENTIAL . . . . . . . . . . . . . . . . . . . . CREDE
3. HTTP Layering over SPDY . . . . . . . . . . . . . . . . . . HTTPL
3.1. Connection Management . . . . . . . . . . . . . . . . . ancho
3.1.1. Use of GOAWAY . . . . . . . . . . . . . . . . . . . ancho
3.2. HTTP Request/Response . . . . . . . . . . . . . . . . . ancho
3.2.1. Request . . . . . . . . . . . . . . . . . . . . . . ancho
3.2.2. Response . . . . . . . . . . . . . . . . . . . . . ancho
3.2.3. Authentication . . . . . . . . . . . . . . . . . . Authe
3.3. Server Push Transactions . . . . . . . . . . . . . . . ancho
3.3.1. Server implementation . . . . . . . . . . . . . . . ancho
3.3.2. Client implementation . . . . . . . . . . . . . . . ancho
Belshe & Peon Expires February 2, 2013 [Page 2]
Internet-Draft SPDY August 2012
4. WebSocket Layering over SPDY . . . . . . . . . . . . . . . WebSo
4.1. Connection Management . . . . . . . . . . . . . . . . . ancho
4.1.1. Opening Handshake . . . . . . . . . . . . . . . . . ancho
4.1.2. Closing Handshake . . . . . . . . . . . . . . . . . ancho
4.2. Bi-directional Communication . . . . . . . . . . . . . ancho
4.2.1. Frame mapping . . . . . . . . . . . . . . . . . . . ancho
5. Design Rationale and Notes . . . . . . . . . . . . . . . . ancho
5.1. Separation of Framing Layer and Application Layer . . . ancho
5.2. Error handling - Framing Layer . . . . . . . . . . . . ancho
5.3. One Connection Per Domain . . . . . . . . . . . . . . . ancho
5.4. Fixed vs Variable Length Fields . . . . . . . . . . . . ancho
5.5. Compression Context(s) . . . . . . . . . . . . . . . . ancho
5.6. Unidirectional streams . . . . . . . . . . . . . . . . ancho
5.7. Data Compression . . . . . . . . . . . . . . . . . . . ancho
5.8. Server Push . . . . . . . . . . . . . . . . . . . . . . ancho
6. Security Considerations . . . . . . . . . . . . . . . . . . ancho
6.1. Use of Same-origin constraints . . . . . . . . . . . . ancho
6.2. HTTP Headers and SPDY Headers . . . . . . . . . . . . . ancho
6.3. Cross-Protocol Attacks . . . . . . . . . . . . . . . . ancho
6.4. Server Push Implicit Headers . . . . . . . . . . . . . ancho
7. Privacy Considerations . . . . . . . . . . . . . . . . . . ancho
7.1. Long Lived Connections . . . . . . . . . . . . . . . . ancho
7.2. SETTINGS frame . . . . . . . . . . . . . . . . . . . . ancho
8. Sub-protocol negotiation . . . . . . . . . . . . . . . . . ancho
8.1. Supporting scheme negotiation using SETTINGS frame . . ancho
9. Incompatibilities with SPDY draft #3 . . . . . . . . . . . ancho
10. Requirements Notation . . . . . . . . . . . . . . . . . . . ancho
11. Acknowledgements . . . . . . . . . . . . . . . . . . . . . ancho
12. References . . . . . . . . . . . . . . . . . . . . . . . . ancho
12.1. Normative References . . . . . . . . . . . . . . . . . ancho
12.2. Informative References . . . . . . . . . . . . . . . . ancho
Appendix A. Changes . . . . . . . . . . . . . . . . . . . . . ancho
Belshe & Peon Expires February 2, 2013 [Page 3]
Internet-Draft SPDY August 2012
1. Overview
One of the bottlenecks of HTTP implementations is that HTTP relies on
multiple connections for concurrency. This causes several problems,
including additional round trips for connection setup, slow-start
delays, and connection rationing by the client, where it tries to
avoid opening too many connections to any single server. HTTP
pipelining helps some, but only achieves partial multiplexing. In
addition, pipelining has proven non-deployable in existing browsers
due to intermediary interference.
SPDY adds a framing layer for multiplexing multiple, concurrent
streams across a single TCP connection (or any reliable transport
stream). The framing layer is optimized for HTTP-like request-
response streams, such that applications which run over HTTP today
can work over SPDY with little or no change on behalf of the web
application writer.
The SPDY connection offers four improvements over HTTP:
Multiplexed requests: There is no limit to the number of requests
that can be issued concurrently over a single SPDY connection.
Prioritized requests: Clients can request certain resources to be
delivered first. This avoids the problem of congesting the
network channel with non-critical resources when a high-priority
request is pending.
Compressed headers: Clients today send a significant amount of
redundant data in the form of HTTP headers. Because a single web
page may require 50 or 100 subrequests, this data is significant.
Server pushed streams: Server Push enables content to be pushed
from servers to clients without a request.
SPDY attempts to preserve the existing semantics of HTTP. All
features such as cookies, ETags, Vary headers, Content-Encoding
negotiations, etc work as they do with HTTP; SPDY only replaces the
way the data is written to the network.
1.1. Document Organization
The SPDY Specification is split into two parts: a framing layer
(Section 2), which multiplexes a TCP connection into independent,
length-prefixed frames, and an HTTP layer (Section 3), which
specifies the mechanism for overlaying HTTP request/response pairs on
top of the framing layer. While some of the framing layer concepts
are isolated from the HTTP layer, building a generic framing layer
Belshe & Peon Expires February 2, 2013 [Page 4]
Internet-Draft SPDY August 2012
has not been a goal. The framing layer is tailored to the needs of
the HTTP protocol and server push.
1.2. Definitions
client: The endpoint initiating the SPDY connection.
connection: A transport-level connection between two endpoints.
endpoint: Either the client or server of a connection.
frame: A header-prefixed sequence of bytes sent over a SPDY
connection.
server: The endpoint which did not initiate the SPDY connection.
connection error: An error on the SPDY connection.
stream: A potentially bi-directional flow of bytes across a
virtual channel within a SPDY connection.
stream error: An error on an individual SPDY stream.
2. SPDY Framing Layer
2.1. Connection
The SPDY framing layer runs atop a reliable transport layer such as
TCP [RFC0793]. The client is the TCP connection initiator. SPDY
connections are persistent connections.
For best performance, it is expected that non-battery operated
clients will leave open connections until the user navigates away
from all web pages referencing the connection, or until the server
closes the connection. Servers are encouraged to leave connections
open for as long as possible, but can terminate idle connections if
necessary. When either endpoint closes the transport-level
connection, it MUST first send a GOAWAY (Section 2.7.7) frame so that
the endpoints can reliably determine if requests finished before the
close. It is expected that battery-operated clients may have more
involved heuristics as to when a connection should be closed.
2.2. Connection Header
Upon establishment of a TCP connection and determination that SPDY
will be used by both peers to communicate, each endpoint MUST send a
connection header as a final confirmation and to establish the
default parameters for the SPDY connection.
Belshe & Peon Expires February 2, 2013 [Page 5]
Internet-Draft SPDY August 2012
The client connection header is a sequence of 25 octets (in hex
notation)
464f4f202a20485454502f322e300d0a0d0a42410d0a0d0a
(the string "FOO * HTTP/2.0\r\n\r\nBA\r\n\r\n") followed by a
SETTINGS frame (Section 2.7.4). The client sends the client
connection header immediately upon receipt of a 101 Switching
Protocols response (indicating a successful upgrade), or after
receiving a TLS Finished message from the server. If starting an
SPDY connection with prior knowledge of server support for the
protocol, the client connection header is sent upon connection
establishment.
The client connection header is selected so that a large
proportion of HTTP/1.1 or HTTP/1.0 servers and intermediaries do
not attempt to process further frames. Note that this does not
address the concerns raised in [TALKING].
The server connection header consists of just a SETTINGS frame
(Section 2.7.4) that MUST be the first frame the server sends in the
SPDY connection.
To avoid unnecessary latency, clients are permitted to send
additional frames to the server immediately after sending the client
connection header, without waiting to receive the server connection
header. It is important to note, however, that the server connection
header SETTINGS frame might include parameters that necessarily alter
how a client is expected to communicate with the server. Upon
receiving the SETTINGS frame, the client is expected to honor any
parameters established.
Clients and servers MUST terminate the TCP connection if either peer
does not begin with a valid connection header. A GOAWAY frame
(Section 2.7.7) MAY be omitted if it is clear that the peer is not
using SPDY.
2.3. Framing
Once the SPDY connection is established, clients and servers can
begin exchanging frames.
2.3.1. Frame Header
SPDY frames share a common base format consisting of an 8-byte header
followed by 0 to 65535 bytes of data.
Belshe & Peon Expires February 2, 2013 [Page 6]
Internet-Draft SPDY August 2012
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length (16) | Type (8) | Flags (8) |
+-+-------------+---------------+-------------------------------+
|R| Stream Identifier (31) |
+-+-------------------------------------------------------------+
| Frame Data (0...) ...
+---------------------------------------------------------------+
Frame Header
The fields of the frame header are defined as:
Length: The length of the frame data expressed as an unsigned 16-bit
integer. The 8 bytes of the frame header are not included in this
value.
Type: The 8-bit type of the frame. The frame type determines how
the remainder of the frame header and data are interpreted.
Implementations MUST ignore unsupported and unrecognized frame
types.
Flags: An 8-bit field reserved for frame-type specific boolean
flags.
The least significant bit (0x1) - the FINAL bit - is defined for
all frame types as an indication that this frame is the last the
endpoint will send for the identified stream. Setting this flag
causes the stream to enter the half-closed state (Section 2.4.3).
Implementations MUST process the FINAL bit for all frames whose
stream identifier field is not 0x0. The FINAL bit MUST NOT be set
on frames that use a stream identifier of 0.
The remaining flags can be assigned semantics specific to the
indicated frame type. Flags that have no defined semantics for a
particular frame type MUST be ignored, and MUST be left unset (0)
when sending.
R: A reserved 1-bit field. The semantics of this bit are undefined
and the bit MUST remain unset (0) when sending and MUST be ignored
when receiving.
Stream Identifier: A 31-bit stream identifier (see Section 2.4.1).
A value 0 is reserved for frames that are associated with the
connection as a whole as opposed to an individual stream.
The structure and content of the remaining frame data is dependent
Belshe & Peon Expires February 2, 2013 [Page 7]
Internet-Draft SPDY August 2012
entirely on the frame type.
2.3.2. Frame Size
Implementations with limited resources might not be capable of
processing large frame sizes. Such implementations MAY choose to
place additional limits on the maximum frame size. However, all
implementations MUST be capable of receiving and processing frames
containing at least 8192 octets of data. [[anchor5: Ed. Question:
Does this minimum include the 8-byte header or just the frame data?]]
An implementation MUST terminate a stream immediately if it is unable
to process a frame due it's size. This is done by sending an
RST_STREAM frame (Section 2.7.3) containing the FRAME_TOO_LARGE error
code.
[[anchor6: : Need a way to signal the maximum frame size; no way to
RST_STREAM on non-stream-related frames.]]Issue 28 [1]
2.4. Streams
A "stream" is an independent, bi-directional sequence of frames
exchanged between the client and server within a SPDY connection.
Streams have several important characteristics:
o Streams can be established and used unilaterally or shared by
either the client or server.
o Streams can be rejected or cancelled by either endpoint.
o Multiple types of frames can be sent by either endpoint within a
single stream.
o The order in which frames are sent within a stream is significant.
Recipients are required to process frames in the order they are
received.
o Streams optionally carry a set of name-value header pairs that are
expressed within the headers block of HEADERS+PRIORITY, HEADERS,
or PUSH_PROMISE frames.
o A single SPDY connection can contain multiple concurrently active
streams, with either endpoint interleaving frames from multiple
streams.
Belshe & Peon Expires February 2, 2013 [Page 8]
Internet-Draft SPDY August 2012
2.4.1. Stream Creation
There is no coordination or shared action between the client and
server required to create a stream. Rather, new streams are
established by sending a frame whose stream identifier field
references a previously unused stream identifier.
All streams are identified by an unsigned 31-bit integer. Streams
initiated by a client use odd numbered stream identifiers; those
initiated by the server use even numbered stream identifiers. A
stream identifier of zero MUST NOT be used to establish a new stream.
The identifier of a newly established stream MUST be numerically
greater than all previously established streams from that endpoint
within the SPDY connection, unless the identifier has been reserved
using a PUSH_PROMISE (Section 2.7.5) frame. An endpoint that
receives an unexpected stream identifier MUST respond with a
connection error (Section 2.5.1) of type PROTOCOL_ERROR.
A peer can limit the total number of concurrently active streams
using the SETTINGS_MAX_CONCURRENT_STREAMS parameters within a
SETTINGS frame. The maximum concurrent streams setting is specific
to each endpoint and applies only to the peer. That is, clients
specify the maximum number of concurrent streams the server can
initiate, and servers specify the maximum number of concurrent
streams the client can initiate. Peer endpoints MUST NOT exceed this
limit. All concurrently active streams initiated by an endpoint,
including streams that are half-open (Section 2.4.3) in any
direction, count toward that endpoint's limit.
Stream identifiers cannot be reused within a connection. Long-lived
connections can cause an endpoint to exhaust the available range of
stream identifiers. A client that is unable to establish a new
stream identifier can establish a new connection for new streams.
Either endpoint can request the early termination of an unwanted
stream by sending an RST_STREAM frame (Section 2.5.2) with an error
code of either REFUSED_STREAM (if no frames have been processed) or
CANCEL (if at least one frame has been processed). Such termination
might not take effect immediately as the peer might have sent
additional frames on the stream prior to receiving the termination
request.
2.4.2. Stream priority
The endpoint establishing a new stream can assign a priority for the
stream. Priority is represented as an unsigned 31-bit integer. 0
represents the highest priority and 2-1 represents the lowest
Belshe & Peon Expires February 2, 2013 [Page 9]
Internet-Draft SPDY August 2012
priority.
The purpose of this value is to allow the initiating endpoint to
request that frames for the stream be processed with higher priority
relative to any other concurrently active streams. That is, if an
endpoint receives interleaved frames for multiple streams, the
endpoint ought to make a best-effort attempt at processing frames for
higher priority streams before processing those for lower priority
streams.
Explicitly setting the priority for a stream does not guarantee any
particular processing order for the stream relative to any other
stream. Nor is there is any mechanism provided by which the
initiator of a stream can force or require a receiving endpoint to
process frames from one stream before processing frames from another.
2.4.3. Stream half-close
When an endpoint sends a frame for a stream with the FINAL flag set,
the stream is considered to be half-closed for that endpoint.
Subsequent frames MUST NOT be sent by that endpoint for the half
closed stream for the remaining duration of the SPDY connection.
When both endpoints have sent frames with the FINAL flag set, the
stream is considered to be fully closed.
If an endpoint receives additional frames for a stream that was
previously half-closed by the sending peer, the recipient MUST
respond with a stream error (Section 2.5.2) of type STREAM_CLOSED.
An endpoint that has not yet half-closed a stream by sending the
FINAL flag can continue sending frames on the stream.
It is not necessary for an endpoint to half-close a stream for which
it has not sent any frames. This allows endpoints to use fully
unidirectional streams that do not require explicit action or
acknowledgement from the receiver.
2.4.4. Stream close
Streams can be terminated in the following ways:
Normal termination: Normal stream termination occurs when both
client and server have half-closed the stream by sending a frame
containing a FINAL flag (Section 2.3.1).
Belshe & Peon Expires February 2, 2013 [Page 10]
Internet-Draft SPDY August 2012
Half-close on unidirectional stream: A stream that only has frames
sent in one direction can be tentatively considered to be closed
once a frame containing a FINAL flag is sent. The active sender
on the stream MUST be prepared to receive frames after closing the
stream.
Abrupt termination: Either peer can send a RST_STREAM control frame
at any time to terminate an active stream. RST_STREAM contains an
error code to indicate the reason for termination. A RST_STREAM
indicates that the sender will transmit no further data on the
stream and that the receiver is advised to cease transmission on
it.
The sender of a RST_STREAM frame MUST allow for frames that have
already been sent by the peer prior to the RST_STREAM being
processed. If in-transit frames alter connection state, these
frames cannot be safely discarded. See Stream Error Handling
(Section 2.5.2) for more details.
TCP connection teardown: If the TCP connection is torn down while
un-closed streams exist, then the endpoint MUST assume that the
stream was abnormally interrupted and may be incomplete.
2.5. Error Handling
SPDY framing permits two classes of error:
o An error condition that renders the entire connection unusable is
a connection error.
o An error in an individual stream is a stream error.
2.5.1. Connection Error Handling
A connection error is any error which prevents further processing of
the framing layer or which corrupts any connection state.
An endpoint that encounters a connection error MUST first send a
GOAWAY (Section 2.7.7) frame with the stream identifier of the last
stream that it successfully received from its peer. The GOAWAY frame
includes an error code that indicates why the connection is
terminating. After sending the GOAWAY frame, the endpoint MUST close
the TCP connection.
It is possible that the GOAWAY will not be reliably received by the
receiving endpoint. In the event of a connection error, GOAWAY only
provides a best-effort attempt to communicate with the peer about why
the connection is being terminated.
Belshe & Peon Expires February 2, 2013 [Page 11]
Internet-Draft SPDY August 2012
An endpoint can end a connection at any time. In particular, an
endpoint MAY choose to treat a stream error as a connection error if
the error is recurrent. Endpoints SHOULD send a GOAWAY frame when
ending a connection, as long as circumstances permit it.
2.5.2. Stream Error Handling
A stream error is an error related to a specific stream identifier
that does not affect processing of other streams at the framing
layer.
An endpoint that detects a stream error sends a RST_STREAM
(Section 2.7.3) frame that contains the stream identifier of the
stream where the error occurred. The RST_STREAM frame includes an
error code that indicates the type of error.
A RST_STREAM is the last frame that an endpoint can send on a stream.
The peer that sends the RST_STREAM frame MUST be prepared to receive
any frames that were sent or enqueued for sending by the remote peer.
These frames can be ignored, except where they modify connection
state (such as the state maintained for header compression
(Section 2.6)).
Normally, an endpoint SHOULD NOT send more than one RST_STREAM frame
for any stream. However, an endpoint MAY send additional RST_STREAM
frames if it receives frames on a closed stream after more than a
round trip time. This behavior is permitted to deal with misbehaving
implementations.
An endpoint MUST NOT send a RST_STREAM in response to an RST_STREAM
frame, to avoid looping.
2.5.3. Error Codes
Error codes are 32-bit fields that are used in RST_STREAM and GOAWAY
frames to convey the reasons for the stream or connection error.
Error codes share a common code space. Some error codes only apply
to specific conditions and have no defined semantics in certain frame
types.
The following error codes are defined:
NO_ERROR (0): The associated condition is not as a result of an
error. For example, a GOAWAY might include this code to indicate
graceful shutdown of a connection.
Belshe & Peon Expires February 2, 2013 [Page 12]
Internet-Draft SPDY August 2012
PROTOCOL_ERROR (1): The endpoint detected an unspecific protocol
error. This error is for use when a more specific error code is
not available.
INTERNAL_ERROR (2): The endpoint encountered an unexpected internal
error.
FLOW_CONTROL_ERROR (3): The endpoint detected that its peer violated
the flow control protocol.
INVALID_STREAM (4): The endpoint received a frame for an inactive
stream.
STREAM_CLOSED (5): The endpoint received a frame after a stream was
half-closed.
FRAME_TOO_LARGE (6): The endpoint received a frame that was larger
than the maximum size that it supports.
REFUSED_STREAM (7): The endpoint is refusing the stream before
processing its payload.
CANCEL (8): Used by the creator of a stream to indicate that the
stream is no longer needed.
2.6. Name/Value Header Block
A Name/Value Header Block augments the streams or group of streams
identified by the HEADERS+PRIORITY (Section 2.7.2), HEADERS
(Section 2.7.8), or PUSH_PROMISE (Section 2.7.5) frame stream with
additional metadata.
At the group level, a map of token-index to key-pair is maintained
for each defined group. There is no persistent mapping from
stream-id to header-group, instead each HeaderBlock includes
reference to the HeaderGroup that will be used in this particular set
of metadata.
The HeaderBlock compressor (described later) is subject to the
following constraints:
TotalHeaderStorageSize : default(16k)
MaxHeaderGroups: default(1)
MaxValEntries: default(64)
It is expected that either party will set these to larger values
Belshe & Peon Expires February 2, 2013 [Page 13]
Internet-Draft SPDY August 2012
immediately upon connection establishment using the SETTINGS frame.
A stream with a HeaderBlock which declares that it is using
HeaderGroup 'G' would use the following algorithm to interpret its
meta-data.
def compute_headers(stream):
headers = {}
for index in stream_group[G]:
headers[lru_lookup[index].key] = lru_lookup[index].val)
for {key, value} in ephemereal_headers_from_HeaderBlock:
headers[key] = value
return headers
A smart implementation will be able to interpret a headers frame
without reconstructing the headers, and thus be able to represent and
interpret headers with less memory and CPU.
The Name/Value Header Block is found in the HEADERS+PRIORITY,
HEADERS, and PUSH_PROMISE control frames, and shares a common format:
0 1 2 3..N N+1..K
+--------+--------+--------+=====+ +=====+
| HG(8) | next-lru-seq-num| Ops | ... | Ops |
+--------+--------+--------+=====+ +=====+
Ops are of the form:
+--------+--------+=========+
| OpCode | NumOps | Op Args |
+--------+--------+=========+
HG: (Header Group) An 8 bit unsigned integer specifying the header
group for this set of headers.
Ops: A number of operations. Operations will be detailed below.
The Opcode field indicates the type of operation.
0x0 (reserved) -- this is not used and is reserved in case a
token-based delimiter is required in the future.
0x1 (Toggle) indicates that the data which follows will be an lru-
index. That lru-index, if present in the current header-group
will be removed from the header group. If it is not present in
the current header group, it will be added to the current header
group. This opcode thus affects what parts of the data stored in
the LRU are interpreted as being visible in the current set of
Belshe & Peon Expires February 2, 2013 [Page 14]
Internet-Draft SPDY August 2012
headers for whatever frame includes the HeaderBlock
0x1 (Clone) indicates that the data which follows will be a key-
index and a string literal. The key-index is used to refer to a
pre-existing key, and thus the operation results in the storing of
the pre-existing key and the new value. The key-value will be
appended to the LRU, and the index in the LRU added to the current
header group.
0x2 (KVSto) indicates that the data which follows will be two
string literals. The first such string represents a new key to be
stored, and the second such string represents a value. As with
Clone, the key-value will be stored in the LRU with a new index,
and that index will be added to the current header group.
0x2 (Eref) indicates that the data which follows will be two
string literals. The first such string represents key, and the
second string represents a value. Unlike KVSto, the Eref does not
modify the compressor state-- it only specified a key-value which
will be interpreted as being part of the meta-data for the frame
which includes the HeaderBlock.
String are always encoded as a single bit, followed by data. If that
bit is '0', then what follows is 7-bit us-ascii, null-terminated. If
that bit is '1', then it is huffman encoded using a canonical
huffman-code and ends with an 'eof' character (which is not part of
the string). If the last bit of the EOF is not immediately before
the byte boundary, the remaining bits of that byte are padded with
zero. Strings in a request are encoded with a different huffman-
encoder than strings in a response, as the frequency of occurance in
these differ by quite a bit.
A string is either:
+-|============================|====================|--------+
|1| huffman-encoded-characters | huffman-eof-symbol |pad-bits|
+-|============================|====================|--------+
or
+-|-------+========+--------+
|0| 7 bit-ascii |00000000|
+-|-------+========+--------+
The NumOps field encodes one minus the number of operations that
follow. Since the field-width is 8 bits, a maximum of 256 ops can be
represented. If more than 256 operations are required, simply repeat
doing this until all operations have been encoded. It is expected
that this will be extremely rare.
Belshe & Peon Expires February 2, 2013 [Page 15]
Internet-Draft SPDY August 2012
Detail of an operation with an opcode of 0x1 (Toggle):
0 1
+--------+--------+
|00000001| NumOps |
+--------+--------+
repeated NumOps times
______/ \______
/ \
+--------+--------+
| LRU idx(16) |
+--------+--------+
Detail of an operation with an opcode of 0x2 (Clone):
0 1
+--------+--------+
|00000010| NumOps |
+--------+--------+
repeated NumOps times
___________/\___________
/ \
+--------+--------+========+
| Key idx(16) | String |
+--------+--------+========+
Detail of an operation with an opcode of 0x3 (KVSto):
0 1
+--------+--------+
|00000011| NumOps |
+--------+--------+
repeated NumOps times
_______/\______
/ \
+========+========+
| String | String |
+========+========+
Belshe & Peon Expires February 2, 2013 [Page 16]
Internet-Draft SPDY August 2012
Detail of an operation with an opcode of 0x4 (Eref):
0 1
+--------+--------+
|00000100| NumOps |
+--------+--------+
repeated NumOps times
_______/\______
/ \
+========+========+
| String | String |
+========+========+
Each header name must have at least one value. Header names are
encoded using the US-ASCII character set [ASCII] and must be all
lower case. The length of each name must be greater than zero. A
recipient of a zero-length name MUST issue a stream error
(Section 2.5.2) with the status code PROTOCOL_ERROR for the
stream-id.
Duplicate header names are allowed, but discouraged, except when
encoding a cookie or set-cookie.
2.6.1. Compression
The Name/Value Header Block is a section of the HEADERS+PRIORITY,
HEADERS, and PUSH_PROMISE frames used to carry header meta-data.
This block is always compressed using zlib compression. Within this
specification, any reference to 'zlib' is referring to the ZLIB
Compressed Data Format Specification Version 3.3 as part of RFC1950.
[RFC1950]
For each HEADERS compression instance, the initial state is
initialized using the following dictionary [UDELCOMPRESSION]:
Request 1 (for index.html):
HEADERS+PRIORITY 1, stream-group (G)=0
Header-block:
Store(0x1): level(C),index(0),k: ":method"
Store(0x1): level(C),index(0),v: "GET"
Store(0x1): level(C),index(1),k: ":version"
Store(0x1): level(C),index(1),v: "HTTP/1.1"
Store(0x1): level(C),index(2),k: "user-agent"
Store(0x1): level(C),index(2),v: "blah blah browser version blah blah"
Store(0x1): level(C),index(3),k: "accept-encoding"
Belshe & Peon Expires February 2, 2013 [Page 17]
Internet-Draft SPDY August 2012
Store(0x1): level(C),index(3),v: "sdch, bzip, compress"
Store(0x1): level(G),index(0),k: ":host"
Store(0x1): level(G),index(0),v: "www.foo.com"
Store(0x1): level(G),index(1),k: "cookie"
Store(0x1): level(G),index(1),v: "SOMELONGSTRINGTHATISMOSTLYOPAQUE;BLAJHBLA"
Store(0x1): level(G),index(2),k: ":path"
Store(0x1): level(G),index(2),v: "/index.html"
Store(0x1): level(G),index(3),k: "date"
Store(0x1): level(G),index(3),v: "Wed Jul 18 11:50:43 2012"
At this point the connection headers table looks like this:
0: ":method", "GET"
1: ":version", "HTTP/1.1"
2: "user-agent", "blah blah browser version blah blah"
3: "accept-encoding", "sdch, bzip, compress"
The stream-group table for group zero looks like this:
0: ":host", "www.foo.com"
1: "cookie", "SOMELONGSTRINGHTATISMOSTLYOPAQUE;BLAJHBLA"
2: ":path", "/index.html"
3: "date", "Wed Jul 18 11:50:43 2012"
Request 1 (on stream 1) would look like the following if forwarded on HTTP/1.1:
GET /index.html HTTP/1.1
host: www.foo.com
date: Wed Jul 18 11:50:43 2012
cookie: SOMELONGSTRINGTHATISMOSTLYOPAQUE;BLAJHBLA
user-agent: blah blah browser version blah blah
accept-encoding: sdch, bzip, compress
Request 2 (for index.js):
HEADERS+PRIORITY 3, stream-group (G)=0
Header-block:
Store(0x1): level(G),index(2),v: "/index.js"
Store(0x1): level(G),index(3),v: "Wed Jul 18 11:50:44 2012"
At this point the connection headers table is unchanged:
0: ":method", "GET"
1: ":version", "HTTP/1.1"
2: "user-agent", "blah blah browser version blah blah"
3: "accept-encoding", "sdch, bzip, compress"
The stream-group table for group zero looks like this:
0: ":host", "www.foo.com"
1: "cookie", "SOMELONGSTRINGHTATISMOSTLYOPAQUE;BLAJHBLA"
2: ":path", "/index.js"
3: "date", "Wed Jul 18 11:50:44 2012"
Belshe & Peon Expires February 2, 2013 [Page 18]
Internet-Draft SPDY August 2012
Both the path and the date have changed.
Request 2 (on stream 3) would look like the following if forwarded on HTTP/1.1:
GET /index.js HTTP/1.1
host: www.foo.com
date: Wed Jul 18 11:50:44 2012
cookie: SOMELONGSTRINGTHATISMOSTLYOPAQUE;BLAJHBLA
user-agent: blah blah browser version blah blah
accept-encoding: sdch, bzip, compress
Request 3 (for index.css):
HEADERS+PRIORITY 5, stream-group (G)=0
Header-block:
Store(0x1): level(G),index(2),v: "/index.css"
Store(0x1): level(G),index(3),v: "Wed Jul 18 11:50:44 PDT 2012"
Connection level-headers are implied.
Stream-group level headers are implied.
For this example, using TaCo (truncate and concatenate) wasn't useful.
If the user, however, changes the cookie on the next request...
Request 3 (for somepage.html):
HEADERS+PRIORITY 5, stream-group (G)=0
Header-block:
Store(0x1): level(G),index(2),v: "/somepage.html"
TaCo(0x1): level(G),index(1),v,TruncTo(40),"FOOBLA"
At this point the connection headers table remains unchanged.
0: ":method", "GET"
1: ":version", "HTTP/1.1"
2: "user-agent", "blah blah browser version blah blah"
3: "accept-encoding", "sdch, bzip, compress"
The stream-group table for group zero looks like this:
0: ":host", "www.foo.com"
1: "cookie", "SOMELONGSTRINGHTATISMOSTLYOPAQUE;FOOBLA"
2: ":path", "/somepate.html"
Both the path and the date have changed.
Request 3 (on stream 5) would look like the following if forwarded on HTTP/1.1:
GET /somepage.html HTTP/1.1
host: www.foo.com
date: Wed Jul 18 11:50:44 2012
cookie: SOMELONGSTRINGTHATISMOSTLYOPAQUE;FOOBLA
user-agent: blah blah browser version blah blah
accept-encoding: sdch, bzip, compress
Belshe & Peon Expires February 2, 2013 [Page 19]
Internet-Draft SPDY August 2012
2.7. Frame Types
This specification defines a number of frame types, each identified
by a unique 8-bit type code. Each frame type serves a distinct
purpose either in the establishment and management of the connection
as a whole, or of individual streams.
The transmission of specific frame types can alter the state of a
connection. If endpoints fail to maintain a synchronized view of the
connection state, successful communication within the connection will
no longer be possible. Therefore, it is important that endpoints
have a shared comprehension of how the state is affected by the use
any given frame. Accordingly, while it is expected that new frame
types will be introduced by extensions to this protocol, only frames
defined by this document are permitted to alter the connection state.
2.7.1. DATA Frames
DATA frames (type=0x0) convey arbitrary, variable-length sequences of
octets associated with a stream. One or more DATA frames are used,
for instance, to carry HTTP request or response payloads.
The DATA frame defines the following flag:
MSG_DONE (0x2): Bit 2 being set signifies that this frame represents
the last frame of a message. This is relevant for layering of
message-based protocols on top of SPDY.
DATA frames MUST be associated with a stream. If a DATA frame is
received whose stream identifier field is 0x0, the recipient MUST
respond with a connection error (Section 2.5.1) of type
PROTOCOL_ERROR.
2.7.2. HEADERS+PRIORITY
The HEADERS+PRIORITY frame (type=0x1) allows the sender to set header
fields and stream priority at the same time.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|X| Priority (31) |
+-+-------------------------------------------------------------+
| Header Block (*) ...
+---------------------------------------------------------------+
HEADERS+PRIORITY Frame Payload
Belshe & Peon Expires February 2, 2013 [Page 20]
Internet-Draft SPDY August 2012
The HEADERS+PRIORITY frame is identical to the HEADERS frame
(Section 2.7.8), preceded by a single reserved bit and a 31-bit
priority; see Section 2.4.2.
HEADERS+PRIORITY uses the same flags as the HEADERS frame, except
that a HEADERS+PRIORITY frame with a CONTINUES bit MUST be followed
by another HEADERS+PRIORITY frame. See HEADERS frame (Section 2.7.8)
for any flags.
HEADERS+PRIORITY frames MUST be associated with a stream. If a
HEADERS+PRIORITY frame is received whose stream identifier field is
0x0, the recipient MUST respond with a connection error
(Section 2.5.1) of type PROTOCOL_ERROR.
The HEADERS+PRIORITY frame modifies the connection state as defined
in Section 2.6.
2.7.3. RST_STREAM
The RST_STREAM frame (type=0x3) allows for abnormal termination of a
stream. When sent by the initiator of a stream, it indicates that
they wish to cancel the stream. When sent by the receiver of a
stream, it indicates that either the receiver is rejecting the
stream, requesting that the stream be cancelled or that an error
condition has occurred.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Error Code (32) |
+---------------------------------------------------------------+
RST_STREAM Frame Payload
The RST_STREAM frame contains a single unsigned, 32-bit integer
identifying the error code (Section 2.5.3). The error code indicates
why the stream is being terminated.
No type-flags are defined.
The RST_STREAM frame fully terminates the referenced stream and
causes it to enter the closed state. After receiving a RST_STREAM on
a stream, the receiver MUST NOT send additional frames for that
stream. However, after sending the RST_STREAM, the sending endpoint
MUST be prepared to receive and process additional frames sent on the
stream that might have been sent by the peer prior to the arrival of
the RST_STREAM.
Belshe & Peon Expires February 2, 2013 [Page 21]
Internet-Draft SPDY August 2012
RST_STREAM frames MUST be associated with a stream. If a RST_STREAM
frame is received whose stream identifier field is 0x0 the recipient
MUST respond with a connection error (Section 2.5.1) of type
PROTOCOL_ERROR.
2.7.4. SETTINGS
The SETTINGS frame (type=0x4) conveys configuration parameters that
affect how endpoints communicate. The parameters are either
constraints on peer behavior or preferences.
SETTINGS frames MUST be sent at the start of a connection, and MAY be
sent at any other time by either endpoint over the lifetime of the
connection.
Implementations MUST support all of the settings defined by this
specification and MAY support additional settings defined by
extensions. Unsupported or unrecognized settings MUST be ignored.
New settings MUST NOT be defined or implemented in a way that
requires endpoints to understand them in order to communicate
successfully.
A SETTINGS frame is not required to include every defined setting;
senders can include only those parameters for which it has accurate
values and a need to convey. When multiple parameters are sent, they
SHOULD be sent in order of numerically lowest ID to highest ID. A
single SETTINGS frame MUST NOT contain multiple values for the same
ID. If the receiver of a SETTINGS frame discovers multiple values
for the same ID, it MUST ignore all values for that ID except the
first one.
Over the lifetime of a connection, an endpoint MAY send multiple
SETTINGS frames containing previously unspecified parameters or new
values for parameters whose values have already been established.
Only the most recent value provided setting value applies.
The SETTINGS frame defines the following flag:
CLEAR_PERSISTED (0x2): Bit 2 being set indicates a request to clear
any previously persisted settings before processing the settings.
Clients MUST NOT set this flag.
SETTINGS frames always apply to a connection, never a single stream.
The stream identifier for a settings frame MUST be zero. If an
endpoint receives a SETTINGS frame whose stream identifier field is
anything other than 0x0, the endpoint MUST respond with a connection
error (Section 2.5.1) of type PROTOCOL_ERROR.
Belshe & Peon Expires February 2, 2013 [Page 22]
Internet-Draft SPDY August 2012
2.7.4.1. Setting Format
The payload of a SETTINGS frame consists of zero or more settings.
Each setting consists of an 8-bit flags field specifying per-item
instructions, an unsigned 24-bit setting identifier, and an unsigned
32-bit value.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|SettingFlags(8)| Setting Identifier (24) |
+---------------+-----------------------------------------------+
| Value (32) |
+---------------------------------------------------------------+
Setting Format
Two flags are defined for the 8-bit flags field:
PERSIST_VALUE (0x1): Bit 1 (the least significant bit) being set
indicates a request from the server to the client to persist this
setting. A client MUST NOT set this flag.
PERSISTED (0x2): Bit 2 being set indicates that this setting is a
persisted setting being returned by the client to the server.
This also indicates that this setting is not a client setting, but
a value previously set by the server. A server MUST NOT set this
flag.
2.7.4.2. Setting Persistence
[[anchor10: Note that persistence of settings is under discussion in
the WG and might be removed in a future version of this document.]]
A server endpoint can request that configuration parameters sent to a
client in a SETTINGS frame are to be persisted by the client across
SPDY connections and returned to the server in any new SETTINGS frame
the client sends to the server in the current connection or any
future connections.
Persistence is requested on a per-setting basis by setting the
PERSIST_VALUE flag (0x1).
Client endpoints are not permitted to make such requests. Servers
MUST ignore any attempt by clients to request that a server persist
configuration parameters.
Persistence of configuration parameters is done on a per-origin basis
Belshe & Peon Expires February 2, 2013 [Page 23]
Internet-Draft SPDY August 2012
(see [RFC6454]). That is, when a client establishes a connection
with a server, and the server requests that the client maintain
persistent settings, the client SHOULD return the persisted settings
on all future connections to the same origin, IP address and TCP
port.
Whenever the client sends a SETTINGS frame in the current connection,
or establishes a new connection with the same origin, persisted
configuration parameters are sent with the PERSISTED flag (0x2) set
for each persisted parameter.
Persisted settings accumulate until the server requests that all
previously persisted settings are to be cleared by setting the
CLEAR_PERSISTED (0x2) flag on the SETTINGS frame.
For example, if the server sends IDs 1, 2, and 3 with the
FLAG_SETTINGS_PERSIST_VALUE in a first SETTINGS frame, and then sends
IDs 4 and 5 with the FLAG_SETTINGS_PERSIST_VALUE in a subsequent
SETTINGS frame, the client will return values for all 5 settings (1,
2, 3, 4, and 5 in this example) to the server.
2.7.4.3. Defined Settings
SETTINGS_UPLOAD_BANDWIDTH (1): indicates the sender's estimated
upload bandwidth for this connection. The value is an the
integral number of kilobytes per second that the sender predicts
as an expected maximum upload channel capacity.
SETTINGS_DOWNLOAD_BANDWIDTH (2): indicates the sender's estimated
download bandwidth for this connection. The value is an integral
number of kilobytes per second that the sender predicts as an
expected maximum download channel capacity.
SETTINGS_ROUND_TRIP_TIME (3): indicates the sender's estimated
round-trip-time for this connection. The round trip time is
defined as the minimum amount of time to send a control frame from
this client to the remote and receive a response. The value is
represented in milliseconds.
SETTINGS_MAX_CONCURRENT_STREAMS (4): indicates the maximum number of
concurrent streams that the sender will allow. This limit is
directional: it applies to the number of streams that the sender
permits the receiver to create. By default there is no limit. It
is recommended that this value be no smaller than 100, so as to
not unnecessarily limit parallelism.
Belshe & Peon Expires February 2, 2013 [Page 24]
Internet-Draft SPDY August 2012
SETTINGS_CURRENT_CWND (5): indicates the sender's current TCP CWND
value.
SETTINGS_DOWNLOAD_RETRANS_RATE (6): indicates the sender's
retransmission rate (bytes retransmitted / total bytes
transmitted).
SETTINGS_INITIAL_WINDOW_SIZE (7): indicates the sender's initial
stream window size (in bytes) for new streams.
SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE (8): indicates the sender's
(which should be the server) size of the client certificate
vector.
SETTINGS_SUPPORTING_SCHEMES (9): indicates the sender's supported
overlayering protocol schemes. The corresponding value must be a
32-bit value, and which contains flags as follows:
bit 0: http
bit 1: https
bit 2: ws
bit 3: wss
SETTINGS_FLOW_CONTROL_OPTIONS (10): indicates that streams directed
to the sender will not be subject to flow control. The least
significant bit (0x1) is set to indicate that new streams are not
flow controlled. All other bits are reserved. This setting
applies to all streams, including existing streams. These bits
cannot be cleared once set, see Section 2.7.9.4.
2.7.5. PUSH_PROMISE
The PUSH_PROMISE frame (type=0x5) is used to notify the peer endpoint
in advance of streams the sender intends to initiate. The
PUSH_PROMISE frame includes the unsigned 31-bit identifier of the
stream the endpoint plans to create along with a minimal set of
Html markup produced by rfcmarkup 1.90, available from
http://tools.ietf.org/tools/rfcmarkup/