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

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

Issue 2754013002: Format all dart: library files (Closed)
Patch Set: 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
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,
floitsch 2017/03/16 10:37:54 This really makes reading this file harder.
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,
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,
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,
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,
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,
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,
29 F,
30 F,
31 T,
32 F,
33 F,
34 F,
35 F,
36 F,
37 F,
38 F,
39 F,
40 F,
41 F,
42 F,
43 F,
44 F,
45 F,
46 F,
47 F,
48 F,
49 F,
50 F,
51 F,
52 F,
53 F,
54 T,
55 F,
56 T,
57 F,
58 F,
59 F,
60 F,
61 F,
62 T,
63 T,
64 F,
65 F,
66 T,
67 F,
68 F,
69 T,
70 F,
71 F,
72 F,
73 F,
74 F,
75 F,
76 F,
77 F,
78 F,
79 F,
80 T,
81 T,
82 T,
83 T,
84 T,
85 T,
86 T,
87 F,
88 F,
89 F,
90 F,
91 F,
92 F,
93 F,
94 F,
95 F,
96 F,
97 F,
98 F,
99 F,
100 F,
101 F,
102 F,
103 F,
104 F,
105 F,
106 F,
107 F,
108 F,
109 F,
110 F,
111 F,
112 F,
113 T,
114 T,
115 T,
116 F,
117 F,
118 F,
119 F,
120 F,
121 F,
122 F,
123 F,
124 F,
125 F,
126 F,
127 F,
128 F,
129 F,
130 F,
131 F,
132 F,
133 F,
134 F,
135 F,
136 F,
137 F,
138 F,
139 F,
140 F,
141 F,
142 F,
143 F,
144 F,
145 T,
146 F,
147 T,
148 F,
149 F,
150 F,
151 F,
152 F,
153 F,
154 F,
155 F,
156 F,
157 F,
158 F,
159 F,
160 F,
161 F,
162 F,
163 F,
164 F,
165 F,
166 F,
167 F,
168 F,
169 F,
170 F,
171 F,
172 F,
173 F,
174 F,
175 F,
176 F,
177 F,
178 F,
179 F,
180 F,
181 F,
182 F,
183 F,
184 F,
185 F,
186 F,
187 F,
188 F,
189 F,
190 F,
191 F,
192 F,
193 F,
194 F,
195 F,
196 F,
197 F,
198 F,
199 F,
200 F,
201 F,
202 F,
203 F,
204 F,
205 F,
206 F,
207 F,
208 F,
209 F,
210 F,
211 F,
212 F,
213 F,
214 F,
215 F,
216 F,
217 F,
218 F,
219 F,
220 F,
221 F,
222 F,
223 F,
224 F,
225 F,
226 F,
227 F,
228 F,
229 F,
230 F,
231 F,
232 F,
233 F,
234 F,
235 F,
236 F,
237 F,
238 F,
239 F,
240 F,
241 F,
242 F,
243 F,
244 F,
245 F,
246 F,
247 F,
248 F,
249 F,
250 F,
251 F,
252 F,
253 F,
254 F,
255 F,
256 F,
257 F,
258 F,
259 F,
260 F,
261 F,
262 F,
263 F,
264 F,
265 F,
266 F,
267 F,
268 F,
269 F,
270 F,
271 F,
272 F,
273 F,
274 F,
275 F,
276 F,
277 F
278 ];
29 } 279 }
30 280
31
32 // Frequently used character codes. 281 // Frequently used character codes.
33 class _CharCode { 282 class _CharCode {
34 static const int HT = 9; 283 static const int HT = 9;
35 static const int LF = 10; 284 static const int LF = 10;
36 static const int CR = 13; 285 static const int CR = 13;
37 static const int SP = 32; 286 static const int SP = 32;
38 static const int AMPERSAND = 38; 287 static const int AMPERSAND = 38;
39 static const int COMMA = 44; 288 static const int COMMA = 44;
40 static const int DASH = 45; 289 static const int DASH = 45;
41 static const int SLASH = 47; 290 static const int SLASH = 47;
42 static const int ZERO = 48; 291 static const int ZERO = 48;
43 static const int ONE = 49; 292 static const int ONE = 49;
44 static const int COLON = 58; 293 static const int COLON = 58;
45 static const int SEMI_COLON = 59; 294 static const int SEMI_COLON = 59;
46 static const int EQUAL = 61; 295 static const int EQUAL = 61;
47 } 296 }
48 297
49
50 // States of the HTTP parser state machine. 298 // States of the HTTP parser state machine.
51 class _State { 299 class _State {
52 static const int START = 0; 300 static const int START = 0;
53 static const int METHOD_OR_RESPONSE_HTTP_VERSION = 1; 301 static const int METHOD_OR_RESPONSE_HTTP_VERSION = 1;
54 static const int RESPONSE_HTTP_VERSION = 2; 302 static const int RESPONSE_HTTP_VERSION = 2;
55 static const int REQUEST_LINE_METHOD = 3; 303 static const int REQUEST_LINE_METHOD = 3;
56 static const int REQUEST_LINE_URI = 4; 304 static const int REQUEST_LINE_URI = 4;
57 static const int REQUEST_LINE_HTTP_VERSION = 5; 305 static const int REQUEST_LINE_HTTP_VERSION = 5;
58 static const int REQUEST_LINE_ENDING = 6; 306 static const int REQUEST_LINE_ENDING = 6;
59 static const int RESPONSE_LINE_STATUS_CODE = 7; 307 static const int RESPONSE_LINE_STATUS_CODE = 7;
(...skipping 29 matching lines...) Expand all
89 static const int HTTP11 = 2; 337 static const int HTTP11 = 2;
90 } 338 }
91 339
92 // States of the HTTP parser state machine. 340 // States of the HTTP parser state machine.
93 class _MessageType { 341 class _MessageType {
94 static const int UNDETERMINED = 0; 342 static const int UNDETERMINED = 0;
95 static const int REQUEST = 1; 343 static const int REQUEST = 1;
96 static const int RESPONSE = 0; 344 static const int RESPONSE = 0;
97 } 345 }
98 346
99
100 /** 347 /**
101 * The _HttpDetachedStreamSubscription takes a subscription and some extra data, 348 * The _HttpDetachedStreamSubscription takes a subscription and some extra data,
102 * and makes it possible to "inject" the data in from of other data events 349 * and makes it possible to "inject" the data in from of other data events
103 * from the subscription. 350 * from the subscription.
104 * 351 *
105 * It does so by overriding pause/resume, so that once the 352 * It does so by overriding pause/resume, so that once the
106 * _HttpDetachedStreamSubscription is resumed, it'll deliver the data before 353 * _HttpDetachedStreamSubscription is resumed, it'll deliver the data before
107 * resuming the underlaying subscription. 354 * resuming the underlaying subscription.
108 */ 355 */
109 class _HttpDetachedStreamSubscription implements StreamSubscription<List<int>> { 356 class _HttpDetachedStreamSubscription implements StreamSubscription<List<int>> {
110 StreamSubscription<List<int>> _subscription; 357 StreamSubscription<List<int>> _subscription;
111 List<int> _injectData; 358 List<int> _injectData;
112 bool _isCanceled = false; 359 bool _isCanceled = false;
113 int _pauseCount = 1; 360 int _pauseCount = 1;
114 Function _userOnData; 361 Function _userOnData;
115 bool _scheduled = false; 362 bool _scheduled = false;
116 363
117 _HttpDetachedStreamSubscription(this._subscription, 364 _HttpDetachedStreamSubscription(
118 this._injectData, 365 this._subscription, this._injectData, this._userOnData);
119 this._userOnData);
120 366
121 bool get isPaused => _subscription.isPaused; 367 bool get isPaused => _subscription.isPaused;
122 368
123 Future<T> asFuture<T>([T futureValue]) => 369 Future<T>
124 _subscription.asFuture<T>(futureValue); 370 asFuture<T>([T futureValue]) => _subscription.asFuture<T>(futureValue);
125 371
126 Future cancel() { 372 Future cancel() {
127 _isCanceled = true; 373 _isCanceled = true;
128 _injectData = null; 374 _injectData = null;
129 return _subscription.cancel(); 375 return _subscription.cancel();
130 } 376 }
131 377
132 void onData(void handleData(List<int> data)) { 378 void onData(void handleData(List<int> data)) {
133 _userOnData = handleData; 379 _userOnData = handleData;
134 _subscription.onData(handleData); 380 _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 420 // To ensure that 'subscription.isPaused' is false, we resume the
175 // subscription here. This is fine as potential events are delayed. 421 // subscription here. This is fine as potential events are delayed.
176 _subscription.resume(); 422 _subscription.resume();
177 if (_userOnData != null) { 423 if (_userOnData != null) {
178 _userOnData(data); 424 _userOnData(data);
179 } 425 }
180 }); 426 });
181 } 427 }
182 } 428 }
183 429
184
185 class _HttpDetachedIncoming extends Stream<List<int>> { 430 class _HttpDetachedIncoming extends Stream<List<int>> {
186 final StreamSubscription<List<int>> subscription; 431 final StreamSubscription<List<int>> subscription;
187 final List<int> bufferedData; 432 final List<int> bufferedData;
188 433
189 _HttpDetachedIncoming(this.subscription, this.bufferedData); 434 _HttpDetachedIncoming(this.subscription, this.bufferedData);
190 435
191 StreamSubscription<List<int>> listen(void onData(List<int> event), 436 StreamSubscription<List<int>> listen(void onData(List<int> event),
192 {Function onError, 437 {Function onError, void onDone(), bool cancelOnError}) {
193 void onDone(),
194 bool cancelOnError}) {
195 if (subscription != null) { 438 if (subscription != null) {
196 subscription 439 subscription
197 ..onData(onData) 440 ..onData(onData)
198 ..onError(onError) 441 ..onError(onError)
199 ..onDone(onDone); 442 ..onDone(onDone);
200 if (bufferedData == null) { 443 if (bufferedData == null) {
201 return subscription..resume(); 444 return subscription..resume();
202 } 445 }
203 return new _HttpDetachedStreamSubscription(subscription, 446 return new _HttpDetachedStreamSubscription(
204 bufferedData, 447 subscription, bufferedData, onData)..resume();
205 onData)
206 ..resume();
207 } else { 448 } else {
208 // TODO(26379): add test for this branch. 449 // TODO(26379): add test for this branch.
209 return new Stream<List<int>>.fromIterable([bufferedData]) 450 return new Stream<List<int>>.fromIterable([bufferedData]).listen(onData,
210 .listen(onData, 451 onError: onError, onDone: onDone, cancelOnError: cancelOnError);
211 onError: onError,
212 onDone: onDone,
213 cancelOnError: cancelOnError);
214 } 452 }
215 } 453 }
216 } 454 }
217 455
218
219 /** 456 /**
220 * HTTP parser which parses the data stream given to [consume]. 457 * HTTP parser which parses the data stream given to [consume].
221 * 458 *
222 * If an HTTP parser error occours, the parser will signal an error to either 459 * If an HTTP parser error occours, the parser will signal an error to either
223 * the current _HttpIncoming or the _parser itself. 460 * the current _HttpIncoming or the _parser itself.
224 * 461 *
225 * The connection upgrades (e.g. switching from HTTP/1.1 to the 462 * The connection upgrades (e.g. switching from HTTP/1.1 to the
226 * WebSocket protocol) is handled in a special way. If connection 463 * WebSocket protocol) is handled in a special way. If connection
227 * upgrade is specified in the headers, then on the callback to 464 * upgrade is specified in the headers, then on the callback to
228 * [:responseStart:] the [:upgrade:] property on the [:HttpParser:] 465 * [:responseStart:] the [:upgrade:] property on the [:HttpParser:]
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 _pauseStateChanged(); 534 _pauseStateChanged();
298 }, 535 },
299 onCancel: () { 536 onCancel: () {
300 if (_socketSubscription != null) { 537 if (_socketSubscription != null) {
301 _socketSubscription.cancel(); 538 _socketSubscription.cancel();
302 } 539 }
303 }); 540 });
304 _reset(); 541 _reset();
305 } 542 }
306 543
307
308 StreamSubscription<_HttpIncoming> listen(void onData(_HttpIncoming event), 544 StreamSubscription<_HttpIncoming> listen(void onData(_HttpIncoming event),
309 {Function onError, 545 {Function onError, void onDone(), bool cancelOnError}) {
310 void onDone(),
311 bool cancelOnError}) {
312 return _controller.stream.listen(onData, 546 return _controller.stream.listen(onData,
313 onError: onError, 547 onError: onError, onDone: onDone, cancelOnError: cancelOnError);
314 onDone: onDone,
315 cancelOnError: cancelOnError);
316 } 548 }
317 549
318 void listenToStream(Stream<List<int>> stream) { 550 void listenToStream(Stream<List<int>> stream) {
319 // Listen to the stream and handle data accordingly. When a 551 // Listen to the stream and handle data accordingly. When a
320 // _HttpIncoming is created, _dataPause, _dataResume, _dataDone is 552 // _HttpIncoming is created, _dataPause, _dataResume, _dataDone is
321 // given to provide a way of controlling the parser. 553 // given to provide a way of controlling the parser.
322 // TODO(ajohnsen): Remove _dataPause, _dataResume and _dataDone and clean up 554 // TODO(ajohnsen): Remove _dataPause, _dataResume and _dataDone and clean up
323 // how the _HttpIncoming signals the parser. 555 // how the _HttpIncoming signals the parser.
324 _socketSubscription = stream.listen( 556 _socketSubscription =
325 _onData, 557 stream.listen(_onData, onError: _controller.addError, onDone: _onDone);
326 onError: _controller.addError,
327 onDone: _onDone);
328 } 558 }
329 559
330 void _parse() { 560 void _parse() {
331 try { 561 try {
332 _doParse(); 562 _doParse();
333 } catch (e, s) { 563 } catch (e, s) {
334 _state = _State.FAILURE; 564 _state = _State.FAILURE;
335 _reportError(e, s); 565 _reportError(e, s);
336 } 566 }
337 } 567 }
338 568
339 // Process end of headers. Returns true if the parser should stop 569 // Process end of headers. Returns true if the parser should stop
340 // parsing and return. This will be in case of either an upgrade 570 // parsing and return. This will be in case of either an upgrade
341 // request or a request or response with an empty body. 571 // request or a request or response with an empty body.
342 bool _headersEnd() { 572 bool _headersEnd() {
343 _headers._mutable = false; 573 _headers._mutable = false;
344 574
345 _transferLength = _headers.contentLength; 575 _transferLength = _headers.contentLength;
346 // Ignore the Content-Length header if Transfer-Encoding 576 // Ignore the Content-Length header if Transfer-Encoding
347 // is chunked (RFC 2616 section 4.4) 577 // is chunked (RFC 2616 section 4.4)
348 if (_chunked) _transferLength = -1; 578 if (_chunked) _transferLength = -1;
349 579
350 // If a request message has neither Content-Length nor 580 // If a request message has neither Content-Length nor
351 // Transfer-Encoding the message must not have a body (RFC 581 // Transfer-Encoding the message must not have a body (RFC
352 // 2616 section 4.3). 582 // 2616 section 4.3).
353 if (_messageType == _MessageType.REQUEST && 583 if (_messageType == _MessageType.REQUEST &&
354 _transferLength < 0 && 584 _transferLength < 0 &&
355 _chunked == false) { 585 _chunked == false) {
356 _transferLength = 0; 586 _transferLength = 0;
357 } 587 }
358 if (_connectionUpgrade) { 588 if (_connectionUpgrade) {
359 _state = _State.UPGRADED; 589 _state = _State.UPGRADED;
360 _transferLength = 0; 590 _transferLength = 0;
361 } 591 }
362 _createIncoming(_transferLength); 592 _createIncoming(_transferLength);
363 if (_requestParser) { 593 if (_requestParser) {
364 _incoming.method = 594 _incoming.method = new String.fromCharCodes(_method);
365 new String.fromCharCodes(_method);
366 _incoming.uri = 595 _incoming.uri =
367 Uri.parse( 596 Uri.parse(new String.fromCharCodes(_uri_or_reason_phrase));
368 new String.fromCharCodes(_uri_or_reason_phrase));
369 } else { 597 } else {
370 _incoming.statusCode = _statusCode; 598 _incoming.statusCode = _statusCode;
371 _incoming.reasonPhrase = 599 _incoming.reasonPhrase = new String.fromCharCodes(_uri_or_reason_phrase);
372 new String.fromCharCodes(_uri_or_reason_phrase);
373 } 600 }
374 _method.clear(); 601 _method.clear();
375 _uri_or_reason_phrase.clear(); 602 _uri_or_reason_phrase.clear();
376 if (_connectionUpgrade) { 603 if (_connectionUpgrade) {
377 _incoming.upgraded = true; 604 _incoming.upgraded = true;
378 _parserCalled = false; 605 _parserCalled = false;
379 var tmp = _incoming; 606 var tmp = _incoming;
380 _closeIncoming(); 607 _closeIncoming();
381 _controller.add(tmp); 608 _controller.add(tmp);
382 return true; 609 return true;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 void _doParse() { 643 void _doParse() {
417 assert(!_parserCalled); 644 assert(!_parserCalled);
418 _parserCalled = true; 645 _parserCalled = true;
419 if (_state == _State.CLOSED) { 646 if (_state == _State.CLOSED) {
420 throw new HttpException("Data on closed connection"); 647 throw new HttpException("Data on closed connection");
421 } 648 }
422 if (_state == _State.FAILURE) { 649 if (_state == _State.FAILURE) {
423 throw new HttpException("Data on failed connection"); 650 throw new HttpException("Data on failed connection");
424 } 651 }
425 while (_buffer != null && 652 while (_buffer != null &&
426 _index < _buffer.length && 653 _index < _buffer.length &&
427 _state != _State.FAILURE && 654 _state != _State.FAILURE &&
428 _state != _State.UPGRADED) { 655 _state != _State.UPGRADED) {
429 // Depending on _incoming, we either break on _bodyPaused or _paused. 656 // Depending on _incoming, we either break on _bodyPaused or _paused.
430 if ((_incoming != null && _bodyPaused) || 657 if ((_incoming != null && _bodyPaused) ||
431 (_incoming == null && _paused)) { 658 (_incoming == null && _paused)) {
432 _parserCalled = false; 659 _parserCalled = false;
433 return; 660 return;
434 } 661 }
435 int byte = _buffer[_index++]; 662 int byte = _buffer[_index++];
436 switch (_state) { 663 switch (_state) {
437 case _State.START: 664 case _State.START:
438 if (byte == _Const.HTTP[0]) { 665 if (byte == _Const.HTTP[0]) {
(...skipping 12 matching lines...) Expand all
451 _state = _State.REQUEST_LINE_METHOD; 678 _state = _State.REQUEST_LINE_METHOD;
452 } 679 }
453 break; 680 break;
454 681
455 case _State.METHOD_OR_RESPONSE_HTTP_VERSION: 682 case _State.METHOD_OR_RESPONSE_HTTP_VERSION:
456 if (_httpVersionIndex < _Const.HTTP.length && 683 if (_httpVersionIndex < _Const.HTTP.length &&
457 byte == _Const.HTTP[_httpVersionIndex]) { 684 byte == _Const.HTTP[_httpVersionIndex]) {
458 // Continue parsing HTTP version. 685 // Continue parsing HTTP version.
459 _httpVersionIndex++; 686 _httpVersionIndex++;
460 } else if (_httpVersionIndex == _Const.HTTP.length && 687 } else if (_httpVersionIndex == _Const.HTTP.length &&
461 byte == _CharCode.SLASH) { 688 byte == _CharCode.SLASH) {
462 // HTTP/ parsed. As method is a token this cannot be a 689 // HTTP/ parsed. As method is a token this cannot be a
463 // method anymore. 690 // method anymore.
464 _httpVersionIndex++; 691 _httpVersionIndex++;
465 if (_requestParser) { 692 if (_requestParser) {
466 throw new HttpException("Invalid request line"); 693 throw new HttpException("Invalid request line");
467 } 694 }
468 _state = _State.RESPONSE_HTTP_VERSION; 695 _state = _State.RESPONSE_HTTP_VERSION;
469 } else { 696 } else {
470 // Did not parse HTTP version. Expect method instead. 697 // Did not parse HTTP version. Expect method instead.
471 for (int i = 0; i < _httpVersionIndex; i++) { 698 for (int i = 0; i < _httpVersionIndex; i++) {
(...skipping 11 matching lines...) Expand all
483 } 710 }
484 } 711 }
485 break; 712 break;
486 713
487 case _State.RESPONSE_HTTP_VERSION: 714 case _State.RESPONSE_HTTP_VERSION:
488 if (_httpVersionIndex < _Const.HTTP1DOT.length) { 715 if (_httpVersionIndex < _Const.HTTP1DOT.length) {
489 // Continue parsing HTTP version. 716 // Continue parsing HTTP version.
490 _expect(byte, _Const.HTTP1DOT[_httpVersionIndex]); 717 _expect(byte, _Const.HTTP1DOT[_httpVersionIndex]);
491 _httpVersionIndex++; 718 _httpVersionIndex++;
492 } else if (_httpVersionIndex == _Const.HTTP1DOT.length && 719 } else if (_httpVersionIndex == _Const.HTTP1DOT.length &&
493 byte == _CharCode.ONE) { 720 byte == _CharCode.ONE) {
494 // HTTP/1.1 parsed. 721 // HTTP/1.1 parsed.
495 _httpVersion = _HttpVersion.HTTP11; 722 _httpVersion = _HttpVersion.HTTP11;
496 _persistentConnection = true; 723 _persistentConnection = true;
497 _httpVersionIndex++; 724 _httpVersionIndex++;
498 } else if (_httpVersionIndex == _Const.HTTP1DOT.length && 725 } else if (_httpVersionIndex == _Const.HTTP1DOT.length &&
499 byte == _CharCode.ZERO) { 726 byte == _CharCode.ZERO) {
500 // HTTP/1.0 parsed. 727 // HTTP/1.0 parsed.
501 _httpVersion = _HttpVersion.HTTP10; 728 _httpVersion = _HttpVersion.HTTP10;
502 _persistentConnection = false; 729 _persistentConnection = false;
503 _httpVersionIndex++; 730 _httpVersionIndex++;
504 } else if (_httpVersionIndex == _Const.HTTP1DOT.length + 1) { 731 } else if (_httpVersionIndex == _Const.HTTP1DOT.length + 1) {
505 _expect(byte, _CharCode.SP); 732 _expect(byte, _CharCode.SP);
506 // HTTP version parsed. 733 // HTTP version parsed.
507 _state = _State.RESPONSE_LINE_STATUS_CODE; 734 _state = _State.RESPONSE_LINE_STATUS_CODE;
508 } else { 735 } else {
509 throw new HttpException("Invalid response line"); 736 throw new HttpException("Invalid response line");
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 } 828 }
602 break; 829 break;
603 830
604 case _State.RESPONSE_LINE_ENDING: 831 case _State.RESPONSE_LINE_ENDING:
605 _expect(byte, _CharCode.LF); 832 _expect(byte, _CharCode.LF);
606 _messageType == _MessageType.RESPONSE; 833 _messageType == _MessageType.RESPONSE;
607 if (_statusCode < 100 || _statusCode > 599) { 834 if (_statusCode < 100 || _statusCode > 599) {
608 throw new HttpException("Invalid response status code"); 835 throw new HttpException("Invalid response status code");
609 } else { 836 } else {
610 // Check whether this response will never have a body. 837 // Check whether this response will never have a body.
611 if (_statusCode <= 199 || _statusCode == 204 || 838 if (_statusCode <= 199 ||
839 _statusCode == 204 ||
612 _statusCode == 304) { 840 _statusCode == 304) {
613 _noMessageBody = true; 841 _noMessageBody = true;
614 } 842 }
615 } 843 }
616 _state = _State.HEADER_START; 844 _state = _State.HEADER_START;
617 break; 845 break;
618 846
619 case _State.HEADER_START: 847 case _State.HEADER_START:
620 _headers = new _HttpHeaders(version); 848 _headers = new _HttpHeaders(version);
621 if (byte == _CharCode.CR) { 849 if (byte == _CharCode.CR) {
622 _state = _State.HEADER_ENDING; 850 _state = _State.HEADER_ENDING;
623 } else if (byte == _CharCode.LF) { 851 } else if (byte == _CharCode.LF) {
624 _state = _State.HEADER_ENDING; 852 _state = _State.HEADER_ENDING;
625 _index--; // Make the new state see the LF again. 853 _index--; // Make the new state see the LF again.
626 } else { 854 } else {
627 // Start of new header field. 855 // Start of new header field.
628 _headerField.add(_toLowerCaseByte(byte)); 856 _headerField.add(_toLowerCaseByte(byte));
629 _state = _State.HEADER_FIELD; 857 _state = _State.HEADER_FIELD;
630 } 858 }
631 break; 859 break;
632 860
633 case _State.HEADER_FIELD: 861 case _State.HEADER_FIELD:
634 if (byte == _CharCode.COLON) { 862 if (byte == _CharCode.COLON) {
635 _state = _State.HEADER_VALUE_START; 863 _state = _State.HEADER_VALUE_START;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 } else { 902 } else {
675 String headerField = new String.fromCharCodes(_headerField); 903 String headerField = new String.fromCharCodes(_headerField);
676 String headerValue = new String.fromCharCodes(_headerValue); 904 String headerValue = new String.fromCharCodes(_headerValue);
677 if (headerField == "transfer-encoding" && 905 if (headerField == "transfer-encoding" &&
678 _caseInsensitiveCompare("chunked".codeUnits, _headerValue)) { 906 _caseInsensitiveCompare("chunked".codeUnits, _headerValue)) {
679 _chunked = true; 907 _chunked = true;
680 } 908 }
681 if (headerField == "connection") { 909 if (headerField == "connection") {
682 List<String> tokens = _tokenizeFieldValue(headerValue); 910 List<String> tokens = _tokenizeFieldValue(headerValue);
683 for (int i = 0; i < tokens.length; i++) { 911 for (int i = 0; i < tokens.length; i++) {
684 if (_caseInsensitiveCompare("upgrade".codeUnits, 912 if (_caseInsensitiveCompare(
685 tokens[i].codeUnits)) { 913 "upgrade".codeUnits, tokens[i].codeUnits)) {
686 _connectionUpgrade = true; 914 _connectionUpgrade = true;
687 } 915 }
688 _headers._add(headerField, tokens[i]); 916 _headers._add(headerField, tokens[i]);
689 } 917 }
690 } else { 918 } else {
691 _headers._add(headerField, headerValue); 919 _headers._add(headerField, headerValue);
692 } 920 }
693 _headerField.clear(); 921 _headerField.clear();
694 _headerValue.clear(); 922 _headerValue.clear();
695 923
696 if (byte == _CharCode.CR) { 924 if (byte == _CharCode.CR) {
697 _state = _State.HEADER_ENDING; 925 _state = _State.HEADER_ENDING;
698 } else if (byte == _CharCode.LF) { 926 } else if (byte == _CharCode.LF) {
699 _state = _State.HEADER_ENDING; 927 _state = _State.HEADER_ENDING;
700 _index--; // Make the new state see the LF again. 928 _index--; // Make the new state see the LF again.
701 } else { 929 } else {
702 // Start of new header field. 930 // Start of new header field.
703 _headerField.add(_toLowerCaseByte(byte)); 931 _headerField.add(_toLowerCaseByte(byte));
704 _state = _State.HEADER_FIELD; 932 _state = _State.HEADER_FIELD;
705 } 933 }
706 } 934 }
707 break; 935 break;
708 936
709 case _State.HEADER_ENDING: 937 case _State.HEADER_ENDING:
710 _expect(byte, _CharCode.LF); 938 _expect(byte, _CharCode.LF);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
765 case _State.BODY: 993 case _State.BODY:
766 // The body is not handled one byte at a time but in blocks. 994 // The body is not handled one byte at a time but in blocks.
767 _index--; 995 _index--;
768 int dataAvailable = _buffer.length - _index; 996 int dataAvailable = _buffer.length - _index;
769 if (_remainingContent >= 0 && dataAvailable > _remainingContent) { 997 if (_remainingContent >= 0 && dataAvailable > _remainingContent) {
770 dataAvailable = _remainingContent; 998 dataAvailable = _remainingContent;
771 } 999 }
772 // Always present the data as a view. This way we can handle all 1000 // 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 1001 // cases like this, and the user will not experince different data
774 // typed (which could lead to polymorphic user code). 1002 // typed (which could lead to polymorphic user code).
775 List<int> data = new Uint8List.view(_buffer.buffer, 1003 List<int> data = new Uint8List.view(
776 _buffer.offsetInBytes + _index, 1004 _buffer.buffer, _buffer.offsetInBytes + _index, dataAvailable);
777 dataAvailable);
778 _bodyController.add(data); 1005 _bodyController.add(data);
779 if (_remainingContent != -1) { 1006 if (_remainingContent != -1) {
780 _remainingContent -= data.length; 1007 _remainingContent -= data.length;
781 } 1008 }
782 _index += data.length; 1009 _index += data.length;
783 if (_remainingContent == 0) { 1010 if (_remainingContent == 0) {
784 if (!_chunked) { 1011 if (!_chunked) {
785 _reset(); 1012 _reset();
786 _closeIncoming(); 1013 _closeIncoming();
787 } else { 1014 } else {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
824 void _onDone() { 1051 void _onDone() {
825 // onDone cancles the subscription. 1052 // onDone cancles the subscription.
826 _socketSubscription = null; 1053 _socketSubscription = null;
827 if (_state == _State.CLOSED || _state == _State.FAILURE) return; 1054 if (_state == _State.CLOSED || _state == _State.FAILURE) return;
828 1055
829 if (_incoming != null) { 1056 if (_incoming != null) {
830 if (_state != _State.UPGRADED && 1057 if (_state != _State.UPGRADED &&
831 !(_state == _State.START && !_requestParser) && 1058 !(_state == _State.START && !_requestParser) &&
832 !(_state == _State.BODY && !_chunked && _transferLength == -1)) { 1059 !(_state == _State.BODY && !_chunked && _transferLength == -1)) {
833 _bodyController.addError( 1060 _bodyController.addError(
834 new HttpException("Connection closed while receiving data")); 1061 new HttpException("Connection closed while receiving data"));
835 } 1062 }
836 _closeIncoming(true); 1063 _closeIncoming(true);
837 _controller.close(); 1064 _controller.close();
838 return; 1065 return;
839 } 1066 }
840 // If the connection is idle the HTTP stream is closed. 1067 // If the connection is idle the HTTP stream is closed.
841 if (_state == _State.START) { 1068 if (_state == _State.START) {
842 if (!_requestParser) { 1069 if (!_requestParser) {
843 _reportError(new HttpException( 1070 _reportError(new HttpException(
844 "Connection closed before full header was received")); 1071 "Connection closed before full header was received"));
845 } 1072 }
846 _controller.close(); 1073 _controller.close();
847 return; 1074 return;
848 } 1075 }
849 1076
850 if (_state == _State.UPGRADED) { 1077 if (_state == _State.UPGRADED) {
851 _controller.close(); 1078 _controller.close();
852 return; 1079 return;
853 } 1080 }
854 1081
855 if (_state < _State.FIRST_BODY_STATE) { 1082 if (_state < _State.FIRST_BODY_STATE) {
856 _state = _State.FAILURE; 1083 _state = _State.FAILURE;
857 // Report the error through the error callback if any. Otherwise 1084 // Report the error through the error callback if any. Otherwise
858 // throw the error. 1085 // throw the error.
859 _reportError(new HttpException( 1086 _reportError(new HttpException(
860 "Connection closed before full header was received")); 1087 "Connection closed before full header was received"));
861 _controller.close(); 1088 _controller.close();
862 return; 1089 return;
863 } 1090 }
864 1091
865 if (!_chunked && _transferLength == -1) { 1092 if (!_chunked && _transferLength == -1) {
866 _state = _State.CLOSED; 1093 _state = _State.CLOSED;
867 } else { 1094 } else {
868 _state = _State.FAILURE; 1095 _state = _State.FAILURE;
869 // Report the error through the error callback if any. Otherwise 1096 // Report the error through the error callback if any. Otherwise
870 // throw the error. 1097 // throw the error.
871 _reportError(new HttpException( 1098 _reportError(
872 "Connection closed before full body was received")); 1099 new HttpException("Connection closed before full body was received"));
873 } 1100 }
874 _controller.close(); 1101 _controller.close();
875 } 1102 }
876 1103
877 String get version { 1104 String get version {
878 switch (_httpVersion) { 1105 switch (_httpVersion) {
879 case _HttpVersion.HTTP10: 1106 case _HttpVersion.HTTP10:
880 return "1.0"; 1107 return "1.0";
881 case _HttpVersion.HTTP11: 1108 case _HttpVersion.HTTP11:
882 return "1.1"; 1109 return "1.1";
883 } 1110 }
884 return null; 1111 return null;
885 } 1112 }
886 1113
887 int get messageType => _messageType; 1114 int get messageType => _messageType;
888 int get transferLength => _transferLength; 1115 int get transferLength => _transferLength;
889 bool get upgrade => _connectionUpgrade && _state == _State.UPGRADED; 1116 bool get upgrade => _connectionUpgrade && _state == _State.UPGRADED;
890 bool get persistentConnection => _persistentConnection; 1117 bool get persistentConnection => _persistentConnection;
891 1118
892 void set isHead(bool value) { 1119 void set isHead(bool value) {
893 if (value) _noMessageBody = true; 1120 if (value) _noMessageBody = true;
894 } 1121 }
895 1122
896 _HttpDetachedIncoming detachIncoming() { 1123 _HttpDetachedIncoming detachIncoming() {
897 // Simulate detached by marking as upgraded. 1124 // Simulate detached by marking as upgraded.
898 _state = _State.UPGRADED; 1125 _state = _State.UPGRADED;
899 return new _HttpDetachedIncoming(_socketSubscription, 1126 return new _HttpDetachedIncoming(_socketSubscription, readUnparsedData());
900 readUnparsedData());
901 } 1127 }
902 1128
903 List<int> readUnparsedData() { 1129 List<int> readUnparsedData() {
904 if (_buffer == null) return null; 1130 if (_buffer == null) return null;
905 if (_index == _buffer.length) return null; 1131 if (_index == _buffer.length) return null;
906 var result = _buffer.sublist(_index); 1132 var result = _buffer.sublist(_index);
907 _releaseBuffer(); 1133 _releaseBuffer();
908 return result; 1134 return result;
909 } 1135 }
910 1136
(...skipping 24 matching lines...) Expand all
935 void _releaseBuffer() { 1161 void _releaseBuffer() {
936 _buffer = null; 1162 _buffer = null;
937 _index = null; 1163 _index = null;
938 } 1164 }
939 1165
940 static bool _isTokenChar(int byte) { 1166 static bool _isTokenChar(int byte) {
941 return byte > 31 && byte < 128 && !_Const.SEPARATOR_MAP[byte]; 1167 return byte > 31 && byte < 128 && !_Const.SEPARATOR_MAP[byte];
942 } 1168 }
943 1169
944 static bool _isValueChar(int byte) { 1170 static bool _isValueChar(int byte) {
945 return (byte > 31 && byte < 128) || (byte == _CharCode.SP) || 1171 return (byte > 31 && byte < 128) ||
1172 (byte == _CharCode.SP) ||
946 (byte == _CharCode.HT); 1173 (byte == _CharCode.HT);
947 } 1174 }
948 1175
949 static List<String> _tokenizeFieldValue(String headerValue) { 1176 static List<String> _tokenizeFieldValue(String headerValue) {
950 List<String> tokens = new List<String>(); 1177 List<String> tokens = new List<String>();
951 int start = 0; 1178 int start = 0;
952 int index = 0; 1179 int index = 0;
953 while (index < headerValue.length) { 1180 while (index < headerValue.length) {
954 if (headerValue[index] == ",") { 1181 if (headerValue[index] == ",") {
955 tokens.add(headerValue.substring(start, index)); 1182 tokens.add(headerValue.substring(start, index));
(...skipping 26 matching lines...) Expand all
982 } 1209 }
983 1210
984 int _expect(int val1, int val2) { 1211 int _expect(int val1, int val2) {
985 if (val1 != val2) { 1212 if (val1 != val2) {
986 throw new HttpException("Failed to parse HTTP"); 1213 throw new HttpException("Failed to parse HTTP");
987 } 1214 }
988 } 1215 }
989 1216
990 int _expectHexDigit(int byte) { 1217 int _expectHexDigit(int byte) {
991 if (0x30 <= byte && byte <= 0x39) { 1218 if (0x30 <= byte && byte <= 0x39) {
992 return byte - 0x30; // 0 - 9 1219 return byte - 0x30; // 0 - 9
993 } else if (0x41 <= byte && byte <= 0x46) { 1220 } else if (0x41 <= byte && byte <= 0x46) {
994 return byte - 0x41 + 10; // A - F 1221 return byte - 0x41 + 10; // A - F
995 } else if (0x61 <= byte && byte <= 0x66) { 1222 } else if (0x61 <= byte && byte <= 0x66) {
996 return byte - 0x61 + 10; // a - f 1223 return byte - 0x61 + 10; // a - f
997 } else { 1224 } else {
998 throw new HttpException("Failed to parse HTTP"); 1225 throw new HttpException("Failed to parse HTTP");
999 } 1226 }
1000 } 1227 }
1001 1228
1002 void _createIncoming(int transferLength) { 1229 void _createIncoming(int transferLength) {
1003 assert(_incoming == null); 1230 assert(_incoming == null);
1004 assert(_bodyController == null); 1231 assert(_bodyController == null);
1005 assert(!_bodyPaused); 1232 assert(!_bodyPaused);
1006 var incoming; 1233 var incoming;
(...skipping 18 matching lines...) Expand all
1025 _pauseStateChanged(); 1252 _pauseStateChanged();
1026 }, 1253 },
1027 onCancel: () { 1254 onCancel: () {
1028 if (incoming != _incoming) return; 1255 if (incoming != _incoming) return;
1029 if (_socketSubscription != null) { 1256 if (_socketSubscription != null) {
1030 _socketSubscription.cancel(); 1257 _socketSubscription.cancel();
1031 } 1258 }
1032 _closeIncoming(true); 1259 _closeIncoming(true);
1033 _controller.close(); 1260 _controller.close();
1034 }); 1261 });
1035 incoming = _incoming = new _HttpIncoming( 1262 incoming = _incoming =
1036 _headers, transferLength, _bodyController.stream); 1263 new _HttpIncoming(_headers, transferLength, _bodyController.stream);
1037 _bodyPaused = true; 1264 _bodyPaused = true;
1038 _pauseStateChanged(); 1265 _pauseStateChanged();
1039 } 1266 }
1040 1267
1041 void _closeIncoming([bool closing = false]) { 1268 void _closeIncoming([bool closing = false]) {
1042 // Ignore multiple close (can happen in re-entrance). 1269 // Ignore multiple close (can happen in re-entrance).
1043 if (_incoming == null) return; 1270 if (_incoming == null) return;
1044 var tmp = _incoming; 1271 var tmp = _incoming;
1045 tmp.close(closing); 1272 tmp.close(closing);
1046 _incoming = null; 1273 _incoming = null;
(...skipping 17 matching lines...) Expand all
1064 } 1291 }
1065 } 1292 }
1066 1293
1067 void _reportError(error, [stackTrace]) { 1294 void _reportError(error, [stackTrace]) {
1068 if (_socketSubscription != null) _socketSubscription.cancel(); 1295 if (_socketSubscription != null) _socketSubscription.cancel();
1069 _state = _State.FAILURE; 1296 _state = _State.FAILURE;
1070 _controller.addError(error, stackTrace); 1297 _controller.addError(error, stackTrace);
1071 _controller.close(); 1298 _controller.close();
1072 } 1299 }
1073 } 1300 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698