Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(836)

Unified Diff: sdk/lib/io/http_parser.dart

Issue 11359085: Refactor HTTP parser to hold current buffer (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed more comments Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sdk/lib/io/http_impl.dart ('k') | tests/standalone/io/http_parser_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/io/http_parser.dart
diff --git a/sdk/lib/io/http_parser.dart b/sdk/lib/io/http_parser.dart
index a5549c5d3a519fceace71023d934c2330baab503..61e0a64a588e34fc9111455ccda531969c1bc8bb 100644
--- a/sdk/lib/io/http_parser.dart
+++ b/sdk/lib/io/http_parser.dart
@@ -116,11 +116,12 @@ class _MessageType {
* object will be [:true:] indicating that from now on the protocol is
* not HTTP anymore and no more callbacks will happen, that is
* [:dataReceived:] and [:dataEnd:] are not called in this case as
- * there is no more HTTP data. After the upgrade the call to
- * [:writeList:] causing the upgrade will return with the number of
- * bytes parsed as HTTP. Any unparsed bytes is part of the protocol
- * the connection is upgrading to and should be handled according to
- * that protocol.
+ * there is no more HTTP data. After the upgrade the method
+ * [:readUnparsedData:] can be used to read any remaining bytes in the
+ * HTTP parser which are part of the protocol the connection is
+ * upgrading to. These bytes cannot be processed by the HTTP parser
+ * and should be handled according to whatever protocol is being
+ * upgraded to.
*/
class _HttpParser {
_HttpParser() {
@@ -136,9 +137,7 @@ class _HttpParser {
// Request-Line = Method SP Request-URI SP HTTP-Version CRLF
// Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
// message-header = field-name ":" [ field-value ]
- int writeList(List<int> buffer, int offset, int count) {
- int index = offset;
- int lastIndex = offset + count;
+ void _parse() {
try {
if (_state == _State.CLOSED) {
throw new HttpParserException("Data on closed connection");
@@ -149,10 +148,11 @@ class _HttpParser {
if (_state == _State.FAILURE) {
throw new HttpParserException("Data on failed connection");
}
- while ((index < lastIndex) &&
+ while (_buffer != null &&
+ _index < _lastIndex &&
_state != _State.FAILURE &&
_state != _State.UPGRADED) {
- int byte = buffer[index];
+ int byte = _buffer[_index++];
switch (_state) {
case _State.START:
if (byte == _Const.HTTP[0]) {
@@ -325,7 +325,9 @@ class _HttpParser {
statusCode <= 199 || statusCode == 204 || statusCode == 304;
}
if (responseStart != null) {
- responseStart(statusCode, _uri_or_reason_phrase.toString(), version);
+ responseStart(statusCode,
+ _uri_or_reason_phrase.toString(),
+ version);
}
_method_or_status_code.clear();
_uri_or_reason_phrase.clear();
@@ -438,8 +440,6 @@ class _HttpParser {
}
if (_connectionUpgrade) {
_state = _State.UPGRADED;
- _unparsedData =
- buffer.getRange(index + 1, count - (index + 1 - offset));
if (headersComplete != null) headersComplete();
} else {
if (headersComplete != null) headersComplete();
@@ -513,22 +513,23 @@ class _HttpParser {
case _State.BODY:
// The body is not handled one byte at a time but in blocks.
- int dataAvailable = lastIndex - index;
+ _index--;
+ int dataAvailable = _lastIndex - _index;
List<int> data;
if (_remainingContent == null ||
dataAvailable <= _remainingContent) {
data = new Uint8List(dataAvailable);
- data.setRange(0, dataAvailable, buffer, index);
+ data.setRange(0, dataAvailable, _buffer, _index);
} else {
data = new Uint8List(_remainingContent);
- data.setRange(0, _remainingContent, buffer, index);
+ data.setRange(0, _remainingContent, _buffer, _index);
}
if (dataReceived != null) dataReceived(data);
if (_remainingContent != null) {
_remainingContent -= data.length;
}
- index += data.length;
+ _index += data.length;
if (_remainingContent == 0) {
if (!_chunked) {
_bodyEnd();
@@ -537,9 +538,6 @@ class _HttpParser {
_state = _State.CHUNK_SIZE_STARTING_CR;
}
}
-
- // Hack - as we always do index++ below.
- index--;
break;
case _State.FAILURE:
@@ -552,9 +550,6 @@ class _HttpParser {
assert(false);
break;
}
-
- // Move to the next byte.
- index++;
}
} catch (e) {
// Report the error through the error callback if any. Otherwise
@@ -567,8 +562,17 @@ class _HttpParser {
}
}
- // Return the number of bytes parsed.
- return index - offset;
+ // If all data is parsed or not needed due to failure there is no
+ // need to hold on to the buffer.
+ if (_state != _State.UPGRADED) _releaseBuffer();
+ }
+
+ void writeList(List<int> buffer, int offset, int count) {
+ assert(_buffer == null);
+ _buffer = buffer;
+ _index = offset;
+ _lastIndex = offset + count;
+ _parse();
}
void connectionClosed() {
@@ -623,7 +627,13 @@ class _HttpParser {
bool get isIdle => _state == _State.START;
- List<int> get unparsedData => _unparsedData;
+ List<int> readUnparsedData() {
+ if (_buffer == null) return [];
+ if (_index == _lastIndex) return [];
+ var result = _buffer.getRange(_index, _lastIndex - _index);
+ _releaseBuffer();
+ return result;
+ }
void _bodyEnd() {
if (dataEnd != null) {
@@ -650,6 +660,12 @@ class _HttpParser {
_remainingContent = null;
}
+ _releaseBuffer() {
+ _buffer = null;
+ _index = null;
+ _lastIndex = null;
+ }
+
bool _isTokenChar(int byte) {
return byte > 31 && byte < 128 && _Const.SEPARATORS.indexOf(byte) == -1;
}
@@ -696,6 +712,11 @@ class _HttpParser {
}
}
+ // The data that is currently being parsed.
+ List<int> _buffer;
+ int _index;
+ int _lastIndex;
+
int _state;
int _httpVersionIndex;
int _messageType;
@@ -714,7 +735,6 @@ class _HttpParser {
String _responseToMethod; // Indicates the method used for the request.
int _remainingContent;
- List<int> _unparsedData; // Unparsed data after connection upgrade.
// Callbacks.
Function requestStart;
Function responseStart;
« no previous file with comments | « sdk/lib/io/http_impl.dart ('k') | tests/standalone/io/http_parser_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698