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

Side by Side Diff: runtime/bin/socket_impl.dart

Issue 8437090: Change the handling of closing sockets (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed review comments by ager@ Created 9 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 | « runtime/bin/socket.dart ('k') | runtime/bin/socket_stream.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) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 5
6 class _SocketBase { 6 class _SocketBase {
7 // Bit flags used when communicating between the eventhandler and 7 // Bit flags used when communicating between the eventhandler and
8 // dart code. The EVENT flags are used to indicate events of 8 // dart code. The EVENT flags are used to indicate events of
9 // interest when sending a message from dart code to the 9 // interest when sending a message from dart code to the
10 // eventhandler. When receiving a message from the eventhandler the 10 // eventhandler. When receiving a message from the eventhandler the
11 // EVENT flags indicate the events that actually happened. The 11 // EVENT flags indicate the events that actually happened. The
12 // COMMAND flags are used to send commands from dart to the 12 // COMMAND flags are used to send commands from dart to the
13 // eventhandler. COMMAND flags are never received from the 13 // eventhandler. COMMAND flags are never received from the
14 // eventhandler. Additional flags are used to communicate other 14 // eventhandler. Additional flags are used to communicate other
15 // information. 15 // information.
16 static final int _IN_EVENT = 0; 16 static final int _IN_EVENT = 0;
17 static final int _OUT_EVENT = 1; 17 static final int _OUT_EVENT = 1;
18 static final int _ERROR_EVENT = 2; 18 static final int _ERROR_EVENT = 2;
19 static final int _CLOSE_EVENT = 3; 19 static final int _CLOSE_EVENT = 3;
20 20
21 static final int _CLOSE_COMMAND = 8; 21 static final int _CLOSE_COMMAND = 8;
22 static final int _SHUTDOWN_READ_COMMAND = 9;
23 static final int _SHUTDOWN_WRITE_COMMAND = 10;
22 24
23 // Flag send to the eventhandler saying that the file descriptor in 25 // Flag send to the eventhandler saying that the file descriptor in
24 // question represents a listening socket. 26 // question represents a listening socket.
25 static final int _LISTENING_SOCKET = 16; 27 static final int _LISTENING_SOCKET = 16;
26 28
27 static final int _FIRST_EVENT = _IN_EVENT; 29 static final int _FIRST_EVENT = _IN_EVENT;
28 static final int _LAST_EVENT = _CLOSE_EVENT; 30 static final int _LAST_EVENT = _CLOSE_EVENT;
29 31
32 static final int _FIRST_COMMAND = _CLOSE_COMMAND;
33 static final int _LAST_COMMAND = _SHUTDOWN_WRITE_COMMAND;
34
30 _SocketBase () { 35 _SocketBase () {
31 _handler = new ReceivePort(); 36 _handler = new ReceivePort();
32 _handlerMap = new List(_CLOSE_EVENT + 1); 37 _handlerMap = new List(_LAST_EVENT + 1);
33 _handlerMask = 0; 38 _handlerMask = 0;
34 _canActivateHandlers = true; 39 _canActivateHandlers = true;
35 _id = -1; 40 _id = -1;
36 _handler.receive((var message, ignored) { 41 _handler.receive((var message, ignored) {
37 _multiplex(message); 42 _multiplex(message);
38 }); 43 });
39 EventHandler._start(); 44 EventHandler._start();
40 } 45 }
41 46
42 /* 47 /*
43 * Multiplexes socket events to the right socket handler. 48 * Multiplexes socket events to the right socket handler.
44 */ 49 */
45 void _multiplex(List<int> message) { 50 void _multiplex(List<int> message) {
46 assert(message.length == 1); 51 assert(message.length == 1);
47 _canActivateHandlers = false; 52 _canActivateHandlers = false;
48 int event_mask = message[0]; 53 int event_mask = message[0];
49 for (int i = _FIRST_EVENT; i <= _LAST_EVENT; i++) { 54 for (int i = _FIRST_EVENT; i <= _LAST_EVENT; i++) {
50 if (((event_mask & (1 << i)) != 0) && _handlerMap[i] != null) { 55 if (((event_mask & (1 << i)) != 0)) {
51 var handleEvent = _handlerMap[i]; 56 if ((i == _CLOSE_EVENT) && this is _Socket && _id >= 0) {
57 if (_closedWrite) _close();
58 }
52 59
60 var eventHandler = _handlerMap[i];
61 if (eventHandler != null) {
53 // Unregister the out handler before executing it. 62 // Unregister the out handler before executing it.
54 if (i == _OUT_EVENT) _setHandler(i, null); 63 if (i == _OUT_EVENT) _setHandler(i, null);
55 64
56 // Don't call the in handler if there is no data available 65 // Don't call the in handler if there is no data available
57 // after all. 66 // after all.
58 if (i == _IN_EVENT && this is _Socket && available() == 0) continue; 67 if (i == _IN_EVENT && this is _Socket && available() == 0) {
59 68 continue;
60 handleEvent(); 69 }
70 eventHandler();
61 } 71 }
62 } 72 }
73 }
63 _canActivateHandlers = true; 74 _canActivateHandlers = true;
64 _activateHandlers(); 75 _activateHandlers();
65 } 76 }
66 77
67 void _setHandler(int event, void callback()) { 78 void _setHandler(int event, void callback()) {
68 if (callback == null) { 79 if (callback == null) {
69 _handlerMask &= ~(1 << event); 80 _handlerMask &= ~(1 << event);
70 } else { 81 } else {
71 _handlerMask |= (1 << event); 82 _handlerMask |= (1 << event);
72 } 83 }
73 _handlerMap[event] = callback; 84 _handlerMap[event] = callback;
74 _activateHandlers(); 85 _activateHandlers();
75 } 86 }
76 87
77 void _getPort() native "Socket_GetPort"; 88 void _getPort() native "Socket_GetPort";
78 89
79 void set errorHandler(void callback()) { 90 void set errorHandler(void callback()) {
80 _setHandler(_ERROR_EVENT, callback); 91 _setHandler(_ERROR_EVENT, callback);
81 } 92 }
82 93
83 void _activateHandlers() { 94 void _activateHandlers() {
84 if (_canActivateHandlers && (_id >= 0)) { 95 if (_canActivateHandlers && (_id >= 0)) {
85 int data = _handlerMask; 96 int data = _handlerMask;
86 if (_isListenSocket()) data |= (1 << _LISTENING_SOCKET); 97 if (_isListenSocket()) {
98 data |= (1 << _LISTENING_SOCKET);
99 } else {
100 if (_closedRead) { data &= ~(1 << _IN_EVENT); }
101 if (_closedWrite) { data &= ~(1 << _OUT_EVENT); }
102 if (_isListenSocket()) data |= (1 << _LISTENING_SOCKET);
103 }
87 EventHandler._sendData(_id, _handler, data); 104 EventHandler._sendData(_id, _handler, data);
88 } 105 }
89 } 106 }
90 107
91 void _scheduleEvent(int event) { 108 void _scheduleEvent(int event) {
92 _handler.toSendPort().send([1 << event], null); 109 _handler.toSendPort().send([1 << event], null);
93 } 110 }
94 111
95 int get port() { 112 int get port() {
96 if (_port === null) { 113 if (_port === null) {
97 _port = _getPort(); 114 _port = _getPort();
98 } 115 }
99 return _port; 116 return _port;
100 } 117 }
101 118
102 void close() { 119 void close([bool halfClose = false]) {
103 if (_id >= 0) { 120 if (_id >= 0) {
104 EventHandler._sendData(_id, _handler, 1 << _CLOSE_COMMAND); 121 if (halfClose) {
105 _handler.close(); 122 _closeWrite();
106 _handler = null; 123 } else {
107 _id = -1; 124 _close();
125 }
108 } else if (_handler != null) { 126 } else if (_handler != null) {
109 // This is to support closing sockets created but never assigned 127 // This is to support closing sockets created but never assigned
110 // any actual socket. 128 // any actual socket.
111 _handler.close(); 129 _handler.close();
112 _handler = null; 130 _handler = null;
113 } 131 }
114 } 132 }
115 133
134 void _closeWrite() {
135 if (_closedRead) {
136 _close();
137 } else {
138 EventHandler._sendData(_id, _handler, 1 << _SHUTDOWN_WRITE_COMMAND);
139 }
140 _closedWrite = true;
141 }
142
143 void _closeRead() {
144 if (_closedWrite) {
145 _close();
146 } else {
147 EventHandler._sendData(_id, _handler, 1 << _SHUTDOWN_READ_COMMAND);
148 }
149 _closedRead = true;
150 }
151
152 void _close() {
153 EventHandler._sendData(_id, _handler, 1 << _CLOSE_COMMAND);
154 _handler.close();
155 _handler = null;
156 _id = -1;
157 }
158
116 abstract bool _isListenSocket(); 159 abstract bool _isListenSocket();
117 160
118 /* 161 /*
119 * Socket id is set from native. -1 indicates that the socket was closed. 162 * Socket id is set from native. -1 indicates that the socket was closed.
120 */ 163 */
121 int _id; 164 int _id;
122 165
123 /* 166 /*
124 * Dedicated ReceivePort for socket events. 167 * Dedicated ReceivePort for socket events.
125 */ 168 */
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 ServerSocket socket = new _ServerSocket._internal(); 202 ServerSocket socket = new _ServerSocket._internal();
160 if (!socket._createBindListen(bindAddress, port, backlog)) { 203 if (!socket._createBindListen(bindAddress, port, backlog)) {
161 return null; 204 return null;
162 } 205 }
163 if (port != 0) { 206 if (port != 0) {
164 socket._port = port; 207 socket._port = port;
165 } 208 }
166 return socket; 209 return socket;
167 } 210 }
168 211
169 _ServerSocket._internal() : super() {} 212 _ServerSocket._internal();
170 213
171 Socket accept() { 214 Socket accept() {
172 if (_id >= 0) { 215 if (_id >= 0) {
173 _Socket socket = new _Socket._internal(); 216 _Socket socket = new _Socket._internal();
174 if (_accept(socket)) { 217 if (_accept(socket)) {
175 return socket; 218 return socket;
176 } 219 }
177 return null; 220 return null;
178 } 221 }
179 throw new 222 throw new
(...skipping 12 matching lines...) Expand all
192 bool _isListenSocket() => true; 235 bool _isListenSocket() => true;
193 } 236 }
194 237
195 238
196 class _Socket extends _SocketBase implements Socket { 239 class _Socket extends _SocketBase implements Socket {
197 /* 240 /*
198 * Constructor for socket. First a socket object is allocated 241 * Constructor for socket. First a socket object is allocated
199 * in which the native socket is stored. After that _createConnect is 242 * in which the native socket is stored. After that _createConnect is
200 * called which creates a file discriptor and connects to the given 243 * called which creates a file discriptor and connects to the given
201 * host on the given port. Null is returned if file descriptor creation 244 * host on the given port. Null is returned if file descriptor creation
202 * or connect failsed 245 * or connect failed.
203 */ 246 */
204 factory _Socket(String host, int port) { 247 factory _Socket(String host, int port) {
205 Socket socket = new _Socket._internal(); 248 Socket socket = new _Socket._internal();
206 if (!socket._createConnect(host, port)) { 249 if (!socket._createConnect(host, port)) {
207 return null; 250 return null;
208 } 251 }
209 return socket; 252 return socket;
210 } 253 }
211 254
212 _Socket._internal() : super() {} 255 _Socket._internal();
256 _Socket._internalInputOnly() : _closedRead = true;
257 _Socket._internalOutputOnly() : _closedWrite = true;
213 258
214 int available() { 259 int available() {
215 if (_id >= 0) { 260 if (_id >= 0) {
216 return _available(); 261 return _available();
217 } 262 }
218 throw new 263 throw new
219 SocketIOException("Error: available failed - invalid socket handle"); 264 SocketIOException("Error: available failed - invalid socket handle");
220 } 265 }
221 266
222 int _available() native "Socket_Available"; 267 int _available() native "Socket_Available";
223 268
269 bool get closed() => _closed;
270
224 int readList(List<int> buffer, int offset, int bytes) { 271 int readList(List<int> buffer, int offset, int bytes) {
225 if (_id >= 0) { 272 if (_id >= 0) {
226 if (bytes == 0) { 273 if (bytes == 0) {
227 return 0; 274 return 0;
228 } 275 }
229 if (offset < 0) { 276 if (offset < 0) {
230 throw new IndexOutOfRangeException(offset); 277 throw new IndexOutOfRangeException(offset);
231 } 278 }
232 if (bytes < 0) { 279 if (bytes < 0) {
233 throw new IndexOutOfRangeException(bytes); 280 throw new IndexOutOfRangeException(bytes);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 return _inputStream; 341 return _inputStream;
295 } 342 }
296 343
297 OutputStream get outputStream() { 344 OutputStream get outputStream() {
298 if (_outputStream === null) { 345 if (_outputStream === null) {
299 _outputStream = new SocketOutputStream(this); 346 _outputStream = new SocketOutputStream(this);
300 } 347 }
301 return _outputStream; 348 return _outputStream;
302 } 349 }
303 350
351 bool _closedRead = false;
352 bool _closedWrite = false;
304 SocketInputStream _inputStream; 353 SocketInputStream _inputStream;
305 SocketOutputStream _outputStream; 354 SocketOutputStream _outputStream;
306 } 355 }
307 356
OLDNEW
« no previous file with comments | « runtime/bin/socket.dart ('k') | runtime/bin/socket_stream.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698