Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |