| OLD | NEW |
| 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 | 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 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 if (eventHandler != null) { | 57 if (eventHandler != null) { |
| 58 // Unregister the out handler before executing it. | 58 // Unregister the out handler before executing it. |
| 59 if (i == _OUT_EVENT) _setHandler(i, null); | 59 if (i == _OUT_EVENT) _setHandler(i, null); |
| 60 | 60 |
| 61 // Don't call the in handler if there is no data available | 61 // Don't call the in handler if there is no data available |
| 62 // after all. | 62 // after all. |
| 63 if ((i == _IN_EVENT) && (this is _Socket) && (available() == 0)) { | 63 if ((i == _IN_EVENT) && (this is _Socket) && (available() == 0)) { |
| 64 continue; | 64 continue; |
| 65 } | 65 } |
| 66 if (i == _ERROR_EVENT) { | 66 if (i == _ERROR_EVENT) { |
| 67 eventHandler(new SocketIOException("")); | 67 eventHandler(new SocketIOException("", _getError())); |
| 68 close(); | 68 close(); |
| 69 } else { | 69 } else { |
| 70 eventHandler(); | 70 eventHandler(); |
| 71 } | 71 } |
| 72 } | 72 } |
| 73 } | 73 } |
| 74 } | 74 } |
| 75 _canActivateHandlers = true; | 75 _canActivateHandlers = true; |
| 76 _activateHandlers(); | 76 _activateHandlers(); |
| 77 } | 77 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 89 _closedRead && | 89 _closedRead && |
| 90 _handlerMask == 0 && | 90 _handlerMask == 0 && |
| 91 _handler != null) { | 91 _handler != null) { |
| 92 _handler.close(); | 92 _handler.close(); |
| 93 _handler = null; | 93 _handler = null; |
| 94 } else { | 94 } else { |
| 95 _activateHandlers(); | 95 _activateHandlers(); |
| 96 } | 96 } |
| 97 } | 97 } |
| 98 | 98 |
| 99 OSError _getError() native "Socket_GetError"; |
| 99 int _getPort() native "Socket_GetPort"; | 100 int _getPort() native "Socket_GetPort"; |
| 100 | 101 |
| 101 void set onError(void callback(Exception e)) { | 102 void set onError(void callback(Exception e)) { |
| 102 _setHandler(_ERROR_EVENT, callback); | 103 _setHandler(_ERROR_EVENT, callback); |
| 103 } | 104 } |
| 104 | 105 |
| 105 void _activateHandlers() { | 106 void _activateHandlers() { |
| 106 if (_canActivateHandlers && (_id >= 0)) { | 107 if (_canActivateHandlers && (_id >= 0)) { |
| 107 if (_handlerMask == 0) { | 108 if (_handlerMask == 0) { |
| 108 if (_handler != null) { | 109 if (_handler != null) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 | 179 |
| 179 void _sendToEventHandler(int data) { | 180 void _sendToEventHandler(int data) { |
| 180 if (_handler === null) { | 181 if (_handler === null) { |
| 181 _handler = new ReceivePort(); | 182 _handler = new ReceivePort(); |
| 182 _handler.receive((var message, ignored) { _multiplex(message); }); | 183 _handler.receive((var message, ignored) { _multiplex(message); }); |
| 183 } | 184 } |
| 184 assert(_id >= 0); | 185 assert(_id >= 0); |
| 185 _EventHandler._sendData(_id, _handler, data); | 186 _EventHandler._sendData(_id, _handler, data); |
| 186 } | 187 } |
| 187 | 188 |
| 189 bool _reportError(error, String message) { |
| 190 // For all errors we close the socket, call the error handler and |
| 191 // disable further calls of the error handler. |
| 192 close(); |
| 193 var onError = _handlerMap[_ERROR_EVENT]; |
| 194 if (onError != null) { |
| 195 if (error is OSError) { |
| 196 onError(new SocketIOException(message, error)); |
| 197 } else if (error is List) { |
| 198 assert(_isErrorResponse(error)); |
| 199 switch (error[0]) { |
| 200 case _FileUtils.kIllegalArgumentResponse: |
| 201 onError(new IllegalArgumentException()); |
| 202 break; |
| 203 case _FileUtils.kOSErrorResponse: |
| 204 onError(new SocketIOException( |
| 205 message, new OSError(error[2], error[1]))); |
| 206 break; |
| 207 default: |
| 208 onError(new Exception("Unknown error")); |
| 209 break; |
| 210 } |
| 211 } else { |
| 212 onError(new SocketIOException(message)); |
| 213 } |
| 214 } |
| 215 } |
| 216 |
| 188 int hashCode() => _hashCode; | 217 int hashCode() => _hashCode; |
| 189 | 218 |
| 190 abstract bool _isListenSocket(); | 219 abstract bool _isListenSocket(); |
| 191 abstract bool _isPipe(); | 220 abstract bool _isPipe(); |
| 192 | 221 |
| 193 // Socket id is set from native. -1 indicates that the socket was closed. | 222 // Socket id is set from native. -1 indicates that the socket was closed. |
| 194 int _id; | 223 int _id; |
| 195 | 224 |
| 196 // Dedicated ReceivePort for socket events. | 225 // Dedicated ReceivePort for socket events. |
| 197 ReceivePort _handler; | 226 ReceivePort _handler; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 217 | 246 |
| 218 | 247 |
| 219 class _ServerSocket extends _SocketBase implements ServerSocket { | 248 class _ServerSocket extends _SocketBase implements ServerSocket { |
| 220 // Constructor for server socket. First a socket object is allocated | 249 // Constructor for server socket. First a socket object is allocated |
| 221 // in which the native socket is stored. After that _createBind | 250 // in which the native socket is stored. After that _createBind |
| 222 // is called which creates a file descriptor and binds the given address | 251 // is called which creates a file descriptor and binds the given address |
| 223 // and port to the socket. Null is returned if file descriptor creation or | 252 // and port to the socket. Null is returned if file descriptor creation or |
| 224 // bind failed. | 253 // bind failed. |
| 225 factory _ServerSocket(String bindAddress, int port, int backlog) { | 254 factory _ServerSocket(String bindAddress, int port, int backlog) { |
| 226 _ServerSocket socket = new _ServerSocket._internal(); | 255 _ServerSocket socket = new _ServerSocket._internal(); |
| 227 if (!socket._createBindListen(bindAddress, port, backlog)) { | 256 var result = socket._createBindListen(bindAddress, port, backlog); |
| 257 if (result is OSError) { |
| 228 socket.close(); | 258 socket.close(); |
| 229 return null; | 259 throw new SocketIOException("Failed to create server socket", result); |
| 230 } | 260 } |
| 261 assert(result); |
| 231 if (port != 0) { | 262 if (port != 0) { |
| 232 socket._port = port; | 263 socket._port = port; |
| 233 } | 264 } |
| 234 return socket; | 265 return socket; |
| 235 } | 266 } |
| 236 | 267 |
| 237 _ServerSocket._internal(); | 268 _ServerSocket._internal(); |
| 238 | 269 |
| 239 bool _accept(Socket socket) native "ServerSocket_Accept"; | 270 bool _accept(Socket socket) native "ServerSocket_Accept"; |
| 240 | 271 |
| 241 bool _createBindListen(String bindAddress, int port, int backlog) | 272 bool _createBindListen(String bindAddress, int port, int backlog) |
| 242 native "ServerSocket_CreateBindListen"; | 273 native "ServerSocket_CreateBindListen"; |
| 243 | 274 |
| 244 void set onConnection(void callback(Socket connection)) { | 275 void set onConnection(void callback(Socket connection)) { |
| 245 _clientConnectionHandler = callback; | 276 _clientConnectionHandler = callback; |
| 246 _setHandler(_IN_EVENT, | 277 _setHandler(_IN_EVENT, |
| 247 _clientConnectionHandler != null ? _connectionHandler : null); | 278 _clientConnectionHandler != null ? _connectionHandler : null); |
| 248 } | 279 } |
| 249 | 280 |
| 250 void _connectionHandler() { | 281 void _connectionHandler() { |
| 251 if (_id >= 0) { | 282 if (_id >= 0) { |
| 252 _Socket socket = new _Socket._internal(); | 283 _Socket socket = new _Socket._internal(); |
| 253 if (_accept(socket)) _clientConnectionHandler(socket); | 284 var result = _accept(socket); |
| 285 if (result is OSError) { |
| 286 _reportError(result, "Accept failed"); |
| 287 } else { |
| 288 _clientConnectionHandler(socket); |
| 289 } |
| 254 } | 290 } |
| 255 } | 291 } |
| 256 | 292 |
| 257 bool _isListenSocket() => true; | 293 bool _isListenSocket() => true; |
| 258 bool _isPipe() => false; | 294 bool _isPipe() => false; |
| 259 | 295 |
| 260 var _clientConnectionHandler; | 296 var _clientConnectionHandler; |
| 261 } | 297 } |
| 262 | 298 |
| 263 | 299 |
| 264 class _Socket extends _SocketBase implements Socket { | 300 class _Socket extends _SocketBase implements Socket { |
| 265 static final kSuccessResponse = 0; | 301 static final kSuccessResponse = 0; |
| 266 static final kIllegalArgumentResponse = 1; | 302 static final kIllegalArgumentResponse = 1; |
| 267 static final kOSErrorResponse = 2; | 303 static final kOSErrorResponse = 2; |
| 268 | 304 |
| 269 static final kHostNameLookup = 0; | 305 static final kHostNameLookup = 0; |
| 270 | 306 |
| 271 // Constructs a new socket. During the construction an asynchronous | 307 // Constructs a new socket. During the construction an asynchronous |
| 272 // host name lookup is initiated. The returned socket is not yet | 308 // host name lookup is initiated. The returned socket is not yet |
| 273 // connected but ready for registration of callbacks. | 309 // connected but ready for registration of callbacks. |
| 274 factory _Socket(String host, int port) { | 310 factory _Socket(String host, int port) { |
| 275 Socket socket = new _Socket._internal(); | 311 Socket socket = new _Socket._internal(); |
| 276 _ensureSocketService(); | 312 _ensureSocketService(); |
| 277 List request = new List(2); | 313 List request = new List(2); |
| 278 request[0] = kHostNameLookup; | 314 request[0] = kHostNameLookup; |
| 279 request[1] = host; | 315 request[1] = host; |
| 280 _socketService.call(request).then((response) { | 316 _socketService.call(request).then((response) { |
| 281 if (socket._isErrorResponse(response)) { | 317 if (socket._isErrorResponse(response)) { |
| 282 socket._reportError(response, "Failed host name lookup"); | 318 socket._reportError(response, "Failed host name lookup"); |
| 283 } else { | 319 } else{ |
| 284 if (!socket._createConnect(response, port)) { | 320 var result = socket._createConnect(response, port); |
| 321 if (result is OSError) { |
| 285 socket.close(); | 322 socket.close(); |
| 286 socket._reportError(null, "Connection failed"); | 323 socket._reportError(result, "Connection failed"); |
| 287 } else { | 324 } else { |
| 288 socket._activateHandlers(); | 325 socket._activateHandlers(); |
| 289 } | 326 } |
| 290 } | 327 } |
| 291 }); | 328 }); |
| 292 return socket; | 329 return socket; |
| 293 } | 330 } |
| 294 | 331 |
| 295 _Socket._internal(); | 332 _Socket._internal(); |
| 296 _Socket._internalReadOnly() : _pipe = true { super._closedWrite = true; } | 333 _Socket._internalReadOnly() : _pipe = true { super._closedWrite = true; } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 314 if (offset < 0) { | 351 if (offset < 0) { |
| 315 throw new IndexOutOfRangeException(offset); | 352 throw new IndexOutOfRangeException(offset); |
| 316 } | 353 } |
| 317 if (bytes < 0) { | 354 if (bytes < 0) { |
| 318 throw new IndexOutOfRangeException(bytes); | 355 throw new IndexOutOfRangeException(bytes); |
| 319 } | 356 } |
| 320 if ((offset + bytes) > buffer.length) { | 357 if ((offset + bytes) > buffer.length) { |
| 321 throw new IndexOutOfRangeException(offset + bytes); | 358 throw new IndexOutOfRangeException(offset + bytes); |
| 322 } | 359 } |
| 323 int result = _readList(buffer, offset, bytes); | 360 int result = _readList(buffer, offset, bytes); |
| 324 if (result < 0) { | 361 if (result is OSError) { |
| 325 _reportError(null, "Read failed"); | 362 _reportError(result, "Read failed"); |
| 363 return -1; |
| 326 } | 364 } |
| 327 return result; | 365 return result; |
| 328 } | 366 } |
| 329 throw new | 367 throw new |
| 330 SocketIOException("Error: readList failed - invalid socket handle"); | 368 SocketIOException("Error: readList failed - invalid socket handle"); |
| 331 } | 369 } |
| 332 | 370 |
| 333 int _readList(List<int> buffer, int offset, int bytes) | 371 int _readList(List<int> buffer, int offset, int bytes) |
| 334 native "Socket_ReadList"; | 372 native "Socket_ReadList"; |
| 335 | 373 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 361 for (int i = 0; i < bytes; i++) { | 399 for (int i = 0; i < bytes; i++) { |
| 362 int value = buffer[j]; | 400 int value = buffer[j]; |
| 363 if (value is! int) { | 401 if (value is! int) { |
| 364 throw new FileIOException( | 402 throw new FileIOException( |
| 365 "List element is not an integer at index $j"); | 403 "List element is not an integer at index $j"); |
| 366 } | 404 } |
| 367 outBuffer[i] = value; | 405 outBuffer[i] = value; |
| 368 j++; | 406 j++; |
| 369 } | 407 } |
| 370 } | 408 } |
| 371 var bytes_written = _writeList(outBuffer, outOffset, bytes); | 409 var result = _writeList(outBuffer, outOffset, bytes); |
| 372 if (bytes_written < 0) { | 410 if (result is OSError) { |
| 373 // If writing fails we return 0 as the number of bytes and | 411 // If writing fails we return 0 as the number of bytes and |
| 374 // report the error on the error handler. | 412 // report the error on the error handler. |
| 375 bytes_written = 0; | 413 result = 0; |
| 376 _reportError(null, "Write failed"); | 414 _reportError(result, "Write failed"); |
| 377 } | 415 } |
| 378 return bytes_written; | 416 return result; |
| 379 } | 417 } |
| 380 throw new | 418 throw new SocketIOException("writeList failed - invalid socket handle"); |
| 381 SocketIOException("Error: writeList failed - invalid socket handle"); | |
| 382 } | 419 } |
| 383 | 420 |
| 384 int _writeList(List<int> buffer, int offset, int bytes) | 421 int _writeList(List<int> buffer, int offset, int bytes) |
| 385 native "Socket_WriteList"; | 422 native "Socket_WriteList"; |
| 386 | 423 |
| 387 bool _isErrorResponse(response) { | 424 bool _isErrorResponse(response) { |
| 388 return response is List && response[0] != _FileUtils.kSuccessResponse; | 425 return response is List && response[0] != _FileUtils.kSuccessResponse; |
| 389 } | 426 } |
| 390 | 427 |
| 391 bool _reportError(response, String message) { | |
| 392 if (response != null) { | |
| 393 assert(_isErrorResponse(response)); | |
| 394 } | |
| 395 // For all errors we close the socket, call the error handler and | |
| 396 // disable further calls of the error handler. | |
| 397 close(); | |
| 398 var onError = _handlerMap[_ERROR_EVENT]; | |
| 399 if (onError != null) { | |
| 400 if (response != null) { | |
| 401 switch (response[0]) { | |
| 402 case _FileUtils.kIllegalArgumentResponse: | |
| 403 onError(new IllegalArgumentException()); | |
| 404 break; | |
| 405 case _FileUtils.kOSErrorResponse: | |
| 406 onError(new SocketIOException( | |
| 407 message, new OSError(response[2], response[1]))); | |
| 408 break; | |
| 409 default: | |
| 410 onError(new Exception("Unknown error")); | |
| 411 break; | |
| 412 } | |
| 413 } else { | |
| 414 onError(new SocketIOException(message)); | |
| 415 } | |
| 416 } | |
| 417 } | |
| 418 | |
| 419 bool _createConnect(String host, int port) native "Socket_CreateConnect"; | 428 bool _createConnect(String host, int port) native "Socket_CreateConnect"; |
| 420 | 429 |
| 421 void set onWrite(void callback()) { | 430 void set onWrite(void callback()) { |
| 422 if (_outputStream != null) throw new StreamException( | 431 if (_outputStream != null) throw new StreamException( |
| 423 "Cannot set write handler when output stream is used"); | 432 "Cannot set write handler when output stream is used"); |
| 424 _clientWriteHandler = callback; | 433 _clientWriteHandler = callback; |
| 425 _updateOutHandler(); | 434 _updateOutHandler(); |
| 426 } | 435 } |
| 427 | 436 |
| 428 void set onConnect(void callback()) { | 437 void set onConnect(void callback()) { |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 } | 537 } |
| 529 | 538 |
| 530 bool _seenFirstOutEvent = false; | 539 bool _seenFirstOutEvent = false; |
| 531 bool _pipe = false; | 540 bool _pipe = false; |
| 532 Function _clientConnectHandler; | 541 Function _clientConnectHandler; |
| 533 Function _clientWriteHandler; | 542 Function _clientWriteHandler; |
| 534 SocketInputStream _inputStream; | 543 SocketInputStream _inputStream; |
| 535 SocketOutputStream _outputStream; | 544 SocketOutputStream _outputStream; |
| 536 static SendPort _socketService; | 545 static SendPort _socketService; |
| 537 } | 546 } |
| OLD | NEW |