| 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 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 1053 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1064 } | 1064 } |
| 1065 | 1065 |
| 1066 class _HttpClientConnection { | 1066 class _HttpClientConnection { |
| 1067 final String key; | 1067 final String key; |
| 1068 final Socket _socket; | 1068 final Socket _socket; |
| 1069 final bool _proxyTunnel; | 1069 final bool _proxyTunnel; |
| 1070 final _HttpParser _httpParser; | 1070 final _HttpParser _httpParser; |
| 1071 StreamSubscription _subscription; | 1071 StreamSubscription _subscription; |
| 1072 final _HttpClient _httpClient; | 1072 final _HttpClient _httpClient; |
| 1073 bool _dispose = false; | 1073 bool _dispose = false; |
| 1074 Timer _idleTimer; |
| 1074 | 1075 |
| 1075 Completer<_HttpIncoming> _nextResponseCompleter; | 1076 Completer<_HttpIncoming> _nextResponseCompleter; |
| 1076 Future _streamFuture; | 1077 Future _streamFuture; |
| 1077 | 1078 |
| 1078 _HttpClientConnection(String this.key, | 1079 _HttpClientConnection(String this.key, |
| 1079 Socket this._socket, | 1080 Socket this._socket, |
| 1080 _HttpClient this._httpClient, | 1081 _HttpClient this._httpClient, |
| 1081 [this._proxyTunnel = false]) | 1082 [this._proxyTunnel = false]) |
| 1082 : _httpParser = new _HttpParser.responseParser() { | 1083 : _httpParser = new _HttpParser.responseParser() { |
| 1083 _socket.pipe(_httpParser); | 1084 _socket.pipe(_httpParser); |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1266 key, secureSocket, request._httpClient, true); | 1267 key, secureSocket, request._httpClient, true); |
| 1267 }); | 1268 }); |
| 1268 } | 1269 } |
| 1269 | 1270 |
| 1270 HttpConnectionInfo get connectionInfo => _HttpConnectionInfo.create(_socket); | 1271 HttpConnectionInfo get connectionInfo => _HttpConnectionInfo.create(_socket); |
| 1271 | 1272 |
| 1272 static makeKey(bool isSecure, String host, int port) { | 1273 static makeKey(bool isSecure, String host, int port) { |
| 1273 return isSecure ? "ssh:$host:$port" : "$host:$port"; | 1274 return isSecure ? "ssh:$host:$port" : "$host:$port"; |
| 1274 } | 1275 } |
| 1275 | 1276 |
| 1277 void stopTimer() { |
| 1278 if (_idleTimer != null) { |
| 1279 _idleTimer.cancel(); |
| 1280 _idleTimer = null; |
| 1281 } |
| 1282 } |
| 1283 |
| 1284 void startTimer() { |
| 1285 assert(_idleTimer == null); |
| 1286 _idleTimer = new Timer( |
| 1287 _httpClient.idleTimeout, |
| 1288 () { |
| 1289 _idleTimer = null; |
| 1290 close(); |
| 1291 }); |
| 1292 } |
| 1276 } | 1293 } |
| 1277 | 1294 |
| 1278 class _ConnnectionInfo { | 1295 class _ConnnectionInfo { |
| 1279 _ConnnectionInfo(_HttpClientConnection this.connection, _Proxy this.proxy); | 1296 _ConnnectionInfo(_HttpClientConnection this.connection, _Proxy this.proxy); |
| 1280 final _HttpClientConnection connection; | 1297 final _HttpClientConnection connection; |
| 1281 final _Proxy proxy; | 1298 final _Proxy proxy; |
| 1282 } | 1299 } |
| 1283 | 1300 |
| 1284 | 1301 |
| 1285 class _HttpClient implements HttpClient { | 1302 class _HttpClient implements HttpClient { |
| 1286 // TODO(ajohnsen): Use eviction timeout. | 1303 // TODO(ajohnsen): Use eviction timeout. |
| 1287 static const int DEFAULT_EVICTION_TIMEOUT = 60000; | |
| 1288 bool _closing = false; | 1304 bool _closing = false; |
| 1289 | 1305 |
| 1290 final Map<String, Set<_HttpClientConnection>> _idleConnections | 1306 final Map<String, Set<_HttpClientConnection>> _idleConnections |
| 1291 = new Map<String, Set<_HttpClientConnection>>(); | 1307 = new Map<String, Set<_HttpClientConnection>>(); |
| 1292 final Set<_HttpClientConnection> _activeConnections | 1308 final Set<_HttpClientConnection> _activeConnections |
| 1293 = new Set<_HttpClientConnection>(); | 1309 = new Set<_HttpClientConnection>(); |
| 1294 final List<_Credentials> _credentials = []; | 1310 final List<_Credentials> _credentials = []; |
| 1295 final List<_ProxyCredentials> _proxyCredentials = []; | 1311 final List<_ProxyCredentials> _proxyCredentials = []; |
| 1296 Function _authenticate; | 1312 Function _authenticate; |
| 1297 Function _authenticateProxy; | 1313 Function _authenticateProxy; |
| 1298 Function _findProxy = HttpClient.findProxyFromEnvironment; | 1314 Function _findProxy = HttpClient.findProxyFromEnvironment; |
| 1315 Duration _idleTimeout = const Duration(seconds: 15); |
| 1316 |
| 1317 Timer _noActiveTimer; |
| 1318 |
| 1319 Duration get idleTimeout => _idleTimeout; |
| 1320 |
| 1321 void set idleTimeout(Duration timeout) { |
| 1322 _idleTimeout = timeout; |
| 1323 var idle = _idleConnections.values.forEach( |
| 1324 (l) => l.forEach((c) { |
| 1325 // Reset timer. This is fine, as it's not happening often. |
| 1326 c.stopTimer(); |
| 1327 c.startTimer(); |
| 1328 })); |
| 1329 } |
| 1299 | 1330 |
| 1300 Future<HttpClientRequest> open(String method, | 1331 Future<HttpClientRequest> open(String method, |
| 1301 String host, | 1332 String host, |
| 1302 int port, | 1333 int port, |
| 1303 String path) { | 1334 String path) { |
| 1304 // TODO(sgjesse): The path set here can contain both query and | 1335 // TODO(sgjesse): The path set here can contain both query and |
| 1305 // fragment. They should be cracked and set correctly. | 1336 // fragment. They should be cracked and set correctly. |
| 1306 return _openUrl(method, new Uri.fromComponents( | 1337 return _openUrl(method, new Uri.fromComponents( |
| 1307 scheme: "http", domain: host, port: port, path: path)); | 1338 scheme: "http", domain: host, port: port, path: path)); |
| 1308 } | 1339 } |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1457 }); | 1488 }); |
| 1458 } | 1489 } |
| 1459 | 1490 |
| 1460 // Return a live connection to the idle pool. | 1491 // Return a live connection to the idle pool. |
| 1461 void _returnConnection(_HttpClientConnection connection) { | 1492 void _returnConnection(_HttpClientConnection connection) { |
| 1462 _activeConnections.remove(connection); | 1493 _activeConnections.remove(connection); |
| 1463 if (_closing) { | 1494 if (_closing) { |
| 1464 connection.close(); | 1495 connection.close(); |
| 1465 return; | 1496 return; |
| 1466 } | 1497 } |
| 1467 // TODO(ajohnsen): Listen for socket close events. | |
| 1468 if (!_idleConnections.containsKey(connection.key)) { | 1498 if (!_idleConnections.containsKey(connection.key)) { |
| 1469 _idleConnections[connection.key] = new LinkedHashSet(); | 1499 _idleConnections[connection.key] = new LinkedHashSet(); |
| 1470 } | 1500 } |
| 1471 _idleConnections[connection.key].add(connection); | 1501 _idleConnections[connection.key].add(connection); |
| 1502 connection.startTimer(); |
| 1503 _updateTimers(); |
| 1472 } | 1504 } |
| 1473 | 1505 |
| 1474 // Remove a closed connnection from the active set. | 1506 // Remove a closed connnection from the active set. |
| 1475 void _connectionClosed(_HttpClientConnection connection) { | 1507 void _connectionClosed(_HttpClientConnection connection) { |
| 1508 connection.stopTimer(); |
| 1476 _activeConnections.remove(connection); | 1509 _activeConnections.remove(connection); |
| 1477 if (_idleConnections.containsKey(connection.key)) { | 1510 if (_idleConnections.containsKey(connection.key)) { |
| 1478 _idleConnections[connection.key].remove(connection); | 1511 _idleConnections[connection.key].remove(connection); |
| 1479 if (_idleConnections[connection.key].isEmpty) { | 1512 if (_idleConnections[connection.key].isEmpty) { |
| 1480 _idleConnections.remove(connection.key); | 1513 _idleConnections.remove(connection.key); |
| 1481 } | 1514 } |
| 1482 } | 1515 } |
| 1516 _updateTimers(); |
| 1517 } |
| 1518 |
| 1519 void _updateTimers() { |
| 1520 if (_activeConnections.isEmpty) { |
| 1521 if (!_idleConnections.isEmpty && _noActiveTimer == null) { |
| 1522 _noActiveTimer = new Timer(const Duration(milliseconds: 100), () { |
| 1523 _noActiveTimer = null; |
| 1524 if (_activeConnections.isEmpty) { |
| 1525 close(); |
| 1526 _closing = false; |
| 1527 } |
| 1528 }); |
| 1529 } |
| 1530 } else if (_noActiveTimer != null) { |
| 1531 _noActiveTimer.cancel(); |
| 1532 _noActiveTimer = null; |
| 1533 } |
| 1483 } | 1534 } |
| 1484 | 1535 |
| 1485 // Get a new _HttpClientConnection, either from the idle pool or created from | 1536 // Get a new _HttpClientConnection, either from the idle pool or created from |
| 1486 // a new Socket. | 1537 // a new Socket. |
| 1487 Future<_ConnnectionInfo> _getConnection(String uriHost, | 1538 Future<_ConnnectionInfo> _getConnection(String uriHost, |
| 1488 int uriPort, | 1539 int uriPort, |
| 1489 _ProxyConfiguration proxyConf, | 1540 _ProxyConfiguration proxyConf, |
| 1490 bool isSecure) { | 1541 bool isSecure) { |
| 1491 Iterator<_Proxy> proxies = proxyConf.proxies.iterator; | 1542 Iterator<_Proxy> proxies = proxyConf.proxies.iterator; |
| 1492 | 1543 |
| 1493 Future<_ConnnectionInfo> connect(error) { | 1544 Future<_ConnnectionInfo> connect(error) { |
| 1494 if (!proxies.moveNext()) return new Future.error(error); | 1545 if (!proxies.moveNext()) return new Future.error(error); |
| 1495 _Proxy proxy = proxies.current; | 1546 _Proxy proxy = proxies.current; |
| 1496 String host = proxy.isDirect ? uriHost: proxy.host; | 1547 String host = proxy.isDirect ? uriHost: proxy.host; |
| 1497 int port = proxy.isDirect ? uriPort: proxy.port; | 1548 int port = proxy.isDirect ? uriPort: proxy.port; |
| 1498 String key = _HttpClientConnection.makeKey(isSecure, host, port); | 1549 String key = _HttpClientConnection.makeKey(isSecure, host, port); |
| 1499 if (_idleConnections.containsKey(key)) { | 1550 if (_idleConnections.containsKey(key)) { |
| 1500 var connection = _idleConnections[key].first; | 1551 var connection = _idleConnections[key].first; |
| 1501 _idleConnections[key].remove(connection); | 1552 _idleConnections[key].remove(connection); |
| 1502 if (_idleConnections[key].isEmpty) { | 1553 if (_idleConnections[key].isEmpty) { |
| 1503 _idleConnections.remove(key); | 1554 _idleConnections.remove(key); |
| 1504 } | 1555 } |
| 1556 connection.stopTimer(); |
| 1505 _activeConnections.add(connection); | 1557 _activeConnections.add(connection); |
| 1558 _updateTimers(); |
| 1506 return new Future.value(new _ConnnectionInfo(connection, proxy)); | 1559 return new Future.value(new _ConnnectionInfo(connection, proxy)); |
| 1507 } | 1560 } |
| 1508 return (isSecure && proxy.isDirect | 1561 return (isSecure && proxy.isDirect |
| 1509 ? SecureSocket.connect(host, | 1562 ? SecureSocket.connect(host, |
| 1510 port, | 1563 port, |
| 1511 sendClientCertificate: true) | 1564 sendClientCertificate: true) |
| 1512 : Socket.connect(host, port)) | 1565 : Socket.connect(host, port)) |
| 1513 .then((socket) { | 1566 .then((socket) { |
| 1514 socket.setOption(SocketOption.TCP_NODELAY, true); | 1567 socket.setOption(SocketOption.TCP_NODELAY, true); |
| 1515 var connection = new _HttpClientConnection(key, socket, this); | 1568 var connection = new _HttpClientConnection(key, socket, this); |
| (...skipping 719 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2235 | 2288 |
| 2236 | 2289 |
| 2237 class _RedirectInfo implements RedirectInfo { | 2290 class _RedirectInfo implements RedirectInfo { |
| 2238 const _RedirectInfo(int this.statusCode, | 2291 const _RedirectInfo(int this.statusCode, |
| 2239 String this.method, | 2292 String this.method, |
| 2240 Uri this.location); | 2293 Uri this.location); |
| 2241 final int statusCode; | 2294 final int statusCode; |
| 2242 final String method; | 2295 final String method; |
| 2243 final Uri location; | 2296 final Uri location; |
| 2244 } | 2297 } |
| OLD | NEW |