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

Side by Side Diff: samples/chat/http_impl.dart

Issue 9495007: Prepare the HTTP library for inclusion in the standalone VM (step 2) (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed review comments Created 8 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 | Annotate | Revision Log
« no previous file with comments | « samples/chat/http.dart ('k') | samples/tests/samples/src/chat/ChatServerTest.dart » ('j') | 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 // Global constants. 5 // Global constants.
6 class _Const { 6 class _Const {
7 // Bytes for "HTTP/1.0". 7 // Bytes for "HTTP/1.0".
8 static final HTTP10 = const [72, 84, 84, 80, 47, 49, 46, 48]; 8 static final HTTP10 = const [72, 84, 84, 80, 47, 49, 46, 48];
9 // Bytes for "HTTP/1.1". 9 // Bytes for "HTTP/1.1".
10 static final HTTP11 = const [72, 84, 84, 80, 47, 49, 46, 49]; 10 static final HTTP11 = const [72, 84, 84, 80, 47, 49, 46, 49];
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 StringBuffer _headerField; 399 StringBuffer _headerField;
400 StringBuffer _headerValue; 400 StringBuffer _headerValue;
401 401
402 int _contentLength; 402 int _contentLength;
403 bool _keepAlive; 403 bool _keepAlive;
404 bool _chunked; 404 bool _chunked;
405 405
406 int _remainingContent; 406 int _remainingContent;
407 407
408 // Callbacks. 408 // Callbacks.
409 var requestStart; 409 Function requestStart;
410 var responseStart; 410 Function responseStart;
411 var headerReceived; 411 Function headerReceived;
412 var headersComplete; 412 Function headersComplete;
413 var dataReceived; 413 Function dataReceived;
414 var dataEnd; 414 Function dataEnd;
415 } 415 }
416 416
417 417
418 // Utility class which can deliver bytes one by one from a number of
419 // buffers added.
420 class _BufferList {
421 _BufferList() : _index = 0, _length = 0, _buffers = new Queue();
422
423 void add(List<int> buffer) {
424 _buffers.addLast(buffer);
425 _length += buffer.length;
426 }
427
428 int next() {
429 int value = _buffers.first()[_index++];
430 _length--;
431 if (_index == _buffers.first().length) {
432 _buffers.removeFirst();
433 _index = 0;
434 }
435 return value;
436 }
437
438 int get length() => _length;
439
440 int _length;
441 Queue<List<int>> _buffers;
442 int _index;
443 }
444
445
446 // Utility class for decoding UTF-8 from data delivered as a stream of
447 // bytes.
448 class _UTF8Decoder {
449 _UTF8Decoder()
450 : _bufferList = new _BufferList(),
451 _result = new StringBuffer();
452
453 // Add UTF-8 encoded data.
454 int writeList(List<int> buffer) {
455 _bufferList.add(buffer);
456 // Only process as much data as we know is safe.
457 while (_bufferList.length >= 4) {
458 _processNext();
459 }
460 }
461
462 // Return the decoded string.
463 String toString() {
464 // Process any leftover data.
465 while (_bufferList.length > 0) {
466 _processNext();
467 }
468 return _result.toString();
469 }
470
471 // Process the next UTF-8 encoded character.
472 void _processNext() {
473 int value = _bufferList.next() & 0xFF;
474 if ((value & 0x80) == 0x80) {
475 int additionalBytes;
476 if ((value & 0xe0) == 0xc0) { // 110xxxxx
477 value = value & 0x1F;
478 additionalBytes = 1;
479 } else if ((value & 0xf0) == 0xe0) { // 1110xxxx
480 value = value & 0x0F;
481 additionalBytes = 2;
482 } else { // 11110xxx
483 value = value & 0x07;
484 additionalBytes = 3;
485 }
486 for (int i = 0; i < additionalBytes; i++) {
487 int byte = _bufferList.next();
488 value = value << 6 | (byte & 0x3F);
489 }
490 }
491 _result.addCharCode(value);
492 }
493
494 _BufferList _bufferList;
495 StringBuffer _result;
496 }
497
498
499 // Utility class for encoding a string into UTF-8 byte stream. 418 // Utility class for encoding a string into UTF-8 byte stream.
500 class _UTF8Encoder { 419 class _UTF8Encoder {
501 static List<int> encodeString(String string) { 420 static List<int> encodeString(String string) {
502 int size = _encodingSize(string); 421 int size = _encodingSize(string);
503 ByteArray result = new ByteArray(size); 422 ByteArray result = new ByteArray(size);
504 _encodeString(string, result); 423 _encodeString(string, result);
505 return result; 424 return result;
506 } 425 }
507 426
508 static int _encodingSize(String string) => _encodeString(string, null); 427 static int _encodingSize(String string) => _encodeString(string, null);
(...skipping 28 matching lines...) Expand all
537 } 456 }
538 } else { 457 } else {
539 pos += additionalBytes; 458 pos += additionalBytes;
540 } 459 }
541 } 460 }
542 return pos; 461 return pos;
543 } 462 }
544 } 463 }
545 464
546 465
547 class _HTTPRequestOrResponse { 466 class _HTTPRequestResponseBase {
548 _HTTPRequestOrResponse(_HTTPConnectionBase this._httpConnection) 467 _HTTPRequestResponseBase(_HTTPConnectionBase this._httpConnection)
549 : _contentLength = -1, 468 : _contentLength = -1,
550 _keepAlive = false, 469 _keepAlive = false,
551 _headers = new Map(); 470 _headers = new Map();
552 471
553 int get contentLength() => _contentLength; 472 int get contentLength() => _contentLength;
554 bool get keepAlive() => _keepAlive; 473 bool get keepAlive() => _keepAlive;
555 474
556 void _setHeader(String name, String value) { 475 void _setHeader(String name, String value) {
557 _headers[name] = value; 476 _headers[name] = value;
558 } 477 }
559 478
560 void _write(List<int> data, bool copyBuffer) { 479 bool _write(List<int> data, bool copyBuffer) {
480 bool allWritten = true;
561 if (data.length > 0) { 481 if (data.length > 0) {
562 if (_contentLength < 0) { 482 if (_contentLength < 0) {
563 // Write chunk size if transfer encoding is chunked. 483 // Write chunk size if transfer encoding is chunked.
564 _writeHexString(data.length); 484 _writeHexString(data.length);
565 _writeCRLF(); 485 _writeCRLF();
566 _httpConnection.outputStream.write(data, copyBuffer); 486 _httpConnection.outputStream.write(data, copyBuffer);
567 _writeCRLF(); 487 allWritten = _writeCRLF();
568 } else { 488 } else {
569 _httpConnection.outputStream.write(data, copyBuffer); 489 allWritten = _httpConnection.outputStream.write(data, copyBuffer);
570 } 490 }
571 } 491 }
492 return allWritten;
572 } 493 }
573 494
574 void _writeList(List<int> data, int offset, int count) { 495 bool _writeList(List<int> data, int offset, int count) {
496 bool allWritten = true;
575 if (count > 0) { 497 if (count > 0) {
576 if (_contentLength < 0) { 498 if (_contentLength < 0) {
577 // Write chunk size if transfer encoding is chunked. 499 // Write chunk size if transfer encoding is chunked.
578 _writeHexString(count); 500 _writeHexString(count);
579 _writeCRLF(); 501 _writeCRLF();
580 _httpConnection.outputStream.writeFrom(data, offset, count); 502 _httpConnection.outputStream.writeFrom(data, offset, count);
581 _writeCRLF(); 503 allWritten = _writeCRLF();
582 } else { 504 } else {
583 _httpConnection.outputStream.writeFrom(data, offset, count); 505 allWritten = _httpConnection.outputStream.writeFrom(data, offset, count) ;
584 } 506 }
585 } 507 }
508 return allWritten;
586 } 509 }
587 510
588 void _writeString(String string) { 511 bool _writeString(String string) {
512 bool allWritten = true;
589 if (string.length > 0) { 513 if (string.length > 0) {
590 // Encode as UTF-8 and write data. 514 // Encode as UTF-8 and write data.
591 List<int> data = _UTF8Encoder.encodeString(string); 515 List<int> data = _UTF8Encoder.encodeString(string);
592 _writeList(data, 0, data.length); 516 allWritten = _writeList(data, 0, data.length);
593 } 517 }
518 return allWritten;
594 } 519 }
595 520
596 void _writeDone() { 521 bool _writeDone() {
522 bool allWritten = true;
597 if (_contentLength < 0) { 523 if (_contentLength < 0) {
598 // Terminate the content if transfer encoding is chunked. 524 // Terminate the content if transfer encoding is chunked.
599 _httpConnection.outputStream.write(_Const.END_CHUNKED); 525 allWritten = _httpConnection.outputStream.write(_Const.END_CHUNKED);
600 } 526 }
527 return allWritten;
601 } 528 }
602 529
603 void _writeHeaders() { 530 bool _writeHeaders() {
604 List<int> data; 531 List<int> data;
605 532
606 // Format headers. 533 // Format headers.
607 _headers.forEach((String name, String value) { 534 _headers.forEach((String name, String value) {
608 data = name.charCodes(); 535 data = name.charCodes();
609 _httpConnection.outputStream.write(data); 536 _httpConnection.outputStream.write(data);
610 data = ": ".charCodes(); 537 data = ": ".charCodes();
611 _httpConnection.outputStream.write(data); 538 _httpConnection.outputStream.write(data);
612 data = value.charCodes(); 539 data = value.charCodes();
613 _httpConnection.outputStream.write(data); 540 _httpConnection.outputStream.write(data);
614 _writeCRLF(); 541 _writeCRLF();
615 }); 542 });
616 // Terminate header. 543 // Terminate header.
617 _writeCRLF(); 544 return _writeCRLF();
618 } 545 }
619 546
620 void _writeHexString(int x) { 547 bool _writeHexString(int x) {
621 final List<int> hexDigits = [0x30, 0x31, 0x32, 0x33, 0x34, 548 final List<int> hexDigits = [0x30, 0x31, 0x32, 0x33, 0x34,
622 0x35, 0x36, 0x37, 0x38, 0x39, 549 0x35, 0x36, 0x37, 0x38, 0x39,
623 0x41, 0x42, 0x43, 0x44, 0x45, 0x46]; 550 0x41, 0x42, 0x43, 0x44, 0x45, 0x46];
624 ByteArray hex = new ByteArray(10); 551 ByteArray hex = new ByteArray(10);
625 int index = hex.length; 552 int index = hex.length;
626 while (x > 0) { 553 while (x > 0) {
627 index--; 554 index--;
628 hex[index] = hexDigits[x % 16]; 555 hex[index] = hexDigits[x % 16];
629 x = x >> 4; 556 x = x >> 4;
630 } 557 }
631 _httpConnection.outputStream.writeFrom(hex, index, hex.length - index); 558 return _httpConnection.outputStream.writeFrom(hex, index, hex.length - index );
632 } 559 }
633 560
634 void _writeCRLF() { 561 bool _writeCRLF() {
635 final CRLF = const [_CharCode.CR, _CharCode.LF]; 562 final CRLF = const [_CharCode.CR, _CharCode.LF];
636 _httpConnection.outputStream.write(CRLF); 563 return _httpConnection.outputStream.write(CRLF);
637 } 564 }
638 565
639 void _writeSP() { 566 bool _writeSP() {
640 final SP = const [_CharCode.SP]; 567 final SP = const [_CharCode.SP];
641 _httpConnection.outputStream.write(SP); 568 return _httpConnection.outputStream.write(SP);
642 }
643
644 void _dataReceivedHandler(List<int> data) {
645 // If no data received handler exists collect data as a string.
646 if (dataReceived != null) {
647 dataReceived(data);
648 } else {
649 if (_decoder == null) _decoder = new _UTF8Decoder();
650 _decoder.writeList(data);
651 }
652 }
653
654 void _dataEndHandler() {
655 if (dataEnd != null) {
656 // Pass the string collected if any.
657 dataEnd(_decoder != null ? _decoder.toString() : null);
658 }
659 } 569 }
660 570
661 _HTTPConnectionBase _httpConnection; 571 _HTTPConnectionBase _httpConnection;
662 Map<String, String> _headers; 572 Map<String, String> _headers;
663 573
664 // Length of the content body. If this is set to -1 (default value) 574 // Length of the content body. If this is set to -1 (default value)
665 // when starting to send data chunked transfer encoding will be 575 // when starting to send data chunked transfer encoding will be
666 // used. 576 // used.
667 int _contentLength; 577 int _contentLength;
668 bool _keepAlive; 578 bool _keepAlive;
669
670 _UTF8Decoder _decoder;
671
672 // Callbacks.
673 var dataReceived;
674 var dataEnd;
675 } 579 }
676 580
677 581
678 // Parsed HTTP request providing information on the HTTP headers. 582 // Parsed HTTP request providing information on the HTTP headers.
679 class _HTTPRequest extends _HTTPRequestOrResponse implements HTTPRequest { 583 class _HTTPRequest extends _HTTPRequestResponseBase implements HTTPRequest {
680 _HTTPRequest(_HTTPConnection connection) : super(connection); 584 _HTTPRequest(_HTTPConnection connection) : super(connection);
681 585
682 String get method() => _method; 586 String get method() => _method;
683 String get uri() => _uri; 587 String get uri() => _uri;
684 String get path() => _path; 588 String get path() => _path;
685 Map get headers() => _headers; 589 Map get headers() => _headers;
686 String get queryString() => _queryString; 590 String get queryString() => _queryString;
687 Map get queryParameters() => _queryParameters; 591 Map get queryParameters() => _queryParameters;
688 592
593 InputStream get inputStream() {
594 if (_inputStream == null) {
595 _inputStream = new _HTTPInputStream(this);
596 }
597 return _inputStream;
598 }
599
689 void _requestStartHandler(String method, String uri) { 600 void _requestStartHandler(String method, String uri) {
690 _method = method; 601 _method = method;
691 _uri = uri; 602 _uri = uri;
692 _parseRequestUri(uri); 603 _parseRequestUri(uri);
693 } 604 }
694 605
695 void _headerReceivedHandler(String name, String value) { 606 void _headerReceivedHandler(String name, String value) {
696 _setHeader(name, value); 607 _setHeader(name, value);
697 } 608 }
698 609
699 void _headersCompleteHandler() { 610 void _headersCompleteHandler() {
700 // Nothing to do. 611 // Prepare for receiving data.
612 _buffer = new _BufferList();
613 }
614
615 void _dataReceivedHandler(List<int> data) {
616 _buffer.add(data);
617 if (_inputStream != null) _inputStream._dataReceived();
618 }
619
620 void _dataEndHandler() {
621 if (_inputStream != null) _inputStream._closeReceived();
701 } 622 }
702 623
703 // Escaped characters in uri are expected to have been parsed. 624 // Escaped characters in uri are expected to have been parsed.
704 void _parseRequestUri(String uri) { 625 void _parseRequestUri(String uri) {
705 int position; 626 int position;
706 position = uri.indexOf("?", 0); 627 position = uri.indexOf("?", 0);
707 if (position == -1) { 628 if (position == -1) {
708 _path = HTTPUtil.decodeUrlEncodedString(_uri); 629 _path = HTTPUtil.decodeUrlEncodedString(_uri);
709 _queryString = null; 630 _queryString = null;
710 _queryParameters = new Map(); 631 _queryParameters = new Map();
711 } else { 632 } else {
712 _path = HTTPUtil.decodeUrlEncodedString(_uri.substring(0, position)); 633 _path = HTTPUtil.decodeUrlEncodedString(_uri.substring(0, position));
713 _queryString = _uri.substring(position + 1); 634 _queryString = _uri.substring(position + 1);
714 _queryParameters = HTTPUtil.splitQueryString(_queryString); 635 _queryParameters = HTTPUtil.splitQueryString(_queryString);
715 } 636 }
716 } 637 }
717 638
639 // Delegate functions for the HTTPInputStream implementation.
640 int _streamAvailable() {
641 return _buffer.length;
642 }
643
644 List<int> _streamRead(int bytesToRead) {
645 return _buffer.readBytes(bytesToRead);
646 }
647
648 int _streamReadInto(List<int> buffer, int offset, int len) {
649 List<int> data = _buffer.readBytes(len);
650 buffer.setRange(offset, data.length, data);
651 }
652
718 String _method; 653 String _method;
719 String _uri; 654 String _uri;
720 String _path; 655 String _path;
721 String _queryString; 656 String _queryString;
722 Map<String, String> _queryParameters; 657 Map<String, String> _queryParameters;
658 _HTTPInputStream _inputStream;
659 _BufferList _buffer;
723 } 660 }
724 661
725 662
726 // HTTP response object for sending a HTTP response. 663 // HTTP response object for sending a HTTP response.
727 class _HTTPResponse extends _HTTPRequestOrResponse implements HTTPResponse { 664 class _HTTPResponse extends _HTTPRequestResponseBase implements HTTPResponse {
728 static final int START = 0; 665 static final int START = 0;
729 static final int HEADERS_SENT = 1; 666 static final int HEADERS_SENT = 1;
730 static final int DONE = 2; 667 static final int DONE = 2;
731 668
732 _HTTPResponse(_HTTPConnection httpConnection) 669 _HTTPResponse(_HTTPConnection httpConnection)
733 : super(httpConnection), 670 : super(httpConnection),
734 statusCode = HTTPStatus.OK, 671 statusCode = HTTPStatus.OK,
735 _state = START; 672 _state = START;
736 673
737 void set contentLength(int contentLength) { 674 void set contentLength(int contentLength) {
(...skipping 20 matching lines...) Expand all
758 _writeHeader(); 695 _writeHeader();
759 } 696 }
760 _outputStream = new _HTTPOutputStream(this); 697 _outputStream = new _HTTPOutputStream(this);
761 } 698 }
762 return _outputStream; 699 return _outputStream;
763 } 700 }
764 701
765 bool writeString(String string) { 702 bool writeString(String string) {
766 // Invoke the output stream getter to make sure the header is sent. 703 // Invoke the output stream getter to make sure the header is sent.
767 outputStream; 704 outputStream;
768 _writeString(string); 705 return _writeString(string);
769 return true;
770 } 706 }
771 707
772 /* 708 // Delegate functions for the HTTPOutputStream implementation.
773 * Delegate functions for the HTTPOutputStream implementation.
774 */
775 bool _streamWrite(List<int> buffer, bool copyBuffer) { 709 bool _streamWrite(List<int> buffer, bool copyBuffer) {
776 _write(buffer, copyBuffer); 710 return _write(buffer, copyBuffer);
777 } 711 }
778 712
779 bool _streamWriteFrom(List<int> buffer, int offset, int len) { 713 bool _streamWriteFrom(List<int> buffer, int offset, int len) {
780 _writeList(buffer, offset, len); 714 return _writeList(buffer, offset, len);
781 } 715 }
782 716
783 void _streamClose() { 717 void _streamClose() {
718 _state = DONE;
784 // Stop tracking no pending write events. 719 // Stop tracking no pending write events.
785 _httpConnection.outputStream.noPendingWriteHandler = null; 720 _httpConnection.outputStream.noPendingWriteHandler = null;
786
787 // Ensure that any trailing data is written. 721 // Ensure that any trailing data is written.
788 _writeDone(); 722 _writeDone();
789 _state = DONE; 723 // If the connection is closing then close the output stream to
724 // fully close the socket.
725 if (_httpConnection._closing) {
726 _httpConnection.outputStream.close();
727 }
790 } 728 }
791 729
792 void _streamSetNoPendingWriteHandler(callback()) { 730 void _streamSetNoPendingWriteHandler(callback()) {
793 _httpConnection.outputStream.noPendingWriteHandler = callback; 731 if (_state != DONE) {
732 _httpConnection.outputStream.noPendingWriteHandler = callback;
733 }
794 } 734 }
795 735
796 void _streamSetCloseHandler(callback()) { 736 void _streamSetCloseHandler(callback()) {
797 // TODO(sgjesse): Handle this. 737 // TODO(sgjesse): Handle this.
798 } 738 }
799 739
800 void _streamSetErrorHandler(callback()) { 740 void _streamSetErrorHandler(callback()) {
801 // TODO(sgjesse): Handle this. 741 // TODO(sgjesse): Handle this.
802 } 742 }
803 743
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
849 case HTTPStatus.NOT_IMPLEMENTED: return "Not Implemented"; 789 case HTTPStatus.NOT_IMPLEMENTED: return "Not Implemented";
850 case HTTPStatus.BAD_GATEWAY: return "Bad Gateway"; 790 case HTTPStatus.BAD_GATEWAY: return "Bad Gateway";
851 case HTTPStatus.SERVICE_UNAVAILABLE: return "Service Unavailable"; 791 case HTTPStatus.SERVICE_UNAVAILABLE: return "Service Unavailable";
852 case HTTPStatus.GATEWAY_TIMEOUT: return "Gateway Time-out"; 792 case HTTPStatus.GATEWAY_TIMEOUT: return "Gateway Time-out";
853 case HTTPStatus.HTTP_VERSION_NOT_SUPPORTED: 793 case HTTPStatus.HTTP_VERSION_NOT_SUPPORTED:
854 return "HTTP Version not supported"; 794 return "HTTP Version not supported";
855 default: return "Status " + statusCode.toString(); 795 default: return "Status " + statusCode.toString();
856 } 796 }
857 } 797 }
858 798
859 void _writeHeader() { 799 bool _writeHeader() {
860 List<int> data; 800 List<int> data;
861 OutputStream stream = _httpConnection.outputStream; 801 OutputStream stream = _httpConnection.outputStream;
862 802
863 // Write status line. 803 // Write status line.
864 stream.write(_Const.HTTP11); 804 stream.write(_Const.HTTP11);
865 _writeSP(); 805 _writeSP();
866 data = statusCode.toString().charCodes(); 806 data = statusCode.toString().charCodes();
867 stream.write(data); 807 stream.write(data);
868 _writeSP(); 808 _writeSP();
869 data = _findReasonPhrase(statusCode).charCodes(); 809 data = _findReasonPhrase(statusCode).charCodes();
870 stream.write(data); 810 stream.write(data);
871 _writeCRLF(); 811 _writeCRLF();
872 812
873 // Determine the value of the "Connection" header 813 // Determine the value of the "Connection" header
874 // based on the keep alive state. 814 // based on the keep alive state.
875 setHeader("Connection", keepAlive ? "keep-alive" : "close"); 815 setHeader("Connection", keepAlive ? "keep-alive" : "close");
876 // Determine the value of the "Transfer-Encoding" header based on 816 // Determine the value of the "Transfer-Encoding" header based on
877 // whether the content length is known. 817 // whether the content length is known.
878 if (_contentLength >= 0) { 818 if (_contentLength >= 0) {
879 setHeader("Content-Length", _contentLength.toString()); 819 setHeader("Content-Length", _contentLength.toString());
880 } else { 820 } else {
881 setHeader("Transfer-Encoding", "chunked"); 821 setHeader("Transfer-Encoding", "chunked");
882 } 822 }
883 823
884 // Write headers. 824 // Write headers.
885 _writeHeaders(); 825 bool allWritten = _writeHeaders();
886 _state = HEADERS_SENT; 826 _state = HEADERS_SENT;
827 return allWritten;
887 } 828 }
888 829
889 // Response status code. 830 // Response status code.
890 int statusCode; 831 int statusCode;
891 String reasonPhrase; 832 String reasonPhrase;
892 _HTTPOutputStream _outputStream; 833 _HTTPOutputStream _outputStream;
893 int _state; 834 int _state;
894 } 835 }
895 836
896 837
838 class _HTTPInputStream extends _BaseDataInputStream implements InputStream {
839 _HTTPInputStream(_HTTPRequestResponseBase this._requestOrResponse) {
840 _checkScheduleCallbacks();
841 }
842
843 int available() {
844 return _requestOrResponse._streamAvailable();
845 }
846
847 void pipe(OutputStream output, [bool close = true]) {
848 _pipe(this, output, close: close);
849 }
850
851 List<int> _read(int bytesToRead) {
852 List<int> result = _requestOrResponse._streamRead(bytesToRead);
853 _checkScheduleCallbacks();
854 return result;
855 }
856
857 int _readInto(List<int> buffer, int offset, int len) {
858 int result = _requestOrResponse._streamReadInto(buffer, offset, len);
859 _checkScheduleCallbacks();
860 return result;
861 }
862
863 void _close() {
864 // TODO(sgjesse): Handle this.
865 }
866
867 void _dataReceived() {
868 super._dataReceived();
869 }
870
871 _HTTPRequestResponseBase _requestOrResponse;
872 }
873
874
897 class _HTTPOutputStream implements OutputStream { 875 class _HTTPOutputStream implements OutputStream {
898 _HTTPOutputStream(_HTTPRequestOrResponse this._requestOrResponse); 876 _HTTPOutputStream(_HTTPRequestResponseBase this._requestOrResponse);
899 877
900 bool write(List<int> buffer, [bool copyBuffer = true]) => 878 bool write(List<int> buffer, [bool copyBuffer = true]) {
901 _requestOrResponse._streamWrite(buffer, copyBuffer); 879 return _requestOrResponse._streamWrite(buffer, copyBuffer);
880 }
902 881
903 bool writeFrom(List<int> buffer, [int offset = 0, int len]) => 882 bool writeFrom(List<int> buffer, [int offset = 0, int len]) {
904 _requestOrResponse._streamWriteFrom(buffer, offset, len); 883 return _requestOrResponse._streamWriteFrom(buffer, offset, len);
884 }
905 885
906 void close() => _requestOrResponse._streamClose(); 886 void close() {
887 _requestOrResponse._streamClose();
888 }
907 889
908 void destroy() { throw "Not implemented"; } 890 void destroy() {
891 throw "Not implemented";
892 }
909 893
910 void set noPendingWriteHandler(void callback()) => 894 void set noPendingWriteHandler(void callback()) {
911 _requestOrResponse._streamSetNoPendingWriteHandler(callback); 895 _requestOrResponse._streamSetNoPendingWriteHandler(callback);
896 }
912 897
913 void set closeHandler(void callback()) => 898 void set closeHandler(void callback()) {
914 _requestOrResponse._streamSetCloseHandler(callback); 899 _requestOrResponse._streamSetCloseHandler(callback);
900 }
915 901
916 void set errorHandler(void callback()) => 902 void set errorHandler(void callback()) {
917 _requestOrResponse._streamSetErrorHandler(callback); 903 _requestOrResponse._streamSetErrorHandler(callback);
904 }
918 905
919 _HTTPRequestOrResponse _requestOrResponse; 906 _HTTPRequestResponseBase _requestOrResponse;
920 } 907 }
921 908
922 909
923 class _HTTPConnectionBase { 910 class _HTTPConnectionBase {
924 _HTTPConnectionBase() : _sendBuffers = new Queue(), 911 _HTTPConnectionBase() : _sendBuffers = new Queue(),
925 _httpParser = new HTTPParser(); 912 _httpParser = new HTTPParser();
926 913
927 void _connectionEstablished(Socket socket) { 914 void _connectionEstablished(Socket socket) {
928 _socket = socket; 915 _socket = socket;
929 // Register handler for socket events. 916 // Register handler for socket events.
930 _socket.dataHandler = _dataHandler; 917 _socket.dataHandler = _dataHandler;
931 _socket.closeHandler = _closeHandler; 918 _socket.closeHandler = _closeHandler;
932 _socket.errorHandler = _errorHandler; 919 _socket.errorHandler = _errorHandler;
933 } 920 }
934 921
935 OutputStream get outputStream() { 922 OutputStream get outputStream() {
936 if (_socket == null) throw new HTTPException("Connection closed");
937 return _socket.outputStream; 923 return _socket.outputStream;
938 } 924 }
939 925
940 void _dataHandler() { 926 void _dataHandler() {
941 int available = _socket.available(); 927 int available = _socket.available();
942 if (available == 0) { 928 if (available == 0) {
943 return; 929 return;
944 } 930 }
945 931
946 ByteArray buffer = new ByteArray(available); 932 ByteArray buffer = new ByteArray(available);
947 int bytesRead = _socket.readList(buffer, 0, available); 933 int bytesRead = _socket.readList(buffer, 0, available);
948 if (bytesRead > 0) { 934 if (bytesRead > 0) {
949 int parsed = _httpParser.writeList(buffer, 0, bytesRead); 935 int parsed = _httpParser.writeList(buffer, 0, bytesRead);
950 if (parsed != bytesRead) { 936 if (parsed != bytesRead) {
951 print("Failed to parse HTTP data $parsed $bytesRead"); 937 print("Failed to parse HTTP data $parsed $bytesRead");
952 _socket.close(); 938 _socket.close();
953 } 939 }
954 } 940 }
955 } 941 }
956 942
957 void _closeHandler() { 943 void _closeHandler() {
958 _socket.close(); 944 // Client closed socket for writing. Socket should still be open
959 // Set to null to avoid further write attempts. 945 // for writing the response.
960 _socket = null; 946 _closing = true;
961 if (_disconnectHandlerCallback != null) _disconnectHandlerCallback(); 947 if (_disconnectHandlerCallback != null) _disconnectHandlerCallback();
962 } 948 }
963 949
964 void _errorHandler() { 950 void _errorHandler() {
965 // If an error occours, treat the socket as closed. 951 // If an error occours, treat the socket as closed.
966 _closeHandler(); 952 _closeHandler();
967 if (_errorHandlerCallback != null) { 953 if (_errorHandlerCallback != null) {
968 _errorHandlerCallback("Connection closed while sending data to client."); 954 _errorHandlerCallback("Connection closed while sending data to client.");
969 } 955 }
970 } 956 }
971 957
972 void set disconnectHandler(void callback()) { 958 void set disconnectHandler(void callback()) {
973 _disconnectHandlerCallback = callback; 959 _disconnectHandlerCallback = callback;
974 } 960 }
975 961
976 void set errorHandler(void callback(String errorMessage)) { 962 void set errorHandler(void callback(String errorMessage)) {
977 _errorHandlerCallback = callback; 963 _errorHandlerCallback = callback;
978 } 964 }
979 965
980 Socket _socket; 966 Socket _socket;
967 bool _closing = false; // Is the socket closed by the client?
981 HTTPParser _httpParser; 968 HTTPParser _httpParser;
982 969
983 Queue _sendBuffers; 970 Queue _sendBuffers;
984 971
985 Function _disconnectHandlerCallback; 972 Function _disconnectHandlerCallback;
986 Function _errorHandlerCallback; 973 Function _errorHandlerCallback;
987 } 974 }
988 975
989 976
990 // HTTP server connection over a socket. 977 // HTTP server connection over a socket.
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1095 1082
1096 ServerSocket _server; // The server listen socket. 1083 ServerSocket _server; // The server listen socket.
1097 List<_HTTPConnection> _connections; // List of currently connected clients. 1084 List<_HTTPConnection> _connections; // List of currently connected clients.
1098 Function _requestHandler; 1085 Function _requestHandler;
1099 Function _errorHandler; 1086 Function _errorHandler;
1100 bool _debugTrace; 1087 bool _debugTrace;
1101 } 1088 }
1102 1089
1103 1090
1104 class _HTTPClientRequest 1091 class _HTTPClientRequest
1105 extends _HTTPRequestOrResponse implements HTTPClientRequest { 1092 extends _HTTPRequestResponseBase implements HTTPClientRequest {
1106 static final int START = 0; 1093 static final int START = 0;
1107 static final int HEADERS_SENT = 1; 1094 static final int HEADERS_SENT = 1;
1108 static final int DONE = 2; 1095 static final int DONE = 2;
1109 1096
1110 _HTTPClientRequest(String this._method, 1097 _HTTPClientRequest(String this._method,
1111 String this._uri, 1098 String this._uri,
1112 _HTTPClientConnection connection) 1099 _HTTPClientConnection connection)
1113 : super(connection), 1100 : super(connection),
1114 _state = START { 1101 _state = START {
1115 _connection = connection; 1102 _connection = connection;
1116 // Default GET requests to have no content. 1103 // Default GET requests to have no content.
1117 if (_method == "GET") { 1104 if (_method == "GET") {
1118 _contentLength = 0; 1105 _contentLength = 0;
1119 } 1106 }
1120 } 1107 }
1121 1108
1122 void set contentLength(int contentLength) => _contentLength = contentLength; 1109 void set contentLength(int contentLength) => _contentLength = contentLength;
1123 void set keepAlive(bool keepAlive) => _keepAlive = keepAlive; 1110 void set keepAlive(bool keepAlive) => _keepAlive = keepAlive;
1124 int get statusCode() { return _statusCode; } 1111 int get statusCode() { return _statusCode; }
1125 String get reasonPhrase() { return _reasonPhrase; } 1112 String get reasonPhrase() { return _reasonPhrase; }
1126 1113
1127 void setHeader(String name, String value) { 1114 void setHeader(String name, String value) {
1128 _setHeader(name, value); 1115 _setHeader(name, value);
1129 } 1116 }
1130 1117
1131 bool writeString(String string) { 1118 bool writeString(String string) {
1132 outputStream; 1119 outputStream;
1133 _writeString(string); 1120 return _writeString(string);
1134 return true;
1135 } 1121 }
1136 1122
1137 OutputStream get outputStream() { 1123 OutputStream get outputStream() {
1138 if (_state == DONE) throw new HTTPException("Request closed"); 1124 if (_state == DONE) throw new HTTPException("Request closed");
1139 if (_outputStream == null) { 1125 if (_outputStream == null) {
1140 // Ensure that headers are written. 1126 // Ensure that headers are written.
1141 if (_state == START) { 1127 if (_state == START) {
1142 _writeHeader(); 1128 _writeHeader();
1143 } 1129 }
1144 _outputStream = new _HTTPOutputStream(this); 1130 _outputStream = new _HTTPOutputStream(this);
1145 } 1131 }
1146 return _outputStream; 1132 return _outputStream;
1147 } 1133 }
1148 1134
1149 /* 1135 // Delegate functions for the HTTPOutputStream implementation.
1150 * Delegate functions for the HTTPOutputStream implementation. 1136 bool _streamWrite(List<int> buffer, bool copyBuffer) {
1151 */ 1137 return _write(buffer, copyBuffer);
1152 void _streamWrite(List<int> buffer, bool copyBuffer) {
1153 _write(buffer, copyBuffer);
1154 } 1138 }
1155 1139
1156 void _streamWriteFrom(List<int> buffer, int offset, int len) { 1140 bool _streamWriteFrom(List<int> buffer, int offset, int len) {
1157 _writeList(buffer, offset, len); 1141 return _writeList(buffer, offset, len);
1158 } 1142 }
1159 1143
1160 void _streamClose() { 1144 void _streamClose() {
1145 _state = DONE;
1146 // Stop tracking no pending write events.
1147 _httpConnection.outputStream.noPendingWriteHandler = null;
1161 // Ensure that any trailing data is written. 1148 // Ensure that any trailing data is written.
1162 _writeDone(); 1149 _writeDone();
1163 _state = DONE; 1150 // If the connection is closing then close the output stream to
1151 // fully close the socket.
1152 if (_httpConnection._closing) {
1153 _httpConnection.outputStream.close();
1154 }
1164 } 1155 }
1165 1156
1166 void _streamSetNoPendingWriteHandler(callback()) { 1157 void _streamSetNoPendingWriteHandler(callback()) {
1167 _httpConnection.outputStream.noPendingWriteHandler = callback; 1158 if (_state != DONE) {
1159 _httpConnection.outputStream.noPendingWriteHandler = callback;
1160 }
1168 } 1161 }
1169 1162
1170 void _streamSetCloseHandler(callback()) { 1163 void _streamSetCloseHandler(callback()) {
1171 // TODO(sgjesse): Handle this. 1164 // TODO(sgjesse): Handle this.
1172 } 1165 }
1173 1166
1174 void _streamSetErrorHandler(callback()) { 1167 void _streamSetErrorHandler(callback()) {
1175 // TODO(sgjesse): Handle this. 1168 // TODO(sgjesse): Handle this.
1176 } 1169 }
1177 1170
(...skipping 29 matching lines...) Expand all
1207 1200
1208 String _method; 1201 String _method;
1209 String _uri; 1202 String _uri;
1210 _HTTPClientConnection _connection; 1203 _HTTPClientConnection _connection;
1211 _HTTPOutputStream _outputStream; 1204 _HTTPOutputStream _outputStream;
1212 int _state; 1205 int _state;
1213 } 1206 }
1214 1207
1215 1208
1216 class _HTTPClientResponse 1209 class _HTTPClientResponse
1217 extends _HTTPRequestOrResponse implements HTTPClientResponse { 1210 extends _HTTPRequestResponseBase implements HTTPClientResponse {
1218 _HTTPClientResponse(_HTTPClientConnection connection) 1211 _HTTPClientResponse(_HTTPClientConnection connection)
1219 : super(connection) { 1212 : super(connection) {
1220 _connection = connection; 1213 _connection = connection;
1221 } 1214 }
1222 1215
1223 int get statusCode() { return _statusCode; } 1216 int get statusCode() { return _statusCode; }
1224 int get reasonPhrase() { return _reasonPhrase; } 1217 int get reasonPhrase() { return _reasonPhrase; }
1225 Map get headers() => _headers; 1218 Map get headers() => _headers;
1226 1219
1220 InputStream get inputStream() {
1221 if (_inputStream == null) {
1222 _inputStream = new _HTTPInputStream(this);
1223 }
1224 return _inputStream;
1225 }
1226
1227 void _requestStartHandler(String method, String uri) { 1227 void _requestStartHandler(String method, String uri) {
1228 // TODO(sgjesse): Error handling 1228 // TODO(sgjesse): Error handling
1229 } 1229 }
1230 1230
1231 void _responseStartHandler(int statusCode, String reasonPhrase) { 1231 void _responseStartHandler(int statusCode, String reasonPhrase) {
1232 _statusCode = statusCode; 1232 _statusCode = statusCode;
1233 _reasonPhrase = reasonPhrase; 1233 _reasonPhrase = reasonPhrase;
1234 } 1234 }
1235 1235
1236 void _headerReceivedHandler(String name, String value) { 1236 void _headerReceivedHandler(String name, String value) {
1237 _setHeader(name, value); 1237 _setHeader(name, value);
1238 } 1238 }
1239 1239
1240 void _headersCompleteHandler() { 1240 void _headersCompleteHandler() {
1241 _buffer = new _BufferList();
1241 if (_connection._responseHandler != null) { 1242 if (_connection._responseHandler != null) {
1242 _connection._responseHandler(this); 1243 _connection._responseHandler(this);
1243 } 1244 }
1244 } 1245 }
1245 1246
1247 void _dataReceivedHandler(List<int> data) {
1248 _buffer.add(data);
1249 if (_inputStream != null) _inputStream._dataReceived();
1250 }
1251
1252 void _dataEndHandler() {
1253 if (_inputStream != null) _inputStream._closeReceived();
1254 }
1255
1256 // Delegate functions for the HTTPInputStream implementation.
1257 int _streamAvailable() {
1258 return _buffer.length;
1259 }
1260
1261 List<int> _streamRead(int bytesToRead) {
1262 return _buffer.readBytes(bytesToRead);
1263 }
1264
1265 int _streamReadInto(List<int> buffer, int offset, int len) {
1266 List<int> data = _buffer.readBytes(len);
1267 buffer.setRange(offset, data.length, data);
1268 return data.length;
1269 }
1270
1246 int _statusCode; 1271 int _statusCode;
1247 String _reasonPhrase; 1272 String _reasonPhrase;
1248 1273
1249 _HTTPClientConnection _connection; 1274 _HTTPClientConnection _connection;
1250 var _responseReceived; 1275 _HTTPInputStream _inputStream;
1276 _BufferList _buffer;
1251 } 1277 }
1252 1278
1253 1279
1254 class _HTTPClientConnection 1280 class _HTTPClientConnection
1255 extends _HTTPConnectionBase implements HTTPClientConnection { 1281 extends _HTTPConnectionBase implements HTTPClientConnection {
1256 _HTTPClientConnection(_HTTPClient this._client); 1282 _HTTPClientConnection(_HTTPClient this._client);
1257 1283
1258 void _connectionEstablished(_SocketConnection socketConn) { 1284 void _connectionEstablished(_SocketConnection socketConn) {
1259 super._connectionEstablished(socketConn._socket); 1285 super._connectionEstablished(socketConn._socket);
1260 _socketConn = socketConn; 1286 _socketConn = socketConn;
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
1544 } else { 1570 } else {
1545 value = queryString.substring(currentPosition, position); 1571 value = queryString.substring(currentPosition, position);
1546 currentPosition = position + 1; 1572 currentPosition = position + 1;
1547 } 1573 }
1548 result[HTTPUtil.decodeUrlEncodedString(name)] = 1574 result[HTTPUtil.decodeUrlEncodedString(name)] =
1549 HTTPUtil.decodeUrlEncodedString(value); 1575 HTTPUtil.decodeUrlEncodedString(value);
1550 } 1576 }
1551 return result; 1577 return result;
1552 } 1578 }
1553 } 1579 }
OLDNEW
« no previous file with comments | « samples/chat/http.dart ('k') | samples/tests/samples/src/chat/ChatServerTest.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698