Mercurial > hg > nginx
diff src/http/ngx_http_spdy.h @ 5121:c0f7b94e88ba
Preliminary experimental support for SPDY draft 2.
author | Valentin Bartenev <vbart@nginx.com> |
---|---|
date | Wed, 20 Mar 2013 10:36:57 +0000 |
parents | |
children | 15a7deeaa19a |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/src/http/ngx_http_spdy.h @@ -0,0 +1,235 @@ +/* + * Copyright (C) Nginx, Inc. + * Copyright (C) Valentin V. Bartenev + */ + + +#ifndef _NGX_HTTP_SPDY_H_INCLUDED_ +#define _NGX_HTTP_SPDY_H_INCLUDED_ + + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_http.h> + +#include <zlib.h> + + +#define NGX_SPDY_VERSION 2 + +#ifdef TLSEXT_TYPE_next_proto_neg +#define NGX_SPDY_NPN_ADVERTISE "\x06spdy/2" +#define NGX_SPDY_NPN_NEGOTIATED "spdy/2" +#endif + +#define NGX_SPDY_STATE_BUFFER_SIZE 16 + +#define NGX_SPDY_CTL_BIT 1 + +#define NGX_SPDY_SYN_STREAM 1 +#define NGX_SPDY_SYN_REPLY 2 +#define NGX_SPDY_RST_STREAM 3 +#define NGX_SPDY_SETTINGS 4 +#define NGX_SPDY_NOOP 5 +#define NGX_SPDY_PING 6 +#define NGX_SPDY_GOAWAY 7 +#define NGX_SPDY_HEADERS 8 + +#define NGX_SPDY_FRAME_HEADER_SIZE 8 + +#define NGX_SPDY_SID_SIZE 4 + +#define NGX_SPDY_SYN_STREAM_SIZE 10 +#define NGX_SPDY_SYN_REPLY_SIZE 6 +#define NGX_SPDY_RST_STREAM_SIZE 8 +#define NGX_SPDY_PING_SIZE 4 +#define NGX_SPDY_GOAWAY_SIZE 4 +#define NGX_SPDY_NV_NUM_SIZE 2 +#define NGX_SPDY_NV_NLEN_SIZE 2 +#define NGX_SPDY_NV_VLEN_SIZE 2 +#define NGX_SPDY_SETTINGS_NUM_SIZE 4 +#define NGX_SPDY_SETTINGS_IDF_SIZE 4 +#define NGX_SPDY_SETTINGS_VAL_SIZE 4 + +#define NGX_SPDY_SETTINGS_PAIR_SIZE \ + (NGX_SPDY_SETTINGS_IDF_SIZE + NGX_SPDY_SETTINGS_VAL_SIZE) + +#define NGX_SPDY_HIGHEST_PRIORITY 0 +#define NGX_SPDY_LOWEST_PRIORITY 3 + +#define NGX_SPDY_FLAG_FIN 0x01 +#define NGX_SPDY_FLAG_UNIDIRECTIONAL 0x02 +#define NGX_SPDY_FLAG_CLEAR_SETTINGS 0x01 + +#define NGX_SPDY_MAX_FRAME_SIZE ((1 << 24) - 1) + +#define NGX_SPDY_DATA_DISCARD 1 +#define NGX_SPDY_DATA_ERROR 2 +#define NGX_SPDY_DATA_INTERNAL_ERROR 3 + + +typedef struct ngx_http_spdy_connection_s ngx_http_spdy_connection_t; +typedef struct ngx_http_spdy_out_frame_s ngx_http_spdy_out_frame_t; + + +typedef u_char *(*ngx_http_spdy_handler_pt) (ngx_http_spdy_connection_t *sc, + u_char *pos, u_char *end); + +struct ngx_http_spdy_connection_s { + ngx_connection_t *connection; + ngx_http_connection_t *http_connection; + + ngx_uint_t processing; + + u_char buffer[NGX_SPDY_STATE_BUFFER_SIZE]; + size_t buffer_used; + ngx_http_spdy_handler_pt handler; + + z_stream zstream_in; + z_stream zstream_out; + + ngx_pool_t *pool; + + ngx_http_spdy_out_frame_t *free_ctl_frames; + ngx_connection_t *free_fake_connections; + + ngx_http_spdy_stream_t **streams_index; + + ngx_http_spdy_out_frame_t *last_out; + ngx_http_spdy_stream_t *last_stream; + + ngx_http_spdy_stream_t *stream; + + ngx_uint_t headers; + size_t length; + u_char flags; + + ngx_uint_t last_sid; + + unsigned blocked:2; + unsigned waiting:1; /* FIXME better name */ +}; + + +struct ngx_http_spdy_stream_s { + ngx_uint_t id; + ngx_http_request_t *request; + ngx_http_spdy_connection_t *connection; + ngx_http_spdy_stream_t *index; + ngx_http_spdy_stream_t *next; + + ngx_uint_t header_buffers; + ngx_uint_t waiting; + ngx_http_spdy_out_frame_t *free_frames; + ngx_chain_t *free_data_headers; + + unsigned priority:2; + unsigned handled:1; + unsigned in_closed:1; + unsigned out_closed:1; + unsigned skip_data:2; +}; + + +struct ngx_http_spdy_out_frame_s { + ngx_http_spdy_out_frame_t *next; + ngx_chain_t *first; + ngx_chain_t *last; + ngx_int_t (*handler)(ngx_http_spdy_connection_t *sc, + ngx_http_spdy_out_frame_t *frame); + + ngx_http_spdy_out_frame_t *free; + + ngx_http_spdy_stream_t *stream; + size_t size; + + ngx_uint_t priority; + unsigned blocked:1; + unsigned fin:1; +}; + + +static ngx_inline void +ngx_http_spdy_queue_frame(ngx_http_spdy_connection_t *sc, + ngx_http_spdy_out_frame_t *frame) +{ + ngx_http_spdy_out_frame_t **out; + + for (out = &sc->last_out; *out; out = &(*out)->next) + { + if (frame->priority >= (*out)->priority) { + break; + } + } + + frame->next = *out; + *out = frame; +} + + +static ngx_inline void +ngx_http_spdy_queue_blocked_frame(ngx_http_spdy_connection_t *sc, + ngx_http_spdy_out_frame_t *frame) +{ + ngx_http_spdy_out_frame_t **out; + + for (out = &sc->last_out; *out && !(*out)->blocked; out = &(*out)->next) + { + if (frame->priority >= (*out)->priority) { + break; + } + } + + frame->next = *out; + *out = frame; +} + + +void ngx_http_spdy_init(ngx_event_t *rev); +void ngx_http_spdy_request_headers_init(); + +ngx_int_t ngx_http_spdy_read_request_body(ngx_http_request_t *r, + ngx_http_client_body_handler_pt post_handler); + +void ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc); + +ngx_int_t ngx_http_spdy_send_output_queue(ngx_http_spdy_connection_t *sc); + + +#define ngx_spdy_frame_aligned_write_uint16(p, s) \ + (*(uint16_t *) (p) = htons((uint16_t) (s)), (p) + sizeof(uint16_t)) + +#define ngx_spdy_frame_aligned_write_uint32(p, s) \ + (*(uint32_t *) (p) = htonl((uint32_t) (s)), (p) + sizeof(uint32_t)) + +#if (NGX_HAVE_NONALIGNED) + +#define ngx_spdy_frame_write_uint16 ngx_spdy_frame_aligned_write_uint16 +#define ngx_spdy_frame_write_uint32 ngx_spdy_frame_aligned_write_uint32 + +#else + +#define ngx_spdy_frame_write_uint16(p, s) \ + ((p)[0] = (u_char) (s) >> 8, (p)[1] = (u_char) (s), (p) + sizeof(uint16_t)) + +#define ngx_spdy_frame_write_uint32(p, s) \ + ((p)[0] = (u_char) (s) >> 24, \ + (p)[1] = (u_char) (s) >> 16, \ + (p)[2] = (u_char) (s) >> 8, \ + (p)[3] = (u_char) (s), (p) + sizeof(uint32_t)) + +#endif + + +#define ngx_spdy_ctl_frame_head(t) \ + ((uint32_t) NGX_SPDY_CTL_BIT << 31 | NGX_SPDY_VERSION << 16 | (t)) + +#define ngx_spdy_frame_write_head(p, t) \ + ngx_spdy_frame_aligned_write_uint32(p, ngx_spdy_ctl_frame_head(t)) + +#define ngx_spdy_frame_write_flags_and_len(p, f, l) \ + ngx_spdy_frame_aligned_write_uint32(p, (f) << 24 | (l)) + +#define ngx_spdy_frame_write_sid ngx_spdy_frame_aligned_write_uint32 + +#endif /* _NGX_HTTP_SPDY_H_INCLUDED_ */