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

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

Issue 8533005: Better handling of stdin/stdout/stderr (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Minor fix 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
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; 22 static final int _SHUTDOWN_READ_COMMAND = 9;
23 static final int _SHUTDOWN_WRITE_COMMAND = 10; 23 static final int _SHUTDOWN_WRITE_COMMAND = 10;
24 24
25 // Flag send to the eventhandler saying that the file descriptor in 25 // Flag send to the eventhandler providing additional information on
26 // question represents a listening socket. 26 // the type of the file descriptor.
27 static final int _LISTENING_SOCKET = 16; 27 static final int _LISTENING_SOCKET = 16;
28 static final int _PIPE = 17;
28 29
29 static final int _FIRST_EVENT = _IN_EVENT; 30 static final int _FIRST_EVENT = _IN_EVENT;
30 static final int _LAST_EVENT = _CLOSE_EVENT; 31 static final int _LAST_EVENT = _CLOSE_EVENT;
31 32
32 static final int _FIRST_COMMAND = _CLOSE_COMMAND; 33 static final int _FIRST_COMMAND = _CLOSE_COMMAND;
33 static final int _LAST_COMMAND = _SHUTDOWN_WRITE_COMMAND; 34 static final int _LAST_COMMAND = _SHUTDOWN_WRITE_COMMAND;
34 35
35 _SocketBase () { 36 _SocketBase () {
36 _handler = new ReceivePort();
37 _handlerMap = new List(_LAST_EVENT + 1); 37 _handlerMap = new List(_LAST_EVENT + 1);
38 _handlerMask = 0; 38 _handlerMask = 0;
39 _canActivateHandlers = true; 39 _canActivateHandlers = true;
40 _id = -1; 40 _id = -1;
41 _handler.receive((var message, ignored) {
42 _multiplex(message);
43 });
44 EventHandler._start(); 41 EventHandler._start();
45 } 42 }
46 43
47 /* 44 // Multiplexes socket events to the socket handlers.
48 * Multiplexes socket events to the right socket handler.
49 */
50 void _multiplex(List<int> message) { 45 void _multiplex(List<int> message) {
51 assert(message.length == 1); 46 assert(message.length == 1);
52 _canActivateHandlers = false; 47 _canActivateHandlers = false;
53 int event_mask = message[0]; 48 int event_mask = message[0];
54 for (int i = _FIRST_EVENT; i <= _LAST_EVENT; i++) { 49 for (int i = _FIRST_EVENT; i <= _LAST_EVENT; i++) {
55 if (((event_mask & (1 << i)) != 0)) { 50 if (((event_mask & (1 << i)) != 0)) {
56 if ((i == _CLOSE_EVENT) && this is _Socket && _id >= 0) { 51 if ((i == _CLOSE_EVENT) && this is _Socket && _id >= 0) {
57 _closedRead = true; 52 _closedRead = true;
58 if (_closedWrite) _close(); 53 if (_closedWrite) _close();
59 } 54 }
(...skipping 16 matching lines...) Expand all
76 _activateHandlers(); 71 _activateHandlers();
77 } 72 }
78 73
79 void _setHandler(int event, void callback()) { 74 void _setHandler(int event, void callback()) {
80 if (callback == null) { 75 if (callback == null) {
81 _handlerMask &= ~(1 << event); 76 _handlerMask &= ~(1 << event);
82 } else { 77 } else {
83 _handlerMask |= (1 << event); 78 _handlerMask |= (1 << event);
84 } 79 }
85 _handlerMap[event] = callback; 80 _handlerMap[event] = callback;
86 _activateHandlers(); 81 // If the socket is only for writing then close the receive port
82 // when not waiting for any events.
83 if (this is _Socket &&
84 _closedRead &&
85 _handlerMask == 0 &&
86 _handler != null) {
87 _handler.close();
88 _handler = null;
89 } else {
90 _activateHandlers();
91 }
87 } 92 }
88 93
89 void _getPort() native "Socket_GetPort"; 94 void _getPort() native "Socket_GetPort";
90 95
91 void set errorHandler(void callback()) { 96 void set errorHandler(void callback()) {
92 _setHandler(_ERROR_EVENT, callback); 97 _setHandler(_ERROR_EVENT, callback);
93 } 98 }
94 99
95 void _activateHandlers() { 100 void _activateHandlers() {
96 if (_canActivateHandlers && (_id >= 0)) { 101 if (_canActivateHandlers && (_id >= 0)) {
97 int data = _handlerMask; 102 int data = _handlerMask;
98 if (_isListenSocket()) { 103 if (_isListenSocket()) {
99 data |= (1 << _LISTENING_SOCKET); 104 data |= (1 << _LISTENING_SOCKET);
100 } else { 105 } else {
101 if (_closedRead) { data &= ~(1 << _IN_EVENT); } 106 if (_closedRead) { data &= ~(1 << _IN_EVENT); }
102 if (_closedWrite) { data &= ~(1 << _OUT_EVENT); } 107 if (_closedWrite) { data &= ~(1 << _OUT_EVENT); }
103 if (_isListenSocket()) data |= (1 << _LISTENING_SOCKET); 108 if (_isPipe()) data |= (1 << _PIPE);
Mads Ager (google) 2011/11/14 14:14:23 Good catch. :)
104 } 109 }
105 EventHandler._sendData(_id, _handler, data); 110 _sendToEventHandler(data);
106 } 111 }
107 } 112 }
108 113
109 void _scheduleEvent(int event) {
110 _handler.toSendPort().send([1 << event], null);
111 }
112
113 int get port() { 114 int get port() {
114 if (_port === null) { 115 if (_port === null) {
115 _port = _getPort(); 116 _port = _getPort();
116 } 117 }
117 return _port; 118 return _port;
118 } 119 }
119 120
120 void close([bool halfClose = false]) { 121 void close([bool halfClose = false]) {
121 if (_id >= 0) { 122 if (_id >= 0) {
122 if (halfClose) { 123 if (halfClose) {
123 _closeWrite(); 124 _closeWrite();
124 } else { 125 } else {
125 _close(); 126 _close();
126 } 127 }
127 } else if (_handler != null) { 128 } else if (_handler != null) {
128 // This is to support closing sockets created but never assigned 129 // This is to support closing sockets created but never assigned
129 // any actual socket. 130 // any actual socket.
130 _handler.close(); 131 _handler.close();
131 _handler = null; 132 _handler = null;
132 } 133 }
133 } 134 }
134 135
135 void _closeWrite() { 136 void _closeWrite() {
136 if (_closedRead) { 137 if (_closedRead) {
137 _close(); 138 _close();
138 } else { 139 } else {
139 EventHandler._sendData(_id, _handler, 1 << _SHUTDOWN_WRITE_COMMAND); 140 _sendToEventHandler(1 << _SHUTDOWN_WRITE_COMMAND);
140 } 141 }
141 _closedWrite = true; 142 _closedWrite = true;
142 } 143 }
143 144
144 void _closeRead() { 145 void _closeRead() {
145 if (_closedWrite) { 146 if (_closedWrite) {
146 _close(); 147 _close();
147 } else { 148 } else {
148 EventHandler._sendData(_id, _handler, 1 << _SHUTDOWN_READ_COMMAND); 149 _sendToEventHandler(1 << _SHUTDOWN_READ_COMMAND);
149 } 150 }
150 _closedRead = true; 151 _closedRead = true;
151 } 152 }
152 153
153 void _close() { 154 void _close() {
154 EventHandler._sendData(_id, _handler, 1 << _CLOSE_COMMAND); 155 _sendToEventHandler(1 << _CLOSE_COMMAND);
155 _handler.close(); 156 _handler.close();
156 _handler = null; 157 _handler = null;
157 _id = -1; 158 _id = -1;
158 } 159 }
159 160
161 void _sendToEventHandler(int data) {
162 if (_handler === null) {
163 _handler = new ReceivePort();
164 _handler.receive((var message, ignored) { _multiplex(message); });
165 }
166 EventHandler._sendData(_id, _handler, data);
167 }
168
160 abstract bool _isListenSocket(); 169 abstract bool _isListenSocket();
170 abstract bool _isPipe();
161 171
162 /* 172 /*
163 * Socket id is set from native. -1 indicates that the socket was closed. 173 * Socket id is set from native. -1 indicates that the socket was closed.
164 */ 174 */
165 int _id; 175 int _id;
166 176
167 /* 177 /*
168 * Dedicated ReceivePort for socket events. 178 * Dedicated ReceivePort for socket events.
169 */ 179 */
170 ReceivePort _handler; 180 ReceivePort _handler;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 bool _accept(Socket socket) native "ServerSocket_Accept"; 238 bool _accept(Socket socket) native "ServerSocket_Accept";
229 239
230 bool _createBindListen(String bindAddress, int port, int backlog) 240 bool _createBindListen(String bindAddress, int port, int backlog)
231 native "ServerSocket_CreateBindListen"; 241 native "ServerSocket_CreateBindListen";
232 242
233 void set connectionHandler(void callback()) { 243 void set connectionHandler(void callback()) {
234 _setHandler(_IN_EVENT, callback); 244 _setHandler(_IN_EVENT, callback);
235 } 245 }
236 246
237 bool _isListenSocket() => true; 247 bool _isListenSocket() => true;
248 bool _isPipe() => false;
238 } 249 }
239 250
240 251
241 class _Socket extends _SocketBase implements Socket { 252 class _Socket extends _SocketBase implements Socket {
242 /* 253 /*
243 * Constructor for socket. First a socket object is allocated 254 * Constructor for socket. First a socket object is allocated
244 * in which the native socket is stored. After that _createConnect is 255 * in which the native socket is stored. After that _createConnect is
245 * called which creates a file discriptor and connects to the given 256 * called which creates a file discriptor and connects to the given
246 * host on the given port. Null is returned if file descriptor creation 257 * host on the given port. Null is returned if file descriptor creation
247 * or connect failed. 258 * or connect failed.
248 */ 259 */
249 factory _Socket(String host, int port) { 260 factory _Socket(String host, int port) {
250 Socket socket = new _Socket._internal(); 261 Socket socket = new _Socket._internal();
251 if (!socket._createConnect(host, port)) { 262 if (!socket._createConnect(host, port)) {
252 socket.close(); 263 socket.close();
253 return null; 264 return null;
254 } 265 }
255 return socket; 266 return socket;
256 } 267 }
257 268
258 _Socket._internal(); 269 _Socket._internal();
259 _Socket._internalReadOnly() : _closedWrite = true; 270 _Socket._internalReadOnly() : _closedWrite = true, _pipe = true;
260 _Socket._internalWriteOnly() : _closedRead = true; 271 _Socket._internalWriteOnly() : _closedRead = true, _pipe = true;
261 272
262 int available() { 273 int available() {
263 if (_id >= 0) { 274 if (_id >= 0) {
264 return _available(); 275 return _available();
265 } 276 }
266 throw new 277 throw new
267 SocketIOException("Error: available failed - invalid socket handle"); 278 SocketIOException("Error: available failed - invalid socket handle");
268 } 279 }
269 280
270 int _available() native "Socket_Available"; 281 int _available() native "Socket_Available";
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 340
330 void set dataHandler(void callback()) { 341 void set dataHandler(void callback()) {
331 _setHandler(_IN_EVENT, callback); 342 _setHandler(_IN_EVENT, callback);
332 } 343 }
333 344
334 void set closeHandler(void callback()) { 345 void set closeHandler(void callback()) {
335 _setHandler(_CLOSE_EVENT, callback); 346 _setHandler(_CLOSE_EVENT, callback);
336 } 347 }
337 348
338 bool _isListenSocket() => false; 349 bool _isListenSocket() => false;
350 bool _isPipe() => _pipe;
339 351
340 InputStream get inputStream() { 352 InputStream get inputStream() {
341 if (_inputStream === null) { 353 if (_inputStream === null) {
342 _inputStream = new SocketInputStream(this); 354 _inputStream = new SocketInputStream(this);
343 } 355 }
344 return _inputStream; 356 return _inputStream;
345 } 357 }
346 358
347 OutputStream get outputStream() { 359 OutputStream get outputStream() {
348 if (_outputStream === null) { 360 if (_outputStream === null) {
349 _outputStream = new SocketOutputStream(this); 361 _outputStream = new SocketOutputStream(this);
350 } 362 }
351 return _outputStream; 363 return _outputStream;
352 } 364 }
353 365
354 bool _closedRead = false; 366 bool _closedRead = false;
355 bool _closedWrite = false; 367 bool _closedWrite = false;
368 bool _pipe = false;
356 SocketInputStream _inputStream; 369 SocketInputStream _inputStream;
357 SocketOutputStream _outputStream; 370 SocketOutputStream _outputStream;
358 } 371 }
359 372
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698