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

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

Issue 36643002: Don't close existing connection on HttpServer close (and stream cancel). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 2 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
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 class _HttpIncoming extends Stream<List<int>> { 7 class _HttpIncoming extends Stream<List<int>> {
8 final int _transferLength; 8 final int _transferLength;
9 final Completer _dataCompleter = new Completer(); 9 final Completer _dataCompleter = new Completer();
10 Stream<List<int>> _stream; 10 Stream<List<int>> _stream;
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 // TODO(ajohnsen): Currently, contentLength, chunkedTransferEncoding and 531 // TODO(ajohnsen): Currently, contentLength, chunkedTransferEncoding and
532 // persistentConnection is not guaranteed to be in sync. 532 // persistentConnection is not guaranteed to be in sync.
533 if (!_headersWritten) { 533 if (!_headersWritten) {
534 if (!_ignoreBody && headers.contentLength == -1) { 534 if (!_ignoreBody && headers.contentLength == -1) {
535 // If no body was written, _ignoreBody is false (it's not a HEAD 535 // If no body was written, _ignoreBody is false (it's not a HEAD
536 // request) and the content-length is unspecified, set contentLength to 536 // request) and the content-length is unspecified, set contentLength to
537 // 0. 537 // 0.
538 headers.chunkedTransferEncoding = false; 538 headers.chunkedTransferEncoding = false;
539 headers.contentLength = 0; 539 headers.contentLength = 0;
540 } else if (!_ignoreBody && headers.contentLength > 0) { 540 } else if (!_ignoreBody && headers.contentLength > 0) {
541 _headersSink.close().catchError((_) {}); 541 _headersSink.addError(new HttpException(
542 return new Future.error(new HttpException(
543 "No content while contentLength was specified to be greater " 542 "No content while contentLength was specified to be greater "
544 " than 0: ${headers.contentLength}.", 543 "than 0: ${headers.contentLength}.",
545 uri: _uri)); 544 uri: _uri));
545 return _headersSink.done;
546 } 546 }
547 } 547 }
548 return _writeHeaders().then((_) => _headersSink.close()); 548 return _writeHeaders().then((_) => _headersSink.close());
549 } 549 }
550 550
551 void _writeHeader(); // TODO(ajohnsen): Better name. 551 void _writeHeader(); // TODO(ajohnsen): Better name.
552 } 552 }
553 553
554 554
555 class _HttpOutboundConsumer implements StreamConsumer { 555 class _HttpOutboundConsumer implements StreamConsumer {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
613 613
614 Future addStream(var stream) { 614 Future addStream(var stream) {
615 // If we saw a socket error subscribe and then cancel, to ignore any data 615 // If we saw a socket error subscribe and then cancel, to ignore any data
616 // on the stream. 616 // on the stream.
617 if (_socketError) { 617 if (_socketError) {
618 stream.listen(null).cancel(); 618 stream.listen(null).cancel();
619 return new Future.value(_outbound); 619 return new Future.value(_outbound);
620 } 620 }
621 _completer = new Completer(); 621 _completer = new Completer();
622 _subscription = stream.listen( 622 _subscription = stream.listen(
623 (data) { 623 (data) => _controller.add(data),
624 _controller.add(data);
625 },
626 onDone: _done, 624 onDone: _done,
627 onError: _done, 625 onError: (e) => _controller.addError(e),
Søren Gjesse 2013/10/23 08:14:05 Do we want to propagate the stack trace here?
Anders Johnsen 2013/10/23 10:23:24 Yes, nice catch! :)
628 cancelOnError: true); 626 cancelOnError: true);
629 // Pause the first request. 627 // Pause the first request.
630 if (_controller == null) _subscription.pause(); 628 if (_controller == null) _subscription.pause();
631 _ensureController(); 629 _ensureController();
632 return _completer.future; 630 return _completer.future;
633 } 631 }
634 632
635 Future close() { 633 Future close() {
636 Future closeOutbound() { 634 Future closeOutbound() {
637 if (_socketError) return new Future.value(_outbound); 635 if (_socketError) return new Future.value(_outbound);
(...skipping 1233 matching lines...) Expand 10 before | Expand all | Expand 10 after
1871 incoming.headers.protocolVersion, 1869 incoming.headers.protocolVersion,
1872 outgoing, 1870 outgoing,
1873 _httpServer.serverHeader); 1871 _httpServer.serverHeader);
1874 var request = new _HttpRequest(response, incoming, _httpServer, this); 1872 var request = new _HttpRequest(response, incoming, _httpServer, this);
1875 _streamFuture = outgoing.done 1873 _streamFuture = outgoing.done
1876 .then((_) { 1874 .then((_) {
1877 response.deadline = null; 1875 response.deadline = null;
1878 if (_state == _DETACHED) return; 1876 if (_state == _DETACHED) return;
1879 if (response.persistentConnection && 1877 if (response.persistentConnection &&
1880 request.persistentConnection && 1878 request.persistentConnection &&
1881 incoming.fullBodyRead) { 1879 incoming.fullBodyRead &&
1880 !_httpParser.upgrade) {
1882 _state = _IDLE; 1881 _state = _IDLE;
1883 _startTimeout(); 1882 _startTimeout();
1884 // Resume the subscription for incoming requests as the 1883 // Resume the subscription for incoming requests as the
1885 // request is now processed. 1884 // request is now processed.
1886 _subscription.resume(); 1885 _subscription.resume();
1887 } else { 1886 } else {
1888 // Close socket, keep-alive not used or body sent before 1887 // Close socket, keep-alive not used or body sent before
1889 // received data was handled. 1888 // received data was handled.
1890 destroy(); 1889 destroy();
1891 } 1890 }
1892 }) 1891 })
1893 .catchError((e) { 1892 .catchError((e) {
1894 destroy(); 1893 destroy();
1895 }); 1894 });
1896 response._ignoreBody = request.method == "HEAD"; 1895 response._ignoreBody = request.method == "HEAD";
1897 response._httpRequest = request; 1896 response._httpRequest = request;
1898 _httpServer._handleRequest(request); 1897 _httpServer._handleRequest(request, this);
1899 }, 1898 },
1900 onDone: () { 1899 onDone: () {
1901 destroy(); 1900 destroy();
1902 }, 1901 },
1903 onError: (error) { 1902 onError: (error) {
1904 // Ignore failed requests that was closed before headers was received. 1903 // Ignore failed requests that was closed before headers was received.
1905 destroy(); 1904 destroy();
1906 }); 1905 });
1907 } 1906 }
1908 1907
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
2000 _connections.add(connection); 1999 _connections.add(connection);
2001 }, 2000 },
2002 onError: _controller.addError, 2001 onError: _controller.addError,
2003 onDone: _controller.close); 2002 onDone: _controller.close);
2004 return _controller.stream.listen(onData, 2003 return _controller.stream.listen(onData,
2005 onError: onError, 2004 onError: onError,
2006 onDone: onDone, 2005 onDone: onDone,
2007 cancelOnError: cancelOnError); 2006 cancelOnError: cancelOnError);
2008 } 2007 }
2009 2008
2010 Future close() { 2009 Future close() {
Søren Gjesse 2013/10/23 08:14:05 I think we still need the public close to do a ful
Anders Johnsen 2013/10/23 10:23:24 The 'problem' is that there is no binding between
Søren Gjesse 2013/10/23 11:05:28 I am fine with adding the force flag. In case forc
Anders Johnsen 2013/10/23 12:06:55 The way we force-close is by calling 'socket.destr
2011 closed = true; 2010 closed = true;
2012 Future result; 2011 Future result;
2013 if (_serverSocket != null && _closeServer) { 2012 if (_serverSocket != null && _closeServer) {
2014 result = _serverSocket.close(); 2013 result = _serverSocket.close();
2015 } else { 2014 } else {
2016 result = new Future.value(); 2015 result = new Future.value();
2017 } 2016 }
2018 if (_sessionManagerInstance != null) { 2017 _maybeCloseSessionManager();
2018 return result;
2019 }
2020
2021 void _maybeCloseSessionManager() {
2022 if (closed &&
2023 _connections.length == 0 &&
2024 _sessionManagerInstance != null) {
2019 _sessionManagerInstance.close(); 2025 _sessionManagerInstance.close();
2020 _sessionManagerInstance = null; 2026 _sessionManagerInstance = null;
2021 } 2027 }
2022 for (_HttpConnection connection in _connections.toList()) {
2023 connection.destroy();
2024 }
2025 _connections.clear();
2026 return result;
2027 } 2028 }
2028 2029
2029 int get port { 2030 int get port {
2030 if (closed) throw new HttpException("HttpServer is not bound to a socket"); 2031 if (closed) throw new HttpException("HttpServer is not bound to a socket");
2031 return _serverSocket.port; 2032 return _serverSocket.port;
2032 } 2033 }
2033 2034
2034 InternetAddress get address { 2035 InternetAddress get address {
2035 if (closed) throw new HttpException("HttpServer is not bound to a socket"); 2036 if (closed) throw new HttpException("HttpServer is not bound to a socket");
2036 return _serverSocket.address; 2037 return _serverSocket.address;
2037 } 2038 }
2038 2039
2039 set sessionTimeout(int timeout) { 2040 set sessionTimeout(int timeout) {
2040 _sessionManager.sessionTimeout = timeout; 2041 _sessionManager.sessionTimeout = timeout;
2041 } 2042 }
2042 2043
2043 void _handleRequest(HttpRequest request) { 2044 void _handleRequest(HttpRequest request, _HttpConnection connection) {
2045 if (closed) {
2046 connection.destroy();
2047 return;
2048 }
2044 _controller.add(request); 2049 _controller.add(request);
2045 } 2050 }
2046 2051
2047 void _handleError(error) { 2052 void _handleError(error) {
2048 if (!closed) _controller.addError(error); 2053 if (!closed) _controller.addError(error);
2049 } 2054 }
2050 2055
2051 void _connectionClosed(_HttpConnection connection) { 2056 void _connectionClosed(_HttpConnection connection) {
2052 _connections.remove(connection); 2057 _connections.remove(connection);
2058 _maybeCloseSessionManager();
2053 } 2059 }
2054 2060
2055 _HttpSessionManager get _sessionManager { 2061 _HttpSessionManager get _sessionManager {
2056 // Lazy init. 2062 // Lazy init.
2057 if (_sessionManagerInstance == null) { 2063 if (_sessionManagerInstance == null) {
2058 _sessionManagerInstance = new _HttpSessionManager(); 2064 _sessionManagerInstance = new _HttpSessionManager();
2059 } 2065 }
2060 return _sessionManagerInstance; 2066 return _sessionManagerInstance;
2061 } 2067 }
2062 2068
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
2169 final String username; 2175 final String username;
2170 final String password; 2176 final String password;
2171 final bool isDirect; 2177 final bool isDirect;
2172 } 2178 }
2173 2179
2174 2180
2175 class _HttpConnectionInfo implements HttpConnectionInfo { 2181 class _HttpConnectionInfo implements HttpConnectionInfo {
2176 static _HttpConnectionInfo create(Socket socket) { 2182 static _HttpConnectionInfo create(Socket socket) {
2177 if (socket == null) return null; 2183 if (socket == null) return null;
2178 try { 2184 try {
2179 _HttpConnectionInfo info = new _HttpConnectionInfo._(); 2185 _HttpConnectionInfo info = new _HttpConnectionInfo();
2180 info.remoteHost = socket.remoteHost; 2186 info.remoteHost = socket.remoteHost;
2181 info.remotePort = socket.remotePort; 2187 info.remotePort = socket.remotePort;
2182 info.localPort = socket.port; 2188 info.localPort = socket.port;
2183 return info; 2189 return info;
2184 } catch (e) { } 2190 } catch (e) { }
2185 return null; 2191 return null;
2186 } 2192 }
2187 2193
2188 _HttpConnectionInfo._();
2189
2190 String remoteHost; 2194 String remoteHost;
2191 int remotePort; 2195 int remotePort;
2192 int localPort; 2196 int localPort;
2193 } 2197 }
2194 2198
2195 2199
2196 class _DetachedSocket extends Stream<List<int>> implements Socket { 2200 class _DetachedSocket extends Stream<List<int>> implements Socket {
2197 final Stream<List<int>> _incoming; 2201 final Stream<List<int>> _incoming;
2198 final Socket _socket; 2202 final Socket _socket;
2199 2203
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
2494 final Uri location; 2498 final Uri location;
2495 } 2499 }
2496 2500
2497 String _getHttpVersion() { 2501 String _getHttpVersion() {
2498 var version = Platform.version; 2502 var version = Platform.version;
2499 // Only include major and minor version numbers. 2503 // Only include major and minor version numbers.
2500 int index = version.indexOf('.', version.indexOf('.') + 1); 2504 int index = version.indexOf('.', version.indexOf('.') + 1);
2501 version = version.substring(0, index); 2505 version = version.substring(0, index);
2502 return 'Dart/$version (dart:io)'; 2506 return 'Dart/$version (dart:io)';
2503 } 2507 }
OLDNEW
« no previous file with comments | « no previous file | tests/standalone/io/http_client_connect_test.dart » ('j') | tests/standalone/io/http_client_connect_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698