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