comparison src/http/ngx_http_spdy.c @ 5643:436f3605195a

SPDY: consistently handle control frames with unknown type. The SPDY draft 2 specification requires that if an endpoint receives a control frame for a type it does not recognize, it must ignore the frame. But the 3 and 3.1 drafts don't seem to declare any behavior for such case. Then sticking with the previous draft in this matter looks to be right. But previously, only 8 least significant bits of the type field were parsed while the rest of 16 bits of the field were checked against zero. Though there are no known frame types bigger than 255, this resulted in inconsistency in handling of such frames: they were not recognized as valid frames at all, and the connection was closed.
author Valentin Bartenev <vbart@nginx.com>
date Mon, 07 Apr 2014 19:27:56 +0400
parents d2ac5cf4056d
children e1dcb983d6b3
comparison
equal deleted inserted replaced
5642:d2ac5cf4056d 5643:436f3605195a
45 #define ngx_spdy_frame_parse_delta(p) \ 45 #define ngx_spdy_frame_parse_delta(p) \
46 (ngx_spdy_frame_parse_uint32(p) & 0x7fffffff) 46 (ngx_spdy_frame_parse_uint32(p) & 0x7fffffff)
47 47
48 48
49 #define ngx_spdy_ctl_frame_check(h) \ 49 #define ngx_spdy_ctl_frame_check(h) \
50 (((h) & 0xffffff00) == ngx_spdy_ctl_frame_head(0)) 50 (((h) & 0xffff0000) == ngx_spdy_ctl_frame_head(0))
51 #define ngx_spdy_data_frame_check(h) \ 51 #define ngx_spdy_data_frame_check(h) \
52 (!((h) & (uint32_t) NGX_SPDY_CTL_BIT << 31)) 52 (!((h) & (uint32_t) NGX_SPDY_CTL_BIT << 31))
53 53
54 #define ngx_spdy_ctl_frame_type(h) ((h) & 0x000000ff) 54 #define ngx_spdy_ctl_frame_type(h) ((h) & 0x0000ffff)
55 #define ngx_spdy_frame_flags(p) ((p) >> 24) 55 #define ngx_spdy_frame_flags(p) ((p) >> 24)
56 #define ngx_spdy_frame_length(p) ((p) & 0x00ffffff) 56 #define ngx_spdy_frame_length(p) ((p) & 0x00ffffff)
57 #define ngx_spdy_frame_id(p) ((p) & 0x00ffffff) 57 #define ngx_spdy_frame_id(p) ((p) & 0x00ffffff)
58 58
59 59
834 834
835 static u_char * 835 static u_char *
836 ngx_http_spdy_state_head(ngx_http_spdy_connection_t *sc, u_char *pos, 836 ngx_http_spdy_state_head(ngx_http_spdy_connection_t *sc, u_char *pos,
837 u_char *end) 837 u_char *end)
838 { 838 {
839 uint32_t head, flen; 839 uint32_t head, flen;
840 ngx_uint_t type;
840 841
841 if (end - pos < NGX_SPDY_FRAME_HEADER_SIZE) { 842 if (end - pos < NGX_SPDY_FRAME_HEADER_SIZE) {
842 return ngx_http_spdy_state_save(sc, pos, end, 843 return ngx_http_spdy_state_save(sc, pos, end,
843 ngx_http_spdy_state_head); 844 ngx_http_spdy_state_head);
844 } 845 }
857 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, 858 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
858 "spdy process frame head:%08XD f:%Xd l:%uz", 859 "spdy process frame head:%08XD f:%Xd l:%uz",
859 head, sc->flags, sc->length); 860 head, sc->flags, sc->length);
860 861
861 if (ngx_spdy_ctl_frame_check(head)) { 862 if (ngx_spdy_ctl_frame_check(head)) {
862 switch (ngx_spdy_ctl_frame_type(head)) { 863 type = ngx_spdy_ctl_frame_type(head);
864
865 switch (type) {
863 866
864 case NGX_SPDY_SYN_STREAM: 867 case NGX_SPDY_SYN_STREAM:
865 return ngx_http_spdy_state_syn_stream(sc, pos, end); 868 return ngx_http_spdy_state_syn_stream(sc, pos, end);
866 869
867 case NGX_SPDY_SYN_REPLY: 870 case NGX_SPDY_SYN_REPLY:
883 return ngx_http_spdy_state_protocol_error(sc); 886 return ngx_http_spdy_state_protocol_error(sc);
884 887
885 case NGX_SPDY_WINDOW_UPDATE: 888 case NGX_SPDY_WINDOW_UPDATE:
886 return ngx_http_spdy_state_window_update(sc, pos, end); 889 return ngx_http_spdy_state_window_update(sc, pos, end);
887 890
888 default: /* TODO logging */ 891 default:
892 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
893 "spdy control frame with unknown type %ui", type);
889 return ngx_http_spdy_state_skip(sc, pos, end); 894 return ngx_http_spdy_state_skip(sc, pos, end);
890 } 895 }
891 } 896 }
892 897
893 if (ngx_spdy_data_frame_check(head)) { 898 if (ngx_spdy_data_frame_check(head)) {