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

Side by Side Diff: sdk/lib/io/http_parser.dart

Issue 2754923002: Tweak corelib files so dartfmt can do a better job. Use // comments to force line wrapping for long… (Closed)
Patch Set: Tweak corelib files so dartfmt can do a better job. Use // comments to force line wrapping for long… Created 3 years, 9 months 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 unified diff | Download patch
« no previous file with comments | « sdk/lib/io/crypto.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of dart.io; 5 part of dart.io;
6 6
7 // Global constants. 7 // Global constants.
8 class _Const { 8 class _Const {
9 // Bytes for "HTTP". 9 // Bytes for "HTTP".
10 static const HTTP = const [72, 84, 84, 80]; 10 static const HTTP = const [72, 84, 84, 80];
11 // Bytes for "HTTP/1.". 11 // Bytes for "HTTP/1.".
12 static const HTTP1DOT = const [72, 84, 84, 80, 47, 49, 46]; 12 static const HTTP1DOT = const [72, 84, 84, 80, 47, 49, 46];
13 // Bytes for "HTTP/1.0". 13 // Bytes for "HTTP/1.0".
14 static const HTTP10 = const [72, 84, 84, 80, 47, 49, 46, 48]; 14 static const HTTP10 = const [72, 84, 84, 80, 47, 49, 46, 48];
15 // Bytes for "HTTP/1.1". 15 // Bytes for "HTTP/1.1".
16 static const HTTP11 = const [72, 84, 84, 80, 47, 49, 46, 49]; 16 static const HTTP11 = const [72, 84, 84, 80, 47, 49, 46, 49];
17 17
18 static const bool T = true; 18 static const bool T = true;
19 static const bool F = false; 19 static const bool F = false;
20 // Loopup-map for the following characters: '()<>@,;:\\"/[]?={} \t'. 20 // Loopup-map for the following characters: '()<>@,;:\\"/[]?={} \t'.
21 static const SEPARATOR_MAP = const [ 21 static const SEPARATOR_MAP = const [
22 F,F,F,F,F,F,F,F,F,T,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,T,F,T,F,F, 22 F, F, F, F, F, F, F, F, F, T, F, F, F, F, F, F, F, F, F, F, F, F, F, F, //
23 F,F,F,T,T,F,F,T,F,F,T,F,F,F,F,F,F,F,F,F,F,T,T,T,T,T,T,T,F,F,F,F,F,F,F,F,F, 23 F, F, F, F, F, F, F, F, T, F, T, F, F, F, F, F, T, T, F, F, T, F, F, T, //
24 F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,T,T,T,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, 24 F, F, F, F, F, F, F, F, F, F, T, T, T, T, T, T, T, F, F, F, F, F, F, F, //
25 F,F,F,F,F,F,F,F,F,F,F,F,T,F,T,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, 25 F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, T, T, T, F, F, //
26 F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, 26 F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, //
27 F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, 27 F, F, F, T, F, T, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, //
28 F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F]; 28 F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, //
29 F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, //
30 F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, //
31 F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, //
32 F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F
33 ];
29 } 34 }
30 35
31
32 // Frequently used character codes. 36 // Frequently used character codes.
33 class _CharCode { 37 class _CharCode {
34 static const int HT = 9; 38 static const int HT = 9;
35 static const int LF = 10; 39 static const int LF = 10;
36 static const int CR = 13; 40 static const int CR = 13;
37 static const int SP = 32; 41 static const int SP = 32;
38 static const int AMPERSAND = 38; 42 static const int AMPERSAND = 38;
39 static const int COMMA = 44; 43 static const int COMMA = 44;
40 static const int DASH = 45; 44 static const int DASH = 45;
41 static const int SLASH = 47; 45 static const int SLASH = 47;
42 static const int ZERO = 48; 46 static const int ZERO = 48;
43 static const int ONE = 49; 47 static const int ONE = 49;
44 static const int COLON = 58; 48 static const int COLON = 58;
45 static const int SEMI_COLON = 59; 49 static const int SEMI_COLON = 59;
46 static const int EQUAL = 61; 50 static const int EQUAL = 61;
47 } 51 }
48 52
49
50 // States of the HTTP parser state machine. 53 // States of the HTTP parser state machine.
51 class _State { 54 class _State {
52 static const int START = 0; 55 static const int START = 0;
53 static const int METHOD_OR_RESPONSE_HTTP_VERSION = 1; 56 static const int METHOD_OR_RESPONSE_HTTP_VERSION = 1;
54 static const int RESPONSE_HTTP_VERSION = 2; 57 static const int RESPONSE_HTTP_VERSION = 2;
55 static const int REQUEST_LINE_METHOD = 3; 58 static const int REQUEST_LINE_METHOD = 3;
56 static const int REQUEST_LINE_URI = 4; 59 static const int REQUEST_LINE_URI = 4;
57 static const int REQUEST_LINE_HTTP_VERSION = 5; 60 static const int REQUEST_LINE_HTTP_VERSION = 5;
58 static const int REQUEST_LINE_ENDING = 6; 61 static const int REQUEST_LINE_ENDING = 6;
59 static const int RESPONSE_LINE_STATUS_CODE = 7; 62 static const int RESPONSE_LINE_STATUS_CODE = 7;
(...skipping 29 matching lines...) Expand all
89 static const int HTTP11 = 2; 92 static const int HTTP11 = 2;
90 } 93 }
91 94
92 // States of the HTTP parser state machine. 95 // States of the HTTP parser state machine.
93 class _MessageType { 96 class _MessageType {
94 static const int UNDETERMINED = 0; 97 static const int UNDETERMINED = 0;
95 static const int REQUEST = 1; 98 static const int REQUEST = 1;
96 static const int RESPONSE = 0; 99 static const int RESPONSE = 0;
97 } 100 }
98 101
99
100 /** 102 /**
101 * The _HttpDetachedStreamSubscription takes a subscription and some extra data, 103 * The _HttpDetachedStreamSubscription takes a subscription and some extra data,
102 * and makes it possible to "inject" the data in from of other data events 104 * and makes it possible to "inject" the data in from of other data events
103 * from the subscription. 105 * from the subscription.
104 * 106 *
105 * It does so by overriding pause/resume, so that once the 107 * It does so by overriding pause/resume, so that once the
106 * _HttpDetachedStreamSubscription is resumed, it'll deliver the data before 108 * _HttpDetachedStreamSubscription is resumed, it'll deliver the data before
107 * resuming the underlaying subscription. 109 * resuming the underlaying subscription.
108 */ 110 */
109 class _HttpDetachedStreamSubscription implements StreamSubscription<List<int>> { 111 class _HttpDetachedStreamSubscription implements StreamSubscription<List<int>> {
110 StreamSubscription<List<int>> _subscription; 112 StreamSubscription<List<int>> _subscription;
111 List<int> _injectData; 113 List<int> _injectData;
112 bool _isCanceled = false; 114 bool _isCanceled = false;
113 int _pauseCount = 1; 115 int _pauseCount = 1;
114 Function _userOnData; 116 Function _userOnData;
115 bool _scheduled = false; 117 bool _scheduled = false;
116 118
117 _HttpDetachedStreamSubscription(this._subscription, 119 _HttpDetachedStreamSubscription(
118 this._injectData, 120 this._subscription, this._injectData, this._userOnData);
119 this._userOnData);
120 121
121 bool get isPaused => _subscription.isPaused; 122 bool get isPaused => _subscription.isPaused;
122 123
123 Future<T> asFuture<T>([T futureValue]) => 124 Future<T>
124 _subscription.asFuture<T>(futureValue); 125 asFuture<T>([T futureValue]) => _subscription.asFuture<T>(futureValue);
125 126
126 Future cancel() { 127 Future cancel() {
127 _isCanceled = true; 128 _isCanceled = true;
128 _injectData = null; 129 _injectData = null;
129 return _subscription.cancel(); 130 return _subscription.cancel();
130 } 131 }
131 132
132 void onData(void handleData(List<int> data)) { 133 void onData(void handleData(List<int> data)) {
133 _userOnData = handleData; 134 _userOnData = handleData;
134 _subscription.onData(handleData); 135 _subscription.onData(handleData);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 // To ensure that 'subscription.isPaused' is false, we resume the 175 // To ensure that 'subscription.isPaused' is false, we resume the
175 // subscription here. This is fine as potential events are delayed. 176 // subscription here. This is fine as potential events are delayed.
176 _subscription.resume(); 177 _subscription.resume();
177 if (_userOnData != null) { 178 if (_userOnData != null) {
178 _userOnData(data); 179 _userOnData(data);
179 } 180 }
180 }); 181 });
181 } 182 }
182 } 183 }
183 184
184
185 class _HttpDetachedIncoming extends Stream<List<int>> { 185 class _HttpDetachedIncoming extends Stream<List<int>> {
186 final StreamSubscription<List<int>> subscription; 186 final StreamSubscription<List<int>> subscription;
187 final List<int> bufferedData; 187 final List<int> bufferedData;
188 188
189 _HttpDetachedIncoming(this.subscription, this.bufferedData); 189 _HttpDetachedIncoming(this.subscription, this.bufferedData);
190 190
191 StreamSubscription<List<int>> listen(void onData(List<int> event), 191 StreamSubscription<List<int>> listen(void onData(List<int> event),
192 {Function onError, 192 {Function onError, void onDone(), bool cancelOnError}) {
193 void onDone(),
194 bool cancelOnError}) {
195 if (subscription != null) { 193 if (subscription != null) {
196 subscription 194 subscription
197 ..onData(onData) 195 ..onData(onData)
198 ..onError(onError) 196 ..onError(onError)
199 ..onDone(onDone); 197 ..onDone(onDone);
200 if (bufferedData == null) { 198 if (bufferedData == null) {
201 return subscription..resume(); 199 return subscription..resume();
202 } 200 }
203 return new _HttpDetachedStreamSubscription(subscription, 201 return new _HttpDetachedStreamSubscription(
204 bufferedData, 202 subscription, bufferedData, onData)..resume();
205 onData)
206 ..resume();
207 } else { 203 } else {
208 // TODO(26379): add test for this branch. 204 // TODO(26379): add test for this branch.
209 return new Stream<List<int>>.fromIterable([bufferedData]) 205 return new Stream<List<int>>.fromIterable([bufferedData]).listen(onData,
210 .listen(onData, 206 onError: onError, onDone: onDone, cancelOnError: cancelOnError);
211 onError: onError,
212 onDone: onDone,
213 cancelOnError: cancelOnError);
214 } 207 }
215 } 208 }
216 } 209 }
217 210
218
219 /** 211 /**
220 * HTTP parser which parses the data stream given to [consume]. 212 * HTTP parser which parses the data stream given to [consume].
221 * 213 *
222 * If an HTTP parser error occours, the parser will signal an error to either 214 * If an HTTP parser error occours, the parser will signal an error to either
223 * the current _HttpIncoming or the _parser itself. 215 * the current _HttpIncoming or the _parser itself.
224 * 216 *
225 * The connection upgrades (e.g. switching from HTTP/1.1 to the 217 * The connection upgrades (e.g. switching from HTTP/1.1 to the
226 * WebSocket protocol) is handled in a special way. If connection 218 * WebSocket protocol) is handled in a special way. If connection
227 * upgrade is specified in the headers, then on the callback to 219 * upgrade is specified in the headers, then on the callback to
228 * [:responseStart:] the [:upgrade:] property on the [:HttpParser:] 220 * [:responseStart:] the [:upgrade:] property on the [:HttpParser:]
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 _pauseStateChanged(); 289 _pauseStateChanged();
298 }, 290 },
299 onCancel: () { 291 onCancel: () {
300 if (_socketSubscription != null) { 292 if (_socketSubscription != null) {
301 _socketSubscription.cancel(); 293 _socketSubscription.cancel();
302 } 294 }
303 }); 295 });
304 _reset(); 296 _reset();
305 } 297 }
306 298
307
308 StreamSubscription<_HttpIncoming> listen(void onData(_HttpIncoming event), 299 StreamSubscription<_HttpIncoming> listen(void onData(_HttpIncoming event),
309 {Function onError, 300 {Function onError, void onDone(), bool cancelOnError}) {
310 void onDone(),
311 bool cancelOnError}) {
312 return _controller.stream.listen(onData, 301 return _controller.stream.listen(onData,
313 onError: onError, 302 onError: onError, onDone: onDone, cancelOnError: cancelOnError);
314 onDone: onDone,
315 cancelOnError: cancelOnError);
316 } 303 }
317 304
318 void listenToStream(Stream<List<int>> stream) { 305 void listenToStream(Stream<List<int>> stream) {
319 // Listen to the stream and handle data accordingly. When a 306 // Listen to the stream and handle data accordingly. When a
320 // _HttpIncoming is created, _dataPause, _dataResume, _dataDone is 307 // _HttpIncoming is created, _dataPause, _dataResume, _dataDone is
321 // given to provide a way of controlling the parser. 308 // given to provide a way of controlling the parser.
322 // TODO(ajohnsen): Remove _dataPause, _dataResume and _dataDone and clean up 309 // TODO(ajohnsen): Remove _dataPause, _dataResume and _dataDone and clean up
323 // how the _HttpIncoming signals the parser. 310 // how the _HttpIncoming signals the parser.
324 _socketSubscription = stream.listen( 311 _socketSubscription =
325 _onData, 312 stream.listen(_onData, onError: _controller.addError, onDone: _onDone);
326 onError: _controller.addError,
327 onDone: _onDone);
328 } 313 }
329 314
330 void _parse() { 315 void _parse() {
331 try { 316 try {
332 _doParse(); 317 _doParse();
333 } catch (e, s) { 318 } catch (e, s) {
334 _state = _State.FAILURE; 319 _state = _State.FAILURE;
335 _reportError(e, s); 320 _reportError(e, s);
336 } 321 }
337 } 322 }
338 323
339 // Process end of headers. Returns true if the parser should stop 324 // Process end of headers. Returns true if the parser should stop
340 // parsing and return. This will be in case of either an upgrade 325 // parsing and return. This will be in case of either an upgrade
341 // request or a request or response with an empty body. 326 // request or a request or response with an empty body.
342 bool _headersEnd() { 327 bool _headersEnd() {
343 _headers._mutable = false; 328 _headers._mutable = false;
344 329
345 _transferLength = _headers.contentLength; 330 _transferLength = _headers.contentLength;
346 // Ignore the Content-Length header if Transfer-Encoding 331 // Ignore the Content-Length header if Transfer-Encoding
347 // is chunked (RFC 2616 section 4.4) 332 // is chunked (RFC 2616 section 4.4)
348 if (_chunked) _transferLength = -1; 333 if (_chunked) _transferLength = -1;
349 334
350 // If a request message has neither Content-Length nor 335 // If a request message has neither Content-Length nor
351 // Transfer-Encoding the message must not have a body (RFC 336 // Transfer-Encoding the message must not have a body (RFC
352 // 2616 section 4.3). 337 // 2616 section 4.3).
353 if (_messageType == _MessageType.REQUEST && 338 if (_messageType == _MessageType.REQUEST &&
354 _transferLength < 0 && 339 _transferLength < 0 &&
355 _chunked == false) { 340 _chunked == false) {
356 _transferLength = 0; 341 _transferLength = 0;
357 } 342 }
358 if (_connectionUpgrade) { 343 if (_connectionUpgrade) {
359 _state = _State.UPGRADED; 344 _state = _State.UPGRADED;
360 _transferLength = 0; 345 _transferLength = 0;
361 } 346 }
362 _createIncoming(_transferLength); 347 _createIncoming(_transferLength);
363 if (_requestParser) { 348 if (_requestParser) {
364 _incoming.method = 349 _incoming.method = new String.fromCharCodes(_method);
365 new String.fromCharCodes(_method);
366 _incoming.uri = 350 _incoming.uri =
367 Uri.parse( 351 Uri.parse(new String.fromCharCodes(_uri_or_reason_phrase));
368 new String.fromCharCodes(_uri_or_reason_phrase));
369 } else { 352 } else {
370 _incoming.statusCode = _statusCode; 353 _incoming.statusCode = _statusCode;
371 _incoming.reasonPhrase = 354 _incoming.reasonPhrase = new String.fromCharCodes(_uri_or_reason_phrase);
372 new String.fromCharCodes(_uri_or_reason_phrase);
373 } 355 }
374 _method.clear(); 356 _method.clear();
375 _uri_or_reason_phrase.clear(); 357 _uri_or_reason_phrase.clear();
376 if (_connectionUpgrade) { 358 if (_connectionUpgrade) {
377 _incoming.upgraded = true; 359 _incoming.upgraded = true;
378 _parserCalled = false; 360 _parserCalled = false;
379 var tmp = _incoming; 361 var tmp = _incoming;
380 _closeIncoming(); 362 _closeIncoming();
381 _controller.add(tmp); 363 _controller.add(tmp);
382 return true; 364 return true;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 void _doParse() { 398 void _doParse() {
417 assert(!_parserCalled); 399 assert(!_parserCalled);
418 _parserCalled = true; 400 _parserCalled = true;
419 if (_state == _State.CLOSED) { 401 if (_state == _State.CLOSED) {
420 throw new HttpException("Data on closed connection"); 402 throw new HttpException("Data on closed connection");
421 } 403 }
422 if (_state == _State.FAILURE) { 404 if (_state == _State.FAILURE) {
423 throw new HttpException("Data on failed connection"); 405 throw new HttpException("Data on failed connection");
424 } 406 }
425 while (_buffer != null && 407 while (_buffer != null &&
426 _index < _buffer.length && 408 _index < _buffer.length &&
427 _state != _State.FAILURE && 409 _state != _State.FAILURE &&
428 _state != _State.UPGRADED) { 410 _state != _State.UPGRADED) {
429 // Depending on _incoming, we either break on _bodyPaused or _paused. 411 // Depending on _incoming, we either break on _bodyPaused or _paused.
430 if ((_incoming != null && _bodyPaused) || 412 if ((_incoming != null && _bodyPaused) ||
431 (_incoming == null && _paused)) { 413 (_incoming == null && _paused)) {
432 _parserCalled = false; 414 _parserCalled = false;
433 return; 415 return;
434 } 416 }
435 int byte = _buffer[_index++]; 417 int byte = _buffer[_index++];
436 switch (_state) { 418 switch (_state) {
437 case _State.START: 419 case _State.START:
438 if (byte == _Const.HTTP[0]) { 420 if (byte == _Const.HTTP[0]) {
(...skipping 12 matching lines...) Expand all
451 _state = _State.REQUEST_LINE_METHOD; 433 _state = _State.REQUEST_LINE_METHOD;
452 } 434 }
453 break; 435 break;
454 436
455 case _State.METHOD_OR_RESPONSE_HTTP_VERSION: 437 case _State.METHOD_OR_RESPONSE_HTTP_VERSION:
456 if (_httpVersionIndex < _Const.HTTP.length && 438 if (_httpVersionIndex < _Const.HTTP.length &&
457 byte == _Const.HTTP[_httpVersionIndex]) { 439 byte == _Const.HTTP[_httpVersionIndex]) {
458 // Continue parsing HTTP version. 440 // Continue parsing HTTP version.
459 _httpVersionIndex++; 441 _httpVersionIndex++;
460 } else if (_httpVersionIndex == _Const.HTTP.length && 442 } else if (_httpVersionIndex == _Const.HTTP.length &&
461 byte == _CharCode.SLASH) { 443 byte == _CharCode.SLASH) {
462 // HTTP/ parsed. As method is a token this cannot be a 444 // HTTP/ parsed. As method is a token this cannot be a
463 // method anymore. 445 // method anymore.
464 _httpVersionIndex++; 446 _httpVersionIndex++;
465 if (_requestParser) { 447 if (_requestParser) {
466 throw new HttpException("Invalid request line"); 448 throw new HttpException("Invalid request line");
467 } 449 }
468 _state = _State.RESPONSE_HTTP_VERSION; 450 _state = _State.RESPONSE_HTTP_VERSION;
469 } else { 451 } else {
470 // Did not parse HTTP version. Expect method instead. 452 // Did not parse HTTP version. Expect method instead.
471 for (int i = 0; i < _httpVersionIndex; i++) { 453 for (int i = 0; i < _httpVersionIndex; i++) {
(...skipping 11 matching lines...) Expand all
483 } 465 }
484 } 466 }
485 break; 467 break;
486 468
487 case _State.RESPONSE_HTTP_VERSION: 469 case _State.RESPONSE_HTTP_VERSION:
488 if (_httpVersionIndex < _Const.HTTP1DOT.length) { 470 if (_httpVersionIndex < _Const.HTTP1DOT.length) {
489 // Continue parsing HTTP version. 471 // Continue parsing HTTP version.
490 _expect(byte, _Const.HTTP1DOT[_httpVersionIndex]); 472 _expect(byte, _Const.HTTP1DOT[_httpVersionIndex]);
491 _httpVersionIndex++; 473 _httpVersionIndex++;
492 } else if (_httpVersionIndex == _Const.HTTP1DOT.length && 474 } else if (_httpVersionIndex == _Const.HTTP1DOT.length &&
493 byte == _CharCode.ONE) { 475 byte == _CharCode.ONE) {
494 // HTTP/1.1 parsed. 476 // HTTP/1.1 parsed.
495 _httpVersion = _HttpVersion.HTTP11; 477 _httpVersion = _HttpVersion.HTTP11;
496 _persistentConnection = true; 478 _persistentConnection = true;
497 _httpVersionIndex++; 479 _httpVersionIndex++;
498 } else if (_httpVersionIndex == _Const.HTTP1DOT.length && 480 } else if (_httpVersionIndex == _Const.HTTP1DOT.length &&
499 byte == _CharCode.ZERO) { 481 byte == _CharCode.ZERO) {
500 // HTTP/1.0 parsed. 482 // HTTP/1.0 parsed.
501 _httpVersion = _HttpVersion.HTTP10; 483 _httpVersion = _HttpVersion.HTTP10;
502 _persistentConnection = false; 484 _persistentConnection = false;
503 _httpVersionIndex++; 485 _httpVersionIndex++;
504 } else if (_httpVersionIndex == _Const.HTTP1DOT.length + 1) { 486 } else if (_httpVersionIndex == _Const.HTTP1DOT.length + 1) {
505 _expect(byte, _CharCode.SP); 487 _expect(byte, _CharCode.SP);
506 // HTTP version parsed. 488 // HTTP version parsed.
507 _state = _State.RESPONSE_LINE_STATUS_CODE; 489 _state = _State.RESPONSE_LINE_STATUS_CODE;
508 } else { 490 } else {
509 throw new HttpException("Invalid response line"); 491 throw new HttpException("Invalid response line");
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 } 583 }
602 break; 584 break;
603 585
604 case _State.RESPONSE_LINE_ENDING: 586 case _State.RESPONSE_LINE_ENDING:
605 _expect(byte, _CharCode.LF); 587 _expect(byte, _CharCode.LF);
606 _messageType == _MessageType.RESPONSE; 588 _messageType == _MessageType.RESPONSE;
607 if (_statusCode < 100 || _statusCode > 599) { 589 if (_statusCode < 100 || _statusCode > 599) {
608 throw new HttpException("Invalid response status code"); 590 throw new HttpException("Invalid response status code");
609 } else { 591 } else {
610 // Check whether this response will never have a body. 592 // Check whether this response will never have a body.
611 if (_statusCode <= 199 || _statusCode == 204 || 593 if (_statusCode <= 199 ||
594 _statusCode == 204 ||
612 _statusCode == 304) { 595 _statusCode == 304) {
613 _noMessageBody = true; 596 _noMessageBody = true;
614 } 597 }
615 } 598 }
616 _state = _State.HEADER_START; 599 _state = _State.HEADER_START;
617 break; 600 break;
618 601
619 case _State.HEADER_START: 602 case _State.HEADER_START:
620 _headers = new _HttpHeaders(version); 603 _headers = new _HttpHeaders(version);
621 if (byte == _CharCode.CR) { 604 if (byte == _CharCode.CR) {
622 _state = _State.HEADER_ENDING; 605 _state = _State.HEADER_ENDING;
623 } else if (byte == _CharCode.LF) { 606 } else if (byte == _CharCode.LF) {
624 _state = _State.HEADER_ENDING; 607 _state = _State.HEADER_ENDING;
625 _index--; // Make the new state see the LF again. 608 _index--; // Make the new state see the LF again.
626 } else { 609 } else {
627 // Start of new header field. 610 // Start of new header field.
628 _headerField.add(_toLowerCaseByte(byte)); 611 _headerField.add(_toLowerCaseByte(byte));
629 _state = _State.HEADER_FIELD; 612 _state = _State.HEADER_FIELD;
630 } 613 }
631 break; 614 break;
632 615
633 case _State.HEADER_FIELD: 616 case _State.HEADER_FIELD:
634 if (byte == _CharCode.COLON) { 617 if (byte == _CharCode.COLON) {
635 _state = _State.HEADER_VALUE_START; 618 _state = _State.HEADER_VALUE_START;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 } else { 657 } else {
675 String headerField = new String.fromCharCodes(_headerField); 658 String headerField = new String.fromCharCodes(_headerField);
676 String headerValue = new String.fromCharCodes(_headerValue); 659 String headerValue = new String.fromCharCodes(_headerValue);
677 if (headerField == "transfer-encoding" && 660 if (headerField == "transfer-encoding" &&
678 _caseInsensitiveCompare("chunked".codeUnits, _headerValue)) { 661 _caseInsensitiveCompare("chunked".codeUnits, _headerValue)) {
679 _chunked = true; 662 _chunked = true;
680 } 663 }
681 if (headerField == "connection") { 664 if (headerField == "connection") {
682 List<String> tokens = _tokenizeFieldValue(headerValue); 665 List<String> tokens = _tokenizeFieldValue(headerValue);
683 for (int i = 0; i < tokens.length; i++) { 666 for (int i = 0; i < tokens.length; i++) {
684 if (_caseInsensitiveCompare("upgrade".codeUnits, 667 if (_caseInsensitiveCompare(
685 tokens[i].codeUnits)) { 668 "upgrade".codeUnits, tokens[i].codeUnits)) {
686 _connectionUpgrade = true; 669 _connectionUpgrade = true;
687 } 670 }
688 _headers._add(headerField, tokens[i]); 671 _headers._add(headerField, tokens[i]);
689 } 672 }
690 } else { 673 } else {
691 _headers._add(headerField, headerValue); 674 _headers._add(headerField, headerValue);
692 } 675 }
693 _headerField.clear(); 676 _headerField.clear();
694 _headerValue.clear(); 677 _headerValue.clear();
695 678
696 if (byte == _CharCode.CR) { 679 if (byte == _CharCode.CR) {
697 _state = _State.HEADER_ENDING; 680 _state = _State.HEADER_ENDING;
698 } else if (byte == _CharCode.LF) { 681 } else if (byte == _CharCode.LF) {
699 _state = _State.HEADER_ENDING; 682 _state = _State.HEADER_ENDING;
700 _index--; // Make the new state see the LF again. 683 _index--; // Make the new state see the LF again.
701 } else { 684 } else {
702 // Start of new header field. 685 // Start of new header field.
703 _headerField.add(_toLowerCaseByte(byte)); 686 _headerField.add(_toLowerCaseByte(byte));
704 _state = _State.HEADER_FIELD; 687 _state = _State.HEADER_FIELD;
705 } 688 }
706 } 689 }
707 break; 690 break;
708 691
709 case _State.HEADER_ENDING: 692 case _State.HEADER_ENDING:
710 _expect(byte, _CharCode.LF); 693 _expect(byte, _CharCode.LF);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
765 case _State.BODY: 748 case _State.BODY:
766 // The body is not handled one byte at a time but in blocks. 749 // The body is not handled one byte at a time but in blocks.
767 _index--; 750 _index--;
768 int dataAvailable = _buffer.length - _index; 751 int dataAvailable = _buffer.length - _index;
769 if (_remainingContent >= 0 && dataAvailable > _remainingContent) { 752 if (_remainingContent >= 0 && dataAvailable > _remainingContent) {
770 dataAvailable = _remainingContent; 753 dataAvailable = _remainingContent;
771 } 754 }
772 // Always present the data as a view. This way we can handle all 755 // Always present the data as a view. This way we can handle all
773 // cases like this, and the user will not experince different data 756 // cases like this, and the user will not experince different data
774 // typed (which could lead to polymorphic user code). 757 // typed (which could lead to polymorphic user code).
775 List<int> data = new Uint8List.view(_buffer.buffer, 758 List<int> data = new Uint8List.view(
776 _buffer.offsetInBytes + _index, 759 _buffer.buffer, _buffer.offsetInBytes + _index, dataAvailable);
777 dataAvailable);
778 _bodyController.add(data); 760 _bodyController.add(data);
779 if (_remainingContent != -1) { 761 if (_remainingContent != -1) {
780 _remainingContent -= data.length; 762 _remainingContent -= data.length;
781 } 763 }
782 _index += data.length; 764 _index += data.length;
783 if (_remainingContent == 0) { 765 if (_remainingContent == 0) {
784 if (!_chunked) { 766 if (!_chunked) {
785 _reset(); 767 _reset();
786 _closeIncoming(); 768 _closeIncoming();
787 } else { 769 } else {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
824 void _onDone() { 806 void _onDone() {
825 // onDone cancles the subscription. 807 // onDone cancles the subscription.
826 _socketSubscription = null; 808 _socketSubscription = null;
827 if (_state == _State.CLOSED || _state == _State.FAILURE) return; 809 if (_state == _State.CLOSED || _state == _State.FAILURE) return;
828 810
829 if (_incoming != null) { 811 if (_incoming != null) {
830 if (_state != _State.UPGRADED && 812 if (_state != _State.UPGRADED &&
831 !(_state == _State.START && !_requestParser) && 813 !(_state == _State.START && !_requestParser) &&
832 !(_state == _State.BODY && !_chunked && _transferLength == -1)) { 814 !(_state == _State.BODY && !_chunked && _transferLength == -1)) {
833 _bodyController.addError( 815 _bodyController.addError(
834 new HttpException("Connection closed while receiving data")); 816 new HttpException("Connection closed while receiving data"));
835 } 817 }
836 _closeIncoming(true); 818 _closeIncoming(true);
837 _controller.close(); 819 _controller.close();
838 return; 820 return;
839 } 821 }
840 // If the connection is idle the HTTP stream is closed. 822 // If the connection is idle the HTTP stream is closed.
841 if (_state == _State.START) { 823 if (_state == _State.START) {
842 if (!_requestParser) { 824 if (!_requestParser) {
843 _reportError(new HttpException( 825 _reportError(new HttpException(
844 "Connection closed before full header was received")); 826 "Connection closed before full header was received"));
845 } 827 }
846 _controller.close(); 828 _controller.close();
847 return; 829 return;
848 } 830 }
849 831
850 if (_state == _State.UPGRADED) { 832 if (_state == _State.UPGRADED) {
851 _controller.close(); 833 _controller.close();
852 return; 834 return;
853 } 835 }
854 836
855 if (_state < _State.FIRST_BODY_STATE) { 837 if (_state < _State.FIRST_BODY_STATE) {
856 _state = _State.FAILURE; 838 _state = _State.FAILURE;
857 // Report the error through the error callback if any. Otherwise 839 // Report the error through the error callback if any. Otherwise
858 // throw the error. 840 // throw the error.
859 _reportError(new HttpException( 841 _reportError(new HttpException(
860 "Connection closed before full header was received")); 842 "Connection closed before full header was received"));
861 _controller.close(); 843 _controller.close();
862 return; 844 return;
863 } 845 }
864 846
865 if (!_chunked && _transferLength == -1) { 847 if (!_chunked && _transferLength == -1) {
866 _state = _State.CLOSED; 848 _state = _State.CLOSED;
867 } else { 849 } else {
868 _state = _State.FAILURE; 850 _state = _State.FAILURE;
869 // Report the error through the error callback if any. Otherwise 851 // Report the error through the error callback if any. Otherwise
870 // throw the error. 852 // throw the error.
871 _reportError(new HttpException( 853 _reportError(
872 "Connection closed before full body was received")); 854 new HttpException("Connection closed before full body was received"));
873 } 855 }
874 _controller.close(); 856 _controller.close();
875 } 857 }
876 858
877 String get version { 859 String get version {
878 switch (_httpVersion) { 860 switch (_httpVersion) {
879 case _HttpVersion.HTTP10: 861 case _HttpVersion.HTTP10:
880 return "1.0"; 862 return "1.0";
881 case _HttpVersion.HTTP11: 863 case _HttpVersion.HTTP11:
882 return "1.1"; 864 return "1.1";
883 } 865 }
884 return null; 866 return null;
885 } 867 }
886 868
887 int get messageType => _messageType; 869 int get messageType => _messageType;
888 int get transferLength => _transferLength; 870 int get transferLength => _transferLength;
889 bool get upgrade => _connectionUpgrade && _state == _State.UPGRADED; 871 bool get upgrade => _connectionUpgrade && _state == _State.UPGRADED;
890 bool get persistentConnection => _persistentConnection; 872 bool get persistentConnection => _persistentConnection;
891 873
892 void set isHead(bool value) { 874 void set isHead(bool value) {
893 if (value) _noMessageBody = true; 875 if (value) _noMessageBody = true;
894 } 876 }
895 877
896 _HttpDetachedIncoming detachIncoming() { 878 _HttpDetachedIncoming detachIncoming() {
897 // Simulate detached by marking as upgraded. 879 // Simulate detached by marking as upgraded.
898 _state = _State.UPGRADED; 880 _state = _State.UPGRADED;
899 return new _HttpDetachedIncoming(_socketSubscription, 881 return new _HttpDetachedIncoming(_socketSubscription, readUnparsedData());
900 readUnparsedData());
901 } 882 }
902 883
903 List<int> readUnparsedData() { 884 List<int> readUnparsedData() {
904 if (_buffer == null) return null; 885 if (_buffer == null) return null;
905 if (_index == _buffer.length) return null; 886 if (_index == _buffer.length) return null;
906 var result = _buffer.sublist(_index); 887 var result = _buffer.sublist(_index);
907 _releaseBuffer(); 888 _releaseBuffer();
908 return result; 889 return result;
909 } 890 }
910 891
(...skipping 24 matching lines...) Expand all
935 void _releaseBuffer() { 916 void _releaseBuffer() {
936 _buffer = null; 917 _buffer = null;
937 _index = null; 918 _index = null;
938 } 919 }
939 920
940 static bool _isTokenChar(int byte) { 921 static bool _isTokenChar(int byte) {
941 return byte > 31 && byte < 128 && !_Const.SEPARATOR_MAP[byte]; 922 return byte > 31 && byte < 128 && !_Const.SEPARATOR_MAP[byte];
942 } 923 }
943 924
944 static bool _isValueChar(int byte) { 925 static bool _isValueChar(int byte) {
945 return (byte > 31 && byte < 128) || (byte == _CharCode.SP) || 926 return (byte > 31 && byte < 128) ||
927 (byte == _CharCode.SP) ||
946 (byte == _CharCode.HT); 928 (byte == _CharCode.HT);
947 } 929 }
948 930
949 static List<String> _tokenizeFieldValue(String headerValue) { 931 static List<String> _tokenizeFieldValue(String headerValue) {
950 List<String> tokens = new List<String>(); 932 List<String> tokens = new List<String>();
951 int start = 0; 933 int start = 0;
952 int index = 0; 934 int index = 0;
953 while (index < headerValue.length) { 935 while (index < headerValue.length) {
954 if (headerValue[index] == ",") { 936 if (headerValue[index] == ",") {
955 tokens.add(headerValue.substring(start, index)); 937 tokens.add(headerValue.substring(start, index));
(...skipping 26 matching lines...) Expand all
982 } 964 }
983 965
984 int _expect(int val1, int val2) { 966 int _expect(int val1, int val2) {
985 if (val1 != val2) { 967 if (val1 != val2) {
986 throw new HttpException("Failed to parse HTTP"); 968 throw new HttpException("Failed to parse HTTP");
987 } 969 }
988 } 970 }
989 971
990 int _expectHexDigit(int byte) { 972 int _expectHexDigit(int byte) {
991 if (0x30 <= byte && byte <= 0x39) { 973 if (0x30 <= byte && byte <= 0x39) {
992 return byte - 0x30; // 0 - 9 974 return byte - 0x30; // 0 - 9
993 } else if (0x41 <= byte && byte <= 0x46) { 975 } else if (0x41 <= byte && byte <= 0x46) {
994 return byte - 0x41 + 10; // A - F 976 return byte - 0x41 + 10; // A - F
995 } else if (0x61 <= byte && byte <= 0x66) { 977 } else if (0x61 <= byte && byte <= 0x66) {
996 return byte - 0x61 + 10; // a - f 978 return byte - 0x61 + 10; // a - f
997 } else { 979 } else {
998 throw new HttpException("Failed to parse HTTP"); 980 throw new HttpException("Failed to parse HTTP");
999 } 981 }
1000 } 982 }
1001 983
1002 void _createIncoming(int transferLength) { 984 void _createIncoming(int transferLength) {
1003 assert(_incoming == null); 985 assert(_incoming == null);
1004 assert(_bodyController == null); 986 assert(_bodyController == null);
1005 assert(!_bodyPaused); 987 assert(!_bodyPaused);
1006 var incoming; 988 var incoming;
(...skipping 18 matching lines...) Expand all
1025 _pauseStateChanged(); 1007 _pauseStateChanged();
1026 }, 1008 },
1027 onCancel: () { 1009 onCancel: () {
1028 if (incoming != _incoming) return; 1010 if (incoming != _incoming) return;
1029 if (_socketSubscription != null) { 1011 if (_socketSubscription != null) {
1030 _socketSubscription.cancel(); 1012 _socketSubscription.cancel();
1031 } 1013 }
1032 _closeIncoming(true); 1014 _closeIncoming(true);
1033 _controller.close(); 1015 _controller.close();
1034 }); 1016 });
1035 incoming = _incoming = new _HttpIncoming( 1017 incoming = _incoming =
1036 _headers, transferLength, _bodyController.stream); 1018 new _HttpIncoming(_headers, transferLength, _bodyController.stream);
1037 _bodyPaused = true; 1019 _bodyPaused = true;
1038 _pauseStateChanged(); 1020 _pauseStateChanged();
1039 } 1021 }
1040 1022
1041 void _closeIncoming([bool closing = false]) { 1023 void _closeIncoming([bool closing = false]) {
1042 // Ignore multiple close (can happen in re-entrance). 1024 // Ignore multiple close (can happen in re-entrance).
1043 if (_incoming == null) return; 1025 if (_incoming == null) return;
1044 var tmp = _incoming; 1026 var tmp = _incoming;
1045 tmp.close(closing); 1027 tmp.close(closing);
1046 _incoming = null; 1028 _incoming = null;
(...skipping 17 matching lines...) Expand all
1064 } 1046 }
1065 } 1047 }
1066 1048
1067 void _reportError(error, [stackTrace]) { 1049 void _reportError(error, [stackTrace]) {
1068 if (_socketSubscription != null) _socketSubscription.cancel(); 1050 if (_socketSubscription != null) _socketSubscription.cancel();
1069 _state = _State.FAILURE; 1051 _state = _State.FAILURE;
1070 _controller.addError(error, stackTrace); 1052 _controller.addError(error, stackTrace);
1071 _controller.close(); 1053 _controller.close();
1072 } 1054 }
1073 } 1055 }
OLDNEW
« no previous file with comments | « sdk/lib/io/crypto.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698