Mercurial > hg > nginx
comparison src/http/ngx_http_spdy.c @ 5690:fb56f5d612a0
SPDY: improved error handling of header block decompression.
Now cases when decompression failed due to internal error
and when a client sent corrupted data are distinguished.
author | Valentin Bartenev <vbart@nginx.com> |
---|---|
date | Wed, 30 Apr 2014 20:34:20 +0400 |
parents | 5d55f03b1e12 |
children | 31349361558e |
comparison
equal
deleted
inserted
replaced
5689:5d55f03b1e12 | 5690:fb56f5d612a0 |
---|---|
121 u_char *pos, u_char *end); | 121 u_char *pos, u_char *end); |
122 static u_char *ngx_http_spdy_state_complete(ngx_http_spdy_connection_t *sc, | 122 static u_char *ngx_http_spdy_state_complete(ngx_http_spdy_connection_t *sc, |
123 u_char *pos, u_char *end); | 123 u_char *pos, u_char *end); |
124 static u_char *ngx_http_spdy_state_save(ngx_http_spdy_connection_t *sc, | 124 static u_char *ngx_http_spdy_state_save(ngx_http_spdy_connection_t *sc, |
125 u_char *pos, u_char *end, ngx_http_spdy_handler_pt handler); | 125 u_char *pos, u_char *end, ngx_http_spdy_handler_pt handler); |
126 | |
127 static u_char *ngx_http_spdy_state_inflate_error( | |
128 ngx_http_spdy_connection_t *sc, int rc); | |
126 static u_char *ngx_http_spdy_state_protocol_error( | 129 static u_char *ngx_http_spdy_state_protocol_error( |
127 ngx_http_spdy_connection_t *sc); | 130 ngx_http_spdy_connection_t *sc); |
128 static u_char *ngx_http_spdy_state_internal_error( | 131 static u_char *ngx_http_spdy_state_internal_error( |
129 ngx_http_spdy_connection_t *sc); | 132 ngx_http_spdy_connection_t *sc); |
130 | 133 |
1034 z = inflate(&sc->zstream_in, Z_NO_FLUSH); | 1037 z = inflate(&sc->zstream_in, Z_NO_FLUSH); |
1035 | 1038 |
1036 if (z == Z_NEED_DICT) { | 1039 if (z == Z_NEED_DICT) { |
1037 z = inflateSetDictionary(&sc->zstream_in, ngx_http_spdy_dict, | 1040 z = inflateSetDictionary(&sc->zstream_in, ngx_http_spdy_dict, |
1038 sizeof(ngx_http_spdy_dict)); | 1041 sizeof(ngx_http_spdy_dict)); |
1042 | |
1039 if (z != Z_OK) { | 1043 if (z != Z_OK) { |
1040 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, | 1044 if (z == Z_DATA_ERROR) { |
1041 "spdy inflateSetDictionary() failed: %d", z); | 1045 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, |
1042 | 1046 "client sent SYN_STREAM frame with header " |
1043 return ngx_http_spdy_state_protocol_error(sc); | 1047 "block encoded using wrong dictionary: %ul", |
1048 (u_long) sc->zstream_in.adler); | |
1049 | |
1050 return ngx_http_spdy_state_protocol_error(sc); | |
1051 } | |
1052 | |
1053 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
1054 "inflateSetDictionary() failed: %d", z); | |
1055 | |
1056 return ngx_http_spdy_state_internal_error(sc); | |
1044 } | 1057 } |
1045 | 1058 |
1046 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 1059 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1047 "spdy inflateSetDictionary(): %d", z); | 1060 "spdy inflateSetDictionary(): %d", z); |
1048 | 1061 |
1049 z = sc->zstream_in.avail_in ? inflate(&sc->zstream_in, Z_NO_FLUSH) | 1062 z = sc->zstream_in.avail_in ? inflate(&sc->zstream_in, Z_NO_FLUSH) |
1050 : Z_OK; | 1063 : Z_OK; |
1051 } | 1064 } |
1052 | 1065 |
1053 if (z != Z_OK) { | 1066 if (z != Z_OK) { |
1054 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, | 1067 return ngx_http_spdy_state_inflate_error(sc, z); |
1055 "spdy inflate() failed: %d", z); | |
1056 | |
1057 return ngx_http_spdy_state_protocol_error(sc); | |
1058 } | 1068 } |
1059 | 1069 |
1060 ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 1070 ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1061 "spdy inflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d", | 1071 "spdy inflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d", |
1062 sc->zstream_in.next_in, sc->zstream_in.next_out, | 1072 sc->zstream_in.next_in, sc->zstream_in.next_out, |
1153 sc->zstream_in.avail_out = buf->end - buf->last - 1; | 1163 sc->zstream_in.avail_out = buf->end - buf->last - 1; |
1154 | 1164 |
1155 z = inflate(&sc->zstream_in, Z_NO_FLUSH); | 1165 z = inflate(&sc->zstream_in, Z_NO_FLUSH); |
1156 | 1166 |
1157 if (z != Z_OK) { | 1167 if (z != Z_OK) { |
1158 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, | 1168 return ngx_http_spdy_state_inflate_error(sc, z); |
1159 "spdy inflate() failed: %d", z); | |
1160 | |
1161 return ngx_http_spdy_state_protocol_error(sc); | |
1162 } | 1169 } |
1163 | 1170 |
1164 sc->length -= sc->zstream_in.next_in - pos; | 1171 sc->length -= sc->zstream_in.next_in - pos; |
1165 pos = sc->zstream_in.next_in; | 1172 pos = sc->zstream_in.next_in; |
1166 | 1173 |
1266 sc->zstream_in.next_out = buffer; | 1273 sc->zstream_in.next_out = buffer; |
1267 sc->zstream_in.avail_out = NGX_SPDY_SKIP_HEADERS_BUFFER_SIZE; | 1274 sc->zstream_in.avail_out = NGX_SPDY_SKIP_HEADERS_BUFFER_SIZE; |
1268 | 1275 |
1269 n = inflate(&sc->zstream_in, Z_NO_FLUSH); | 1276 n = inflate(&sc->zstream_in, Z_NO_FLUSH); |
1270 | 1277 |
1271 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, | |
1272 "spdy inflate(): %d", n); | |
1273 | |
1274 if (n != Z_OK) { | 1278 if (n != Z_OK) { |
1275 /* TODO: logging */ | 1279 return ngx_http_spdy_state_inflate_error(sc, n); |
1276 return ngx_http_spdy_state_protocol_error(sc); | |
1277 } | 1280 } |
1278 } | 1281 } |
1279 | 1282 |
1280 pos = sc->zstream_in.next_in; | 1283 pos = sc->zstream_in.next_in; |
1281 | 1284 |
1910 return end; | 1913 return end; |
1911 } | 1914 } |
1912 | 1915 |
1913 | 1916 |
1914 static u_char * | 1917 static u_char * |
1918 ngx_http_spdy_state_inflate_error(ngx_http_spdy_connection_t *sc, int rc) | |
1919 { | |
1920 if (rc == Z_DATA_ERROR || rc == Z_STREAM_END) { | |
1921 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, | |
1922 "client sent SYN_STREAM frame with " | |
1923 "corrupted header block, inflate() failed: %d", rc); | |
1924 | |
1925 return ngx_http_spdy_state_protocol_error(sc); | |
1926 } | |
1927 | |
1928 ngx_log_error(NGX_LOG_ERR, sc->connection->log, 0, | |
1929 "inflate() failed: %d", rc); | |
1930 | |
1931 return ngx_http_spdy_state_internal_error(sc); | |
1932 } | |
1933 | |
1934 | |
1935 static u_char * | |
1915 ngx_http_spdy_state_protocol_error(ngx_http_spdy_connection_t *sc) | 1936 ngx_http_spdy_state_protocol_error(ngx_http_spdy_connection_t *sc) |
1916 { | 1937 { |
1917 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, | 1938 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, |
1918 "spdy state protocol error"); | 1939 "spdy state protocol error"); |
1919 | 1940 |
1932 ngx_http_spdy_state_internal_error(ngx_http_spdy_connection_t *sc) | 1953 ngx_http_spdy_state_internal_error(ngx_http_spdy_connection_t *sc) |
1933 { | 1954 { |
1934 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, | 1955 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, |
1935 "spdy state internal error"); | 1956 "spdy state internal error"); |
1936 | 1957 |
1937 /* TODO */ | 1958 if (sc->stream) { |
1959 sc->stream->out_closed = 1; | |
1960 ngx_http_spdy_close_stream(sc->stream, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
1961 } | |
1962 | |
1938 ngx_http_spdy_finalize_connection(sc, NGX_HTTP_INTERNAL_SERVER_ERROR); | 1963 ngx_http_spdy_finalize_connection(sc, NGX_HTTP_INTERNAL_SERVER_ERROR); |
1964 | |
1939 return NULL; | 1965 return NULL; |
1940 } | 1966 } |
1941 | 1967 |
1942 | 1968 |
1943 static ngx_int_t | 1969 static ngx_int_t |