nginxtra 1.4.7.9 → 1.6.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/bin/nginxtra +1 -1
  3. data/bin/nginxtra_rails +1 -1
  4. data/lib/nginxtra/version.rb +1 -1
  5. data/vendor/nginx/CHANGES +286 -19
  6. data/vendor/nginx/CHANGES.ru +296 -22
  7. data/vendor/nginx/auto/cc/clang +4 -3
  8. data/vendor/nginx/auto/cc/conf +23 -0
  9. data/vendor/nginx/auto/cc/msvc +1 -0
  10. data/vendor/nginx/auto/cc/name +1 -1
  11. data/vendor/nginx/auto/cc/owc +4 -4
  12. data/vendor/nginx/auto/cc/sunc +1 -1
  13. data/vendor/nginx/auto/endianness +2 -2
  14. data/vendor/nginx/auto/feature +1 -1
  15. data/vendor/nginx/auto/include +1 -1
  16. data/vendor/nginx/auto/lib/libatomic/make +3 -1
  17. data/vendor/nginx/auto/lib/openssl/conf +4 -0
  18. data/vendor/nginx/auto/lib/openssl/make +1 -1
  19. data/vendor/nginx/auto/lib/pcre/conf +5 -0
  20. data/vendor/nginx/auto/lib/pcre/make +11 -11
  21. data/vendor/nginx/auto/lib/pcre/makefile.bcc +4 -3
  22. data/vendor/nginx/auto/lib/pcre/makefile.msvc +2 -1
  23. data/vendor/nginx/auto/lib/pcre/makefile.owc +2 -1
  24. data/vendor/nginx/auto/lib/perl/make +1 -0
  25. data/vendor/nginx/auto/lib/test +1 -1
  26. data/vendor/nginx/auto/lib/zlib/make +22 -1
  27. data/vendor/nginx/auto/modules +8 -0
  28. data/vendor/nginx/auto/options +3 -0
  29. data/vendor/nginx/auto/os/darwin +1 -1
  30. data/vendor/nginx/auto/os/linux +32 -0
  31. data/vendor/nginx/auto/os/win32 +12 -1
  32. data/vendor/nginx/auto/sources +8 -2
  33. data/vendor/nginx/auto/types/sizeof +1 -1
  34. data/vendor/nginx/auto/types/typedef +1 -1
  35. data/vendor/nginx/auto/types/uintptr_t +1 -1
  36. data/vendor/nginx/auto/unix +13 -1
  37. data/vendor/nginx/conf/mime.types +11 -2
  38. data/vendor/nginx/conf/nginx.conf +3 -4
  39. data/vendor/nginx/contrib/README +6 -0
  40. data/vendor/nginx/contrib/vim/ftdetect/nginx.vim +4 -0
  41. data/vendor/nginx/contrib/vim/indent/nginx.vim +11 -0
  42. data/vendor/nginx/contrib/vim/syntax/nginx.vim +703 -0
  43. data/vendor/nginx/src/core/nginx.c +2 -7
  44. data/vendor/nginx/src/core/nginx.h +2 -2
  45. data/vendor/nginx/src/core/ngx_conf_file.c +8 -88
  46. data/vendor/nginx/src/core/ngx_conf_file.h +3 -3
  47. data/vendor/nginx/src/core/ngx_config.h +2 -2
  48. data/vendor/nginx/src/core/ngx_connection.c +100 -29
  49. data/vendor/nginx/src/core/ngx_connection.h +11 -0
  50. data/vendor/nginx/src/core/ngx_core.h +1 -0
  51. data/vendor/nginx/src/core/ngx_cycle.c +23 -99
  52. data/vendor/nginx/src/core/ngx_cycle.h +2 -0
  53. data/vendor/nginx/src/core/ngx_file.c +100 -8
  54. data/vendor/nginx/src/core/ngx_file.h +3 -0
  55. data/vendor/nginx/src/core/ngx_hash.c +6 -9
  56. data/vendor/nginx/src/core/ngx_inet.c +93 -5
  57. data/vendor/nginx/src/core/ngx_inet.h +4 -2
  58. data/vendor/nginx/src/core/ngx_list.c +1 -9
  59. data/vendor/nginx/src/core/ngx_log.c +132 -30
  60. data/vendor/nginx/src/core/ngx_log.h +5 -2
  61. data/vendor/nginx/src/core/ngx_open_file_cache.c +67 -1
  62. data/vendor/nginx/src/core/ngx_palloc.c +5 -2
  63. data/vendor/nginx/src/core/ngx_proxy_protocol.c +91 -0
  64. data/vendor/nginx/src/core/ngx_proxy_protocol.h +23 -0
  65. data/vendor/nginx/src/core/ngx_resolver.c +1080 -285
  66. data/vendor/nginx/src/core/ngx_resolver.h +33 -3
  67. data/vendor/nginx/src/core/ngx_slab.c +7 -2
  68. data/vendor/nginx/src/core/ngx_slab.h +2 -0
  69. data/vendor/nginx/src/core/ngx_string.c +78 -13
  70. data/vendor/nginx/src/core/ngx_string.h +2 -0
  71. data/vendor/nginx/src/event/modules/ngx_devpoll_module.c +2 -2
  72. data/vendor/nginx/src/event/modules/ngx_epoll_module.c +13 -5
  73. data/vendor/nginx/src/event/modules/ngx_select_module.c +1 -1
  74. data/vendor/nginx/src/event/modules/ngx_win32_select_module.c +2 -2
  75. data/vendor/nginx/src/event/ngx_event.c +0 -1
  76. data/vendor/nginx/src/event/ngx_event.h +7 -6
  77. data/vendor/nginx/src/event/ngx_event_accept.c +6 -4
  78. data/vendor/nginx/src/event/ngx_event_connect.c +2 -2
  79. data/vendor/nginx/src/event/ngx_event_openssl.c +304 -13
  80. data/vendor/nginx/src/event/ngx_event_openssl.h +20 -1
  81. data/vendor/nginx/src/event/ngx_event_openssl_stapling.c +35 -23
  82. data/vendor/nginx/src/event/ngx_event_pipe.c +15 -30
  83. data/vendor/nginx/src/http/modules/ngx_http_access_module.c +115 -35
  84. data/vendor/nginx/src/http/modules/ngx_http_auth_basic_module.c +1 -1
  85. data/vendor/nginx/src/http/modules/ngx_http_auth_request_module.c +444 -0
  86. data/vendor/nginx/src/http/modules/ngx_http_autoindex_module.c +2 -1
  87. data/vendor/nginx/src/http/modules/ngx_http_charset_filter_module.c +1 -1
  88. data/vendor/nginx/src/http/modules/ngx_http_dav_module.c +1 -3
  89. data/vendor/nginx/src/http/modules/ngx_http_fastcgi_module.c +251 -36
  90. data/vendor/nginx/src/http/modules/ngx_http_gunzip_filter_module.c +9 -5
  91. data/vendor/nginx/src/http/modules/ngx_http_gzip_filter_module.c +5 -3
  92. data/vendor/nginx/src/http/modules/ngx_http_gzip_static_module.c +1 -1
  93. data/vendor/nginx/src/http/modules/ngx_http_headers_filter_module.c +4 -0
  94. data/vendor/nginx/src/http/modules/ngx_http_image_filter_module.c +8 -2
  95. data/vendor/nginx/src/http/modules/ngx_http_limit_req_module.c +5 -1
  96. data/vendor/nginx/src/http/modules/ngx_http_map_module.c +3 -3
  97. data/vendor/nginx/src/http/modules/ngx_http_memcached_module.c +21 -10
  98. data/vendor/nginx/src/http/modules/ngx_http_mp4_module.c +669 -197
  99. data/vendor/nginx/src/http/modules/ngx_http_proxy_module.c +93 -60
  100. data/vendor/nginx/src/http/modules/ngx_http_range_filter_module.c +13 -6
  101. data/vendor/nginx/src/http/modules/ngx_http_realip_module.c +20 -1
  102. data/vendor/nginx/src/http/modules/ngx_http_referer_module.c +132 -74
  103. data/vendor/nginx/src/http/modules/ngx_http_scgi_module.c +18 -12
  104. data/vendor/nginx/src/http/modules/ngx_http_ssi_filter_module.c +22 -20
  105. data/vendor/nginx/src/http/modules/ngx_http_ssl_module.c +121 -3
  106. data/vendor/nginx/src/http/modules/ngx_http_ssl_module.h +5 -0
  107. data/vendor/nginx/src/http/modules/ngx_http_stub_status_module.c +3 -0
  108. data/vendor/nginx/src/http/modules/ngx_http_sub_filter_module.c +123 -91
  109. data/vendor/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c +29 -19
  110. data/vendor/nginx/src/http/modules/ngx_http_upstream_keepalive_module.c +2 -5
  111. data/vendor/nginx/src/http/modules/ngx_http_uwsgi_module.c +215 -19
  112. data/vendor/nginx/src/http/modules/ngx_http_xslt_filter_module.c +32 -6
  113. data/vendor/nginx/src/http/modules/perl/nginx.xs +4 -7
  114. data/vendor/nginx/src/http/modules/perl/ngx_http_perl_module.c +2 -2
  115. data/vendor/nginx/src/http/ngx_http.c +17 -7
  116. data/vendor/nginx/src/http/ngx_http_cache.h +4 -2
  117. data/vendor/nginx/src/http/ngx_http_copy_filter_module.c +4 -2
  118. data/vendor/nginx/src/http/ngx_http_core_module.c +63 -50
  119. data/vendor/nginx/src/http/ngx_http_core_module.h +5 -0
  120. data/vendor/nginx/src/http/ngx_http_file_cache.c +115 -3
  121. data/vendor/nginx/src/http/ngx_http_header_filter_module.c +9 -6
  122. data/vendor/nginx/src/http/ngx_http_parse.c +88 -10
  123. data/vendor/nginx/src/http/ngx_http_postpone_filter_module.c +2 -4
  124. data/vendor/nginx/src/http/ngx_http_request.c +116 -8
  125. data/vendor/nginx/src/http/ngx_http_request.h +5 -1
  126. data/vendor/nginx/src/http/ngx_http_request_body.c +7 -7
  127. data/vendor/nginx/src/http/ngx_http_script.c +6 -5
  128. data/vendor/nginx/src/http/ngx_http_spdy.c +889 -271
  129. data/vendor/nginx/src/http/ngx_http_spdy.h +51 -28
  130. data/vendor/nginx/src/http/ngx_http_spdy_filter_module.c +382 -167
  131. data/vendor/nginx/src/http/ngx_http_spdy_module.c +65 -8
  132. data/vendor/nginx/src/http/ngx_http_spdy_module.h +5 -0
  133. data/vendor/nginx/src/http/ngx_http_special_response.c +1 -1
  134. data/vendor/nginx/src/http/ngx_http_upstream.c +290 -114
  135. data/vendor/nginx/src/http/ngx_http_upstream.h +9 -5
  136. data/vendor/nginx/src/http/ngx_http_upstream_round_robin.c +32 -24
  137. data/vendor/nginx/src/http/ngx_http_variables.c +40 -6
  138. data/vendor/nginx/src/http/ngx_http_write_filter_module.c +12 -5
  139. data/vendor/nginx/src/mail/ngx_mail.c +4 -2
  140. data/vendor/nginx/src/mail/ngx_mail.h +2 -0
  141. data/vendor/nginx/src/mail/ngx_mail_auth_http_module.c +0 -1
  142. data/vendor/nginx/src/mail/ngx_mail_core_module.c +2 -1
  143. data/vendor/nginx/src/mail/ngx_mail_handler.c +17 -4
  144. data/vendor/nginx/src/mail/ngx_mail_parse.c +32 -2
  145. data/vendor/nginx/src/mail/ngx_mail_proxy_module.c +54 -7
  146. data/vendor/nginx/src/mail/ngx_mail_smtp_handler.c +50 -78
  147. data/vendor/nginx/src/mail/ngx_mail_ssl_module.c +48 -11
  148. data/vendor/nginx/src/mail/ngx_mail_ssl_module.h +3 -0
  149. data/vendor/nginx/src/os/unix/ngx_channel.c +3 -1
  150. data/vendor/nginx/src/os/unix/ngx_darwin_config.h +1 -0
  151. data/vendor/nginx/src/os/unix/ngx_darwin_init.c +1 -1
  152. data/vendor/nginx/src/os/unix/ngx_darwin_sendfile_chain.c +14 -16
  153. data/vendor/nginx/src/os/unix/ngx_errno.h +3 -0
  154. data/vendor/nginx/src/os/unix/ngx_files.h +10 -16
  155. data/vendor/nginx/src/os/unix/ngx_freebsd_config.h +6 -0
  156. data/vendor/nginx/src/os/unix/ngx_freebsd_init.c +1 -1
  157. data/vendor/nginx/src/os/unix/ngx_freebsd_rfork_thread.c +1 -1
  158. data/vendor/nginx/src/os/unix/ngx_freebsd_rfork_thread.h +2 -2
  159. data/vendor/nginx/src/os/unix/ngx_freebsd_sendfile_chain.c +17 -19
  160. data/vendor/nginx/src/os/unix/ngx_linux_config.h +8 -2
  161. data/vendor/nginx/src/os/unix/ngx_linux_sendfile_chain.c +20 -22
  162. data/vendor/nginx/src/os/unix/ngx_posix_config.h +1 -0
  163. data/vendor/nginx/src/os/unix/ngx_process.c +5 -0
  164. data/vendor/nginx/src/os/unix/ngx_process_cycle.c +15 -3
  165. data/vendor/nginx/src/os/unix/ngx_readv_chain.c +2 -1
  166. data/vendor/nginx/src/os/unix/ngx_recv.c +4 -1
  167. data/vendor/nginx/src/os/unix/ngx_solaris_config.h +1 -0
  168. data/vendor/nginx/src/os/unix/ngx_solaris_sendfilev_chain.c +14 -16
  169. metadata +8 -2
