| 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; |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |