Chromium Code Reviews| Index: runtime/bin/http_parser.dart |
| diff --git a/runtime/bin/http_parser.dart b/runtime/bin/http_parser.dart |
| index 499e66c7940a664cb7691d33cc42b0536ada40f1..3c78e26df8f797328dc3c7d7ef0ad17293283d95 100644 |
| --- a/runtime/bin/http_parser.dart |
| +++ b/runtime/bin/http_parser.dart |
| @@ -51,6 +51,7 @@ class _State { |
| static final int HEADER_VALUE_FOLDING_OR_ENDING = 13; |
| static final int HEADER_VALUE_FOLD_OR_END = 14; |
| static final int HEADER_ENDING = 15; |
| + |
| static final int CHUNK_SIZE_STARTING_CR = 16; |
| static final int CHUNK_SIZE_STARTING_LF = 17; |
| static final int CHUNK_SIZE = 18; |
| @@ -59,7 +60,10 @@ class _State { |
| static final int CHUNKED_BODY_DONE_CR = 21; |
| static final int CHUNKED_BODY_DONE_LF = 22; |
| static final int BODY = 23; |
| - static final int FAILURE = 24; |
| + static final int CLOSED = 24; |
| + static final int FAILURE = 25; |
| + |
| + static final int FIRST_BODY_STATE = CHUNK_SIZE_STARTING_CR; |
| } |
| @@ -109,6 +113,9 @@ class _HttpParser { |
| int index = offset; |
| int lastIndex = offset + count; |
| try { |
| + if (_state == _State.CLOSED) { |
| + throw new HttpParserException("Data on closed connection"); |
| + } |
| while ((index < lastIndex) && _state != _State.FAILURE) { |
| int byte = buffer[index]; |
| switch (_state) { |
| @@ -287,9 +294,12 @@ class _HttpParser { |
| // is chunked (RFC 2616 section 4.4) |
| if (headerField == "content-length" && !_chunked) { |
| _contentLength = Math.parseInt(headerValue); |
| - } else if (headerField == "connection" && |
| - headerValue == "keep-alive") { |
| - _keepAlive = true; |
| + } else if (headerField == "connection") { |
| + if (headerValue == "keep-alive") { |
| + _keepAlive = true; |
| + } else if (headerValue == "close") { |
| + _connectionClose = true; |
| + } |
| } else if (headerField == "transfer-encoding" && |
| headerValue == "chunked") { |
| _chunked = true; |
| @@ -314,7 +324,6 @@ class _HttpParser { |
| case _State.HEADER_ENDING: |
| _expect(byte, _CharCode.LF); |
| if (headersComplete != null) headersComplete(); |
| - |
| if (_chunked) { |
| _state = _State.CHUNK_SIZE; |
| _remainingContent = 0; |
| @@ -325,8 +334,8 @@ class _HttpParser { |
| (_noMessageBody || _responseToMethod == "HEAD"))) { |
| // If there is no message body get ready to process the |
| // next request. |
| - if (dataEnd != null) dataEnd(); |
| - _state = _State.START; |
| + _bodyEnd(); |
| + _reset(); |
| } else if (_contentLength > 0) { |
| _remainingContent = _contentLength; |
| _state = _State.BODY; |
| @@ -380,7 +389,7 @@ class _HttpParser { |
| case _State.CHUNKED_BODY_DONE_LF: |
| _expect(byte, _CharCode.LF); |
| - if (dataEnd != null) dataEnd(); |
| + _bodyEnd(); |
| _reset(); |
| break; |
| @@ -404,7 +413,7 @@ class _HttpParser { |
| index += data.length; |
| if (_remainingContent == 0) { |
| if (!_chunked) { |
| - if (dataEnd != null) dataEnd(); |
| + _bodyEnd(); |
| _reset(); |
| } else { |
| _state = _State.CHUNK_SIZE_STARTING_CR; |
| @@ -445,9 +454,25 @@ class _HttpParser { |
| } |
| int connectionClosed() { |
| + if (_state < _State.FIRST_BODY_STATE) { |
| + // Report the error through the error callback if any. Otherwise |
| + // throw the error. |
| + var e = new HttpParserException( |
| + "Connection closed before full header was received"); |
| + if (error != null) { |
| + error(e); |
|
Anders Johnsen
2012/04/03 07:20:16
We should return after 'error(e)' so we don't hit
Søren Gjesse
2012/04/10 13:10:08
Done.
|
| + } else { |
| + throw e; |
| + } |
| + } |
| + |
| if (!_chunked && _contentLength == -1) { |
| - if (dataEnd != null) dataEnd(); |
| + if (_state != _State.START) { |
| + if (dataEnd != null) dataEnd(true); |
| + } |
| + _state = _State.CLOSED; |
| } else { |
| + _state = _State.FAILURE; |
| // Report the error through the error callback if any. Otherwise |
| // throw the error. |
| var e = new HttpParserException( |
| @@ -466,6 +491,14 @@ class _HttpParser { |
| void set responseToMethod(String method) => _responseToMethod = method; |
| + bool get isIdle() => _state == _State.START; |
| + |
| + void _bodyEnd() { |
| + if (dataEnd != null) { |
| + dataEnd(_messageType == _MessageType.RESPONSE && _connectionClose); |
| + } |
| + } |
| + |
| _reset() { |
| _state = _State.START; |
| _messageType = _MessageType.UNDETERMINED; |
| @@ -476,6 +509,7 @@ class _HttpParser { |
| _contentLength = -1; |
| _keepAlive = false; |
| + _connectionClose = false; |
| _chunked = false; |
| _noMessageBody = false; |
| @@ -518,6 +552,7 @@ class _HttpParser { |
| int _contentLength; |
| bool _keepAlive; |
| + bool _connectionClose; |
| bool _chunked; |
| bool _noMessageBody; |