@@ -309,8 +309,9 @@ typedef struct {
309
309
  ngx_int_t nfree;
310
310
 
311
311
  #if (NGX_HTTP_SSL)
312
- ngx_uint_t ssl; /* unsigned ssl:1; */
312
+ unsigned ssl:1;
313
313
  #endif
314
+ unsigned proxy_protocol:1;
314
315
  } ngx_http_connection_t;
315
316
 
316
317
 
@@ -420,6 +421,7 @@ struct ngx_http_request_s {
420
421
  #endif
421
422
 
422
423
  size_t limit_rate;
424
+ size_t limit_rate_after;
423
425
 
424
426
  /* used to learn the Apache compatible response length without a header */
425
427
  size_t header_size;
@@ -526,6 +528,7 @@ struct ngx_http_request_s {
526
528
  unsigned filter_need_in_memory:1;
527
529
  unsigned filter_need_temporary:1;
528
530
  unsigned allow_ranges:1;
531
+ unsigned single_range:1;
529
532
 
530
533
  #if (NGX_STAT_STUB)
531
534
  unsigned stat_reading:1;
@@ -584,6 +587,7 @@ extern ngx_http_header_out_t ngx_http_headers_out[];
584
587
  #define ngx_http_set_connection_log(c, l) \
585
588
  \
586
589
  c->log->file = l->file; \
590
+ c->log->next = l->next; \
587
591
  if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { \
588
592
  c->log->log_level = l->log_level; \
589
593
  }
@@ -43,7 +43,7 @@ ngx_http_read_client_request_body(ngx_http_request_t *r,
43
43
  r->main->count++;
44
44
 
45
45
  #if (NGX_HTTP_SPDY)
46
- if (r->spdy_stream) {
46
+ if (r->spdy_stream && r == r->main) {
47
47
  rc = ngx_http_spdy_read_request_body(r, post_handler);
48
48
  goto done;
49
49
  }
@@ -582,9 +582,9 @@ ngx_http_discarded_request_body_handler(ngx_http_request_t *r)
582
582
  }
583
583
 
584
584
  if (r->lingering_time) {
585
- timer = (ngx_msec_t) (r->lingering_time - ngx_time());
585
+ timer = (ngx_msec_t) r->lingering_time - (ngx_msec_t) ngx_time();
586
586
 
587
- if (timer <= 0) {
587
+ if ((ngx_msec_int_t) timer <= 0) {
588
588
  r->discard_body = 0;
589
589
  r->lingering_close = 0;
590
590
  ngx_http_finalize_request(r, NGX_ERROR);
@@ -726,7 +726,7 @@ ngx_http_discard_request_body_filter(ngx_http_request_t *r, ngx_buf_t *b)
726
726
  size = b->last - b->pos;
727
727
 
728
728
  if ((off_t) size > rb->chunked->size) {
729
- b->pos += rb->chunked->size;
729
+ b->pos += (size_t) rb->chunked->size;
730
730
  rb->chunked->size = 0;
731
731
 
732
732
  } else {
@@ -765,7 +765,7 @@ ngx_http_discard_request_body_filter(ngx_http_request_t *r, ngx_buf_t *b)
765
765
  size = b->last - b->pos;
766
766
 
767
767
  if ((off_t) size > r->headers_in.content_length_n) {
768
- b->pos += r->headers_in.content_length_n;
768
+ b->pos += (size_t) r->headers_in.content_length_n;
769
769
  r->headers_in.content_length_n = 0;
770
770
 
771
771
  } else {
@@ -882,7 +882,7 @@ ngx_http_request_body_length_filter(ngx_http_request_t *r, ngx_chain_t *in)
882
882
  rb->rest -= size;
883
883
 
884
884
  } else {
885
- cl->buf->pos += rb->rest;
885
+ cl->buf->pos += (size_t) rb->rest;
886
886
  rb->rest = 0;
887
887
  b->last = cl->buf->pos;
888
888
  b->last_buf = 1;
@@ -988,7 +988,7 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
988
988
  size = cl->buf->last - cl->buf->pos;
989
989
 
990
990
  if ((off_t) size > rb->chunked->size) {
991
- cl->buf->pos += rb->chunked->size;
991
+ cl->buf->pos += (size_t) rb->chunked->size;
992
992
  r->headers_in.content_length_n += rb->chunked->size;
993
993
  rb->chunked->size = 0;
994
994
 
@@ -1327,16 +1327,17 @@ ngx_http_script_full_name_code(ngx_http_script_engine_t *e)
1327
1327
  {
1328
1328
  ngx_http_script_full_name_code_t *code;
1329
1329
 
1330
- ngx_str_t value;
1330
+ ngx_str_t value, *prefix;
1331
1331
 
1332
1332
  code = (ngx_http_script_full_name_code_t *) e->ip;
1333
1333
 
1334
1334
  value.data = e->buf.data;
1335
1335
  value.len = e->pos - e->buf.data;
1336
1336
 
1337
- if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &value, code->conf_prefix)
1338
- != NGX_OK)
1339
- {
1337
+ prefix = code->conf_prefix ? (ngx_str_t *) &ngx_cycle->conf_prefix:
1338
+ (ngx_str_t *) &ngx_cycle->prefix;
1339
+
1340
+ if (ngx_get_full_name(e->request->pool, prefix, &value) != NGX_OK) {
1340
1341
  e->ip = ngx_http_script_exit;
1341
1342
  e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
1342
1343
  return;
@@ -1393,7 +1394,7 @@ ngx_http_script_if_code(ngx_http_script_engine_t *e)
1393
1394
 
1394
1395
  e->sp--;
1395
1396
 
1396
- if (e->sp->len && (e->sp->len !=1 || e->sp->data[0] != '0')) {
1397
+ if (e->sp->len && (e->sp->len != 1 || e->sp->data[0] != '0')) {
1397
1398
  if (code->loc_conf) {
1398
1399
  e->request->loc_conf = code->loc_conf;
1399
1400
  ngx_http_update_location_config(e->request);
@@ -42,16 +42,19 @@
42
42
 
43
43
  #define ngx_spdy_frame_parse_sid(p) \
44
44
  (ngx_spdy_frame_parse_uint32(p) & 0x7fffffff)
45
+ #define ngx_spdy_frame_parse_delta(p) \
46
+ (ngx_spdy_frame_parse_uint32(p) & 0x7fffffff)
45
47
 
46
48
 
47
49
  #define ngx_spdy_ctl_frame_check(h) \
48
- (((h) & 0xffffff00) == ngx_spdy_ctl_frame_head(0))
50
+ (((h) & 0xffff0000) == ngx_spdy_ctl_frame_head(0))
49
51
  #define ngx_spdy_data_frame_check(h) \
50
52
  (!((h) & (uint32_t) NGX_SPDY_CTL_BIT << 31))
51
53
 
52
- #define ngx_spdy_ctl_frame_type(h) ((h) & 0x000000ff)
54
+ #define ngx_spdy_ctl_frame_type(h) ((h) & 0x0000ffff)
53
55
  #define ngx_spdy_frame_flags(p) ((p) >> 24)
54
56
  #define ngx_spdy_frame_length(p) ((p) & 0x00ffffff)
57
+ #define ngx_spdy_frame_id(p) ((p) & 0x00ffffff)
55
58
 
56
59
 
57
60
  #define NGX_SPDY_SKIP_HEADERS_BUFFER_SIZE 4096
@@ -64,10 +67,21 @@
64
67
  #define NGX_SPDY_CANCEL 5
65
68
  #define NGX_SPDY_INTERNAL_ERROR 6
66
69
  #define NGX_SPDY_FLOW_CONTROL_ERROR 7
70
+ #define NGX_SPDY_STREAM_IN_USE 8
71
+ #define NGX_SPDY_STREAM_ALREADY_CLOSED 9
72
+ /* deprecated 10 */
73
+ #define NGX_SPDY_FRAME_TOO_LARGE 11
67
74
 
68
75
  #define NGX_SPDY_SETTINGS_MAX_STREAMS 4
76
+ #define NGX_SPDY_SETTINGS_INIT_WINDOW 7
69
77
 
70
78
  #define NGX_SPDY_SETTINGS_FLAG_PERSIST 0x01
79
+ #define NGX_SPDY_SETTINGS_FLAG_PERSISTED 0x02
80
+
81
+ #define NGX_SPDY_MAX_WINDOW NGX_MAX_INT32_VALUE
82
+ #define NGX_SPDY_CONNECTION_WINDOW 65536
83
+ #define NGX_SPDY_INIT_STREAM_WINDOW 65536
84
+ #define NGX_SPDY_STREAM_WINDOW NGX_SPDY_MAX_WINDOW
71
85
 
72
86
  typedef struct {
73
87
  ngx_uint_t hash;
@@ -81,8 +95,8 @@ static void ngx_http_spdy_read_handler(ngx_event_t *rev);
81
95
  static void ngx_http_spdy_write_handler(ngx_event_t *wev);
82
96
  static void ngx_http_spdy_handle_connection(ngx_http_spdy_connection_t *sc);
83
97
 
84
- static u_char *ngx_http_spdy_state_detect_settings(
85
- ngx_http_spdy_connection_t *sc, u_char *pos, u_char *end);
98
+ static u_char *ngx_http_spdy_proxy_protocol(ngx_http_spdy_connection_t *sc,
99
+ u_char *pos, u_char *end);
86
100
  static u_char *ngx_http_spdy_state_head(ngx_http_spdy_connection_t *sc,
87
101
  u_char *pos, u_char *end);
88
102
  static u_char *ngx_http_spdy_state_syn_stream(ngx_http_spdy_connection_t *sc,
@@ -93,8 +107,12 @@ static u_char *ngx_http_spdy_state_headers_error(ngx_http_spdy_connection_t *sc,
93
107
  u_char *pos, u_char *end);
94
108
  static u_char *ngx_http_spdy_state_headers_skip(ngx_http_spdy_connection_t *sc,
95
109
  u_char *pos, u_char *end);
110
+ static u_char *ngx_http_spdy_state_window_update(ngx_http_spdy_connection_t *sc,
111
+ u_char *pos, u_char *end);
96
112
  static u_char *ngx_http_spdy_state_data(ngx_http_spdy_connection_t *sc,
97
113
  u_char *pos, u_char *end);
114
+ static u_char *ngx_http_spdy_state_read_data(ngx_http_spdy_connection_t *sc,
115
+ u_char *pos, u_char *end);
98
116
  static u_char *ngx_http_spdy_state_rst_stream(ngx_http_spdy_connection_t *sc,
99
117
  u_char *pos, u_char *end);
100
118
  static u_char *ngx_http_spdy_state_ping(ngx_http_spdy_connection_t *sc,
@@ -103,8 +121,6 @@ static u_char *ngx_http_spdy_state_skip(ngx_http_spdy_connection_t *sc,
103
121
  u_char *pos, u_char *end);
104
122
  static u_char *ngx_http_spdy_state_settings(ngx_http_spdy_connection_t *sc,
105
123
  u_char *pos, u_char *end);
106
- static u_char *ngx_http_spdy_state_noop(ngx_http_spdy_connection_t *sc,
107
- u_char *pos, u_char *end);
108
124
  static u_char *ngx_http_spdy_state_complete(ngx_http_spdy_connection_t *sc,
109
125
  u_char *pos, u_char *end);
110
126
  static u_char *ngx_http_spdy_state_save(ngx_http_spdy_connection_t *sc,
@@ -114,6 +130,8 @@ static u_char *ngx_http_spdy_state_protocol_error(
114
130
  static u_char *ngx_http_spdy_state_internal_error(
115
131
  ngx_http_spdy_connection_t *sc);
116
132
 
133
+ static ngx_int_t ngx_http_spdy_send_window_update(
134
+ ngx_http_spdy_connection_t *sc, ngx_uint_t sid, ngx_uint_t delta);
117
135
  static ngx_int_t ngx_http_spdy_send_rst_stream(ngx_http_spdy_connection_t *sc,
118
136
  ngx_uint_t sid, ngx_uint_t status, ngx_uint_t priority);
119
137
  static ngx_int_t ngx_http_spdy_send_settings(ngx_http_spdy_connection_t *sc);
@@ -138,55 +156,220 @@ static ngx_int_t ngx_http_spdy_alloc_large_header_buffer(ngx_http_request_t *r);
138
156
  static ngx_int_t ngx_http_spdy_handle_request_header(ngx_http_request_t *r);
139
157
  static ngx_int_t ngx_http_spdy_parse_method(ngx_http_request_t *r);
140
158
  static ngx_int_t ngx_http_spdy_parse_scheme(ngx_http_request_t *r);
141
- static ngx_int_t ngx_http_spdy_parse_url(ngx_http_request_t *r);
159
+ static ngx_int_t ngx_http_spdy_parse_host(ngx_http_request_t *r);
160
+ static ngx_int_t ngx_http_spdy_parse_path(ngx_http_request_t *r);
142
161
  static ngx_int_t ngx_http_spdy_parse_version(ngx_http_request_t *r);
143
162
 
144
163
  static ngx_int_t ngx_http_spdy_construct_request_line(ngx_http_request_t *r);
145
164
  static void ngx_http_spdy_run_request(ngx_http_request_t *r);
146
165
  static ngx_int_t ngx_http_spdy_init_request_body(ngx_http_request_t *r);
147
166
 
167
+ static ngx_int_t ngx_http_spdy_terminate_stream(ngx_http_spdy_connection_t *sc,
168
+ ngx_http_spdy_stream_t *stream, ngx_uint_t status);
169
+
170
+ static void ngx_http_spdy_close_stream_handler(ngx_event_t *ev);
171
+
148
172
  static void ngx_http_spdy_handle_connection_handler(ngx_event_t *rev);
149
173
  static void ngx_http_spdy_keepalive_handler(ngx_event_t *rev);
150
174
  static void ngx_http_spdy_finalize_connection(ngx_http_spdy_connection_t *sc,
151
175
  ngx_int_t rc);
152
176
 
177
+ static ngx_int_t ngx_http_spdy_adjust_windows(ngx_http_spdy_connection_t *sc,
178
+ ssize_t delta);
179
+
153
180
  static void ngx_http_spdy_pool_cleanup(void *data);
154
181
 
155
182
  static void *ngx_http_spdy_zalloc(void *opaque, u_int items, u_int size);
156
183
  static void ngx_http_spdy_zfree(void *opaque, void *address);
157
184
 
158
185
 
159
- static const u_char ngx_http_spdy_dict[] =
160
- "options" "get" "head" "post" "put" "delete" "trace"
161
- "accept" "accept-charset" "accept-encoding" "accept-language"
162
- "authorization" "expect" "from" "host"
163
- "if-modified-since" "if-match" "if-none-match" "if-range"
164
- "if-unmodifiedsince" "max-forwards" "proxy-authorization"
165
- "range" "referer" "te" "user-agent"
166
- "100" "101" "200" "201" "202" "203" "204" "205" "206"
167
- "300" "301" "302" "303" "304" "305" "306" "307"
168
- "400" "401" "402" "403" "404" "405" "406" "407" "408" "409" "410"
169
- "411" "412" "413" "414" "415" "416" "417"
170
- "500" "501" "502" "503" "504" "505"
171
- "accept-ranges" "age" "etag" "location" "proxy-authenticate" "public"
172
- "retry-after" "server" "vary" "warning" "www-authenticate" "allow"
173
- "content-base" "content-encoding" "cache-control" "connection" "date"
174
- "trailer" "transfer-encoding" "upgrade" "via" "warning"
175
- "content-language" "content-length" "content-location"
176
- "content-md5" "content-range" "content-type" "etag" "expires"
177
- "last-modified" "set-cookie"
178
- "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday" "Sunday"
179
- "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"
180
- "chunked" "text/html" "image/png" "image/jpg" "image/gif"
181
- "application/xml" "application/xhtml" "text/plain" "public" "max-age"
182
- "charset=iso-8859-1" "utf-8" "gzip" "deflate" "HTTP/1.1" "status"
183
- "version" "url";
186
+ static const u_char ngx_http_spdy_dict[] = {
187
+ 0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, /* - - - - o p t i */
188
+ 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, /* o n s - - - - h */
189
+ 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, /* e a d - - - - p */
190
+ 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, /* o s t - - - - p */
191
+ 0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, /* u t - - - - d e */
192
+ 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, /* l e t e - - - - */
193
+ 0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, /* t r a c e - - - */
194
+ 0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, /* - a c c e p t - */
195
+ 0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, /* - - - a c c e p */
196
+ 0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, /* t - c h a r s e */
197
+ 0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, /* t - - - - a c c */
198
+ 0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, /* e p t - e n c o */
199
+ 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, /* d i n g - - - - */
200
+ 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, /* a c c e p t - l */
201
+ 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, /* a n g u a g e - */
202
+ 0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, /* - - - a c c e p */
203
+ 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, /* t - r a n g e s */
204
+ 0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, /* - - - - a g e - */
205
+ 0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, /* - - - a l l o w */
206
+ 0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, /* - - - - a u t h */
207
+ 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, /* o r i z a t i o */
208
+ 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, /* n - - - - c a c */
209
+ 0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, /* h e - c o n t r */
210
+ 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, /* o l - - - - c o */
211
+ 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, /* n n e c t i o n */
212
+ 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, /* - - - - c o n t */
213
+ 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, /* e n t - b a s e */
214
+ 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, /* - - - - c o n t */
215
+ 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, /* e n t - e n c o */
216
+ 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, /* d i n g - - - - */
217
+ 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, /* c o n t e n t - */
218
+ 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, /* l a n g u a g e */
219
+ 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, /* - - - - c o n t */
220
+ 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, /* e n t - l e n g */
221
+ 0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, /* t h - - - - c o */
222
+ 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, /* n t e n t - l o */
223
+ 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, /* c a t i o n - - */
224
+ 0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, /* - - c o n t e n */
225
+ 0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, /* t - m d 5 - - - */
226
+ 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, /* - c o n t e n t */
227
+ 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, /* - r a n g e - - */
228
+ 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, /* - - c o n t e n */
229
+ 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, /* t - t y p e - - */
230
+ 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, /* - - d a t e - - */
231
+ 0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, /* - - e t a g - - */
232
+ 0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, /* - - e x p e c t */
233
+ 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, /* - - - - e x p i */
234
+ 0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, /* r e s - - - - f */
235
+ 0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, /* r o m - - - - h */
236
+ 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, /* o s t - - - - i */
237
+ 0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, /* f - m a t c h - */
238
+ 0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, /* - - - i f - m o */
239
+ 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, /* d i f i e d - s */
240
+ 0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, /* i n c e - - - - */
241
+ 0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, /* i f - n o n e - */
242
+ 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, /* m a t c h - - - */
243
+ 0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, /* - i f - r a n g */
244
+ 0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, /* e - - - - i f - */
245
+ 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, /* u n m o d i f i */
246
+ 0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, /* e d - s i n c e */
247
+ 0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, /* - - - - l a s t */
248
+ 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, /* - m o d i f i e */
249
+ 0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, /* d - - - - l o c */
250
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, /* a t i o n - - - */
251
+ 0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, /* - m a x - f o r */
252
+ 0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, /* w a r d s - - - */
253
+ 0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, /* - p r a g m a - */
254
+ 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, /* - - - p r o x y */
255
+ 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, /* - a u t h e n t */
256
+ 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, /* i c a t e - - - */
257
+ 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, /* - p r o x y - a */
258
+ 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, /* u t h o r i z a */
259
+ 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, /* t i o n - - - - */
260
+ 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, /* r a n g e - - - */
261
+ 0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, /* - r e f e r e r */
262
+ 0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, /* - - - - r e t r */
263
+ 0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, /* y - a f t e r - */
264
+ 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, /* - - - s e r v e */
265
+ 0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, /* r - - - - t e - */
266
+ 0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, /* - - - t r a i l */
267
+ 0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, /* e r - - - - t r */
268
+ 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, /* a n s f e r - e */
269
+ 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, /* n c o d i n g - */
270
+ 0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, /* - - - u p g r a */
271
+ 0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, /* d e - - - - u s */
272
+ 0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, /* e r - a g e n t */
273
+ 0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, /* - - - - v a r y */
274
+ 0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, /* - - - - v i a - */
275
+ 0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, /* - - - w a r n i */
276
+ 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, /* n g - - - - w w */
277
+ 0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, /* w - a u t h e n */
278
+ 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, /* t i c a t e - - */
279
+ 0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, /* - - m e t h o d */
280
+ 0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, /* - - - - g e t - */
281
+ 0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, /* - - - s t a t u */
282
+ 0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, /* s - - - - 2 0 0 */
283
+ 0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, /* - O K - - - - v */
284
+ 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, /* e r s i o n - - */
285
+ 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, /* - - H T T P - 1 */
286
+ 0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, /* - 1 - - - - u r */
287
+ 0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, /* l - - - - p u b */
288
+ 0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, /* l i c - - - - s */
289
+ 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, /* e t - c o o k i */
290
+ 0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, /* e - - - - k e e */
291
+ 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, /* p - a l i v e - */
292
+ 0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, /* - - - o r i g i */
293
+ 0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, /* n 1 0 0 1 0 1 2 */
294
+ 0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, /* 0 1 2 0 2 2 0 5 */
295
+ 0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, /* 2 0 6 3 0 0 3 0 */
296
+ 0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, /* 2 3 0 3 3 0 4 3 */
297
+ 0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, /* 0 5 3 0 6 3 0 7 */
298
+ 0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, /* 4 0 2 4 0 5 4 0 */
299
+ 0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, /* 6 4 0 7 4 0 8 4 */
300
+ 0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, /* 0 9 4 1 0 4 1 1 */
301
+ 0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, /* 4 1 2 4 1 3 4 1 */
302
+ 0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, /* 4 4 1 5 4 1 6 4 */
303
+ 0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, /* 1 7 5 0 2 5 0 4 */
304
+ 0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, /* 5 0 5 2 0 3 - N */
305
+ 0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, /* o n - A u t h o */
306
+ 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, /* r i t a t i v e */
307
+ 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, /* - I n f o r m a */
308
+ 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, /* t i o n 2 0 4 - */
309
+ 0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, /* N o - C o n t e */
310
+ 0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, /* n t 3 0 1 - M o */
311
+ 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, /* v e d - P e r m */
312
+ 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, /* a n e n t l y 4 */
313
+ 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, /* 0 0 - B a d - R */
314
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, /* e q u e s t 4 0 */
315
+ 0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, /* 1 - U n a u t h */
316
+ 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, /* o r i z e d 4 0 */
317
+ 0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, /* 3 - F o r b i d */
318
+ 0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, /* d e n 4 0 4 - N */
319
+ 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, /* o t - F o u n d */
320
+ 0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, /* 5 0 0 - I n t e */
321
+ 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, /* r n a l - S e r */
322
+ 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, /* v e r - E r r o */
323
+ 0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, /* r 5 0 1 - N o t */
324
+ 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, /* - I m p l e m e */
325
+ 0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, /* n t e d 5 0 3 - */
326
+ 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, /* S e r v i c e - */
327
+ 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, /* U n a v a i l a */
328
+ 0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, /* b l e J a n - F */
329
+ 0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, /* e b - M a r - A */
330
+ 0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, /* p r - M a y - J */
331
+ 0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, /* u n - J u l - A */
332
+ 0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, /* u g - S e p t - */
333
+ 0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, /* O c t - N o v - */
334
+ 0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, /* D e c - 0 0 - 0 */
335
+ 0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, /* 0 - 0 0 - M o n */
336
+ 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, /* - - T u e - - W */
337
+ 0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, /* e d - - T h u - */
338
+ 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, /* - F r i - - S a */
339
+ 0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, /* t - - S u n - - */
340
+ 0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, /* G M T c h u n k */
341
+ 0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, /* e d - t e x t - */
342
+ 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, /* h t m l - i m a */
343
+ 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, /* g e - p n g - i */
344
+ 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, /* m a g e - j p g */
345
+ 0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, /* - i m a g e - g */
346
+ 0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, /* i f - a p p l i */
347
+ 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, /* c a t i o n - x */
348
+ 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, /* m l - a p p l i */
349
+ 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, /* c a t i o n - x */
350
+ 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, /* h t m l - x m l */
351
+ 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, /* - t e x t - p l */
352
+ 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, /* a i n - t e x t */
353
+ 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, /* - j a v a s c r */
354
+ 0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, /* i p t - p u b l */
355
+ 0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, /* i c p r i v a t */
356
+ 0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, /* e m a x - a g e */
357
+ 0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, /* - g z i p - d e */
358
+ 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, /* f l a t e - s d */
359
+ 0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, /* c h c h a r s e */
360
+ 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, /* t - u t f - 8 c */
361
+ 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, /* h a r s e t - i */
362
+ 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, /* s o - 8 8 5 9 - */
363
+ 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, /* 1 - u t f - - - */
364
+ 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e /* - e n q - 0 - */
365
+ };
184
366
 
185
367
 
186
368
  static ngx_http_spdy_request_header_t ngx_http_spdy_request_headers[] = {
187
369
  { 0, 6, "method", ngx_http_spdy_parse_method },
188
370
  { 0, 6, "scheme", ngx_http_spdy_parse_scheme },
189
- { 0, 3, "url", ngx_http_spdy_parse_url },
371
+ { 0, 4, "host", ngx_http_spdy_parse_host },
372
+ { 0, 4, "path", ngx_http_spdy_parse_path },
190
373
  { 0, 7, "version", ngx_http_spdy_parse_version },
191
374
  };
192
375
 
@@ -233,7 +416,17 @@ ngx_http_spdy_init(ngx_event_t *rev)
233
416
  sc->connection = c;
234
417
  sc->http_connection = hc;
235
418
 
236
- sc->handler = ngx_http_spdy_state_detect_settings;
419
+ sc->send_window = NGX_SPDY_CONNECTION_WINDOW;
420
+ sc->recv_window = NGX_SPDY_CONNECTION_WINDOW;
421
+
422
+ sc->init_window = NGX_SPDY_INIT_STREAM_WINDOW;
423
+
424
+ sc->handler = ngx_http_spdy_state_head;
425
+
426
+ if (hc->proxy_protocol) {
427
+ c->log->action = "reading PROXY protocol";
428
+ sc->handler = ngx_http_spdy_proxy_protocol;
429
+ }
237
430
 
238
431
  sc->zstream_in.zalloc = ngx_http_spdy_zalloc;
239
432
  sc->zstream_in.zfree = ngx_http_spdy_zfree;
@@ -295,6 +488,24 @@ ngx_http_spdy_init(ngx_event_t *rev)
295
488
  return;
296
489
  }
297
490
 
491
+ if (ngx_http_spdy_send_settings(sc) == NGX_ERROR) {
492
+ ngx_http_close_connection(c);
493
+ return;
494
+ }
495
+
496
+ if (ngx_http_spdy_send_window_update(sc, 0, NGX_SPDY_MAX_WINDOW
497
+ - sc->recv_window)
498
+ == NGX_ERROR)
499
+ {
500
+ ngx_http_close_connection(c);
501
+ return;
502
+ }
503
+
504
+ sc->recv_window = NGX_SPDY_MAX_WINDOW;
505
+
506
+ ngx_queue_init(&sc->waiting);
507
+ ngx_queue_init(&sc->posted);
508
+
298
509
  c->data = sc;
299
510
 
300
511
  rev->handler = ngx_http_spdy_read_handler;
@@ -344,7 +555,7 @@ ngx_http_spdy_read_handler(ngx_event_t *rev)
344
555
  break;
345
556
  }
346
557
 
347
- if (n == 0 && (sc->waiting || sc->processing)) {
558
+ if (n == 0 && (sc->incomplete || sc->processing)) {
348
559
  ngx_log_error(NGX_LOG_INFO, c->log, 0,
349
560
  "client closed prematurely connection");
350
561
  }
@@ -358,7 +569,7 @@ ngx_http_spdy_read_handler(ngx_event_t *rev)
358
569
  end += n;
359
570
 
360
571
  sc->buffer_used = 0;
361
- sc->waiting = 0;
572
+ sc->incomplete = 0;
362
573
 
363
574
  do {
364
575
  p = sc->handler(sc, p, end);
@@ -376,6 +587,11 @@ ngx_http_spdy_read_handler(ngx_event_t *rev)
376
587
  return;
377
588
  }
378
589
 
590
+ if (sc->last_out && ngx_http_spdy_send_output_queue(sc) == NGX_ERROR) {
591
+ ngx_http_spdy_finalize_connection(sc, NGX_HTTP_CLIENT_CLOSED_REQUEST);
592
+ return;
593
+ }
594
+
379
595
  sc->blocked = 0;
380
596
 
381
597
  if (sc->processing) {
@@ -393,8 +609,9 @@ static void
393
609
  ngx_http_spdy_write_handler(ngx_event_t *wev)
394
610
  {
395
611
  ngx_int_t rc;
612
+ ngx_queue_t *q;
396
613
  ngx_connection_t *c;
397
- ngx_http_spdy_stream_t *stream, *s, *sn;
614
+ ngx_http_spdy_stream_t *stream;
398
615
  ngx_http_spdy_connection_t *sc;
399
616
 
400
617
  c = wev->data;
@@ -409,7 +626,7 @@ ngx_http_spdy_write_handler(ngx_event_t *wev)
409
626
 
410
627
  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "spdy write handler");
411
628
 
412
- sc->blocked = 2;
629
+ sc->blocked = 1;
413
630
 
414
631
  rc = ngx_http_spdy_send_output_queue(sc);
415
632
 
@@ -418,20 +635,13 @@ ngx_http_spdy_write_handler(ngx_event_t *wev)
418
635
  return;
419
636
  }
420
637
 
421
- stream = NULL;
638
+ while (!ngx_queue_empty(&sc->posted)) {
639
+ q = ngx_queue_head(&sc->posted);
422
640
 
423
- for (s = sc->last_stream; s; s = sn) {
424
- sn = s->next;
425
- s->next = stream;
426
- stream = s;
427
- }
641
+ ngx_queue_remove(q);
428
642
 
429
- sc->last_stream = NULL;
643
+ stream = ngx_queue_data(q, ngx_http_spdy_stream_t, queue);
430
644
 
431
- sc->blocked = 1;
432
-
433
- for ( /* void */ ; stream; stream = sn) {
434
- sn = stream->next;
435
645
  stream->handled = 0;
436
646
 
437
647
  ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
@@ -484,9 +694,9 @@ ngx_http_spdy_send_output_queue(ngx_http_spdy_connection_t *sc)
484
694
  out = frame;
485
695
 
486
696
  ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0,
487
- "spdy frame out: %p sid:%ui prio:%ui bl:%ui size:%uz",
697
+ "spdy frame out: %p sid:%ui prio:%ui bl:%d len:%uz",
488
698
  out, out->stream ? out->stream->id : 0, out->priority,
489
- out->blocked, out->size);
699
+ out->blocked, out->length);
490
700
  }
491
701
 
492
702
  cl = c->send_chain(c, cl, 0);
@@ -517,7 +727,9 @@ ngx_http_spdy_send_output_queue(ngx_http_spdy_connection_t *sc)
517
727
  }
518
728
  }
519
729
 
520
- for ( /* void */ ; out; out = out->next) {
730
+ for ( /* void */ ; out; out = fn) {
731
+ fn = out->next;
732
+
521
733
  if (out->handler(sc, out) != NGX_OK) {
522
734
  out->blocked = 1;
523
735
  out->priority = NGX_SPDY_HIGHEST_PRIORITY;
@@ -525,9 +737,9 @@ ngx_http_spdy_send_output_queue(ngx_http_spdy_connection_t *sc)
525
737
  }
526
738
 
527
739
  ngx_log_debug4(NGX_LOG_DEBUG_HTTP, c->log, 0,
528
- "spdy frame sent: %p sid:%ui bl:%ui size:%uz",
740
+ "spdy frame sent: %p sid:%ui bl:%d len:%uz",
529
741
  out, out->stream ? out->stream->id : 0,
530
- out->blocked, out->size);
742
+ out->blocked, out->length);
531
743
  }
532
744
 
533
745
  frame = NULL;
@@ -567,7 +779,7 @@ ngx_http_spdy_handle_connection(ngx_http_spdy_connection_t *sc)
567
779
 
568
780
  sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx,
569
781
  ngx_http_spdy_module);
570
- if (sc->waiting) {
782
+ if (sc->incomplete) {
571
783
  ngx_add_timer(c->read, sscf->recv_timeout);
572
784
  return;
573
785
  }
@@ -605,34 +817,18 @@ ngx_http_spdy_handle_connection(ngx_http_spdy_connection_t *sc)
605
817
 
606
818
 
607
819
  static u_char *
608
- ngx_http_spdy_state_detect_settings(ngx_http_spdy_connection_t *sc,
609
- u_char *pos, u_char *end)
820
+ ngx_http_spdy_proxy_protocol(ngx_http_spdy_connection_t *sc, u_char *pos,
821
+ u_char *end)
610
822
  {
611
- if (end - pos < NGX_SPDY_FRAME_HEADER_SIZE) {
612
- return ngx_http_spdy_state_save(sc, pos, end,
613
- ngx_http_spdy_state_detect_settings);
614
- }
615
-
616
- /*
617
- * Since this is the first frame in a buffer,
618
- * then it is properly aligned
619
- */
620
-
621
- if (*(uint32_t *) pos == htonl(ngx_spdy_ctl_frame_head(NGX_SPDY_SETTINGS)))
622
- {
623
- sc->length = ngx_spdy_frame_length(htonl(((uint32_t *) pos)[1]));
624
-
625
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
626
- "spdy SETTINGS frame received, size: %uz", sc->length);
627
-
628
- pos += NGX_SPDY_FRAME_HEADER_SIZE;
823
+ pos = ngx_proxy_protocol_parse(sc->connection, pos, end);
629
824
 
630
- return ngx_http_spdy_state_settings(sc, pos, end);
825
+ if (pos == NULL) {
826
+ return ngx_http_spdy_state_protocol_error(sc);
631
827
  }
632
828
 
633
- ngx_http_spdy_send_settings(sc);
829
+ sc->connection->log->action = "processing SPDY";
634
830
 
635
- return ngx_http_spdy_state_head(sc, pos, end);
831
+ return ngx_http_spdy_state_complete(sc, pos, end);
636
832
  }
637
833
 
638
834
 
@@ -640,7 +836,8 @@ static u_char *
640
836
  ngx_http_spdy_state_head(ngx_http_spdy_connection_t *sc, u_char *pos,
641
837
  u_char *end)
642
838
  {
643
- uint32_t head, flen;
839
+ uint32_t head, flen;
840
+ ngx_uint_t type;
644
841
 
645
842
  if (end - pos < NGX_SPDY_FRAME_HEADER_SIZE) {
646
843
  return ngx_http_spdy_state_save(sc, pos, end,
@@ -659,11 +856,13 @@ ngx_http_spdy_state_head(ngx_http_spdy_connection_t *sc, u_char *pos,
659
856
  pos += sizeof(uint32_t);
660
857
 
661
858
  ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
662
- "spdy process frame head:%08Xd f:%ui l:%ui",
859
+ "spdy process frame head:%08XD f:%Xd l:%uz",
663
860
  head, sc->flags, sc->length);
664
861
 
665
862
  if (ngx_spdy_ctl_frame_check(head)) {
666
- switch (ngx_spdy_ctl_frame_type(head)) {
863
+ type = ngx_spdy_ctl_frame_type(head);
864
+
865
+ switch (type) {
667
866
 
668
867
  case NGX_SPDY_SYN_STREAM:
669
868
  return ngx_http_spdy_state_syn_stream(sc, pos, end);
@@ -675,10 +874,7 @@ ngx_http_spdy_state_head(ngx_http_spdy_connection_t *sc, u_char *pos,
675
874
  return ngx_http_spdy_state_rst_stream(sc, pos, end);
676
875
 
677
876
  case NGX_SPDY_SETTINGS:
678
- return ngx_http_spdy_state_skip(sc, pos, end);
679
-
680
- case NGX_SPDY_NOOP:
681
- return ngx_http_spdy_state_noop(sc, pos, end);
877
+ return ngx_http_spdy_state_settings(sc, pos, end);
682
878
 
683
879
  case NGX_SPDY_PING:
684
880
  return ngx_http_spdy_state_ping(sc, pos, end);
@@ -689,7 +885,12 @@ ngx_http_spdy_state_head(ngx_http_spdy_connection_t *sc, u_char *pos,
689
885
  case NGX_SPDY_HEADERS:
690
886
  return ngx_http_spdy_state_protocol_error(sc);
691
887
 
692
- default: /* TODO logging */
888
+ case NGX_SPDY_WINDOW_UPDATE:
889
+ return ngx_http_spdy_state_window_update(sc, pos, end);
890
+
891
+ default:
892
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
893
+ "spdy control frame with unknown type %ui", type);
693
894
  return ngx_http_spdy_state_skip(sc, pos, end);
694
895
  }
695
896
  }
@@ -729,7 +930,7 @@ ngx_http_spdy_state_syn_stream(ngx_http_spdy_connection_t *sc, u_char *pos,
729
930
  sc->length -= NGX_SPDY_SYN_STREAM_SIZE;
730
931
 
731
932
  sid = ngx_spdy_frame_parse_sid(pos);
732
- prio = pos[8] >> 6;
933
+ prio = pos[8] >> 5;
733
934
 
734
935
  pos += NGX_SPDY_SYN_STREAM_SIZE;
735
936
 
@@ -742,7 +943,7 @@ ngx_http_spdy_state_syn_stream(ngx_http_spdy_connection_t *sc, u_char *pos,
742
943
  if (sc->processing >= sscf->concurrent_streams) {
743
944
 
744
945
  ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
745
- "spdy concurrent streams excessed %ui", sc->processing);
946
+ "spdy concurrent streams exceeded %ui", sc->processing);
746
947
 
747
948
  if (ngx_http_spdy_send_rst_stream(sc, sid, NGX_SPDY_REFUSED_STREAM,
748
949
  prio)
@@ -809,6 +1010,8 @@ ngx_http_spdy_state_headers(ngx_http_spdy_connection_t *sc, u_char *pos,
809
1010
  sc->zstream_in.next_in = pos;
810
1011
  sc->zstream_in.avail_in = size;
811
1012
  sc->zstream_in.next_out = buf->last;
1013
+
1014
+ /* one byte is reserved for null-termination of the last header value */
812
1015
  sc->zstream_in.avail_out = buf->end - buf->last - 1;
813
1016
 
814
1017
  z = inflate(&sc->zstream_in, Z_NO_FLUSH);
@@ -851,18 +1054,28 @@ ngx_http_spdy_state_headers(ngx_http_spdy_connection_t *sc, u_char *pos,
851
1054
  if (r->headers_in.headers.part.elts == NULL) {
852
1055
 
853
1056
  if (buf->last - buf->pos < NGX_SPDY_NV_NUM_SIZE) {
1057
+
1058
+ if (complete) {
1059
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1060
+ "client sent SYN_STREAM frame "
1061
+ "with invalid HEADERS block");
1062
+ ngx_http_spdy_close_stream(sc->stream, NGX_HTTP_BAD_REQUEST);
1063
+ return ngx_http_spdy_state_protocol_error(sc);
1064
+ }
1065
+
854
1066
  return ngx_http_spdy_state_save(sc, pos, end,
855
1067
  ngx_http_spdy_state_headers);
856
1068
  }
857
1069
 
858
- sc->headers = ngx_spdy_frame_parse_uint16(buf->pos);
1070
+ sc->entries = ngx_spdy_frame_parse_uint32(buf->pos);
859
1071
 
860
1072
  buf->pos += NGX_SPDY_NV_NUM_SIZE;
861
1073
 
862
1074
  ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
863
- "spdy headers count: %ui", sc->headers);
1075
+ "spdy HEADERS block consists of %ui entries",
1076
+ sc->entries);
864
1077
 
865
- if (ngx_list_init(&r->headers_in.headers, r->pool, sc->headers + 3,
1078
+ if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
866
1079
  sizeof(ngx_table_elt_t))
867
1080
  != NGX_OK)
868
1081
  {
@@ -881,14 +1094,14 @@ ngx_http_spdy_state_headers(ngx_http_spdy_connection_t *sc, u_char *pos,
881
1094
  }
882
1095
  }
883
1096
 
884
- while (sc->headers) {
1097
+ while (sc->entries) {
885
1098
 
886
1099
  rc = ngx_http_spdy_parse_header(r);
887
1100
 
888
1101
  switch (rc) {
889
1102
 
890
1103
  case NGX_DONE:
891
- sc->headers--;
1104
+ sc->entries--;
892
1105
 
893
1106
  case NGX_OK:
894
1107
  break;
@@ -912,9 +1125,14 @@ ngx_http_spdy_state_headers(ngx_http_spdy_connection_t *sc, u_char *pos,
912
1125
  return ngx_http_spdy_state_headers_error(sc, pos, end);
913
1126
  }
914
1127
 
1128
+ /* null-terminate the last processed header name or value */
1129
+ *buf->pos = '\0';
1130
+
915
1131
  buf = r->header_in;
916
1132
 
917
1133
  sc->zstream_in.next_out = buf->last;
1134
+
1135
+ /* one byte is reserved for null-termination */
918
1136
  sc->zstream_in.avail_out = buf->end - buf->last - 1;
919
1137
 
920
1138
  z = inflate(&sc->zstream_in, Z_NO_FLUSH);
@@ -983,10 +1201,10 @@ ngx_http_spdy_state_headers(ngx_http_spdy_connection_t *sc, u_char *pos,
983
1201
  }
984
1202
  }
985
1203
 
986
- if (buf->pos != buf->last) {
987
- /* TODO: improve error message */
988
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
989
- "end %ui %p %p", complete, buf->pos, buf->last);
1204
+ if (buf->pos != buf->last || sc->zstream_in.avail_in) {
1205
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1206
+ "client sent SYN_STREAM frame "
1207
+ "with invalid HEADERS block");
990
1208
  ngx_http_spdy_close_stream(sc->stream, NGX_HTTP_BAD_REQUEST);
991
1209
  return ngx_http_spdy_state_protocol_error(sc);
992
1210
  }
@@ -996,6 +1214,9 @@ ngx_http_spdy_state_headers(ngx_http_spdy_connection_t *sc, u_char *pos,
996
1214
  ngx_http_spdy_state_headers);
997
1215
  }
998
1216
 
1217
+ /* null-terminate the last header value */
1218
+ *buf->pos = '\0';
1219
+
999
1220
  ngx_http_spdy_run_request(r);
1000
1221
 
1001
1222
  return ngx_http_spdy_state_complete(sc, pos, end);
@@ -1063,15 +1284,225 @@ ngx_http_spdy_state_headers_skip(ngx_http_spdy_connection_t *sc, u_char *pos,
1063
1284
  }
1064
1285
 
1065
1286
 
1287
+ static u_char *
1288
+ ngx_http_spdy_state_window_update(ngx_http_spdy_connection_t *sc, u_char *pos,
1289
+ u_char *end)
1290
+ {
1291
+ size_t delta;
1292
+ ngx_uint_t sid;
1293
+ ngx_event_t *wev;
1294
+ ngx_queue_t *q;
1295
+ ngx_http_spdy_stream_t *stream;
1296
+
1297
+ if (end - pos < NGX_SPDY_WINDOW_UPDATE_SIZE) {
1298
+ return ngx_http_spdy_state_save(sc, pos, end,
1299
+ ngx_http_spdy_state_window_update);
1300
+ }
1301
+
1302
+ if (sc->length != NGX_SPDY_WINDOW_UPDATE_SIZE) {
1303
+ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1304
+ "client sent WINDOW_UPDATE frame "
1305
+ "with incorrect length %uz", sc->length);
1306
+
1307
+ return ngx_http_spdy_state_protocol_error(sc);
1308
+ }
1309
+
1310
+ sid = ngx_spdy_frame_parse_sid(pos);
1311
+
1312
+ pos += NGX_SPDY_SID_SIZE;
1313
+
1314
+ delta = ngx_spdy_frame_parse_delta(pos);
1315
+
1316
+ pos += NGX_SPDY_DELTA_SIZE;
1317
+
1318
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1319
+ "spdy WINDOW_UPDATE sid:%ui delta:%ui", sid, delta);
1320
+
1321
+ if (sid) {
1322
+ stream = ngx_http_spdy_get_stream_by_id(sc, sid);
1323
+
1324
+ if (stream == NULL) {
1325
+ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1326
+ "client sent WINDOW_UPDATE frame "
1327
+ "for unknown stream %ui", sid);
1328
+
1329
+ if (ngx_http_spdy_send_rst_stream(sc, sid, NGX_SPDY_INVALID_STREAM,
1330
+ NGX_SPDY_LOWEST_PRIORITY)
1331
+ == NGX_ERROR)
1332
+ {
1333
+ return ngx_http_spdy_state_internal_error(sc);
1334
+ }
1335
+
1336
+ return ngx_http_spdy_state_complete(sc, pos, end);
1337
+ }
1338
+
1339
+ if (stream->send_window > (ssize_t) (NGX_SPDY_MAX_WINDOW - delta)) {
1340
+
1341
+ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1342
+ "client violated flow control for stream %ui: "
1343
+ "received WINDOW_UPDATE frame with delta %uz "
1344
+ "that is not allowed for window %z",
1345
+ sid, delta, stream->send_window);
1346
+
1347
+ if (ngx_http_spdy_terminate_stream(sc, stream,
1348
+ NGX_SPDY_FLOW_CONTROL_ERROR)
1349
+ == NGX_ERROR)
1350
+ {
1351
+ return ngx_http_spdy_state_internal_error(sc);
1352
+ }
1353
+
1354
+ return ngx_http_spdy_state_complete(sc, pos, end);
1355
+ }
1356
+
1357
+ stream->send_window += delta;
1358
+
1359
+ if (stream->exhausted) {
1360
+ stream->exhausted = 0;
1361
+
1362
+ wev = stream->request->connection->write;
1363
+
1364
+ if (!wev->timer_set) {
1365
+ wev->delayed = 0;
1366
+ wev->handler(wev);
1367
+ }
1368
+ }
1369
+
1370
+ } else {
1371
+ sc->send_window += delta;
1372
+
1373
+ if (sc->send_window > NGX_SPDY_MAX_WINDOW) {
1374
+ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1375
+ "client violated connection flow control: "
1376
+ "received WINDOW_UPDATE frame with delta %uz "
1377
+ "that is not allowed for window %uz",
1378
+ delta, sc->send_window);
1379
+
1380
+ return ngx_http_spdy_state_protocol_error(sc);
1381
+ }
1382
+
1383
+ while (!ngx_queue_empty(&sc->waiting)) {
1384
+ q = ngx_queue_head(&sc->waiting);
1385
+
1386
+ ngx_queue_remove(q);
1387
+
1388
+ stream = ngx_queue_data(q, ngx_http_spdy_stream_t, queue);
1389
+
1390
+ stream->handled = 0;
1391
+
1392
+ wev = stream->request->connection->write;
1393
+
1394
+ if (!wev->timer_set) {
1395
+ wev->delayed = 0;
1396
+ wev->handler(wev);
1397
+
1398
+ if (sc->send_window == 0) {
1399
+ break;
1400
+ }
1401
+ }
1402
+ }
1403
+ }
1404
+
1405
+ return ngx_http_spdy_state_complete(sc, pos, end);
1406
+ }
1407
+
1408
+
1066
1409
  static u_char *
1067
1410
  ngx_http_spdy_state_data(ngx_http_spdy_connection_t *sc, u_char *pos,
1068
1411
  u_char *end)
1412
+ {
1413
+ ngx_http_spdy_stream_t *stream;
1414
+
1415
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1416
+ "spdy DATA frame");
1417
+
1418
+ if (sc->length > sc->recv_window) {
1419
+ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1420
+ "client violated connection flow control: length of "
1421
+ "received DATA frame %uz, while available window %uz",
1422
+ sc->length, sc->recv_window);
1423
+
1424
+ return ngx_http_spdy_state_protocol_error(sc);
1425
+ }
1426
+
1427
+ sc->recv_window -= sc->length;
1428
+
1429
+ if (sc->recv_window < NGX_SPDY_MAX_WINDOW / 4) {
1430
+
1431
+ if (ngx_http_spdy_send_window_update(sc, 0,
1432
+ NGX_SPDY_MAX_WINDOW
1433
+ - sc->recv_window)
1434
+ == NGX_ERROR)
1435
+ {
1436
+ return ngx_http_spdy_state_internal_error(sc);
1437
+ }
1438
+
1439
+ sc->recv_window = NGX_SPDY_MAX_WINDOW;
1440
+ }
1441
+
1442
+ stream = sc->stream;
1443
+
1444
+ if (stream == NULL) {
1445
+ return ngx_http_spdy_state_skip(sc, pos, end);
1446
+ }
1447
+
1448
+ if (sc->length > stream->recv_window) {
1449
+ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1450
+ "client violated flow control for stream %ui: length of "
1451
+ "received DATA frame %uz, while available window %uz",
1452
+ stream->id, sc->length, stream->recv_window);
1453
+
1454
+ if (ngx_http_spdy_terminate_stream(sc, stream,
1455
+ NGX_SPDY_FLOW_CONTROL_ERROR)
1456
+ == NGX_ERROR)
1457
+ {
1458
+ return ngx_http_spdy_state_internal_error(sc);
1459
+ }
1460
+
1461
+ return ngx_http_spdy_state_skip(sc, pos, end);
1462
+ }
1463
+
1464
+ stream->recv_window -= sc->length;
1465
+
1466
+ if (stream->recv_window < NGX_SPDY_STREAM_WINDOW / 4) {
1467
+
1468
+ if (ngx_http_spdy_send_window_update(sc, stream->id,
1469
+ NGX_SPDY_STREAM_WINDOW
1470
+ - stream->recv_window)
1471
+ == NGX_ERROR)
1472
+ {
1473
+ return ngx_http_spdy_state_internal_error(sc);
1474
+ }
1475
+
1476
+ stream->recv_window = NGX_SPDY_STREAM_WINDOW;
1477
+ }
1478
+
1479
+ if (stream->in_closed) {
1480
+ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1481
+ "client sent DATA frame for half closed stream %ui",
1482
+ stream->id);
1483
+
1484
+ if (ngx_http_spdy_terminate_stream(sc, stream,
1485
+ NGX_SPDY_STREAM_ALREADY_CLOSED)
1486
+ == NGX_ERROR)
1487
+ {
1488
+ return ngx_http_spdy_state_internal_error(sc);
1489
+ }
1490
+
1491
+ return ngx_http_spdy_state_skip(sc, pos, end);
1492
+ }
1493
+
1494
+ return ngx_http_spdy_state_read_data(sc, pos, end);
1495
+ }
1496
+
1497
+
1498
+ static u_char *
1499
+ ngx_http_spdy_state_read_data(ngx_http_spdy_connection_t *sc, u_char *pos,
1500
+ u_char *end)
1069
1501
  {
1070
1502
  size_t size;
1071
1503
  ssize_t n;
1072
1504
  ngx_buf_t *buf;
1073
1505
  ngx_int_t rc;
1074
- ngx_uint_t complete;
1075
1506
  ngx_temp_file_t *tf;
1076
1507
  ngx_http_request_t *r;
1077
1508
  ngx_http_spdy_stream_t *stream;
@@ -1080,18 +1511,10 @@ ngx_http_spdy_state_data(ngx_http_spdy_connection_t *sc, u_char *pos,
1080
1511
 
1081
1512
  stream = sc->stream;
1082
1513
 
1083
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1084
- "spdy DATA frame");
1085
-
1086
1514
  if (stream == NULL) {
1087
1515
  return ngx_http_spdy_state_skip(sc, pos, end);
1088
1516
  }
1089
1517
 
1090
- if (stream->in_closed) {
1091
- /* TODO log */
1092
- return ngx_http_spdy_state_protocol_error(sc);
1093
- }
1094
-
1095
1518
  if (stream->skip_data) {
1096
1519
 
1097
1520
  if (sc->flags & NGX_SPDY_FLAG_FIN) {
@@ -1104,13 +1527,8 @@ ngx_http_spdy_state_data(ngx_http_spdy_connection_t *sc, u_char *pos,
1104
1527
 
1105
1528
  size = end - pos;
1106
1529
 
1107
- if (size >= sc->length) {
1530
+ if (size > sc->length) {
1108
1531
  size = sc->length;
1109
- complete = 1;
1110
-
1111
- } else {
1112
- sc->length -= size;
1113
- complete = 0;
1114
1532
  }
1115
1533
 
1116
1534
  r = stream->request;
@@ -1152,6 +1570,8 @@ ngx_http_spdy_state_data(ngx_http_spdy_connection_t *sc, u_char *pos,
1152
1570
  }
1153
1571
  }
1154
1572
 
1573
+ sc->length -= size;
1574
+
1155
1575
  if (tf) {
1156
1576
  buf->start = pos;
1157
1577
  buf->pos = pos;
@@ -1180,15 +1600,28 @@ ngx_http_spdy_state_data(ngx_http_spdy_connection_t *sc, u_char *pos,
1180
1600
  r->request_length += size;
1181
1601
  }
1182
1602
 
1183
- if (!complete) {
1603
+ if (sc->length) {
1184
1604
  return ngx_http_spdy_state_save(sc, pos, end,
1185
- ngx_http_spdy_state_data);
1605
+ ngx_http_spdy_state_read_data);
1186
1606
  }
1187
1607
 
1188
1608
  if (sc->flags & NGX_SPDY_FLAG_FIN) {
1189
1609
 
1190
1610
  stream->in_closed = 1;
1191
1611
 
1612
+ if (r->headers_in.content_length_n < 0) {
1613
+ r->headers_in.content_length_n = rb->rest;
1614
+
1615
+ } else if (r->headers_in.content_length_n != rb->rest) {
1616
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1617
+ "client prematurely closed stream: "
1618
+ "%O of %O bytes of request body received",
1619
+ rb->rest, r->headers_in.content_length_n);
1620
+
1621
+ stream->skip_data = NGX_SPDY_DATA_ERROR;
1622
+ goto error;
1623
+ }
1624
+
1192
1625
  if (tf) {
1193
1626
  ngx_memzero(buf, sizeof(ngx_buf_t));
1194
1627
 
@@ -1199,11 +1632,8 @@ ngx_http_spdy_state_data(ngx_http_spdy_connection_t *sc, u_char *pos,
1199
1632
  rb->buf = NULL;
1200
1633
  }
1201
1634
 
1202
- if (r->headers_in.content_length_n < 0) {
1203
- r->headers_in.content_length_n = rb->rest;
1204
- }
1205
-
1206
1635
  if (rb->post_handler) {
1636
+ r->read_event_handler = ngx_http_block_reading;
1207
1637
  rb->post_handler(r);
1208
1638
  }
1209
1639
  }
@@ -1237,7 +1667,6 @@ ngx_http_spdy_state_rst_stream(ngx_http_spdy_connection_t *sc, u_char *pos,
1237
1667
  ngx_uint_t sid, status;
1238
1668
  ngx_event_t *ev;
1239
1669
  ngx_connection_t *fc;
1240
- ngx_http_request_t *r;
1241
1670
  ngx_http_spdy_stream_t *stream;
1242
1671
 
1243
1672
  if (end - pos < NGX_SPDY_RST_STREAM_SIZE) {
@@ -1246,7 +1675,10 @@ ngx_http_spdy_state_rst_stream(ngx_http_spdy_connection_t *sc, u_char *pos,
1246
1675
  }
1247
1676
 
1248
1677
  if (sc->length != NGX_SPDY_RST_STREAM_SIZE) {
1249
- /* TODO logging */
1678
+ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1679
+ "client sent RST_STREAM frame with incorrect length %uz",
1680
+ sc->length);
1681
+
1250
1682
  return ngx_http_spdy_state_protocol_error(sc);
1251
1683
  }
1252
1684
 
@@ -1261,55 +1693,42 @@ ngx_http_spdy_state_rst_stream(ngx_http_spdy_connection_t *sc, u_char *pos,
1261
1693
  ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1262
1694
  "spdy RST_STREAM sid:%ui st:%ui", sid, status);
1263
1695
 
1696
+ stream = ngx_http_spdy_get_stream_by_id(sc, sid);
1697
+ if (stream == NULL) {
1698
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1699
+ "unknown stream, probably it has been closed already");
1700
+ return ngx_http_spdy_state_complete(sc, pos, end);
1701
+ }
1264
1702
 
1265
- switch (status) {
1703
+ stream->in_closed = 1;
1704
+ stream->out_closed = 1;
1266
1705
 
1267
- case NGX_SPDY_PROTOCOL_ERROR:
1268
- /* TODO logging */
1269
- return ngx_http_spdy_state_protocol_error(sc);
1706
+ fc = stream->request->connection;
1707
+ fc->error = 1;
1270
1708
 
1271
- case NGX_SPDY_INVALID_STREAM:
1272
- /* TODO */
1273
- break;
1709
+ switch (status) {
1274
1710
 
1275
- case NGX_SPDY_REFUSED_STREAM:
1276
- /* TODO */
1711
+ case NGX_SPDY_CANCEL:
1712
+ ngx_log_error(NGX_LOG_INFO, fc->log, 0,
1713
+ "client canceled stream %ui", sid);
1277
1714
  break;
1278
1715
 
1279
- case NGX_SPDY_UNSUPPORTED_VERSION:
1280
- /* TODO logging */
1281
- return ngx_http_spdy_state_protocol_error(sc);
1282
-
1283
- case NGX_SPDY_CANCEL:
1284
1716
  case NGX_SPDY_INTERNAL_ERROR:
1285
- stream = ngx_http_spdy_get_stream_by_id(sc, sid);
1286
- if (stream == NULL) {
1287
- /* TODO false cancel */
1288
- break;
1289
- }
1290
-
1291
- stream->in_closed = 1;
1292
- stream->out_closed = 1;
1293
-
1294
- r = stream->request;
1295
-
1296
- fc = r->connection;
1297
- fc->error = 1;
1298
-
1299
- ev = fc->read;
1300
- ev->handler(ev);
1301
-
1717
+ ngx_log_error(NGX_LOG_INFO, fc->log, 0,
1718
+ "client terminated stream %ui because of internal error",
1719
+ sid);
1302
1720
  break;
1303
1721
 
1304
- case NGX_SPDY_FLOW_CONTROL_ERROR:
1305
- /* TODO logging */
1306
- return ngx_http_spdy_state_protocol_error(sc);
1307
-
1308
1722
  default:
1309
- /* TODO */
1310
- return ngx_http_spdy_state_protocol_error(sc);
1723
+ ngx_log_error(NGX_LOG_INFO, fc->log, 0,
1724
+ "client terminated stream %ui with status %ui",
1725
+ sid, status);
1726
+ break;
1311
1727
  }
1312
1728
 
1729
+ ev = fc->read;
1730
+ ev->handler(ev);
1731
+
1313
1732
  return ngx_http_spdy_state_complete(sc, pos, end);
1314
1733
  }
1315
1734
 
@@ -1382,70 +1801,77 @@ static u_char *
1382
1801
  ngx_http_spdy_state_settings(ngx_http_spdy_connection_t *sc, u_char *pos,
1383
1802
  u_char *end)
1384
1803
  {
1385
- ngx_uint_t v;
1386
- ngx_http_spdy_srv_conf_t *sscf;
1804
+ ngx_uint_t fid, val;
1387
1805
 
1388
- if (sc->headers == 0) {
1806
+ if (sc->entries == 0) {
1389
1807
 
1390
1808
  if (end - pos < NGX_SPDY_SETTINGS_NUM_SIZE) {
1391
1809
  return ngx_http_spdy_state_save(sc, pos, end,
1392
1810
  ngx_http_spdy_state_settings);
1393
1811
  }
1394
1812
 
1395
- sc->headers = ngx_spdy_frame_parse_uint32(pos);
1813
+ sc->entries = ngx_spdy_frame_parse_uint32(pos);
1396
1814
 
1397
1815
  pos += NGX_SPDY_SETTINGS_NUM_SIZE;
1398
1816
  sc->length -= NGX_SPDY_SETTINGS_NUM_SIZE;
1399
1817
 
1400
- if (sc->length < sc->headers * NGX_SPDY_SETTINGS_PAIR_SIZE) {
1818
+ if (sc->length < sc->entries * NGX_SPDY_SETTINGS_PAIR_SIZE) {
1401
1819
  /* TODO logging */
1402
1820
  return ngx_http_spdy_state_protocol_error(sc);
1403
1821
  }
1404
1822
 
1405
1823
  ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1406
1824
  "spdy SETTINGS frame consists of %ui entries",
1407
- sc->headers);
1825
+ sc->entries);
1408
1826
  }
1409
1827
 
1410
- while (sc->headers) {
1828
+ while (sc->entries) {
1411
1829
  if (end - pos < NGX_SPDY_SETTINGS_PAIR_SIZE) {
1412
1830
  return ngx_http_spdy_state_save(sc, pos, end,
1413
1831
  ngx_http_spdy_state_settings);
1414
1832
  }
1415
1833
 
1416
- sc->headers--;
1834
+ sc->entries--;
1835
+ sc->length -= NGX_SPDY_SETTINGS_PAIR_SIZE;
1417
1836
 
1418
- if (pos[0] != NGX_SPDY_SETTINGS_MAX_STREAMS) {
1419
- pos += NGX_SPDY_SETTINGS_PAIR_SIZE;
1420
- sc->length -= NGX_SPDY_SETTINGS_PAIR_SIZE;
1421
- continue;
1422
- }
1837
+ fid = ngx_spdy_frame_parse_uint32(pos);
1838
+
1839
+ pos += NGX_SPDY_SETTINGS_FID_SIZE;
1840
+
1841
+ val = ngx_spdy_frame_parse_uint32(pos);
1423
1842
 
1424
- v = ngx_spdy_frame_parse_uint32(pos + NGX_SPDY_SETTINGS_IDF_SIZE);
1843
+ pos += NGX_SPDY_SETTINGS_VAL_SIZE;
1425
1844
 
1426
- sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx,
1427
- ngx_http_spdy_module);
1845
+ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1846
+ "spdy SETTINGS entry fl:%ui id:%ui val:%ui",
1847
+ ngx_spdy_frame_flags(fid), ngx_spdy_frame_id(fid), val);
1428
1848
 
1429
- if (v != sscf->concurrent_streams) {
1430
- ngx_http_spdy_send_settings(sc);
1849
+ if (ngx_spdy_frame_flags(fid) == NGX_SPDY_SETTINGS_FLAG_PERSISTED) {
1850
+ continue;
1431
1851
  }
1432
1852
 
1433
- return ngx_http_spdy_state_skip(sc, pos, end);
1434
- }
1853
+ switch (ngx_spdy_frame_id(fid)) {
1435
1854
 
1436
- ngx_http_spdy_send_settings(sc);
1855
+ case NGX_SPDY_SETTINGS_INIT_WINDOW:
1437
1856
 
1438
- return ngx_http_spdy_state_complete(sc, pos, end);
1439
- }
1857
+ if (val > NGX_SPDY_MAX_WINDOW) {
1858
+ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1859
+ "client sent SETTINGS frame with "
1860
+ "incorrect INIT_WINDOW value: %ui", val);
1861
+
1862
+ return ngx_http_spdy_state_protocol_error(sc);
1863
+ }
1440
1864
 
1865
+ if (ngx_http_spdy_adjust_windows(sc, val - sc->init_window)
1866
+ != NGX_OK)
1867
+ {
1868
+ return ngx_http_spdy_state_internal_error(sc);
1869
+ }
1441
1870
 
1442
- static u_char *
1443
- ngx_http_spdy_state_noop(ngx_http_spdy_connection_t *sc, u_char *pos,
1444
- u_char *end)
1445
- {
1446
- if (sc->length) {
1447
- /* TODO logging */
1448
- return ngx_http_spdy_state_protocol_error(sc);
1871
+ sc->init_window = val;
1872
+
1873
+ continue;
1874
+ }
1449
1875
  }
1450
1876
 
1451
1877
  return ngx_http_spdy_state_complete(sc, pos, end);
@@ -1465,20 +1891,22 @@ static u_char *
1465
1891
  ngx_http_spdy_state_save(ngx_http_spdy_connection_t *sc,
1466
1892
  u_char *pos, u_char *end, ngx_http_spdy_handler_pt handler)
1467
1893
  {
1468
- #if 1
1469
- if (end - pos > NGX_SPDY_STATE_BUFFER_SIZE) {
1894
+ size_t size;
1895
+
1896
+ size = end - pos;
1897
+
1898
+ if (size > NGX_SPDY_STATE_BUFFER_SIZE) {
1470
1899
  ngx_log_error(NGX_LOG_ALERT, sc->connection->log, 0,
1471
1900
  "spdy state buffer overflow: "
1472
- "%i bytes required", end - pos);
1901
+ "%uz bytes required", size);
1473
1902
  return ngx_http_spdy_state_internal_error(sc);
1474
1903
  }
1475
- #endif
1476
1904
 
1477
1905
  ngx_memcpy(sc->buffer, pos, NGX_SPDY_STATE_BUFFER_SIZE);
1478
1906
 
1479
- sc->buffer_used = end - pos;
1907
+ sc->buffer_used = size;
1480
1908
  sc->handler = handler;
1481
- sc->waiting = 1;
1909
+ sc->incomplete = 1;
1482
1910
 
1483
1911
  return end;
1484
1912
  }
@@ -1508,6 +1936,41 @@ ngx_http_spdy_state_internal_error(ngx_http_spdy_connection_t *sc)
1508
1936
  }
1509
1937
 
1510
1938
 
1939
+ static ngx_int_t
1940
+ ngx_http_spdy_send_window_update(ngx_http_spdy_connection_t *sc, ngx_uint_t sid,
1941
+ ngx_uint_t delta)
1942
+ {
1943
+ u_char *p;
1944
+ ngx_buf_t *buf;
1945
+ ngx_http_spdy_out_frame_t *frame;
1946
+
1947
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1948
+ "spdy write WINDOW_UPDATE sid:%ui delta:%ui", sid, delta);
1949
+
1950
+ frame = ngx_http_spdy_get_ctl_frame(sc, NGX_SPDY_WINDOW_UPDATE_SIZE,
1951
+ NGX_SPDY_HIGHEST_PRIORITY);
1952
+ if (frame == NULL) {
1953
+ return NGX_ERROR;
1954
+ }
1955
+
1956
+ buf = frame->first->buf;
1957
+
1958
+ p = buf->pos;
1959
+
1960
+ p = ngx_spdy_frame_write_head(p, NGX_SPDY_WINDOW_UPDATE);
1961
+ p = ngx_spdy_frame_write_flags_and_len(p, 0, NGX_SPDY_WINDOW_UPDATE_SIZE);
1962
+
1963
+ p = ngx_spdy_frame_write_sid(p, sid);
1964
+ p = ngx_spdy_frame_aligned_write_uint32(p, delta);
1965
+
1966
+ buf->last = p;
1967
+
1968
+ ngx_http_spdy_queue_frame(sc, frame);
1969
+
1970
+ return NGX_OK;
1971
+ }
1972
+
1973
+
1511
1974
  static ngx_int_t
1512
1975
  ngx_http_spdy_send_rst_stream(ngx_http_spdy_connection_t *sc, ngx_uint_t sid,
1513
1976
  ngx_uint_t status, ngx_uint_t priority)
@@ -1587,7 +2050,6 @@ ngx_http_spdy_send_settings(ngx_http_spdy_connection_t *sc)
1587
2050
  {
1588
2051
  u_char *p;
1589
2052
  ngx_buf_t *buf;
1590
- ngx_pool_t *pool;
1591
2053
  ngx_chain_t *cl;
1592
2054
  ngx_http_spdy_srv_conf_t *sscf;
1593
2055
  ngx_http_spdy_out_frame_t *frame;
@@ -1595,21 +2057,19 @@ ngx_http_spdy_send_settings(ngx_http_spdy_connection_t *sc)
1595
2057
  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1596
2058
  "spdy create SETTINGS frame");
1597
2059
 
1598
- pool = sc->connection->pool;
1599
-
1600
- frame = ngx_palloc(pool, sizeof(ngx_http_spdy_out_frame_t));
2060
+ frame = ngx_palloc(sc->pool, sizeof(ngx_http_spdy_out_frame_t));
1601
2061
  if (frame == NULL) {
1602
2062
  return NGX_ERROR;
1603
2063
  }
1604
2064
 
1605
- cl = ngx_alloc_chain_link(pool);
2065
+ cl = ngx_alloc_chain_link(sc->pool);
1606
2066
  if (cl == NULL) {
1607
2067
  return NGX_ERROR;
1608
2068
  }
1609
2069
 
1610
- buf = ngx_create_temp_buf(pool, NGX_SPDY_FRAME_HEADER_SIZE
1611
- + NGX_SPDY_SETTINGS_NUM_SIZE
1612
- + NGX_SPDY_SETTINGS_PAIR_SIZE);
2070
+ buf = ngx_create_temp_buf(sc->pool, NGX_SPDY_FRAME_HEADER_SIZE
2071
+ + NGX_SPDY_SETTINGS_NUM_SIZE
2072
+ + 2 * NGX_SPDY_SETTINGS_PAIR_SIZE);
1613
2073
  if (buf == NULL) {
1614
2074
  return NGX_ERROR;
1615
2075
  }
@@ -1622,11 +2082,10 @@ ngx_http_spdy_send_settings(ngx_http_spdy_connection_t *sc)
1622
2082
  frame->first = cl;
1623
2083
  frame->last = cl;
1624
2084
  frame->handler = ngx_http_spdy_settings_frame_handler;
1625
- #if (NGX_DEBUG)
1626
2085
  frame->stream = NULL;
1627
- frame->size = NGX_SPDY_FRAME_HEADER_SIZE
1628
- + NGX_SPDY_SETTINGS_NUM_SIZE
1629
- + NGX_SPDY_SETTINGS_PAIR_SIZE;
2086
+ #if (NGX_DEBUG)
2087
+ frame->length = NGX_SPDY_SETTINGS_NUM_SIZE
2088
+ + 2 * NGX_SPDY_SETTINGS_PAIR_SIZE;
1630
2089
  #endif
1631
2090
  frame->priority = NGX_SPDY_HIGHEST_PRIORITY;
1632
2091
  frame->blocked = 0;
@@ -1635,19 +2094,20 @@ ngx_http_spdy_send_settings(ngx_http_spdy_connection_t *sc)
1635
2094
 
1636
2095
  p = ngx_spdy_frame_write_head(p, NGX_SPDY_SETTINGS);
1637
2096
  p = ngx_spdy_frame_write_flags_and_len(p, NGX_SPDY_FLAG_CLEAR_SETTINGS,
1638
- NGX_SPDY_SETTINGS_NUM_SIZE
1639
- + NGX_SPDY_SETTINGS_PAIR_SIZE);
2097
+ NGX_SPDY_SETTINGS_NUM_SIZE
2098
+ + 2 * NGX_SPDY_SETTINGS_PAIR_SIZE);
1640
2099
 
1641
- p = ngx_spdy_frame_aligned_write_uint32(p, 1);
1642
- p = ngx_spdy_frame_aligned_write_uint32(p,
1643
- NGX_SPDY_SETTINGS_MAX_STREAMS << 24
1644
- | NGX_SPDY_SETTINGS_FLAG_PERSIST);
2100
+ p = ngx_spdy_frame_aligned_write_uint32(p, 2);
1645
2101
 
1646
2102
  sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx,
1647
2103
  ngx_http_spdy_module);
1648
2104
 
2105
+ p = ngx_spdy_frame_write_flags_and_id(p, 0, NGX_SPDY_SETTINGS_MAX_STREAMS);
1649
2106
  p = ngx_spdy_frame_aligned_write_uint32(p, sscf->concurrent_streams);
1650
2107
 
2108
+ p = ngx_spdy_frame_write_flags_and_id(p, 0, NGX_SPDY_SETTINGS_INIT_WINDOW);
2109
+ p = ngx_spdy_frame_aligned_write_uint32(p, NGX_SPDY_STREAM_WINDOW);
2110
+
1651
2111
  buf->last = p;
1652
2112
 
1653
2113
  ngx_http_spdy_queue_frame(sc, frame);
@@ -1675,7 +2135,7 @@ ngx_http_spdy_settings_frame_handler(ngx_http_spdy_connection_t *sc,
1675
2135
 
1676
2136
 
1677
2137
  static ngx_http_spdy_out_frame_t *
1678
- ngx_http_spdy_get_ctl_frame(ngx_http_spdy_connection_t *sc, size_t size,
2138
+ ngx_http_spdy_get_ctl_frame(ngx_http_spdy_connection_t *sc, size_t length,
1679
2139
  ngx_uint_t priority)
1680
2140
  {
1681
2141
  ngx_chain_t *cl;
@@ -1684,7 +2144,7 @@ ngx_http_spdy_get_ctl_frame(ngx_http_spdy_connection_t *sc, size_t size,
1684
2144
  frame = sc->free_ctl_frames;
1685
2145
 
1686
2146
  if (frame) {
1687
- sc->free_ctl_frames = frame->free;
2147
+ sc->free_ctl_frames = frame->next;
1688
2148
 
1689
2149
  cl = frame->first;
1690
2150
  cl->buf->pos = cl->buf->start;
@@ -1711,19 +2171,17 @@ ngx_http_spdy_get_ctl_frame(ngx_http_spdy_connection_t *sc, size_t size,
1711
2171
  frame->first = cl;
1712
2172
  frame->last = cl;
1713
2173
  frame->handler = ngx_http_spdy_ctl_frame_handler;
2174
+ frame->stream = NULL;
1714
2175
  }
1715
2176
 
1716
- frame->free = NULL;
1717
-
1718
2177
  #if (NGX_DEBUG)
1719
- if (size > NGX_SPDY_CTL_FRAME_BUFFER_SIZE - NGX_SPDY_FRAME_HEADER_SIZE) {
2178
+ if (length > NGX_SPDY_CTL_FRAME_BUFFER_SIZE - NGX_SPDY_FRAME_HEADER_SIZE) {
1720
2179
  ngx_log_error(NGX_LOG_ALERT, sc->pool->log, 0,
1721
- "requested control frame is too big: %z", size);
2180
+ "requested control frame is too big: %uz", length);
1722
2181
  return NULL;
1723
2182
  }
1724
2183
 
1725
- frame->stream = NULL;
1726
- frame->size = size;
2184
+ frame->length = length;
1727
2185
  #endif
1728
2186
 
1729
2187
  frame->priority = priority;
@@ -1745,7 +2203,7 @@ ngx_http_spdy_ctl_frame_handler(ngx_http_spdy_connection_t *sc,
1745
2203
  return NGX_AGAIN;
1746
2204
  }
1747
2205
 
1748
- frame->free = sc->free_ctl_frames;
2206
+ frame->next = sc->free_ctl_frames;
1749
2207
  sc->free_ctl_frames = frame;
1750
2208
 
1751
2209
  return NGX_OK;
@@ -1814,7 +2272,7 @@ ngx_http_spdy_create_stream(ngx_http_spdy_connection_t *sc, ngx_uint_t id,
1814
2272
 
1815
2273
  rev->data = fc;
1816
2274
  rev->ready = 1;
1817
- rev->handler = ngx_http_empty_handler;
2275
+ rev->handler = ngx_http_spdy_close_stream_handler;
1818
2276
  rev->log = log;
1819
2277
 
1820
2278
  ngx_memcpy(wev, rev, sizeof(ngx_event_t));
@@ -1864,6 +2322,10 @@ ngx_http_spdy_create_stream(ngx_http_spdy_connection_t *sc, ngx_uint_t id,
1864
2322
  stream->id = id;
1865
2323
  stream->request = r;
1866
2324
  stream->connection = sc;
2325
+
2326
+ stream->send_window = sc->init_window;
2327
+ stream->recv_window = NGX_SPDY_STREAM_WINDOW;
2328
+
1867
2329
  stream->priority = priority;
1868
2330
 
1869
2331
  sscf = ngx_http_get_module_srv_conf(r, ngx_http_spdy_module);
@@ -1907,7 +2369,7 @@ static ngx_int_t
1907
2369
  ngx_http_spdy_parse_header(ngx_http_request_t *r)
1908
2370
  {
1909
2371
  u_char *p, *end, ch;
1910
- ngx_uint_t len, hash;
2372
+ ngx_uint_t hash;
1911
2373
  ngx_http_core_srv_conf_t *cscf;
1912
2374
 
1913
2375
  enum {
@@ -1930,16 +2392,17 @@ ngx_http_spdy_parse_header(ngx_http_request_t *r)
1930
2392
  return NGX_AGAIN;
1931
2393
  }
1932
2394
 
1933
- len = ngx_spdy_frame_parse_uint16(p);
2395
+ r->lowcase_index = ngx_spdy_frame_parse_uint32(p);
1934
2396
 
1935
- if (!len) {
2397
+ if (r->lowcase_index == 0) {
1936
2398
  return NGX_HTTP_PARSE_INVALID_HEADER;
1937
2399
  }
1938
2400
 
2401
+ /* null-terminate the previous header value */
2402
+ *p = '\0';
2403
+
1939
2404
  p += NGX_SPDY_NV_NLEN_SIZE;
1940
2405
 
1941
- r->header_name_end = p + len;
1942
- r->lowcase_index = len;
1943
2406
  r->invalid_header = 0;
1944
2407
 
1945
2408
  state = sw_name;
@@ -1948,13 +2411,18 @@ ngx_http_spdy_parse_header(ngx_http_request_t *r)
1948
2411
 
1949
2412
  case sw_name:
1950
2413
 
1951
- if (r->header_name_end > end) {
2414
+ if ((ngx_uint_t) (end - p) < r->lowcase_index) {
1952
2415
  break;
1953
2416
  }
1954
2417
 
1955
2418
  cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1956
2419
 
1957
2420
  r->header_name_start = p;
2421
+ r->header_name_end = p + r->lowcase_index;
2422
+
2423
+ if (p[0] == ':') {
2424
+ p++;
2425
+ }
1958
2426
 
1959
2427
  hash = 0;
1960
2428
 
@@ -1999,30 +2467,26 @@ ngx_http_spdy_parse_header(ngx_http_request_t *r)
1999
2467
  break;
2000
2468
  }
2001
2469
 
2002
- len = ngx_spdy_frame_parse_uint16(p);
2470
+ r->lowcase_index = ngx_spdy_frame_parse_uint32(p);
2003
2471
 
2004
- if (!len) {
2005
- return NGX_ERROR;
2006
- }
2472
+ /* null-terminate header name */
2473
+ *p = '\0';
2007
2474
 
2008
2475
  p += NGX_SPDY_NV_VLEN_SIZE;
2009
2476
 
2010
- r->header_end = p + len;
2011
-
2012
2477
  state = sw_value;
2013
2478
 
2014
2479
  /* fall through */
2015
2480
 
2016
2481
  case sw_value:
2017
2482
 
2018
- if (r->header_end > end) {
2483
+ if ((ngx_uint_t) (end - p) < r->lowcase_index) {
2019
2484
  break;
2020
2485
  }
2021
2486
 
2022
2487
  r->header_start = p;
2023
2488
 
2024
- for ( /* void */ ; p != r->header_end; p++) {
2025
-
2489
+ while (r->lowcase_index--) {
2026
2490
  ch = *p;
2027
2491
 
2028
2492
  if (ch == '\0') {
@@ -2031,7 +2495,7 @@ ngx_http_spdy_parse_header(ngx_http_request_t *r)
2031
2495
  return NGX_ERROR;
2032
2496
  }
2033
2497
 
2034
- r->header_size = p - r->header_start;
2498
+ r->header_end = p;
2035
2499
  r->header_in->pos = p + 1;
2036
2500
 
2037
2501
  return NGX_OK;
@@ -2040,9 +2504,11 @@ ngx_http_spdy_parse_header(ngx_http_request_t *r)
2040
2504
  if (ch == CR || ch == LF) {
2041
2505
  return NGX_HTTP_PARSE_INVALID_HEADER;
2042
2506
  }
2507
+
2508
+ p++;
2043
2509
  }
2044
2510
 
2045
- r->header_size = p - r->header_start;
2511
+ r->header_end = p;
2046
2512
  r->header_in->pos = p;
2047
2513
 
2048
2514
  r->state = 0;
@@ -2091,7 +2557,7 @@ ngx_http_spdy_alloc_large_header_buffer(ngx_http_request_t *r)
2091
2557
  }
2092
2558
 
2093
2559
  ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2094
- "spdy large header alloc: %p %uz",
2560
+ "spdy large header alloc: %p %z",
2095
2561
  buf->pos, buf->end - buf->last);
2096
2562
 
2097
2563
  old = r->header_in->pos;
@@ -2101,13 +2567,6 @@ ngx_http_spdy_alloc_large_header_buffer(ngx_http_request_t *r)
2101
2567
  buf->last = ngx_cpymem(new, old, rest);
2102
2568
  }
2103
2569
 
2104
- if (r->header_name_end > old) {
2105
- r->header_name_end = new + (r->header_name_end - old);
2106
-
2107
- } else if (r->header_end > old) {
2108
- r->header_end = new + (r->header_end - old);
2109
- }
2110
-
2111
2570
  r->header_in = buf;
2112
2571
 
2113
2572
  stream->header_buffers++;
@@ -2135,21 +2594,25 @@ ngx_http_spdy_handle_request_header(ngx_http_request_t *r)
2135
2594
  return NGX_OK;
2136
2595
  }
2137
2596
 
2138
- } else {
2597
+ }
2598
+
2599
+ if (r->header_name_start[0] == ':') {
2600
+ r->header_name_start++;
2601
+
2139
2602
  for (i = 0; i < NGX_SPDY_REQUEST_HEADERS; i++) {
2140
2603
  sh = &ngx_http_spdy_request_headers[i];
2141
2604
 
2142
2605
  if (sh->hash != r->header_hash
2143
- || sh->len != r->lowcase_index
2144
- || ngx_strncmp(sh->header, r->header_name_start,
2145
- r->lowcase_index)
2146
- != 0)
2606
+ || sh->len != r->header_name_end - r->header_name_start
2607
+ || ngx_strncmp(sh->header, r->header_name_start, sh->len) != 0)
2147
2608
  {
2148
2609
  continue;
2149
2610
  }
2150
2611
 
2151
2612
  return sh->handler(r);
2152
2613
  }
2614
+
2615
+ return NGX_HTTP_PARSE_INVALID_REQUEST;
2153
2616
  }
2154
2617
 
2155
2618
  h = ngx_list_push(&r->headers_in.headers);
@@ -2161,13 +2624,11 @@ ngx_http_spdy_handle_request_header(ngx_http_request_t *r)
2161
2624
 
2162
2625
  h->hash = r->header_hash;
2163
2626
 
2164
- h->key.len = r->lowcase_index;
2627
+ h->key.len = r->header_name_end - r->header_name_start;
2165
2628
  h->key.data = r->header_name_start;
2166
- h->key.data[h->key.len] = '\0';
2167
2629
 
2168
- h->value.len = r->header_size;
2630
+ h->value.len = r->header_end - r->header_start;
2169
2631
  h->value.data = r->header_start;
2170
- h->value.data[h->value.len] = '\0';
2171
2632
 
2172
2633
  h->lowcase_key = h->key.data;
2173
2634
 
@@ -2176,7 +2637,7 @@ ngx_http_spdy_handle_request_header(ngx_http_request_t *r)
2176
2637
 
2177
2638
 
2178
2639
  void
2179
- ngx_http_spdy_request_headers_init()
2640
+ ngx_http_spdy_request_headers_init(void)
2180
2641
  {
2181
2642
  ngx_uint_t i;
2182
2643
  ngx_http_spdy_request_header_t *h;
@@ -2226,7 +2687,7 @@ ngx_http_spdy_parse_method(ngx_http_request_t *r)
2226
2687
  return NGX_HTTP_PARSE_INVALID_HEADER;
2227
2688
  }
2228
2689
 
2229
- len = r->header_size;
2690
+ len = r->header_end - r->header_start;
2230
2691
 
2231
2692
  r->method_name.len = len;
2232
2693
  r->method_name.data = r->header_start;
@@ -2287,7 +2748,39 @@ ngx_http_spdy_parse_scheme(ngx_http_request_t *r)
2287
2748
 
2288
2749
 
2289
2750
  static ngx_int_t
2290
- ngx_http_spdy_parse_url(ngx_http_request_t *r)
2751
+ ngx_http_spdy_parse_host(ngx_http_request_t *r)
2752
+ {
2753
+ ngx_table_elt_t *h;
2754
+
2755
+ if (r->headers_in.host) {
2756
+ return NGX_HTTP_PARSE_INVALID_HEADER;
2757
+ }
2758
+
2759
+ h = ngx_list_push(&r->headers_in.headers);
2760
+ if (h == NULL) {
2761
+ ngx_http_spdy_close_stream(r->spdy_stream,
2762
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
2763
+ return NGX_ERROR;
2764
+ }
2765
+
2766
+ r->headers_in.host = h;
2767
+
2768
+ h->hash = r->header_hash;
2769
+
2770
+ h->key.len = r->header_name_end - r->header_name_start;
2771
+ h->key.data = r->header_name_start;
2772
+
2773
+ h->value.len = r->header_end - r->header_start;
2774
+ h->value.data = r->header_start;
2775
+
2776
+ h->lowcase_key = h->key.data;
2777
+
2778
+ return NGX_OK;
2779
+ }
2780
+
2781
+
2782
+ static ngx_int_t
2783
+ ngx_http_spdy_parse_path(ngx_http_request_t *r)
2291
2784
  {
2292
2785
  if (r->unparsed_uri.len) {
2293
2786
  return NGX_HTTP_PARSE_INVALID_HEADER;
@@ -2319,7 +2812,7 @@ ngx_http_spdy_parse_version(ngx_http_request_t *r)
2319
2812
 
2320
2813
  p = r->header_start;
2321
2814
 
2322
- if (r->header_size < 8 || !(ngx_str5cmp(p, 'H', 'T', 'T', 'P', '/'))) {
2815
+ if (r->header_end - p < 8 || !(ngx_str5cmp(p, 'H', 'T', 'T', 'P', '/'))) {
2323
2816
  return NGX_HTTP_PARSE_INVALID_REQUEST;
2324
2817
  }
2325
2818
 
@@ -2335,6 +2828,10 @@ ngx_http_spdy_parse_version(ngx_http_request_t *r)
2335
2828
 
2336
2829
  ch = *p;
2337
2830
 
2831
+ if (ch == '.') {
2832
+ break;
2833
+ }
2834
+
2338
2835
  if (ch < '0' || ch > '9') {
2339
2836
  return NGX_HTTP_PARSE_INVALID_REQUEST;
2340
2837
  }
@@ -2365,7 +2862,7 @@ ngx_http_spdy_parse_version(ngx_http_request_t *r)
2365
2862
  r->http_minor = r->http_minor * 10 + ch - '0';
2366
2863
  }
2367
2864
 
2368
- r->http_protocol.len = r->header_size;
2865
+ r->http_protocol.len = r->header_end - r->header_start;
2369
2866
  r->http_protocol.data = r->header_start;
2370
2867
  r->http_version = r->http_major * 1000 + r->http_minor;
2371
2868
 
@@ -2465,6 +2962,16 @@ ngx_http_spdy_run_request(ngx_http_request_t *r)
2465
2962
  return;
2466
2963
  }
2467
2964
 
2965
+ if (r->headers_in.content_length_n > 0 && r->spdy_stream->in_closed) {
2966
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
2967
+ "client prematurely closed stream");
2968
+
2969
+ r->spdy_stream->skip_data = NGX_SPDY_DATA_ERROR;
2970
+
2971
+ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
2972
+ return;
2973
+ }
2974
+
2468
2975
  ngx_http_process_request(r);
2469
2976
  }
2470
2977
 
@@ -2597,10 +3104,55 @@ ngx_http_spdy_read_request_body(ngx_http_request_t *r,
2597
3104
 
2598
3105
  r->request_body->post_handler = post_handler;
2599
3106
 
3107
+ r->read_event_handler = ngx_http_test_reading;
3108
+ r->write_event_handler = ngx_http_request_empty_handler;
3109
+
2600
3110
  return NGX_AGAIN;
2601
3111
  }
2602
3112
 
2603
3113
 
3114
+ static ngx_int_t
3115
+ ngx_http_spdy_terminate_stream(ngx_http_spdy_connection_t *sc,
3116
+ ngx_http_spdy_stream_t *stream, ngx_uint_t status)
3117
+ {
3118
+ ngx_event_t *rev;
3119
+ ngx_connection_t *fc;
3120
+
3121
+ if (ngx_http_spdy_send_rst_stream(sc, stream->id, status,
3122
+ NGX_SPDY_HIGHEST_PRIORITY)
3123
+ == NGX_ERROR)
3124
+ {
3125
+ return NGX_ERROR;
3126
+ }
3127
+
3128
+ stream->out_closed = 1;
3129
+
3130
+ fc = stream->request->connection;
3131
+ fc->error = 1;
3132
+
3133
+ rev = fc->read;
3134
+ rev->handler(rev);
3135
+
3136
+ return NGX_OK;
3137
+ }
3138
+
3139
+
3140
+ static void
3141
+ ngx_http_spdy_close_stream_handler(ngx_event_t *ev)
3142
+ {
3143
+ ngx_connection_t *fc;
3144
+ ngx_http_request_t *r;
3145
+
3146
+ fc = ev->data;
3147
+ r = fc->data;
3148
+
3149
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3150
+ "spdy close stream handler");
3151
+
3152
+ ngx_http_spdy_close_stream(r->spdy_stream, 0);
3153
+ }
3154
+
3155
+
2604
3156
  void
2605
3157
  ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc)
2606
3158
  {
@@ -2612,9 +3164,16 @@ ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc)
2612
3164
 
2613
3165
  sc = stream->connection;
2614
3166
 
2615
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
2616
- "spdy close stream %ui, processing %ui",
2617
- stream->id, sc->processing);
3167
+ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
3168
+ "spdy close stream %ui, queued %ui, processing %ui",
3169
+ stream->id, stream->queued, sc->processing);
3170
+
3171
+ fc = stream->request->connection;
3172
+
3173
+ if (stream->queued) {
3174
+ fc->write->handler = ngx_http_spdy_close_stream_handler;
3175
+ return;
3176
+ }
2618
3177
 
2619
3178
  if (!stream->out_closed) {
2620
3179
  if (ngx_http_spdy_send_rst_stream(sc, stream->id,
@@ -2650,14 +3209,13 @@ ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc)
2650
3209
  index = &s->index;
2651
3210
  }
2652
3211
 
2653
- fc = stream->request->connection;
2654
-
2655
3212
  ngx_http_free_request(stream->request, rc);
2656
3213
 
2657
3214
  ev = fc->read;
2658
3215
 
2659
3216
  if (ev->active || ev->disabled) {
2660
- ngx_del_event(ev, NGX_READ_EVENT, 0);
3217
+ ngx_log_error(NGX_LOG_ALERT, sc->connection->log, 0,
3218
+ "spdy fake read event was activated");
2661
3219
  }
2662
3220
 
2663
3221
  if (ev->timer_set) {
@@ -2671,7 +3229,8 @@ ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc)
2671
3229
  ev = fc->write;
2672
3230
 
2673
3231
  if (ev->active || ev->disabled) {
2674
- ngx_del_event(ev, NGX_WRITE_EVENT, 0);
3232
+ ngx_log_error(NGX_LOG_ALERT, sc->connection->log, 0,
3233
+ "spdy fake write event was activated");
2675
3234
  }
2676
3235
 
2677
3236
  if (ev->timer_set) {
@@ -2802,6 +3361,7 @@ ngx_http_spdy_finalize_connection(ngx_http_spdy_connection_t *sc,
2802
3361
 
2803
3362
  c->error = 1;
2804
3363
  c->read->handler = ngx_http_empty_handler;
3364
+ c->write->handler = ngx_http_empty_handler;
2805
3365
 
2806
3366
  sc->last_out = NULL;
2807
3367
 
@@ -2816,15 +3376,18 @@ ngx_http_spdy_finalize_connection(ngx_http_spdy_connection_t *sc,
2816
3376
  stream = sc->streams_index[i];
2817
3377
 
2818
3378
  while (stream) {
2819
- r = stream->request;
3379
+ stream->handled = 0;
2820
3380
 
3381
+ r = stream->request;
2821
3382
  fc = r->connection;
3383
+
2822
3384
  fc->error = 1;
2823
3385
 
2824
- if (stream->waiting) {
2825
- r->blocked -= stream->waiting;
2826
- stream->waiting = 0;
3386
+ if (stream->queued) {
3387
+ stream->queued = 0;
3388
+
2827
3389
  ev = fc->write;
3390
+ ev->delayed = 0;
2828
3391
 
2829
3392
  } else {
2830
3393
  ev = fc->read;
@@ -2847,6 +3410,61 @@ ngx_http_spdy_finalize_connection(ngx_http_spdy_connection_t *sc,
2847
3410
  }
2848
3411
 
2849
3412
 
3413
+ static ngx_int_t
3414
+ ngx_http_spdy_adjust_windows(ngx_http_spdy_connection_t *sc, ssize_t delta)
3415
+ {
3416
+ ngx_uint_t i, size;
3417
+ ngx_event_t *wev;
3418
+ ngx_http_spdy_stream_t *stream, *sn;
3419
+ ngx_http_spdy_srv_conf_t *sscf;
3420
+
3421
+ sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx,
3422
+ ngx_http_spdy_module);
3423
+
3424
+ size = ngx_http_spdy_streams_index_size(sscf);
3425
+
3426
+ for (i = 0; i < size; i++) {
3427
+
3428
+ for (stream = sc->streams_index[i]; stream; stream = sn) {
3429
+ sn = stream->index;
3430
+
3431
+ if (delta > 0
3432
+ && stream->send_window
3433
+ > (ssize_t) (NGX_SPDY_MAX_WINDOW - delta))
3434
+ {
3435
+ if (ngx_http_spdy_terminate_stream(sc, stream,
3436
+ NGX_SPDY_FLOW_CONTROL_ERROR)
3437
+ == NGX_ERROR)
3438
+ {
3439
+ return NGX_ERROR;
3440
+ }
3441
+
3442
+ continue;
3443
+ }
3444
+
3445
+ stream->send_window += delta;
3446
+
3447
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
3448
+ "spdy:%ui adjust window:%z",
3449
+ stream->id, stream->send_window);
3450
+
3451
+ if (stream->send_window > 0 && stream->exhausted) {
3452
+ stream->exhausted = 0;
3453
+
3454
+ wev = stream->request->connection->write;
3455
+
3456
+ if (!wev->timer_set) {
3457
+ wev->delayed = 0;
3458
+ wev->handler(wev);
3459
+ }
3460
+ }
3461
+ }
3462
+ }
3463
+
3464
+ return NGX_OK;
3465
+ }
3466
+
3467
+
2850
3468
  static void
2851
3469
  ngx_http_spdy_pool_cleanup(void *data)
2852
3470
  {