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

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