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

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

Issue 11410003: Refactoring of the HTTP library (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed review comments Created 8 years, 1 month 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 | « no previous file | sdk/lib/io/http_parser.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 class _HttpHeaders implements HttpHeaders { 5 class _HttpHeaders implements HttpHeaders {
6 _HttpHeaders() : _headers = new Map<String, List<String>>(); 6 _HttpHeaders() : _headers = new Map<String, List<String>>();
7 7
8 List<String> operator[](String name) { 8 List<String> operator[](String name) {
9 name = name.toLowerCase(); 9 name = name.toLowerCase();
10 return _headers[name]; 10 return _headers[name];
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 String value; 598 String value;
599 Date expires; 599 Date expires;
600 int maxAge; 600 int maxAge;
601 String domain; 601 String domain;
602 String path; 602 String path;
603 bool httpOnly = false; 603 bool httpOnly = false;
604 bool secure = false; 604 bool secure = false;
605 } 605 }
606 606
607 607
608 // The close queue handles graceful closing of HTTP connections. When
609 // a connection is added to the queue it will enter a wait state
610 // waiting for all data written and possibly socket shutdown from
611 // peer.
612 class _CloseQueue {
613 _CloseQueue() : _q = new Set<_HttpConnectionBase>();
614
615 void add(_HttpConnectionBase connection) {
616 void closeIfDone() {
617 // We only check for write closed here. This means that we are
618 // not waiting for the client to half-close the socket before
619 // fully closing the socket.
620 if (!connection._isWriteClosed) return;
621 _q.remove(connection);
622 connection._socket.close();
623 if (connection.onClosed != null) connection.onClosed();
624 }
625
626 // If the connection is already fully closed don't insert it into the queue.
627 if (connection._isFullyClosed) {
628 connection._socket.close();
629 if (connection.onClosed != null) connection.onClosed();
630 return;
631 }
632
633 _q.add(connection);
634
635 // If output stream is not closed for writing close it now and
636 // wait for callback when closed.
637 if (!connection._isWriteClosed) {
638 connection._socket.outputStream.close();
639 connection._socket.outputStream.onClosed = () {
640 connection._state |= _HttpConnectionBase.WRITE_CLOSED;
641 closeIfDone();
642 };
643 } else {
644 connection._socket.outputStream.onClosed = () { assert(false); };
645 }
646
647 // If socket is not closed for reading wait for callback.
648 if (!connection._isReadClosed) {
649 connection._socket.onClosed = () {
650 connection._state |= _HttpConnectionBase.READ_CLOSED;
651 // This is a nop, as we are not using the read closed
652 // information for anything. For both server and client
653 // connections the inbound message have been read to
654 // completion when the socket enters the close queue.
655 };
656 } else {
657 connection._socket.onClosed = () { assert(false); };
658 }
659
660 // Ignore any data on a socket in the close queue.
661 connection._socket.onData = connection._socket.read;
662
663 // If an error occurs immediately close the socket.
664 connection._socket.onError = (e) {
665 connection._state |= _HttpConnectionBase.WRITE_CLOSED;
666 closeIfDone();
667 };
668 }
669
670 void shutdown() {
671 _q.forEach((_HttpConnectionBase connection) {
672 connection._socket.close();
673 });
674 }
675
676 final Set<_HttpConnectionBase> _q;
677 }
678
679
608 class _HttpRequestResponseBase { 680 class _HttpRequestResponseBase {
609 final int START = 0; 681 final int START = 0;
610 final int HEADER_SENT = 1; 682 final int HEADER_SENT = 1;
611 final int DONE = 2; 683 final int DONE = 2;
612 final int UPGRADED = 3; 684 final int UPGRADED = 3;
613 685
614 _HttpRequestResponseBase(_HttpConnectionBase this._httpConnection) 686 _HttpRequestResponseBase(_HttpConnectionBase this._httpConnection)
615 : _headers = new _HttpHeaders() { 687 : _headers = new _HttpHeaders() {
616 _state = START; 688 _state = START;
617 _headResponse = false; 689 _headResponse = false;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 bool allWritten = true; 761 bool allWritten = true;
690 if (_contentLength < 0) { 762 if (_contentLength < 0) {
691 // Terminate the content if transfer encoding is chunked. 763 // Terminate the content if transfer encoding is chunked.
692 allWritten = _httpConnection._write(_Const.END_CHUNKED); 764 allWritten = _httpConnection._write(_Const.END_CHUNKED);
693 } else { 765 } else {
694 if (!_headResponse && _bodyBytesWritten < _contentLength) { 766 if (!_headResponse && _bodyBytesWritten < _contentLength) {
695 throw new HttpException("Sending less than specified content length"); 767 throw new HttpException("Sending less than specified content length");
696 } 768 }
697 assert(_headResponse || _bodyBytesWritten == _contentLength); 769 assert(_headResponse || _bodyBytesWritten == _contentLength);
698 } 770 }
699 // If we are done writing the response, and either the client has
700 // closed or the connection is not persistent, we can close. Also
701 // if using HTTP 1.0 and the content length was not known we must
702 // close to indicate end of body.
703 if (!persistentConnection || _httpConnection._closing ||
704 (_protocolVersion == "1.0" && _contentLength < 0)) {
705 _httpConnection._close();
706 }
707 return allWritten; 771 return allWritten;
708 } 772 }
709 773
710 bool _writeHeaders() { 774 bool _writeHeaders() {
711 _headers._mutable = false; 775 _headers._mutable = false;
712 _headers._write(_httpConnection); 776 _headers._write(_httpConnection);
713 // Terminate header. 777 // Terminate header.
714 return _writeCRLF(); 778 return _writeCRLF();
715 } 779 }
716 780
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after
1006 if (_state == START) { 1070 if (_state == START) {
1007 _writeHeader(); 1071 _writeHeader();
1008 } 1072 }
1009 _state = UPGRADED; 1073 _state = UPGRADED;
1010 // Ensure that any trailing data is written. 1074 // Ensure that any trailing data is written.
1011 _writeDone(); 1075 _writeDone();
1012 // Indicate to the connection that the response handling is done. 1076 // Indicate to the connection that the response handling is done.
1013 return _httpConnection._detachSocket(); 1077 return _httpConnection._detachSocket();
1014 } 1078 }
1015 1079
1016 void _responseEnd() {
1017 _ensureHeadersSent();
1018 _state = DONE;
1019 // Stop tracking no pending write events.
1020 _httpConnection._onNoPendingWrites = null;
1021 // Ensure that any trailing data is written.
1022 _writeDone();
1023 // Indicate to the connection that the response handling is done.
1024 _httpConnection._responseDone();
1025 }
1026
1027 // Delegate functions for the HttpOutputStream implementation. 1080 // Delegate functions for the HttpOutputStream implementation.
1028 bool _streamWrite(List<int> buffer, bool copyBuffer) { 1081 bool _streamWrite(List<int> buffer, bool copyBuffer) {
1029 if (_done) throw new HttpException("Response closed"); 1082 if (_done) throw new HttpException("Response closed");
1030 return _write(buffer, copyBuffer); 1083 return _write(buffer, copyBuffer);
1031 } 1084 }
1032 1085
1033 bool _streamWriteFrom(List<int> buffer, int offset, int len) { 1086 bool _streamWriteFrom(List<int> buffer, int offset, int len) {
1034 if (_done) throw new HttpException("Response closed"); 1087 if (_done) throw new HttpException("Response closed");
1035 return _writeList(buffer, offset, len); 1088 return _writeList(buffer, offset, len);
1036 } 1089 }
1037 1090
1038 void _streamFlush() { 1091 void _streamFlush() {
1039 _httpConnection._flush(); 1092 _httpConnection._flush();
1040 } 1093 }
1041 1094
1042 void _streamClose() { 1095 void _streamClose() {
1043 _responseEnd(); 1096 _ensureHeadersSent();
1097 _state = DONE;
1098 // Stop tracking no pending write events.
1099 _httpConnection._onNoPendingWrites = null;
1100 // Ensure that any trailing data is written.
1101 _writeDone();
1102 // Indicate to the connection that the response handling is done.
1103 _httpConnection._responseClosed();
1044 } 1104 }
1045 1105
1046 void _streamSetNoPendingWriteHandler(callback()) { 1106 void _streamSetNoPendingWriteHandler(callback()) {
1047 if (_state != DONE) { 1107 if (_state != DONE) {
1048 _httpConnection._onNoPendingWrites = callback; 1108 _httpConnection._onNoPendingWrites = callback;
1049 } 1109 }
1050 } 1110 }
1051 1111
1052 void _streamSetCloseHandler(callback()) { 1112 void _streamSetCloseHandler(callback()) {
1053 // TODO(sgjesse): Handle this. 1113 // TODO(sgjesse): Handle this.
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1250 1310
1251 void set onError(void callback(e)) { 1311 void set onError(void callback(e)) {
1252 _requestOrResponse._streamSetErrorHandler(callback); 1312 _requestOrResponse._streamSetErrorHandler(callback);
1253 } 1313 }
1254 1314
1255 _HttpRequestResponseBase _requestOrResponse; 1315 _HttpRequestResponseBase _requestOrResponse;
1256 } 1316 }
1257 1317
1258 1318
1259 abstract class _HttpConnectionBase { 1319 abstract class _HttpConnectionBase {
1260 _HttpConnectionBase() : _httpParser = new _HttpParser(), 1320 static const int IDLE = 0;
1261 hashCode = _nextHashCode { 1321 static const int ACTIVE = 1;
1322 static const int REQUEST_DONE = 2;
1323 static const int RESPONSE_DONE = 4;
1324 static const int ALL_DONE = REQUEST_DONE | RESPONSE_DONE;
1325 static const int READ_CLOSED = 8;
1326 static const int WRITE_CLOSED = 16;
1327 static const int FULLY_CLOSED = READ_CLOSED | WRITE_CLOSED;
1328
1329 _HttpConnectionBase() : hashCode = _nextHashCode {
1262 _nextHashCode = (_nextHashCode + 1) & 0xFFFFFFF; 1330 _nextHashCode = (_nextHashCode + 1) & 0xFFFFFFF;
1263 } 1331 }
1264 1332
1333 bool get _isRequestDone => (_state & REQUEST_DONE) == REQUEST_DONE;
1334 bool get _isResponseDone => (_state & RESPONSE_DONE) == RESPONSE_DONE;
1335 bool get _isAllDone => (_state & ALL_DONE) == ALL_DONE;
1336 bool get _isReadClosed => (_state & READ_CLOSED) == READ_CLOSED;
1337 bool get _isWriteClosed => (_state & WRITE_CLOSED) == WRITE_CLOSED;
1338 bool get _isFullyClosed => (_state & FULLY_CLOSED) == FULLY_CLOSED;
1339
1265 void _connectionEstablished(Socket socket) { 1340 void _connectionEstablished(Socket socket) {
1266 _socket = socket; 1341 _socket = socket;
1267 // Register handler for socket events. 1342 // Register handlers for socket events. All socket events are
1268 _socket.onData = _onData; 1343 // passed to the HTTP parser.
1269 _socket.onClosed = _onClosed; 1344 _socket.onData = () {
1270 _socket.onError = _onError; 1345 List<int> buffer = _socket.read();
1346 if (buffer != null) {
1347 _httpParser.streamData(buffer);
1348 }
1349 };
1350 _socket.onClosed = _httpParser.streamDone;
1351 _socket.onError = _httpParser.streamError;
1271 // Ignore errors in the socket output stream as this is getting 1352 // Ignore errors in the socket output stream as this is getting
1272 // the same errors as the socket itself. 1353 // the same errors as the socket itself.
1273 _socket.outputStream.onError = (e) => null; 1354 _socket.outputStream.onError = (e) => null;
1274 } 1355 }
1275 1356
1276 bool _write(List<int> data, [bool copyBuffer = false]) { 1357 bool _write(List<int> data, [bool copyBuffer = false]) {
1277 if (!_error && !_closing) { 1358 return _socket.outputStream.write(data, copyBuffer);
1278 return _socket.outputStream.write(data, copyBuffer);
1279 }
1280 } 1359 }
1281 1360
1282 bool _writeFrom(List<int> buffer, [int offset, int len]) { 1361 bool _writeFrom(List<int> buffer, [int offset, int len]) {
1283 if (!_error && !_closing) { 1362 return _socket.outputStream.writeFrom(buffer, offset, len);
1284 return _socket.outputStream.writeFrom(buffer, offset, len);
1285 }
1286 } 1363 }
1287 1364
1288 bool _flush() { 1365 bool _flush() {
1289 _socket.outputStream.flush(); 1366 _socket.outputStream.flush();
1290 } 1367 }
1291 1368
1292 bool _close() { 1369 bool _close() {
1293 _closing = true;
1294 _socket.outputStream.close(); 1370 _socket.outputStream.close();
1295 } 1371 }
1296 1372
1297 bool _destroy() { 1373 bool _destroy() {
1298 _closing = true;
1299 _socket.close(); 1374 _socket.close();
1300 } 1375 }
1301 1376
1302 void _onData() {
1303 List<int> buffer = _socket.read();
1304 if (buffer != null) {
1305 _httpParser.writeList(buffer, 0, buffer.length);
1306 }
1307 }
1308
1309 void _onClosed() {
1310 _closing = true;
1311 _onConnectionClosed(null);
1312 }
1313
1314 void _onError(e) {
1315 // If an error occurs, make sure to close the socket if one is associated.
1316 _error = true;
1317 if (_socket != null) {
1318 _socket.close();
1319 }
1320 _onConnectionClosed(e);
1321 }
1322
1323 DetachedSocket _detachSocket() { 1377 DetachedSocket _detachSocket() {
1324 _socket.onData = null; 1378 _socket.onData = null;
1325 _socket.onClosed = null; 1379 _socket.onClosed = null;
1326 _socket.onError = null; 1380 _socket.onError = null;
1327 _socket.outputStream.onNoPendingWrites = null; 1381 _socket.outputStream.onNoPendingWrites = null;
1328 Socket socket = _socket; 1382 Socket socket = _socket;
1329 _socket = null; 1383 _socket = null;
1330 if (onDetach != null) onDetach(); 1384 if (onDetach != null) onDetach();
1331 return new _DetachedSocket(socket, _httpParser.readUnparsedData()); 1385 return new _DetachedSocket(socket, _httpParser.readUnparsedData());
1332 } 1386 }
1333 1387
1334 HttpConnectionInfo get connectionInfo { 1388 HttpConnectionInfo get connectionInfo {
1335 if (_socket == null || _closing || _error) return null; 1389 if (_socket == null) return null;
1336 try { 1390 try {
1337 _HttpConnectionInfo info = new _HttpConnectionInfo(); 1391 _HttpConnectionInfo info = new _HttpConnectionInfo();
1338 info.remoteHost = _socket.remoteHost; 1392 info.remoteHost = _socket.remoteHost;
1339 info.remotePort = _socket.remotePort; 1393 info.remotePort = _socket.remotePort;
1340 info.localPort = _socket.port; 1394 info.localPort = _socket.port;
1341 return info; 1395 return info;
1342 } catch (e) { } 1396 } catch (e) { }
1343 return null; 1397 return null;
1344 } 1398 }
1345 1399
1346 void _onConnectionClosed(e);
1347 void _responseDone();
1348
1349 void set _onNoPendingWrites(void callback()) { 1400 void set _onNoPendingWrites(void callback()) {
1350 if (!_error) { 1401 _socket.outputStream.onNoPendingWrites = callback;
1351 _socket.outputStream.onNoPendingWrites = callback;
1352 }
1353 } 1402 }
1354 1403
1404 int _state = IDLE;
1405
1355 Socket _socket; 1406 Socket _socket;
1356 bool _closing = false; // Is the socket closed by the client?
1357 bool _error = false; // Is the socket closed due to an error?
1358 _HttpParser _httpParser; 1407 _HttpParser _httpParser;
1359 1408
1409 // Callbacks.
1360 Function onDetach; 1410 Function onDetach;
1411 Function onClosed;
1361 1412
1362 // Hash code for HTTP connection. Currently this is just a counter. 1413 // Hash code for HTTP connection. Currently this is just a counter.
1363 final int hashCode; 1414 final int hashCode;
1364 static int _nextHashCode = 0; 1415 static int _nextHashCode = 0;
1365 } 1416 }
1366 1417
1367 1418
1368 // HTTP server connection over a socket. 1419 // HTTP server connection over a socket.
1369 class _HttpConnection extends _HttpConnectionBase { 1420 class _HttpConnection extends _HttpConnectionBase {
1370 _HttpConnection(HttpServer this._server) { 1421 _HttpConnection(HttpServer this._server) {
1422 _httpParser = new _HttpParser.requestParser();
1371 // Register HTTP parser callbacks. 1423 // Register HTTP parser callbacks.
1372 _httpParser.requestStart = 1424 _httpParser.requestStart = _onRequestStart;
1373 (method, uri, version) => _onRequestStart(method, uri, version); 1425 _httpParser.headerReceived = _onHeaderReceived;
1374 _httpParser.responseStart = 1426 _httpParser.headersComplete = _onHeadersComplete;
1375 (statusCode, reasonPhrase, version) => 1427 _httpParser.dataReceived = _onDataReceived;
1376 _onResponseStart(statusCode, reasonPhrase, version); 1428 _httpParser.dataEnd = _onDataEnd;
1377 _httpParser.headerReceived = 1429 _httpParser.error = _onError;
1378 (name, value) => _onHeaderReceived(name, value); 1430 _httpParser.closed = _onClosed;
1379 _httpParser.headersComplete = () => _onHeadersComplete(); 1431 _httpParser.responseStart = (statusCode, reasonPhrase, version) {
1380 _httpParser.dataReceived = (data) => _onDataReceived(data); 1432 assert(false);
1381 _httpParser.dataEnd = (close) => _onDataEnd(close); 1433 };
1382 _httpParser.error = (e) => _onError(e);
1383 } 1434 }
1384 1435
1385 void _onConnectionClosed(e) { 1436 void _onClosed() {
1386 // Don't report errors when HTTP parser is in idle state. Clients 1437 _state |= _HttpConnectionBase.READ_CLOSED;
1387 // can close the connection and cause a connection reset by peer 1438 }
1388 // error which is OK. 1439
1389 if (e != null && !_httpParser.isIdle) { 1440 void _onError(e) {
1390 onError(e); 1441 onError(e);
1391 // Propagate the error to the streams. 1442 // Propagate the error to the streams.
1392 if (_request != null && _request._streamErrorHandler != null) { 1443 if (_request != null && _request._streamErrorHandler != null) {
1393 _request._streamErrorHandler(e); 1444 _request._streamErrorHandler(e);
1394 }
1395 if (_response != null && _response._streamErrorHandler != null) {
1396 _response._streamErrorHandler(e);
1397 }
1398 } 1445 }
1399 1446 if (_response != null && _response._streamErrorHandler != null) {
1400 // If currently not processing any request close the socket when 1447 _response._streamErrorHandler(e);
1401 // we are done writing the response.
1402 if (_httpParser.isIdle) {
1403 // If the httpParser is idle and we get an error from the
1404 // connection we deal with that as a closed connection and not
1405 // as an error. When the client disappears we get a connection
1406 // reset by peer and that is OK.
1407 if (e != null) {
1408 onClosed();
1409 } else {
1410 _socket.outputStream.onClosed = () {
1411 _destroy();
1412 onClosed();
1413 };
1414 // If the client closes and we are done writing the response
1415 // the connection should be closed.
1416 if (_response == null) _close();
1417 }
1418 } else {
1419 // Processing a request.
1420 if (e == null) {
1421 // Indicate connection close to the HTTP parser.
1422 _httpParser.connectionClosed();
1423 }
1424 } 1448 }
1449 if (_socket != null) _socket.close();
1425 } 1450 }
1426 1451
1427 void _onRequestStart(String method, String uri, String version) { 1452 void _onRequestStart(String method, String uri, String version) {
1453 _state = _HttpConnectionBase.ACTIVE;
1428 // Create new request and response objects for this request. 1454 // Create new request and response objects for this request.
1429 _request = new _HttpRequest(this); 1455 _request = new _HttpRequest(this);
1430 _response = new _HttpResponse(this); 1456 _response = new _HttpResponse(this);
1431 _request._onRequestStart(method, uri, version); 1457 _request._onRequestStart(method, uri, version);
1432 _request._protocolVersion = version; 1458 _request._protocolVersion = version;
1433 _response._protocolVersion = version; 1459 _response._protocolVersion = version;
1434 _response._headResponse = method == "HEAD"; 1460 _response._headResponse = method == "HEAD";
1435 } 1461 }
1436 1462
1437 void _onResponseStart(int statusCode, String reasonPhrase, String version) {
1438 // TODO(sgjesse): Error handling.
1439 }
1440
1441 void _onHeaderReceived(String name, String value) { 1463 void _onHeaderReceived(String name, String value) {
1442 _request._onHeaderReceived(name, value); 1464 _request._onHeaderReceived(name, value);
1443 } 1465 }
1444 1466
1445 void _onHeadersComplete() { 1467 void _onHeadersComplete() {
1446 _request._onHeadersComplete(); 1468 _request._onHeadersComplete();
1447 _response.persistentConnection = _httpParser.persistentConnection; 1469 _response.persistentConnection = _httpParser.persistentConnection;
1448 if (onRequestReceived != null) { 1470 if (onRequestReceived != null) {
1449 onRequestReceived(_request, _response); 1471 onRequestReceived(_request, _response);
1450 } 1472 }
1451 } 1473 }
1452 1474
1453 void _onDataReceived(List<int> data) { 1475 void _onDataReceived(List<int> data) {
1454 _request._onDataReceived(data); 1476 _request._onDataReceived(data);
1455 } 1477 }
1456 1478
1479 void _checkDone() {
1480 if (_isAllDone) {
1481 // If we are done writing the response, and either the client
1482 // has closed or the connection is not persistent, we must
1483 // close. Also if using HTTP 1.0 and the content length was not
1484 // known we must close to indicate end of body.
1485 bool close =
1486 !_response.persistentConnection ||
1487 (_response._protocolVersion == "1.0" && _response._contentLength < 0);
1488 _request = null;
1489 _response = null;
1490 if (_isReadClosed || close) {
1491 _server._closeQueue.add(this);
1492 } else {
1493 _state = _HttpConnectionBase.IDLE;
1494 }
1495 }
1496 }
1497
1457 void _onDataEnd(bool close) { 1498 void _onDataEnd(bool close) {
1458 _request._onDataEnd(); 1499 _request._onDataEnd();
1500 _state |= _HttpConnectionBase.REQUEST_DONE;
1501 _checkDone();
1459 } 1502 }
1460 1503
1461 void _responseDone() { 1504 void _responseClosed() {
1462 // If the connection is closing then close the output stream to 1505 _state |= _HttpConnectionBase.RESPONSE_DONE;
1463 // fully close the socket. 1506 _checkDone();
1464 if (_closing) {
1465 _socket.outputStream.onClosed = () {
1466 _socket.close();
1467 onClosed();
1468 };
1469 }
1470 _response = null;
1471 } 1507 }
1472 1508
1473 HttpServer _server; 1509 HttpServer _server;
1474 HttpRequest _request; 1510 HttpRequest _request;
1475 HttpResponse _response; 1511 HttpResponse _response;
1476 1512
1477 // Callbacks. 1513 // Callbacks.
1478 Function onRequestReceived; 1514 Function onRequestReceived;
1479 Function onClosed;
1480 Function onError; 1515 Function onError;
1481 } 1516 }
1482 1517
1483 1518
1484 class _RequestHandlerRegistration { 1519 class _RequestHandlerRegistration {
1485 _RequestHandlerRegistration(Function this._matcher, Function this._handler); 1520 _RequestHandlerRegistration(Function this._matcher, Function this._handler);
1486 Function _matcher; 1521 Function _matcher;
1487 Function _handler; 1522 Function _handler;
1488 } 1523 }
1489 1524
1490 // HTTP server waiting for socket connections. The connections are 1525 // HTTP server waiting for socket connections. The connections are
1491 // managed by the server and as requests are received the request. 1526 // managed by the server and as requests are received the request.
1492 class _HttpServer implements HttpServer { 1527 class _HttpServer implements HttpServer {
1493 _HttpServer() : _connections = new Set<_HttpConnection>(), 1528 _HttpServer() : _connections = new Set<_HttpConnection>(),
1494 _handlers = new List<_RequestHandlerRegistration>(); 1529 _handlers = new List<_RequestHandlerRegistration>(),
1530 _closeQueue = new _CloseQueue();
1495 1531
1496 void listen(String host, int port, {int backlog: 128}) { 1532 void listen(String host, int port, {int backlog: 128}) {
1497 listenOn(new ServerSocket(host, port, backlog)); 1533 listenOn(new ServerSocket(host, port, backlog));
1498 _closeServer = true; 1534 _closeServer = true;
1499 } 1535 }
1500 1536
1501 void listenOn(ServerSocket serverSocket) { 1537 void listenOn(ServerSocket serverSocket) {
1502 void onConnection(Socket socket) { 1538 void onConnection(Socket socket) {
1503 // Accept the client connection. 1539 // Accept the client connection.
1504 _HttpConnection connection = new _HttpConnection(this); 1540 _HttpConnection connection = new _HttpConnection(this);
(...skipping 20 matching lines...) Expand all
1525 void handler(HttpRequest request, HttpResponse response)) { 1561 void handler(HttpRequest request, HttpResponse response)) {
1526 _handlers.add(new _RequestHandlerRegistration(matcher, handler)); 1562 _handlers.add(new _RequestHandlerRegistration(matcher, handler));
1527 } 1563 }
1528 1564
1529 void set defaultRequestHandler( 1565 void set defaultRequestHandler(
1530 void handler(HttpRequest request, HttpResponse response)) { 1566 void handler(HttpRequest request, HttpResponse response)) {
1531 _defaultHandler = handler; 1567 _defaultHandler = handler;
1532 } 1568 }
1533 1569
1534 void close() { 1570 void close() {
1571 _closeQueue.shutdown();
1535 if (_sessionManagerInstance != null) { 1572 if (_sessionManagerInstance != null) {
1536 _sessionManagerInstance.close(); 1573 _sessionManagerInstance.close();
1537 _sessionManagerInstance = null; 1574 _sessionManagerInstance = null;
1538 } 1575 }
1539 if (_server != null && _closeServer) { 1576 if (_server != null && _closeServer) {
1540 _server.close(); 1577 _server.close();
1541 } 1578 }
1542 _server = null; 1579 _server = null;
1543 for (_HttpConnection connection in _connections) { 1580 for (_HttpConnection connection in _connections) {
1544 connection._destroy(); 1581 connection._destroy();
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1595 return _sessionManagerInstance; 1632 return _sessionManagerInstance;
1596 } 1633 }
1597 1634
1598 1635
1599 ServerSocket _server; // The server listen socket. 1636 ServerSocket _server; // The server listen socket.
1600 bool _closeServer = false; 1637 bool _closeServer = false;
1601 Set<_HttpConnection> _connections; // Set of currently connected clients. 1638 Set<_HttpConnection> _connections; // Set of currently connected clients.
1602 List<_RequestHandlerRegistration> _handlers; 1639 List<_RequestHandlerRegistration> _handlers;
1603 Object _defaultHandler; 1640 Object _defaultHandler;
1604 Function _onError; 1641 Function _onError;
1642 _CloseQueue _closeQueue;
1605 _HttpSessionManager _sessionManagerInstance; 1643 _HttpSessionManager _sessionManagerInstance;
1606 } 1644 }
1607 1645
1608 1646
1609 class _HttpClientRequest 1647 class _HttpClientRequest
1610 extends _HttpRequestResponseBase implements HttpClientRequest { 1648 extends _HttpRequestResponseBase implements HttpClientRequest {
1611 _HttpClientRequest(String this._method, 1649 _HttpClientRequest(String this._method,
1612 Uri this._uri, 1650 Uri this._uri,
1613 _HttpClientConnection connection) 1651 _HttpClientConnection connection)
1614 : super(connection) { 1652 : super(connection) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1652 _httpConnection._flush(); 1690 _httpConnection._flush();
1653 } 1691 }
1654 1692
1655 void _streamClose() { 1693 void _streamClose() {
1656 _ensureHeadersSent(); 1694 _ensureHeadersSent();
1657 _state = DONE; 1695 _state = DONE;
1658 // Stop tracking no pending write events. 1696 // Stop tracking no pending write events.
1659 _httpConnection._onNoPendingWrites = null; 1697 _httpConnection._onNoPendingWrites = null;
1660 // Ensure that any trailing data is written. 1698 // Ensure that any trailing data is written.
1661 _writeDone(); 1699 _writeDone();
1662 _connection._requestDone(); 1700 _connection._requestClosed();
1663 } 1701 }
1664 1702
1665 void _streamSetNoPendingWriteHandler(callback()) { 1703 void _streamSetNoPendingWriteHandler(callback()) {
1666 if (_state != DONE) { 1704 if (_state != DONE) {
1667 _httpConnection._onNoPendingWrites = callback; 1705 _httpConnection._onNoPendingWrites = callback;
1668 } 1706 }
1669 } 1707 }
1670 1708
1671 void _streamSetCloseHandler(callback()) { 1709 void _streamSetCloseHandler(callback()) {
1672 // TODO(sgjesse): Handle this. 1710 // TODO(sgjesse): Handle this.
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1767 return _cookies; 1805 return _cookies;
1768 } 1806 }
1769 1807
1770 InputStream get inputStream { 1808 InputStream get inputStream {
1771 if (_inputStream == null) { 1809 if (_inputStream == null) {
1772 _inputStream = new _HttpInputStream(this); 1810 _inputStream = new _HttpInputStream(this);
1773 } 1811 }
1774 return _inputStream; 1812 return _inputStream;
1775 } 1813 }
1776 1814
1777 void _onRequestStart(String method, String uri, String version) {
1778 // TODO(sgjesse): Error handling
1779 }
1780
1781 void _onResponseStart(int statusCode, String reasonPhrase, String version) { 1815 void _onResponseStart(int statusCode, String reasonPhrase, String version) {
1782 _statusCode = statusCode; 1816 _statusCode = statusCode;
1783 _reasonPhrase = reasonPhrase; 1817 _reasonPhrase = reasonPhrase;
1784 } 1818 }
1785 1819
1786 void _onHeaderReceived(String name, String value) { 1820 void _onHeaderReceived(String name, String value) {
1787 _headers.add(name, value); 1821 _headers.add(name, value);
1788 } 1822 }
1789 1823
1790 void _handleUnauthorized() { 1824 void _handleUnauthorized() {
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
1899 _connection._onResponse(this); 1933 _connection._onResponse(this);
1900 } 1934 }
1901 } 1935 }
1902 1936
1903 void _onDataReceived(List<int> data) { 1937 void _onDataReceived(List<int> data) {
1904 _buffer.add(data); 1938 _buffer.add(data);
1905 if (_inputStream != null) _inputStream._dataReceived(); 1939 if (_inputStream != null) _inputStream._dataReceived();
1906 } 1940 }
1907 1941
1908 void _onDataEnd() { 1942 void _onDataEnd() {
1909 _connection._responseDone();
1910 if (_inputStream != null) { 1943 if (_inputStream != null) {
1911 _inputStream._closeReceived(); 1944 _inputStream._closeReceived();
1912 } else { 1945 } else {
1913 inputStream._streamMarkedClosed = true; 1946 inputStream._streamMarkedClosed = true;
1914 } 1947 }
1915 } 1948 }
1916 1949
1917 // Delegate functions for the HttpInputStream implementation. 1950 // Delegate functions for the HttpInputStream implementation.
1918 int _streamAvailable() { 1951 int _streamAvailable() {
1919 return _buffer.length; 1952 return _buffer.length;
(...skipping 19 matching lines...) Expand all
1939 _HttpClientConnection _connection; 1972 _HttpClientConnection _connection;
1940 _HttpInputStream _inputStream; 1973 _HttpInputStream _inputStream;
1941 _BufferList _buffer; 1974 _BufferList _buffer;
1942 1975
1943 Function _streamErrorHandler; 1976 Function _streamErrorHandler;
1944 } 1977 }
1945 1978
1946 1979
1947 class _HttpClientConnection 1980 class _HttpClientConnection
1948 extends _HttpConnectionBase implements HttpClientConnection { 1981 extends _HttpConnectionBase implements HttpClientConnection {
1949 static const int NONE = 0;
1950 static const int REQUEST_DONE = 1;
1951 static const int RESPONSE_DONE = 2;
1952 static const int ALL_DONE = REQUEST_DONE | RESPONSE_DONE;
1953 1982
1954 _HttpClientConnection(_HttpClient this._client); 1983 _HttpClientConnection(_HttpClient this._client) {
1984 _httpParser = new _HttpParser.responseParser();
1985 }
1955 1986
1956 void _connectionEstablished(_SocketConnection socketConn) { 1987 void _connectionEstablished(_SocketConnection socketConn) {
1957 super._connectionEstablished(socketConn._socket); 1988 super._connectionEstablished(socketConn._socket);
1958 _socketConn = socketConn; 1989 _socketConn = socketConn;
1959 // Register HTTP parser callbacks. 1990 // Register HTTP parser callbacks.
1960 _httpParser.requestStart = 1991 _httpParser.responseStart = _onResponseStart;
1961 (method, uri, version) => _onRequestStart(method, uri, version); 1992 _httpParser.headerReceived = _onHeaderReceived;
1962 _httpParser.responseStart = 1993 _httpParser.headersComplete = _onHeadersComplete;
1963 (statusCode, reasonPhrase, version) => 1994 _httpParser.dataReceived = _onDataReceived;
1964 _onResponseStart(statusCode, reasonPhrase, version); 1995 _httpParser.dataEnd = _onDataEnd;
1965 _httpParser.headerReceived = 1996 _httpParser.error = _onError;
1966 (name, value) => _onHeaderReceived(name, value); 1997 _httpParser.closed = _onClosed;
1967 _httpParser.headersComplete = () => _onHeadersComplete(); 1998 _httpParser.requestStart = (method, uri, version) { assert(false); };
1968 _httpParser.dataReceived = (data) => _onDataReceived(data); 1999 _state = _HttpConnectionBase.ACTIVE;
1969 _httpParser.dataEnd = (closed) => _onDataEnd(closed);
1970 _httpParser.error = (e) => _onError(e);
1971 } 2000 }
1972 2001
1973 bool get _isRequestDone => (_state & REQUEST_DONE) == REQUEST_DONE;
1974 bool get _isResponseDone => (_state & RESPONSE_DONE) == RESPONSE_DONE;
1975 bool get _isAllDone => (_state & ALL_DONE) == ALL_DONE;
1976
1977 void _checkSocketDone() { 2002 void _checkSocketDone() {
1978 if (_isAllDone) { 2003 if (_isAllDone) {
1979 if (!_closing) { 2004 // If we are done writing the response, and either the server
2005 // has closed or the connection is not persistent, we must
2006 // close.
2007 if (_isReadClosed || !_response.persistentConnection) {
2008 this.onClosed = () {
2009 _client._closedSocketConnection(_socketConn);
2010 };
2011 _client._closeQueue.add(this);
2012 } else {
1980 _client._returnSocketConnection(_socketConn); 2013 _client._returnSocketConnection(_socketConn);
1981 } 2014 _socket = null;
1982 _socket = null; 2015 _socketConn = null;
1983 _socketConn = null; 2016 assert(_pendingRedirect == null || _pendingRetry == null);
1984 assert(_pendingRedirect == null || _pendingRetry == null); 2017 if (_pendingRedirect != null) {
1985 if (_pendingRedirect != null) { 2018 _doRedirect(_pendingRedirect);
1986 _doRedirect(_pendingRedirect); 2019 _pendingRedirect = null;
1987 _pendingRedirect = null; 2020 } else if (_pendingRetry != null) {
1988 } else if (_pendingRetry != null) { 2021 _doRetry(_pendingRetry);
1989 _doRetry(_pendingRetry); 2022 _pendingRetry = null;
1990 _pendingRetry = null; 2023 }
1991 } 2024 }
1992 } 2025 }
1993 } 2026 }
1994 2027
1995 void _requestDone() { 2028 void _requestClosed() {
1996 _state |= REQUEST_DONE; 2029 _state |= _HttpConnectionBase.REQUEST_DONE;
1997 _checkSocketDone(); 2030 _checkSocketDone();
1998 } 2031 }
1999 2032
2000 void _responseDone() {
2001 if (_closing) {
2002 if (_socket != null) {
2003 _socket.close();
2004 }
2005 }
2006 _state |= RESPONSE_DONE;
2007 _checkSocketDone();
2008 }
2009
2010 HttpClientRequest open(String method, Uri uri) { 2033 HttpClientRequest open(String method, Uri uri) {
2011 _method = method; 2034 _method = method;
2012 // Tell the HTTP parser the method it is expecting a response to. 2035 // Tell the HTTP parser the method it is expecting a response to.
2013 _httpParser.responseToMethod = method; 2036 _httpParser.responseToMethod = method;
2014 _request = new _HttpClientRequest(method, uri, this); 2037 _request = new _HttpClientRequest(method, uri, this);
2015 _response = new _HttpClientResponse(this); 2038 _response = new _HttpClientResponse(this);
2016 return _request; 2039 return _request;
2017 } 2040 }
2018 2041
2019 DetachedSocket detachSocket() { 2042 DetachedSocket detachSocket() {
2020 return _detachSocket(); 2043 return _detachSocket();
2021 } 2044 }
2022 2045
2023 void _onConnectionClosed(e) { 2046 void _onClosed() {
2047 _state |= _HttpConnectionBase.READ_CLOSED;
2048 }
2049
2050 void _onError(e) {
2024 // Socket is closed either due to an error or due to normal socket close. 2051 // Socket is closed either due to an error or due to normal socket close.
2025 if (e != null) { 2052 if (_onErrorCallback != null) {
2026 if (_onErrorCallback != null) { 2053 _onErrorCallback(e);
2027 _onErrorCallback(e); 2054 } else {
2028 } else { 2055 throw e;
2029 throw e;
2030 }
2031 } 2056 }
2032 _closing = true; 2057 // Propagate the error to the streams.
2033 if (e != null) { 2058 if (_response != null && _response._streamErrorHandler != null) {
2034 // Propagate the error to the streams. 2059 _response._streamErrorHandler(e);
2035 if (_response != null && _response._streamErrorHandler != null) { 2060 }
2036 _response._streamErrorHandler(e); 2061 if (_socketConn != null) {
2037 } 2062 _client._closeSocketConnection(_socketConn);
2038 _responseDone();
2039 } else {
2040 // If there was no socket error the socket was closed
2041 // normally. Indicate closing to the HTTP Parser as there might
2042 // still be an HTTP error.
2043 _httpParser.connectionClosed();
2044 } 2063 }
2045 } 2064 }
2046 2065
2047 void _onRequestStart(String method, String uri, String version) {
2048 // TODO(sgjesse): Error handling.
2049 }
2050
2051 void _onResponseStart(int statusCode, String reasonPhrase, String version) { 2066 void _onResponseStart(int statusCode, String reasonPhrase, String version) {
2052 _response._onResponseStart(statusCode, reasonPhrase, version); 2067 _response._onResponseStart(statusCode, reasonPhrase, version);
2053 } 2068 }
2054 2069
2055 void _onHeaderReceived(String name, String value) { 2070 void _onHeaderReceived(String name, String value) {
2056 _response._onHeaderReceived(name, value); 2071 _response._onHeaderReceived(name, value);
2057 } 2072 }
2058 2073
2059 void _onHeadersComplete() { 2074 void _onHeadersComplete() {
2060 _response._onHeadersComplete(); 2075 _response._onHeadersComplete();
2061 } 2076 }
2062 2077
2063 void _onDataReceived(List<int> data) { 2078 void _onDataReceived(List<int> data) {
2064 _response._onDataReceived(data); 2079 _response._onDataReceived(data);
2065 } 2080 }
2066 2081
2067 void _onDataEnd(bool close) { 2082 void _onDataEnd(bool close) {
2068 if (close) _closing = true;
2069 _response._onDataEnd(); 2083 _response._onDataEnd();
2084 _state |= _HttpConnectionBase.RESPONSE_DONE;
2085 _checkSocketDone();
2070 } 2086 }
2071 2087
2072 void set onRequest(void handler(HttpClientRequest request)) { 2088 void set onRequest(void handler(HttpClientRequest request)) {
2073 _onRequest = handler; 2089 _onRequest = handler;
2074 } 2090 }
2075 2091
2076 void set onResponse(void handler(HttpClientResponse response)) { 2092 void set onResponse(void handler(HttpClientResponse response)) {
2077 _onResponse = handler; 2093 _onResponse = handler;
2078 } 2094 }
2079 2095
2080 void set onError(void callback(e)) { 2096 void set onError(void callback(e)) {
2081 _onErrorCallback = callback; 2097 _onErrorCallback = callback;
2082 } 2098 }
2083 2099
2084 void _doRetry(_RedirectInfo retry) { 2100 void _doRetry(_RedirectInfo retry) {
2085 assert(_socketConn == null); 2101 assert(_socketConn == null);
2086 _request = null; 2102 _request = null;
2087 _response = null; 2103 _response = null;
2088 2104
2089 // Retry the URL using the same connection instance. 2105 // Retry the URL using the same connection instance.
2090 _state = NONE; 2106 _state = _HttpConnectionBase.IDLE;
2091 _client._openUrl(retry.method, retry.location, this); 2107 _client._openUrl(retry.method, retry.location, this);
2092 } 2108 }
2093 2109
2094 void _retry() { 2110 void _retry() {
2095 var retry = new _RedirectInfo(_response.statusCode, _method, _request._uri); 2111 var retry = new _RedirectInfo(_response.statusCode, _method, _request._uri);
2096 // The actual retry is postponed until both response and request 2112 // The actual retry is postponed until both response and request
2097 // are done. 2113 // are done.
2098 if (_isAllDone) { 2114 if (_isAllDone) {
2099 _doRetry(retry); 2115 _doRetry(retry);
2100 } else { 2116 } else {
(...skipping 23 matching lines...) Expand all
2124 // request are done. 2140 // request are done.
2125 if (_isAllDone) { 2141 if (_isAllDone) {
2126 _doRedirect(redirect); 2142 _doRedirect(redirect);
2127 } else { 2143 } else {
2128 // Prepare for redirect. 2144 // Prepare for redirect.
2129 assert(_pendingRetry == null); 2145 assert(_pendingRetry == null);
2130 _pendingRedirect = redirect; 2146 _pendingRedirect = redirect;
2131 } 2147 }
2132 } 2148 }
2133 2149
2134 int _state = NONE;
2135
2136 List<RedirectInfo> get redirects => _redirects; 2150 List<RedirectInfo> get redirects => _redirects;
2137 2151
2138 Function _onRequest; 2152 Function _onRequest;
2139 Function _onResponse; 2153 Function _onResponse;
2140 Function _onErrorCallback; 2154 Function _onErrorCallback;
2141 2155
2142 _HttpClient _client; 2156 _HttpClient _client;
2143 _SocketConnection _socketConn; 2157 _SocketConnection _socketConn;
2144 HttpClientRequest _request; 2158 HttpClientRequest _request;
2145 HttpClientResponse _response; 2159 HttpClientResponse _response;
(...skipping 19 matching lines...) Expand all
2165 int this._port, 2179 int this._port,
2166 Socket this._socket); 2180 Socket this._socket);
2167 2181
2168 void _markReturned() { 2182 void _markReturned() {
2169 _socket.onData = null; 2183 _socket.onData = null;
2170 _socket.onClosed = null; 2184 _socket.onClosed = null;
2171 _socket.onError = null; 2185 _socket.onError = null;
2172 _returnTime = new Date.now(); 2186 _returnTime = new Date.now();
2173 } 2187 }
2174 2188
2189 void _close() {
2190 _socket.onData = null;
2191 _socket.onClosed = null;
2192 _socket.onError = null;
2193 _socket.close();
2194 }
2195
2175 Duration _idleTime(Date now) => now.difference(_returnTime); 2196 Duration _idleTime(Date now) => now.difference(_returnTime);
2176 2197
2177 int get hashCode => _socket.hashCode; 2198 int get hashCode => _socket.hashCode;
2178 2199
2179 String _host; 2200 String _host;
2180 int _port; 2201 int _port;
2181 Socket _socket; 2202 Socket _socket;
2182 Date _returnTime; 2203 Date _returnTime;
2183 } 2204 }
2184 2205
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2234 final String host; 2255 final String host;
2235 final int port; 2256 final int port;
2236 final bool isDirect; 2257 final bool isDirect;
2237 } 2258 }
2238 2259
2239 class _HttpClient implements HttpClient { 2260 class _HttpClient implements HttpClient {
2240 static const int DEFAULT_EVICTION_TIMEOUT = 60000; 2261 static const int DEFAULT_EVICTION_TIMEOUT = 60000;
2241 2262
2242 _HttpClient() : _openSockets = new Map(), 2263 _HttpClient() : _openSockets = new Map(),
2243 _activeSockets = new Set(), 2264 _activeSockets = new Set(),
2265 _closeQueue = new _CloseQueue(),
2244 credentials = new List<_Credentials>(), 2266 credentials = new List<_Credentials>(),
2245 _shutdown = false; 2267 _shutdown = false;
2246 2268
2247 HttpClientConnection open( 2269 HttpClientConnection open(
2248 String method, String host, int port, String path) { 2270 String method, String host, int port, String path) {
2249 // TODO(sgjesse): The path set here can contain both query and 2271 // TODO(sgjesse): The path set here can contain both query and
2250 // fragment. They should be cracked and set correctly. 2272 // fragment. They should be cracked and set correctly.
2251 return _open(method, new Uri.fromComponents( 2273 return _open(method, new Uri.fromComponents(
2252 scheme: "http", domain: host, port: port, path: path)); 2274 scheme: "http", domain: host, port: port, path: path));
2253 } 2275 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2292 } 2314 }
2293 2315
2294 void addCredentials( 2316 void addCredentials(
2295 Uri url, String realm, HttpClientCredentials cr) { 2317 Uri url, String realm, HttpClientCredentials cr) {
2296 credentials.add(new _Credentials(url, realm, cr)); 2318 credentials.add(new _Credentials(url, realm, cr));
2297 } 2319 }
2298 2320
2299 set findProxy(String f(Uri uri)) => _findProxy = f; 2321 set findProxy(String f(Uri uri)) => _findProxy = f;
2300 2322
2301 void shutdown() { 2323 void shutdown() {
2302 _openSockets.forEach((String key, Queue<_SocketConnection> connections) { 2324 _closeQueue.shutdown();
2303 while (!connections.isEmpty) { 2325 _openSockets.forEach((String key, Queue<_SocketConnection> connections) {
2304 _SocketConnection socketConn = connections.removeFirst(); 2326 while (!connections.isEmpty) {
2305 socketConn._socket.close(); 2327 _SocketConnection socketConn = connections.removeFirst();
2306 } 2328 socketConn._socket.close();
2307 }); 2329 }
2308 _activeSockets.forEach((_SocketConnection socketConn) { 2330 });
2309 socketConn._socket.close(); 2331 _activeSockets.forEach((_SocketConnection socketConn) {
2310 }); 2332 socketConn._socket.close();
2333 });
2311 if (_evictionTimer != null) _cancelEvictionTimer(); 2334 if (_evictionTimer != null) _cancelEvictionTimer();
2312 _shutdown = true; 2335 _shutdown = true;
2313 } 2336 }
2314 2337
2315 void _cancelEvictionTimer() { 2338 void _cancelEvictionTimer() {
2316 _evictionTimer.cancel(); 2339 _evictionTimer.cancel();
2317 _evictionTimer = null; 2340 _evictionTimer = null;
2318 } 2341 }
2319 2342
2320 String _connectionKey(String host, int port) { 2343 String _connectionKey(String host, int port) {
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
2496 if (_openSockets.isEmpty) _cancelEvictionTimer(); 2519 if (_openSockets.isEmpty) _cancelEvictionTimer();
2497 } 2520 }
2498 _evictionTimer = new Timer.repeating(10000, _handleEviction); 2521 _evictionTimer = new Timer.repeating(10000, _handleEviction);
2499 } 2522 }
2500 2523
2501 // Return connection. 2524 // Return connection.
2502 _activeSockets.remove(socketConn); 2525 _activeSockets.remove(socketConn);
2503 sockets.addFirst(socketConn); 2526 sockets.addFirst(socketConn);
2504 } 2527 }
2505 2528
2529 void _closeSocketConnection(_SocketConnection socketConn) {
2530 socketConn._close();
2531 _activeSockets.remove(socketConn);
2532 }
2533
2534 void _closedSocketConnection(_SocketConnection socketConn) {
2535 _activeSockets.remove(socketConn);
2536 }
2537
2506 _Credentials _findCredentials(Uri url, [_AuthenticationScheme scheme]) { 2538 _Credentials _findCredentials(Uri url, [_AuthenticationScheme scheme]) {
2507 // Look for credentials. 2539 // Look for credentials.
2508 _Credentials cr = 2540 _Credentials cr =
2509 credentials.reduce(null, (_Credentials prev, _Credentials value) { 2541 credentials.reduce(null, (_Credentials prev, _Credentials value) {
2510 if (value.applies(url, scheme)) { 2542 if (value.applies(url, scheme)) {
2511 if (prev == null) return value; 2543 if (prev == null) return value;
2512 return value.uri.path.length > prev.uri.path.length ? value : prev; 2544 return value.uri.path.length > prev.uri.path.length ? value : prev;
2513 } else { 2545 } else {
2514 return prev; 2546 return prev;
2515 } 2547 }
2516 }); 2548 });
2517 return cr; 2549 return cr;
2518 } 2550 }
2519 2551
2520 void _removeCredentials(_Credentials cr) { 2552 void _removeCredentials(_Credentials cr) {
2521 int index = credentials.indexOf(cr); 2553 int index = credentials.indexOf(cr);
2522 if (index != -1) { 2554 if (index != -1) {
2523 credentials.removeAt(index); 2555 credentials.removeAt(index);
2524 } 2556 }
2525 } 2557 }
2526 2558
2527 Function _onOpen; 2559 Function _onOpen;
2528 Map<String, Queue<_SocketConnection>> _openSockets; 2560 Map<String, Queue<_SocketConnection>> _openSockets;
2529 Set<_SocketConnection> _activeSockets; 2561 Set<_SocketConnection> _activeSockets;
2562 _CloseQueue _closeQueue;
2530 List<_Credentials> credentials; 2563 List<_Credentials> credentials;
2531 Timer _evictionTimer; 2564 Timer _evictionTimer;
2532 Function _findProxy; 2565 Function _findProxy;
2533 Function _authenticate; 2566 Function _authenticate;
2534 bool _shutdown; // Has this HTTP client been shutdown? 2567 bool _shutdown; // Has this HTTP client been shutdown?
2535 } 2568 }
2536 2569
2537 2570
2538 class _HttpConnectionInfo implements HttpConnectionInfo { 2571 class _HttpConnectionInfo implements HttpConnectionInfo {
2539 String remoteHost; 2572 String remoteHost;
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
2655 2688
2656 2689
2657 class _RedirectInfo implements RedirectInfo { 2690 class _RedirectInfo implements RedirectInfo {
2658 const _RedirectInfo(int this.statusCode, 2691 const _RedirectInfo(int this.statusCode,
2659 String this.method, 2692 String this.method,
2660 Uri this.location); 2693 Uri this.location);
2661 final int statusCode; 2694 final int statusCode;
2662 final String method; 2695 final String method;
2663 final Uri location; 2696 final Uri location;
2664 } 2697 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/io/http_parser.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698