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

Unified Diff: runtime/bin/http_impl.dart

Issue 9956062: Refactor the close and error handling of HTTP connections (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed review comments Created 8 years, 9 months 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | runtime/bin/http_parser.dart » ('j') | runtime/bin/http_parser.dart » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/bin/http_impl.dart
diff --git a/runtime/bin/http_impl.dart b/runtime/bin/http_impl.dart
index 921d7cb61077dba34b67f07fef4d7f47af702a56..d210ed92935238f12fa897fada90a555ae36a5b1 100644
--- a/runtime/bin/http_impl.dart
+++ b/runtime/bin/http_impl.dart
@@ -260,6 +260,16 @@ class _HttpResponse extends _HttpRequestResponseBase implements HttpResponse {
return _outputStream;
}
+ void _responseEnd() {
+ _state = DONE;
+ // Stop tracking no pending write events.
+ _httpConnection.outputStream.onNoPendingWrites = null;
+ // Ensure that any trailing data is written.
+ _writeDone();
+ // Indicate to the connection that the response handling is done.
+ _httpConnection._responseDone();
+ }
+
// Delegate functions for the HttpOutputStream implementation.
bool _streamWrite(List<int> buffer, bool copyBuffer) {
return _write(buffer, copyBuffer);
@@ -270,17 +280,7 @@ class _HttpResponse extends _HttpRequestResponseBase implements HttpResponse {
}
void _streamClose() {
- _httpConnection._phase = _HttpConnectionBase.PHASE_IDLE;
- _state = DONE;
- // Stop tracking no pending write events.
- _httpConnection.outputStream.onNoPendingWrites = null;
- // Ensure that any trailing data is written.
- _writeDone();
- // If the connection is closing then close the output stream to
- // fully close the socket.
- if (_httpConnection._closing) {
- _httpConnection.outputStream.close();
- }
+ _responseEnd();
}
void _streamSetNoPendingWriteHandler(callback()) {
@@ -470,12 +470,7 @@ class _HttpOutputStream extends _BaseOutputStream implements OutputStream {
class _HttpConnectionBase implements Hashable {
- static final int PHASE_IDLE = 0;
- static final int PHASE_REQUEST = 1;
- static final int PHASE_RESPONSE = 2;
-
- _HttpConnectionBase() : _phase = PHASE_IDLE,
- _sendBuffers = new Queue(),
+ _HttpConnectionBase() : _sendBuffers = new Queue(),
_httpParser = new _HttpParser();
void _connectionEstablished(Socket socket) {
@@ -508,49 +503,29 @@ class _HttpConnectionBase implements Hashable {
}
void _onClosed() {
- if (_phase != PHASE_IDLE) {
- // Client closed socket for writing. Socket should still be open
- // for writing the response.
- _closing = true;
- } else {
- // The connection is currently not used by any request just close it.
- _socket.close();
- }
- if (_onDisconnectCallback != null) _onDisconnectCallback();
+ _onConnectionClosed(null);
}
void _onError(Exception e) {
// If an error occurs, make sure to close the socket if one is associated.
+ _error = true;
if (_socket != null) {
_socket.close();
}
- if (_onErrorCallback != null) {
- _onErrorCallback(e);
- }
- _propagateError(e);
- }
-
- abstract void _propagateError(Exception e);
-
- void set onDisconnect(void callback()) {
- _onDisconnectCallback = callback;
+ _onConnectionClosed(e);
}
- void set onError(void callback(Exception e)) {
- _onErrorCallback = callback;
- }
+ abstract void _onConnectionClosed(Exception e);
+ abstract void _responseDone();
int hashCode() => _socket.hashCode();
- int _phase;
Socket _socket;
bool _closing = false; // Is the socket closed by the client?
+ bool _error = false; // Is the socket closed due to an error?
_HttpParser _httpParser;
Queue _sendBuffers;
-
- Function _onDisconnectCallback;
- Function _onErrorCallback;
}
@@ -567,13 +542,42 @@ class _HttpConnection extends _HttpConnectionBase {
(name, value) => _onHeaderReceived(name, value);
_httpParser.headersComplete = () => _onHeadersComplete();
_httpParser.dataReceived = (data) => _onDataReceived(data);
- _httpParser.dataEnd = () => _onDataEnd();
+ _httpParser.dataEnd = (close) => _onDataEnd(close);
_httpParser.error = (e) => _onError(e);
}
+ void _onConnectionClosed(Exception e) {
+ if (e != null && onError != null) {
+ onError(e);
+ // Propagate the error to the streams.
+ if (_request != null && _request._streamErrorHandler != null) {
+ _request._streamErrorHandler(e);
+ }
+ if (_response != null && _response._streamErrorHandler != null) {
+ _response._streamErrorHandler(e);
+ }
+ }
+
+ // If currently not processing any request just close the socket.
+ if (_httpParser.isIdle) {
+ _socket.close();
+ if (onClosed != null && e == null) {
+ // Don't call onClosed if onError has been called.
+ onClosed();
+ }
+ return;
+ }
+
+ // Processing a request.
+ if (e == null) {
+ // Indicate connection close to the HTTP parser.
+ _httpParser.connectionClosed();
+ _closing = true;
+ }
+ }
+
void _onRequestStart(String method, String uri) {
// Create new request and response objects for this request.
- _phase = PHASE_REQUEST;
_request = new _HttpRequest(this);
_response = new _HttpResponse(this);
_request._onRequestStart(method, uri);
@@ -590,8 +594,8 @@ class _HttpConnection extends _HttpConnectionBase {
void _onHeadersComplete() {
_request._onHeadersComplete();
_response.keepAlive = _httpParser.keepAlive;
- if (requestReceived != null) {
- requestReceived(_request, _response);
+ if (onRequestReceived != null) {
+ onRequestReceived(_request, _response);
}
}
@@ -599,22 +603,20 @@ class _HttpConnection extends _HttpConnectionBase {
_request._onDataReceived(data);
}
- void _onDataEnd() {
- // Phase might already have gone to PHASE_IDLE if the response is
- // sent without waiting for request body.
- if (_phase == PHASE_REQUEST) {
- _phase = PHASE_RESPONSE;
+ void _onDataEnd(bool close) {
+ if (_request != null) {
+ _request._onDataEnd();
}
- _request._onDataEnd();
+ _request = null;
}
- void _propagateError(Exception e) {
- if (_request != null && _request._streamErrorHandler != null) {
- _request._streamErrorHandler(e);
- }
- if (_response != null && _response._streamErrorHandler != null) {
- _response._streamErrorHandler(e);
+ void _responseDone() {
+ // If the connection is closing then close the output stream to
+ // fully close the socket.
+ if (_closing) {
+ outputStream.close();
}
+ _response = null;
}
HttpServer _server;
@@ -622,7 +624,9 @@ class _HttpConnection extends _HttpConnectionBase {
HttpResponse _response;
// Callbacks.
- var requestReceived;
+ Function onRequestReceived;
+ Function onClosed;
+ Function onError;
}
@@ -640,10 +644,12 @@ class _HttpServer implements HttpServer {
void onConnection(Socket socket) {
// Accept the client connection.
_HttpConnection connection = new _HttpConnection(this);
- connection.requestReceived = _onRequest;
- connection.onDisconnect = () => _connections.remove(connection);
+ connection._connectionEstablished(socket);
+ connection.onRequestReceived = _onRequest;
+ connection.onClosed = () => _connections.remove(connection);
connection.onError = (e) {
if (_onError != null) _onError(e);
+ _connections.remove(connection);
Anders Johnsen 2012/04/03 05:36:37 So, here the order matters. In the future when we
Søren Gjesse 2012/04/10 13:10:08 Moved the remove up before the _onError call. In g
};
connection._connectionEstablished(socket);
_connections.add(connection);
@@ -773,11 +779,6 @@ class _HttpClientRequest
_httpConnection.outputStream.onNoPendingWrites = null;
// Ensure that any trailing data is written.
_writeDone();
- // If the connection is closing then close the output stream to
- // fully close the socket.
- if (_httpConnection._closing) {
- _httpConnection.outputStream.close();
- }
}
void _streamSetNoPendingWriteHandler(callback()) {
@@ -887,6 +888,7 @@ class _HttpClientResponse
void _onDataEnd() {
if (_inputStream != null) _inputStream._closeReceived();
+ _connection._responseDone();
}
// Delegate functions for the HttpInputStream implementation.
@@ -935,18 +937,22 @@ class _HttpClientConnection
(name, value) => _onHeaderReceived(name, value);
_httpParser.headersComplete = () => _onHeadersComplete();
_httpParser.dataReceived = (data) => _onDataReceived(data);
- _httpParser.dataEnd = () => _onDataEnd();
+ _httpParser.dataEnd = (closed) => _onDataEnd(closed);
_httpParser.error = (e) => _onError(e);
// Tell the HTTP parser the method it is expecting a response to.
_httpParser.responseToMethod = _method;
-
- onDisconnect = _onDisconnected;
}
- void _propagateError(Exception e) {
- if (_response != null && _response._streamErrorHandler != null) {
- _response._streamErrorHandler(e);
+ void _responseDone() {
+ if (_closing) {
+ if (_socket != null) {
+ _socket.close();
+ }
+ } else {
+ _client._returnSocketConnection(_socketConn);
}
+ _socket = null;
+ _socketConn = null;
}
HttpClientRequest open(String method, String uri) {
@@ -957,6 +963,28 @@ class _HttpClientConnection
return _request;
}
+ void _onConnectionClosed(Exception e) {
+ // Socket is closed either due to an error or due to normal socket close.
+ if (e != null) {
+ if (_onErrorCallback != null) {
+ _onErrorCallback(e);
+ }
+ }
+ _closing = true;
+ if (e != null) {
+ // Propagate the error to the streams.
+ if (_response != null && _response._streamErrorHandler != null) {
+ _response._streamErrorHandler(e);
+ }
+ _responseDone();
+ } else {
+ // If there was no socket error the socket was closed
+ // normally. Indicate closing to the HTTP Parser as there might
+ // still be an HTTP error.
+ _httpParser.connectionClosed();
+ }
+ }
+
void _onRequestStart(String method, String uri) {
// TODO(sgjesse): Error handling.
}
@@ -977,15 +1005,8 @@ class _HttpClientConnection
_response._onDataReceived(data);
}
- void _onDataEnd() {
- onDisconnect = null;
- if (_response.headers["connection"] == "close") {
- _socket.close();
- } else {
- _client._returnSocketConnection(_socketConn);
- }
- _socket = null;
- _socketConn = null;
+ void _onDataEnd(bool close) {
+ if (close) _closing = true;
_response._onDataEnd();
}
@@ -997,15 +1018,13 @@ class _HttpClientConnection
_onResponse = handler;
}
- void _onDisconnected() {
- if (_onErrorCallback !== null) {
- _onErrorCallback(new HttpException(
- "Client disconnected before response was received."));
- }
+ void set onError(void callback(Exception e)) {
+ _onErrorCallback = callback;
}
Function _onRequest;
Function _onResponse;
+ Function _onErrorCallback;
_HttpClient _client;
_SocketConnection _socketConn;
« no previous file with comments | « no previous file | runtime/bin/http_parser.dart » ('j') | runtime/bin/http_parser.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698