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 1238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1249 footerAndHeader[size + 0] = _CharCode.CR; | 1249 footerAndHeader[size + 0] = _CharCode.CR; |
1250 footerAndHeader[size + 1] = _CharCode.LF; | 1250 footerAndHeader[size + 1] = _CharCode.LF; |
1251 return footerAndHeader; | 1251 return footerAndHeader; |
1252 } | 1252 } |
1253 } | 1253 } |
1254 | 1254 |
1255 class _HttpClientConnection { | 1255 class _HttpClientConnection { |
1256 final String key; | 1256 final String key; |
1257 final Socket _socket; | 1257 final Socket _socket; |
1258 final bool _proxyTunnel; | 1258 final bool _proxyTunnel; |
| 1259 final SecurityContext _context; |
1259 final _HttpParser _httpParser; | 1260 final _HttpParser _httpParser; |
1260 StreamSubscription _subscription; | 1261 StreamSubscription _subscription; |
1261 final _HttpClient _httpClient; | 1262 final _HttpClient _httpClient; |
1262 bool _dispose = false; | 1263 bool _dispose = false; |
1263 Timer _idleTimer; | 1264 Timer _idleTimer; |
1264 bool closed = false; | 1265 bool closed = false; |
1265 Uri _currentUri; | 1266 Uri _currentUri; |
1266 | 1267 |
1267 Completer<_HttpIncoming> _nextResponseCompleter; | 1268 Completer<_HttpIncoming> _nextResponseCompleter; |
1268 Future _streamFuture; | 1269 Future _streamFuture; |
1269 | 1270 |
1270 _HttpClientConnection(this.key, this._socket, this._httpClient, | 1271 _HttpClientConnection(this.key, this._socket, this._httpClient, |
1271 [this._proxyTunnel = false]) | 1272 [this._proxyTunnel = false, this._context]) |
1272 : _httpParser = new _HttpParser.responseParser() { | 1273 : _httpParser = new _HttpParser.responseParser() { |
1273 _httpParser.listenToStream(_socket); | 1274 _httpParser.listenToStream(_socket); |
1274 | 1275 |
1275 // Set up handlers on the parser here, so we are sure to get 'onDone' from | 1276 // Set up handlers on the parser here, so we are sure to get 'onDone' from |
1276 // the parser. | 1277 // the parser. |
1277 _subscription = _httpParser.listen( | 1278 _subscription = _httpParser.listen( |
1278 (incoming) { | 1279 (incoming) { |
1279 // Only handle one incoming response at the time. Keep the | 1280 // Only handle one incoming response at the time. Keep the |
1280 // stream paused until the response have been processed. | 1281 // stream paused until the response have been processed. |
1281 _subscription.pause(); | 1282 _subscription.pause(); |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1489 request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth"); | 1490 request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth"); |
1490 } | 1491 } |
1491 return request.close() | 1492 return request.close() |
1492 .then((response) { | 1493 .then((response) { |
1493 if (response.statusCode != HttpStatus.OK) { | 1494 if (response.statusCode != HttpStatus.OK) { |
1494 throw "Proxy failed to establish tunnel " | 1495 throw "Proxy failed to establish tunnel " |
1495 "(${response.statusCode} ${response.reasonPhrase})"; | 1496 "(${response.statusCode} ${response.reasonPhrase})"; |
1496 } | 1497 } |
1497 var socket = response._httpRequest._httpClientConnection._socket; | 1498 var socket = response._httpRequest._httpClientConnection._socket; |
1498 return SecureSocket.secure( | 1499 return SecureSocket.secure( |
1499 socket, host: host, onBadCertificate: callback); | 1500 socket, |
| 1501 host: host, |
| 1502 context: _context, |
| 1503 onBadCertificate: callback); |
1500 }) | 1504 }) |
1501 .then((secureSocket) { | 1505 .then((secureSocket) { |
1502 String key = _HttpClientConnection.makeKey(true, host, port); | 1506 String key = _HttpClientConnection.makeKey(true, host, port); |
1503 return new _HttpClientConnection( | 1507 return new _HttpClientConnection( |
1504 key, secureSocket, request._httpClient, true); | 1508 key, secureSocket, request._httpClient, true); |
1505 }); | 1509 }); |
1506 } | 1510 } |
1507 | 1511 |
1508 HttpConnectionInfo get connectionInfo => _HttpConnectionInfo.create(_socket); | 1512 HttpConnectionInfo get connectionInfo => _HttpConnectionInfo.create(_socket); |
1509 | 1513 |
(...skipping 26 matching lines...) Expand all Loading... |
1536 _ConnectionInfo(this.connection, this.proxy); | 1540 _ConnectionInfo(this.connection, this.proxy); |
1537 } | 1541 } |
1538 | 1542 |
1539 | 1543 |
1540 class _ConnectionTarget { | 1544 class _ConnectionTarget { |
1541 // Unique key for this connection target. | 1545 // Unique key for this connection target. |
1542 final String key; | 1546 final String key; |
1543 final String host; | 1547 final String host; |
1544 final int port; | 1548 final int port; |
1545 final bool isSecure; | 1549 final bool isSecure; |
| 1550 final SecurityContext context; |
1546 final Set<_HttpClientConnection> _idle = new HashSet(); | 1551 final Set<_HttpClientConnection> _idle = new HashSet(); |
1547 final Set<_HttpClientConnection> _active = new HashSet(); | 1552 final Set<_HttpClientConnection> _active = new HashSet(); |
1548 final Queue _pending = new ListQueue(); | 1553 final Queue _pending = new ListQueue(); |
1549 int _connecting = 0; | 1554 int _connecting = 0; |
1550 | 1555 |
1551 _ConnectionTarget(this.key, this.host, this.port, this.isSecure); | 1556 _ConnectionTarget(this.key, |
| 1557 this.host, |
| 1558 this.port, |
| 1559 this.isSecure, |
| 1560 this.context); |
1552 | 1561 |
1553 bool get isEmpty => _idle.isEmpty && _active.isEmpty && _connecting == 0; | 1562 bool get isEmpty => _idle.isEmpty && _active.isEmpty && _connecting == 0; |
1554 | 1563 |
1555 bool get hasIdle => _idle.isNotEmpty; | 1564 bool get hasIdle => _idle.isNotEmpty; |
1556 | 1565 |
1557 bool get hasActive => _active.isNotEmpty || _connecting > 0; | 1566 bool get hasActive => _active.isNotEmpty || _connecting > 0; |
1558 | 1567 |
1559 _HttpClientConnection takeIdle() { | 1568 _HttpClientConnection takeIdle() { |
1560 assert(hasIdle); | 1569 assert(hasIdle); |
1561 _HttpClientConnection connection = _idle.first; | 1570 _HttpClientConnection connection = _idle.first; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1613 if (client.maxConnectionsPerHost != null && | 1622 if (client.maxConnectionsPerHost != null && |
1614 _active.length + _connecting >= client.maxConnectionsPerHost) { | 1623 _active.length + _connecting >= client.maxConnectionsPerHost) { |
1615 var completer = new Completer(); | 1624 var completer = new Completer(); |
1616 _pending.add(() { | 1625 _pending.add(() { |
1617 connect(uriHost, uriPort, proxy, client) | 1626 connect(uriHost, uriPort, proxy, client) |
1618 .then(completer.complete, onError: completer.completeError); | 1627 .then(completer.complete, onError: completer.completeError); |
1619 }); | 1628 }); |
1620 return completer.future; | 1629 return completer.future; |
1621 } | 1630 } |
1622 var currentBadCertificateCallback = client._badCertificateCallback; | 1631 var currentBadCertificateCallback = client._badCertificateCallback; |
1623 bool callback(X509Certificate certificate) => | 1632 callback(X509Certificate certificate) => |
1624 currentBadCertificateCallback == null ? false : | 1633 currentBadCertificateCallback == null ? false : |
1625 currentBadCertificateCallback(certificate, uriHost, uriPort); | 1634 currentBadCertificateCallback(certificate, uriHost, uriPort); |
1626 Future socketFuture = (isSecure && proxy.isDirect | 1635 Future socketFuture = (isSecure && proxy.isDirect |
1627 ? SecureSocket.connect(host, | 1636 ? SecureSocket.connect(host, |
1628 port, | 1637 port, |
| 1638 context: context, |
1629 sendClientCertificate: true, | 1639 sendClientCertificate: true, |
1630 onBadCertificate: callback) | 1640 onBadCertificate: callback) |
1631 : Socket.connect(host, port)); | 1641 : Socket.connect(host, port)); |
1632 _connecting++; | 1642 _connecting++; |
1633 return socketFuture.then((socket) { | 1643 return socketFuture.then((socket) { |
1634 _connecting--; | 1644 _connecting--; |
1635 socket.setOption(SocketOption.TCP_NODELAY, true); | 1645 socket.setOption(SocketOption.TCP_NODELAY, true); |
1636 var connection = new _HttpClientConnection(key, socket, client); | 1646 var connection = |
| 1647 new _HttpClientConnection(key, socket, client, false, context); |
1637 if (isSecure && !proxy.isDirect) { | 1648 if (isSecure && !proxy.isDirect) { |
1638 connection._dispose = true; | 1649 connection._dispose = true; |
1639 return connection.createProxyTunnel(uriHost, uriPort, proxy, callback) | 1650 return connection.createProxyTunnel(uriHost, uriPort, proxy, callback) |
1640 .then((tunnel) { | 1651 .then((tunnel) { |
1641 client._getConnectionTarget(uriHost, uriPort, true) | 1652 client._getConnectionTarget(uriHost, uriPort, true) |
1642 .addNewActive(tunnel); | 1653 .addNewActive(tunnel); |
1643 return new _ConnectionInfo(tunnel, proxy); | 1654 return new _ConnectionInfo(tunnel, proxy); |
1644 }); | 1655 }); |
1645 } else { | 1656 } else { |
1646 addNewActive(connection); | 1657 addNewActive(connection); |
1647 return new _ConnectionInfo(connection, proxy); | 1658 return new _ConnectionInfo(connection, proxy); |
1648 } | 1659 } |
1649 }, onError: (error) { | 1660 }, onError: (error) { |
1650 _connecting--; | 1661 _connecting--; |
1651 _checkPending(); | 1662 _checkPending(); |
1652 throw error; | 1663 throw error; |
1653 }); | 1664 }); |
1654 } | 1665 } |
1655 } | 1666 } |
1656 | 1667 |
1657 | 1668 |
1658 class _HttpClient implements HttpClient { | 1669 class _HttpClient implements HttpClient { |
1659 bool _closing = false; | 1670 bool _closing = false; |
1660 bool _closingForcefully = false; | 1671 bool _closingForcefully = false; |
1661 final Map<String, _ConnectionTarget> _connectionTargets | 1672 final Map<String, _ConnectionTarget> _connectionTargets |
1662 = new HashMap<String, _ConnectionTarget>(); | 1673 = new HashMap<String, _ConnectionTarget>(); |
1663 final List<_Credentials> _credentials = []; | 1674 final List<_Credentials> _credentials = []; |
1664 final List<_ProxyCredentials> _proxyCredentials = []; | 1675 final List<_ProxyCredentials> _proxyCredentials = []; |
| 1676 final SecurityContext _context; |
1665 Function _authenticate; | 1677 Function _authenticate; |
1666 Function _authenticateProxy; | 1678 Function _authenticateProxy; |
1667 Function _findProxy = HttpClient.findProxyFromEnvironment; | 1679 Function _findProxy = HttpClient.findProxyFromEnvironment; |
1668 Duration _idleTimeout = const Duration(seconds: 15); | 1680 Duration _idleTimeout = const Duration(seconds: 15); |
1669 Function _badCertificateCallback; | 1681 Function _badCertificateCallback; |
1670 | 1682 |
1671 Duration get idleTimeout => _idleTimeout; | 1683 Duration get idleTimeout => _idleTimeout; |
1672 | 1684 |
1673 int maxConnectionsPerHost; | 1685 int maxConnectionsPerHost; |
1674 | 1686 |
1675 bool autoUncompress = true; | 1687 bool autoUncompress = true; |
1676 | 1688 |
1677 String userAgent = _getHttpVersion(); | 1689 String userAgent = _getHttpVersion(); |
1678 | 1690 |
| 1691 _HttpClient(SecurityContext this._context); |
| 1692 |
1679 void set idleTimeout(Duration timeout) { | 1693 void set idleTimeout(Duration timeout) { |
1680 _idleTimeout = timeout; | 1694 _idleTimeout = timeout; |
1681 for (var c in _connectionTargets.values) { | 1695 for (var c in _connectionTargets.values) { |
1682 for (var idle in c._idle) { | 1696 for (var idle in c._idle) { |
1683 // Reset timer. This is fine, as it's not happening often. | 1697 // Reset timer. This is fine, as it's not happening often. |
1684 idle.stopTimer(); | 1698 idle.stopTimer(); |
1685 idle.startTimer(); | 1699 idle.startTimer(); |
1686 } | 1700 } |
1687 } | 1701 } |
1688 } | 1702 } |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1887 } | 1901 } |
1888 | 1902 |
1889 void _closeConnections(bool force) { | 1903 void _closeConnections(bool force) { |
1890 for (var connectionTarget in _connectionTargets.values.toList()) { | 1904 for (var connectionTarget in _connectionTargets.values.toList()) { |
1891 connectionTarget.close(force); | 1905 connectionTarget.close(force); |
1892 } | 1906 } |
1893 } | 1907 } |
1894 | 1908 |
1895 _ConnectionTarget _getConnectionTarget(String host, int port, bool isSecure) { | 1909 _ConnectionTarget _getConnectionTarget(String host, int port, bool isSecure) { |
1896 String key = _HttpClientConnection.makeKey(isSecure, host, port); | 1910 String key = _HttpClientConnection.makeKey(isSecure, host, port); |
1897 return _connectionTargets.putIfAbsent( | 1911 return _connectionTargets.putIfAbsent(key, () { |
1898 key, () => new _ConnectionTarget(key, host, port, isSecure)); | 1912 return new _ConnectionTarget(key, host, port, isSecure, _context); |
| 1913 }); |
1899 } | 1914 } |
1900 | 1915 |
1901 // Get a new _HttpClientConnection, from the matching _ConnectionTarget. | 1916 // Get a new _HttpClientConnection, from the matching _ConnectionTarget. |
1902 Future<_ConnectionInfo> _getConnection(String uriHost, | 1917 Future<_ConnectionInfo> _getConnection(String uriHost, |
1903 int uriPort, | 1918 int uriPort, |
1904 _ProxyConfiguration proxyConf, | 1919 _ProxyConfiguration proxyConf, |
1905 bool isSecure) { | 1920 bool isSecure) { |
1906 Iterator<_Proxy> proxies = proxyConf.proxies.iterator; | 1921 Iterator<_Proxy> proxies = proxyConf.proxies.iterator; |
1907 | 1922 |
1908 Future<_ConnectionInfo> connect(error) { | 1923 Future<_ConnectionInfo> connect(error) { |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2200 address, int port, int backlog, bool v6Only, bool shared) { | 2215 address, int port, int backlog, bool v6Only, bool shared) { |
2201 return ServerSocket.bind( | 2216 return ServerSocket.bind( |
2202 address, port, backlog: backlog, v6Only: v6Only, shared: shared) | 2217 address, port, backlog: backlog, v6Only: v6Only, shared: shared) |
2203 .then((socket) { | 2218 .then((socket) { |
2204 return new _HttpServer._(socket, true); | 2219 return new _HttpServer._(socket, true); |
2205 }); | 2220 }); |
2206 } | 2221 } |
2207 | 2222 |
2208 static Future<HttpServer> bindSecure(address, | 2223 static Future<HttpServer> bindSecure(address, |
2209 int port, | 2224 int port, |
| 2225 SecurityContext context, |
2210 int backlog, | 2226 int backlog, |
2211 bool v6Only, | 2227 bool v6Only, |
2212 String certificate_name, | 2228 String certificate_name, |
2213 bool requestClientCertificate, | 2229 bool requestClientCertificate, |
2214 bool shared) { | 2230 bool shared) { |
2215 return SecureServerSocket.bind( | 2231 return SecureServerSocket.bind( |
2216 address, | 2232 address, |
2217 port, | 2233 port, |
2218 certificate_name, | 2234 context, |
2219 backlog: backlog, | 2235 backlog: backlog, |
2220 v6Only: v6Only, | 2236 v6Only: v6Only, |
2221 requestClientCertificate: requestClientCertificate, | 2237 requestClientCertificate: requestClientCertificate, |
2222 shared: shared) | 2238 shared: shared) |
2223 .then((socket) { | 2239 .then((socket) { |
2224 return new _HttpServer._(socket, true); | 2240 return new _HttpServer._(socket, true); |
2225 }); | 2241 }); |
2226 } | 2242 } |
2227 | 2243 |
2228 _HttpServer._(this._serverSocket, this._closeServer) { | 2244 _HttpServer._(this._serverSocket, this._closeServer) { |
(...skipping 619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2848 const _RedirectInfo(this.statusCode, this.method, this.location); | 2864 const _RedirectInfo(this.statusCode, this.method, this.location); |
2849 } | 2865 } |
2850 | 2866 |
2851 String _getHttpVersion() { | 2867 String _getHttpVersion() { |
2852 var version = Platform.version; | 2868 var version = Platform.version; |
2853 // Only include major and minor version numbers. | 2869 // Only include major and minor version numbers. |
2854 int index = version.indexOf('.', version.indexOf('.') + 1); | 2870 int index = version.indexOf('.', version.indexOf('.') + 1); |
2855 version = version.substring(0, index); | 2871 version = version.substring(0, index); |
2856 return 'Dart/$version (dart:io)'; | 2872 return 'Dart/$version (dart:io)'; |
2857 } | 2873 } |
OLD | NEW |