| OLD | NEW |
| 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 const int _OUTGOING_BUFFER_SIZE = 8 * 1024; | 7 const int _OUTGOING_BUFFER_SIZE = 8 * 1024; |
| 8 | 8 |
| 9 class _HttpIncoming extends Stream<List<int>> { | 9 class _HttpIncoming extends Stream<List<int>> { |
| 10 final int _transferLength; | 10 final int _transferLength; |
| (...skipping 1341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1352 _streamFuture = outgoing.done | 1352 _streamFuture = outgoing.done |
| 1353 .then((s) { | 1353 .then((s) { |
| 1354 // Request sent, set up response completer. | 1354 // Request sent, set up response completer. |
| 1355 _nextResponseCompleter = new Completer(); | 1355 _nextResponseCompleter = new Completer(); |
| 1356 | 1356 |
| 1357 // Listen for response. | 1357 // Listen for response. |
| 1358 _nextResponseCompleter.future | 1358 _nextResponseCompleter.future |
| 1359 .then((incoming) { | 1359 .then((incoming) { |
| 1360 _currentUri = null; | 1360 _currentUri = null; |
| 1361 incoming.dataDone.then((closing) { | 1361 incoming.dataDone.then((closing) { |
| 1362 if (closed) return; |
| 1362 if (!closing && | 1363 if (!closing && |
| 1363 !_dispose && | 1364 !_dispose && |
| 1364 incoming.headers.persistentConnection && | 1365 incoming.headers.persistentConnection && |
| 1365 request.persistentConnection) { | 1366 request.persistentConnection) { |
| 1366 // Return connection, now we are done. | 1367 // Return connection, now we are done. |
| 1367 _httpClient._returnConnection(this); | 1368 _httpClient._returnConnection(this); |
| 1368 _subscription.resume(); | 1369 _subscription.resume(); |
| 1369 } else { | 1370 } else { |
| 1370 destroy(); | 1371 destroy(); |
| 1371 } | 1372 } |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1495 | 1496 |
| 1496 class _ConnnectionInfo { | 1497 class _ConnnectionInfo { |
| 1497 final _HttpClientConnection connection; | 1498 final _HttpClientConnection connection; |
| 1498 final _Proxy proxy; | 1499 final _Proxy proxy; |
| 1499 | 1500 |
| 1500 _ConnnectionInfo(this.connection, this.proxy); | 1501 _ConnnectionInfo(this.connection, this.proxy); |
| 1501 } | 1502 } |
| 1502 | 1503 |
| 1503 | 1504 |
| 1504 class _HttpClient implements HttpClient { | 1505 class _HttpClient implements HttpClient { |
| 1505 // TODO(ajohnsen): Use eviction timeout. | |
| 1506 bool _closing = false; | 1506 bool _closing = false; |
| 1507 | |
| 1508 final Map<String, Set<_HttpClientConnection>> _idleConnections | 1507 final Map<String, Set<_HttpClientConnection>> _idleConnections |
| 1509 = new HashMap<String, Set<_HttpClientConnection>>(); | 1508 = new HashMap<String, Set<_HttpClientConnection>>(); |
| 1510 final Set<_HttpClientConnection> _activeConnections | 1509 final Map<String, Set<_HttpClientConnection>> _activeConnections |
| 1511 = new HashSet<_HttpClientConnection>(); | 1510 = new HashMap<String, Set<_HttpClientConnection>>(); |
| 1512 final List<_Credentials> _credentials = []; | 1511 final List<_Credentials> _credentials = []; |
| 1513 final List<_ProxyCredentials> _proxyCredentials = []; | 1512 final List<_ProxyCredentials> _proxyCredentials = []; |
| 1514 Function _authenticate; | 1513 Function _authenticate; |
| 1515 Function _authenticateProxy; | 1514 Function _authenticateProxy; |
| 1516 Function _findProxy = HttpClient.findProxyFromEnvironment; | 1515 Function _findProxy = HttpClient.findProxyFromEnvironment; |
| 1517 Duration _idleTimeout = const Duration(seconds: 15); | 1516 Duration _idleTimeout = const Duration(seconds: 15); |
| 1518 Function _badCertificateCallback; | 1517 Function _badCertificateCallback; |
| 1519 | 1518 |
| 1520 Timer _noActiveTimer; | 1519 Timer _noActiveTimer; |
| 1521 | 1520 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1592 [], | 1591 [], |
| 1593 (l, e) { | 1592 (l, e) { |
| 1594 l.addAll(e); | 1593 l.addAll(e); |
| 1595 return l; | 1594 return l; |
| 1596 }); | 1595 }); |
| 1597 idle.forEach((e) { | 1596 idle.forEach((e) { |
| 1598 e.close(); | 1597 e.close(); |
| 1599 }); | 1598 }); |
| 1600 assert(_idleConnections.isEmpty); | 1599 assert(_idleConnections.isEmpty); |
| 1601 if (force) { | 1600 if (force) { |
| 1602 for (var connection in _activeConnections.toList()) { | 1601 for (var connection in |
| 1602 _activeConnections.values.expand((s) => s).toList()) { |
| 1603 connection.destroy(); | 1603 connection.destroy(); |
| 1604 } | 1604 } |
| 1605 assert(_activeConnections.isEmpty); | 1605 assert(_activeConnections.isEmpty); |
| 1606 _activeConnections.clear(); | 1606 _activeConnections.clear(); |
| 1607 } | 1607 } |
| 1608 } | 1608 } |
| 1609 | 1609 |
| 1610 set authenticate(Future<bool> f(Uri url, String scheme, String realm)) { | 1610 set authenticate(Future<bool> f(Uri url, String scheme, String realm)) { |
| 1611 _authenticate = f; | 1611 _authenticate = f; |
| 1612 } | 1612 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1696 } | 1696 } |
| 1697 } | 1697 } |
| 1698 return request | 1698 return request |
| 1699 ..headers.chunkedTransferEncoding = false | 1699 ..headers.chunkedTransferEncoding = false |
| 1700 ..contentLength = 0; | 1700 ..contentLength = 0; |
| 1701 }); | 1701 }); |
| 1702 } | 1702 } |
| 1703 | 1703 |
| 1704 // Return a live connection to the idle pool. | 1704 // Return a live connection to the idle pool. |
| 1705 void _returnConnection(_HttpClientConnection connection) { | 1705 void _returnConnection(_HttpClientConnection connection) { |
| 1706 _activeConnections.remove(connection); | 1706 var key = connection.key; |
| 1707 _activeConnections[key].remove(connection); |
| 1708 if (_activeConnections[key].isEmpty) { |
| 1709 _activeConnections.remove(key); |
| 1710 } |
| 1707 if (_closing) { | 1711 if (_closing) { |
| 1708 connection.close(); | 1712 connection.close(); |
| 1709 return; | 1713 return; |
| 1710 } | 1714 } |
| 1711 if (!_idleConnections.containsKey(connection.key)) { | 1715 _idleConnections |
| 1712 _idleConnections[connection.key] = new HashSet(); | 1716 .putIfAbsent(key, () => new HashSet()) |
| 1713 } | 1717 .add(connection); |
| 1714 _idleConnections[connection.key].add(connection); | |
| 1715 connection.startTimer(); | 1718 connection.startTimer(); |
| 1716 _updateTimers(); | 1719 _updateTimers(); |
| 1717 } | 1720 } |
| 1718 | 1721 |
| 1719 // Remove a closed connnection from the active set. | 1722 // Remove a closed connnection from the active set. |
| 1720 void _connectionClosed(_HttpClientConnection connection) { | 1723 void _connectionClosed(_HttpClientConnection connection) { |
| 1721 connection.stopTimer(); | 1724 connection.stopTimer(); |
| 1722 _activeConnections.remove(connection); | 1725 var key = connection.key; |
| 1723 if (_idleConnections.containsKey(connection.key)) { | 1726 if (_activeConnections.containsKey(key)) { |
| 1724 _idleConnections[connection.key].remove(connection); | 1727 _activeConnections[key].remove(connection); |
| 1725 if (_idleConnections[connection.key].isEmpty) { | 1728 if (_activeConnections[key].isEmpty) { |
| 1726 _idleConnections.remove(connection.key); | 1729 _activeConnections.remove(key); |
| 1730 } |
| 1731 } |
| 1732 if (_idleConnections.containsKey(key)) { |
| 1733 _idleConnections[key].remove(connection); |
| 1734 if (_idleConnections[key].isEmpty) { |
| 1735 _idleConnections.remove(key); |
| 1727 } | 1736 } |
| 1728 } | 1737 } |
| 1729 _updateTimers(); | 1738 _updateTimers(); |
| 1730 } | 1739 } |
| 1731 | 1740 |
| 1732 void _updateTimers() { | 1741 void _updateTimers() { |
| 1733 if (_activeConnections.isEmpty) { | 1742 if (_activeConnections.isEmpty) { |
| 1734 if (!_idleConnections.isEmpty && _noActiveTimer == null) { | 1743 if (!_idleConnections.isEmpty && _noActiveTimer == null) { |
| 1735 _noActiveTimer = new Timer(const Duration(milliseconds: 100), () { | 1744 _noActiveTimer = new Timer(const Duration(milliseconds: 100), () { |
| 1736 _noActiveTimer = null; | 1745 _noActiveTimer = null; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1760 String host = proxy.isDirect ? uriHost: proxy.host; | 1769 String host = proxy.isDirect ? uriHost: proxy.host; |
| 1761 int port = proxy.isDirect ? uriPort: proxy.port; | 1770 int port = proxy.isDirect ? uriPort: proxy.port; |
| 1762 String key = _HttpClientConnection.makeKey(isSecure, host, port); | 1771 String key = _HttpClientConnection.makeKey(isSecure, host, port); |
| 1763 if (_idleConnections.containsKey(key)) { | 1772 if (_idleConnections.containsKey(key)) { |
| 1764 var connection = _idleConnections[key].first; | 1773 var connection = _idleConnections[key].first; |
| 1765 _idleConnections[key].remove(connection); | 1774 _idleConnections[key].remove(connection); |
| 1766 if (_idleConnections[key].isEmpty) { | 1775 if (_idleConnections[key].isEmpty) { |
| 1767 _idleConnections.remove(key); | 1776 _idleConnections.remove(key); |
| 1768 } | 1777 } |
| 1769 connection.stopTimer(); | 1778 connection.stopTimer(); |
| 1770 _activeConnections.add(connection); | 1779 _activeConnections |
| 1780 .putIfAbsent(key, () => new HashSet()) |
| 1781 .add(connection); |
| 1771 _updateTimers(); | 1782 _updateTimers(); |
| 1772 return new Future.value(new _ConnnectionInfo(connection, proxy)); | 1783 return new Future.value(new _ConnnectionInfo(connection, proxy)); |
| 1773 } | 1784 } |
| 1774 var currentBadCertificateCallback = _badCertificateCallback; | 1785 var currentBadCertificateCallback = _badCertificateCallback; |
| 1775 bool callback(X509Certificate certificate) => | 1786 bool callback(X509Certificate certificate) => |
| 1776 currentBadCertificateCallback == null ? false : | 1787 currentBadCertificateCallback == null ? false : |
| 1777 currentBadCertificateCallback(certificate, uriHost, uriPort); | 1788 currentBadCertificateCallback(certificate, uriHost, uriPort); |
| 1778 Future socketFuture = (isSecure && proxy.isDirect | 1789 Future socketFuture = (isSecure && proxy.isDirect |
| 1779 ? SecureSocket.connect(host, | 1790 ? SecureSocket.connect(host, |
| 1780 port, | 1791 port, |
| 1781 sendClientCertificate: true, | 1792 sendClientCertificate: true, |
| 1782 onBadCertificate: callback) | 1793 onBadCertificate: callback) |
| 1783 : Socket.connect(host, port)); | 1794 : Socket.connect(host, port)); |
| 1784 return socketFuture.then((socket) { | 1795 return socketFuture.then((socket) { |
| 1785 socket.setOption(SocketOption.TCP_NODELAY, true); | 1796 socket.setOption(SocketOption.TCP_NODELAY, true); |
| 1786 var connection = new _HttpClientConnection(key, socket, this); | 1797 var connection = new _HttpClientConnection(key, socket, this); |
| 1787 if (isSecure && !proxy.isDirect) { | 1798 if (isSecure && !proxy.isDirect) { |
| 1788 connection._dispose = true; | 1799 connection._dispose = true; |
| 1789 return connection.createProxyTunnel( | 1800 return connection.createProxyTunnel( |
| 1790 uriHost, uriPort, proxy, callback) | 1801 uriHost, uriPort, proxy, callback) |
| 1791 .then((tunnel) { | 1802 .then((tunnel) { |
| 1792 _activeConnections.add(tunnel); | 1803 _activeConnections |
| 1804 .putIfAbsent(tunnel.key, () => new HashSet()) |
| 1805 .add(tunnel); |
| 1793 return new _ConnnectionInfo(tunnel, proxy); | 1806 return new _ConnnectionInfo(tunnel, proxy); |
| 1794 }); | 1807 }); |
| 1795 } else { | 1808 } else { |
| 1796 _activeConnections.add(connection); | 1809 _activeConnections |
| 1810 .putIfAbsent(key, () => new HashSet()) |
| 1811 .add(connection); |
| 1797 return new _ConnnectionInfo(connection, proxy); | 1812 return new _ConnnectionInfo(connection, proxy); |
| 1798 } | 1813 } |
| 1799 }, onError: (error) { | 1814 }, onError: (error) { |
| 1800 // Continue with next proxy. | 1815 // Continue with next proxy. |
| 1801 return connect(error); | 1816 return connect(error); |
| 1802 }); | 1817 }); |
| 1803 } | 1818 } |
| 1804 return connect(new HttpException("No proxies given")); | 1819 return connect(new HttpException("No proxies given")); |
| 1805 } | 1820 } |
| 1806 | 1821 |
| (...skipping 814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2621 const _RedirectInfo(this.statusCode, this.method, this.location); | 2636 const _RedirectInfo(this.statusCode, this.method, this.location); |
| 2622 } | 2637 } |
| 2623 | 2638 |
| 2624 String _getHttpVersion() { | 2639 String _getHttpVersion() { |
| 2625 var version = Platform.version; | 2640 var version = Platform.version; |
| 2626 // Only include major and minor version numbers. | 2641 // Only include major and minor version numbers. |
| 2627 int index = version.indexOf('.', version.indexOf('.') + 1); | 2642 int index = version.indexOf('.', version.indexOf('.') + 1); |
| 2628 version = version.substring(0, index); | 2643 version = version.substring(0, index); |
| 2629 return 'Dart/$version (dart:io)'; | 2644 return 'Dart/$version (dart:io)'; |
| 2630 } | 2645 } |
| OLD | NEW |