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

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

Issue 11316080: Change the HTTP close handling (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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') | sdk/lib/io/http_parser.dart » ('J')
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 // The close queue handles graceful closing of HTTP connections. When 5 // The close queue handles graceful closing of HTTP connections. When
6 // a connection is added to the queue it will enter a wait state 6 // a connection is added to the queue it will enter a wait state
7 // waiting for all data written and possibly socket shutdown from 7 // waiting for all data written and possibly socket shutdown from
8 // peer. 8 // peer.
9 class _CloseQueue { 9 class _CloseQueue {
10 _CloseQueue() : _q = new Set<_HttpConnectionBase>(); 10 _CloseQueue() : _q = new Set<_HttpConnectionBase>();
11 11
12 void add(_HttpConnectionBase connection) { 12 void add(_HttpConnectionBase connection) {
13 void closeIfDone() { 13 void closeIfDone() {
14 // We only check for write closed here. This means that we are 14 // When either the client has closed or all data has been
15 // not waiting for the client to half-close the socket before 15 // written to the client we close the underlying socket
16 // fully closing the socket. 16 // completely.
17 if (!connection._isWriteClosed) return; 17 if (!connection._isWriteClosed && !connection._isReadClosed) return;
Mads Ager (google) 2012/11/20 08:04:28 Maybe remove the negations and make this: if (con
Søren Gjesse 2012/11/20 08:15:11 Much better, done.
18 _q.remove(connection); 18 _q.remove(connection);
19 connection._socket.close(); 19 connection._socket.close();
20 if (connection.onClosed != null) connection.onClosed(); 20 if (connection.onClosed != null) connection.onClosed();
21 } 21 }
22 22
23 // If the connection is already fully closed don't insert it into the queue. 23 // If the connection is already fully closed don't insert it into
24 // the queue.
24 if (connection._isFullyClosed) { 25 if (connection._isFullyClosed) {
25 connection._socket.close(); 26 connection._socket.close();
26 if (connection.onClosed != null) connection.onClosed(); 27 if (connection.onClosed != null) connection.onClosed();
27 return; 28 return;
28 } 29 }
29 30
30 connection._state |= _HttpConnectionBase.CLOSING; 31 connection._state |= _HttpConnectionBase.CLOSING;
31 _q.add(connection); 32 _q.add(connection);
32 33
33 // If output stream is not closed for writing close it now and 34 // If output stream is not closed for writing close it now and
34 // wait for callback when closed. 35 // wait for callback when closed.
35 if (!connection._isWriteClosed) { 36 if (!connection._isWriteClosed) {
36 connection._socket.outputStream.close(); 37 connection._socket.outputStream.close();
37 connection._socket.outputStream.onClosed = () { 38 connection._socket.outputStream.onClosed = () {
38 connection._state |= _HttpConnectionBase.WRITE_CLOSED; 39 connection._state |= _HttpConnectionBase.WRITE_CLOSED;
39 closeIfDone(); 40 closeIfDone();
40 }; 41 };
41 } else { 42 } else {
42 connection._socket.outputStream.onClosed = () { assert(false); }; 43 connection._socket.outputStream.onClosed = () { assert(false); };
43 } 44 }
44 45
45 // If socket is not closed for reading wait for callback. 46 // If socket is not closed for reading wait for callback.
46 if (!connection._isReadClosed) { 47 if (!connection._isReadClosed) {
47 connection._socket.onClosed = () { 48 connection._socket.onClosed = () {
48 connection._state |= _HttpConnectionBase.READ_CLOSED; 49 connection._state |= _HttpConnectionBase.READ_CLOSED;
49 // This is a nop, as we are not using the read closed
50 // information for anything. For both server and client
51 // connections the inbound message have been read to
52 // completion when the socket enters the close queue.
53 closeIfDone(); 50 closeIfDone();
54 }; 51 };
55 } else { 52 } else {
56 connection._socket.onClosed = () { assert(false); }; 53 connection._socket.onClosed = () { assert(false); };
57 } 54 }
58 55
59 // Ignore any data on a socket in the close queue. 56 // Ignore any data on a socket in the close queue.
60 connection._socket.onData = connection._socket.read; 57 connection._socket.onData = connection._socket.read;
61 58
62 // If an error occurs immediately close the socket. 59 // If an error occurs immediately close the socket.
63 connection._socket.onError = (e) { 60 connection._socket.onError = (e) {
61 connection._state |= _HttpConnectionBase.READ_CLOSED;
64 connection._state |= _HttpConnectionBase.WRITE_CLOSED; 62 connection._state |= _HttpConnectionBase.WRITE_CLOSED;
65 closeIfDone(); 63 closeIfDone();
66 }; 64 };
67 } 65 }
68 66
69 void shutdown() { 67 void shutdown() {
70 _q.forEach((_HttpConnectionBase connection) { 68 _q.forEach((_HttpConnectionBase connection) {
71 connection._socket.close(); 69 connection._socket.close();
72 }); 70 });
73 } 71 }
(...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after
869 if (onRequestReceived != null) { 867 if (onRequestReceived != null) {
870 onRequestReceived(_request, _response); 868 onRequestReceived(_request, _response);
871 } 869 }
872 } 870 }
873 871
874 void _onDataReceived(List<int> data) { 872 void _onDataReceived(List<int> data) {
875 _request._onDataReceived(data); 873 _request._onDataReceived(data);
876 } 874 }
877 875
878 void _checkDone() { 876 void _checkDone() {
879 if (_isAllDone) { 877 if (_isReadClosed) {
880 // If we are done writing the response, and either the client 878 // If the client closes the conversation is ended.
881 // has closed or the connection is not persistent, we must 879 _server._closeQueue.add(this);
882 // close. Also if using HTTP 1.0 and the content length was not 880 } else if (_isAllDone) {
883 // known we must close to indicate end of body. 881 // If we are done writing the response, and the connection is
882 // not persistent, we must close. Also if using HTTP 1.0 and the
883 // content length was not known we must close to indicate end of
884 // body.
884 bool close = 885 bool close =
885 !_response.persistentConnection || 886 !_response.persistentConnection ||
886 (_response._protocolVersion == "1.0" && _response._contentLength < 0); 887 (_response._protocolVersion == "1.0" && _response._contentLength < 0);
887 _request = null; 888 _request = null;
888 _response = null; 889 _response = null;
889 if (_isReadClosed || close) { 890 if (close) {
890 _server._closeQueue.add(this); 891 _server._closeQueue.add(this);
891 } else { 892 } else {
892 _state = _HttpConnectionBase.IDLE; 893 _state = _HttpConnectionBase.IDLE;
893 } 894 }
894 } else if (_state == _HttpConnectionBase.READ_CLOSED) {
895 // If entering READ_CLOSED state while idle close the connection.
896 _server._closeQueue.add(this);
897 } 895 }
898 } 896 }
899 897
900 void _onDataEnd(bool close) { 898 void _onDataEnd(bool close) {
901 _request._onDataEnd(); 899 _request._onDataEnd();
902 _state |= _HttpConnectionBase.REQUEST_DONE; 900 _state |= _HttpConnectionBase.REQUEST_DONE;
903 _checkDone(); 901 _checkDone();
904 } 902 }
905 903
906 void _responseClosed() { 904 void _responseClosed() {
(...skipping 1192 matching lines...) Expand 10 before | Expand all | Expand 10 after
2099 2097
2100 2098
2101 class _RedirectInfo implements RedirectInfo { 2099 class _RedirectInfo implements RedirectInfo {
2102 const _RedirectInfo(int this.statusCode, 2100 const _RedirectInfo(int this.statusCode,
2103 String this.method, 2101 String this.method,
2104 Uri this.location); 2102 Uri this.location);
2105 final int statusCode; 2103 final int statusCode;
2106 final String method; 2104 final String method;
2107 final Uri location; 2105 final Uri location;
2108 } 2106 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/io/http_parser.dart » ('j') | sdk/lib/io/http_parser.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698