| 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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 var eventHandler = _handlerMap[i]; | 56 var eventHandler = _handlerMap[i]; |
| 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 eventHandler(); | 66 if (i == _ERROR_EVENT) { |
| 67 eventHandler(new SocketIOException("")); |
| 68 close(); |
| 69 } else { |
| 70 eventHandler(); |
| 71 } |
| 67 } | 72 } |
| 68 } | 73 } |
| 69 } | 74 } |
| 70 _canActivateHandlers = true; | 75 _canActivateHandlers = true; |
| 71 _activateHandlers(); | 76 _activateHandlers(); |
| 72 } | 77 } |
| 73 | 78 |
| 74 void _setHandler(int event, void callback()) { | 79 void _setHandler(int event, Function callback) { |
| 75 if (callback == null) { | 80 if (callback == null) { |
| 76 _handlerMask &= ~(1 << event); | 81 _handlerMask &= ~(1 << event); |
| 77 } else { | 82 } else { |
| 78 _handlerMask |= (1 << event); | 83 _handlerMask |= (1 << event); |
| 79 } | 84 } |
| 80 _handlerMap[event] = callback; | 85 _handlerMap[event] = callback; |
| 81 // If the socket is only for writing then close the receive port | 86 // If the socket is only for writing then close the receive port |
| 82 // when not waiting for any events. | 87 // when not waiting for any events. |
| 83 if (this is _Socket && | 88 if (this is _Socket && |
| 84 _closedRead && | 89 _closedRead && |
| 85 _handlerMask == 0 && | 90 _handlerMask == 0 && |
| 86 _handler != null) { | 91 _handler != null) { |
| 87 _handler.close(); | 92 _handler.close(); |
| 88 _handler = null; | 93 _handler = null; |
| 89 } else { | 94 } else { |
| 90 _activateHandlers(); | 95 _activateHandlers(); |
| 91 } | 96 } |
| 92 } | 97 } |
| 93 | 98 |
| 94 void _getPort() native "Socket_GetPort"; | 99 void _getPort() native "Socket_GetPort"; |
| 95 | 100 |
| 96 void set onError(void callback()) { | 101 void set onError(void callback(Exception e)) { |
| 97 _setHandler(_ERROR_EVENT, callback); | 102 _setHandler(_ERROR_EVENT, callback); |
| 98 } | 103 } |
| 99 | 104 |
| 100 void _activateHandlers() { | 105 void _activateHandlers() { |
| 101 if (_canActivateHandlers && (_id >= 0)) { | 106 if (_canActivateHandlers && (_id >= 0)) { |
| 102 if (_handlerMask == 0) { | 107 if (_handlerMask == 0) { |
| 103 if (_handler != null) { | 108 if (_handler != null) { |
| 104 _handler.close(); | 109 _handler.close(); |
| 105 _handler = null; | 110 _handler = null; |
| 106 } | 111 } |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 } | 253 } |
| 249 | 254 |
| 250 bool _isListenSocket() => true; | 255 bool _isListenSocket() => true; |
| 251 bool _isPipe() => false; | 256 bool _isPipe() => false; |
| 252 | 257 |
| 253 var _clientConnectionHandler; | 258 var _clientConnectionHandler; |
| 254 } | 259 } |
| 255 | 260 |
| 256 | 261 |
| 257 class _Socket extends _SocketBase implements Socket { | 262 class _Socket extends _SocketBase implements Socket { |
| 258 // Constructor for socket. First a socket object is allocated | 263 static final kSuccessResponse = 0; |
| 259 // in which the native socket is stored. After that _createConnect is | 264 static final kIllegalArgumentResponse = 1; |
| 260 // called which creates a file discriptor and connects to the given | 265 static final kOSErrorResponse = 2; |
| 261 // host on the given port. Null is returned if file descriptor creation | 266 |
| 262 // or connect failed. | 267 static final kHostNameLookup = 0; |
| 268 |
| 269 // Constructs a new socket. During the construction an asynchronous |
| 270 // host name lookup is initiated. The returned socket is not yet |
| 271 // connected but ready for registration of callbacks. |
| 263 factory _Socket(String host, int port) { | 272 factory _Socket(String host, int port) { |
| 264 Socket socket = new _Socket._internal(); | 273 Socket socket = new _Socket._internal(); |
| 265 if (!socket._createConnect(host, port)) { | 274 _ensureSocketService(); |
| 266 socket.close(); | 275 List request = new List(2); |
| 267 return null; | 276 request[0] = kHostNameLookup; |
| 268 } | 277 request[1] = host; |
| 278 _socketService.call(request).then((response) { |
| 279 if (socket._isErrorResponse(response)) { |
| 280 socket._reportError(response, "Failed host name lookup"); |
| 281 } else { |
| 282 if (!socket._createConnect(response, port)) { |
| 283 socket.close(); |
| 284 socket._reportError(null, "Connection failed"); |
| 285 } else { |
| 286 socket._activateHandlers(); |
| 287 } |
| 288 } |
| 289 }); |
| 269 return socket; | 290 return socket; |
| 270 } | 291 } |
| 271 | 292 |
| 272 _Socket._internal(); | 293 _Socket._internal(); |
| 273 _Socket._internalReadOnly() : _closedWrite = true, _pipe = true; | 294 _Socket._internalReadOnly() : _closedWrite = true, _pipe = true; |
| 274 _Socket._internalWriteOnly() : _closedRead = true, _pipe = true; | 295 _Socket._internalWriteOnly() : _closedRead = true, _pipe = true; |
| 275 | 296 |
| 276 int available() { | 297 int available() { |
| 277 if (_id >= 0) { | 298 if (_id >= 0) { |
| 278 return _available(); | 299 return _available(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 294 throw new IndexOutOfRangeException(offset); | 315 throw new IndexOutOfRangeException(offset); |
| 295 } | 316 } |
| 296 if (bytes < 0) { | 317 if (bytes < 0) { |
| 297 throw new IndexOutOfRangeException(bytes); | 318 throw new IndexOutOfRangeException(bytes); |
| 298 } | 319 } |
| 299 if ((offset + bytes) > buffer.length) { | 320 if ((offset + bytes) > buffer.length) { |
| 300 throw new IndexOutOfRangeException(offset + bytes); | 321 throw new IndexOutOfRangeException(offset + bytes); |
| 301 } | 322 } |
| 302 int result = _readList(buffer, offset, bytes); | 323 int result = _readList(buffer, offset, bytes); |
| 303 if (result < 0) { | 324 if (result < 0) { |
| 304 _reportError(); | 325 _reportError(null, "Read failed"); |
| 305 } | 326 } |
| 306 return result; | 327 return result; |
| 307 } | 328 } |
| 308 throw new | 329 throw new |
| 309 SocketIOException("Error: readList failed - invalid socket handle"); | 330 SocketIOException("Error: readList failed - invalid socket handle"); |
| 310 } | 331 } |
| 311 | 332 |
| 312 int _readList(List<int> buffer, int offset, int bytes) | 333 int _readList(List<int> buffer, int offset, int bytes) |
| 313 native "Socket_ReadList"; | 334 native "Socket_ReadList"; |
| 314 | 335 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 345 } | 366 } |
| 346 outBuffer[i] = value; | 367 outBuffer[i] = value; |
| 347 j++; | 368 j++; |
| 348 } | 369 } |
| 349 } | 370 } |
| 350 var bytes_written = _writeList(outBuffer, outOffset, bytes); | 371 var bytes_written = _writeList(outBuffer, outOffset, bytes); |
| 351 if (bytes_written < 0) { | 372 if (bytes_written < 0) { |
| 352 // If writing fails we return 0 as the number of bytes and | 373 // If writing fails we return 0 as the number of bytes and |
| 353 // report the error on the error handler. | 374 // report the error on the error handler. |
| 354 bytes_written = 0; | 375 bytes_written = 0; |
| 355 _reportError(); | 376 _reportError(null, "Write failed"); |
| 356 } | 377 } |
| 357 return bytes_written; | 378 return bytes_written; |
| 358 } | 379 } |
| 359 throw new | 380 throw new |
| 360 SocketIOException("Error: writeList failed - invalid socket handle"); | 381 SocketIOException("Error: writeList failed - invalid socket handle"); |
| 361 } | 382 } |
| 362 | 383 |
| 363 int _writeList(List<int> buffer, int offset, int bytes) | 384 int _writeList(List<int> buffer, int offset, int bytes) |
| 364 native "Socket_WriteList"; | 385 native "Socket_WriteList"; |
| 365 | 386 |
| 366 void _reportError() { | 387 bool _isErrorResponse(response) { |
| 388 return response is List && response[0] != _FileUtils.kSuccessResponse; |
| 389 } |
| 390 |
| 391 bool _reportError(response, String message) { |
| 392 if (response != null) { |
| 393 assert(_isErrorResponse(response)); |
| 394 } |
| 367 // For all errors we close the socket, call the error handler and | 395 // For all errors we close the socket, call the error handler and |
| 368 // disable further calls of the error handler. | 396 // disable further calls of the error handler. |
| 369 close(); | 397 close(); |
| 370 var onError = _handlerMap[_ERROR_EVENT]; | 398 var onError = _handlerMap[_ERROR_EVENT]; |
| 371 if (onError != null) { | 399 if (onError != null) { |
| 372 onError(); | 400 if (response != null) { |
| 373 _setHandler(_ERROR_EVENT, 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 } |
| 374 } | 416 } |
| 375 } | 417 } |
| 376 | 418 |
| 377 bool _createConnect(String host, int port) native "Socket_CreateConnect"; | 419 bool _createConnect(String host, int port) native "Socket_CreateConnect"; |
| 378 | 420 |
| 379 void set onWrite(void callback()) { | 421 void set onWrite(void callback()) { |
| 380 if (_outputStream != null) throw new StreamException( | 422 if (_outputStream != null) throw new StreamException( |
| 381 "Cannot set write handler when output stream is used"); | 423 "Cannot set write handler when output stream is used"); |
| 382 _clientWriteHandler = callback; | 424 _clientWriteHandler = callback; |
| 383 _updateOutHandler(); | 425 _updateOutHandler(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 397 } | 439 } |
| 398 | 440 |
| 399 void set onData(void callback()) { | 441 void set onData(void callback()) { |
| 400 if (_inputStream != null) throw new StreamException( | 442 if (_inputStream != null) throw new StreamException( |
| 401 "Cannot set data handler when input stream is used"); | 443 "Cannot set data handler when input stream is used"); |
| 402 _onData = callback; | 444 _onData = callback; |
| 403 } | 445 } |
| 404 | 446 |
| 405 void set onClosed(void callback()) { | 447 void set onClosed(void callback()) { |
| 406 if (_inputStream != null) throw new StreamException( | 448 if (_inputStream != null) throw new StreamException( |
| 407 "Cannot set close handler when input stream is used"); | 449 "Cannot set close handler when input stream is used"); |
| 408 _onClosed = callback; | 450 _onClosed = callback; |
| 409 } | 451 } |
| 410 | 452 |
| 411 bool _isListenSocket() => false; | 453 bool _isListenSocket() => false; |
| 412 | 454 |
| 413 bool _isPipe() => _pipe; | 455 bool _isPipe() => _pipe; |
| 414 | 456 |
| 415 InputStream get inputStream() { | 457 InputStream get inputStream() { |
| 416 if (_inputStream === null) { | 458 if (_inputStream === null) { |
| 417 if (_handlerMap[_IN_EVENT] !== null || | 459 if (_handlerMap[_IN_EVENT] !== null || |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 470 _onWrite = null; | 512 _onWrite = null; |
| 471 } else { | 513 } else { |
| 472 if (_seenFirstOutEvent) { | 514 if (_seenFirstOutEvent) { |
| 473 _onWrite = _clientWriteHandler; | 515 _onWrite = _clientWriteHandler; |
| 474 } else { | 516 } else { |
| 475 _onWrite = firstWriteHandler; | 517 _onWrite = firstWriteHandler; |
| 476 } | 518 } |
| 477 } | 519 } |
| 478 } | 520 } |
| 479 | 521 |
| 522 static SendPort _newServicePort() native "Socket_NewServicePort"; |
| 523 |
| 524 static void _ensureSocketService() { |
| 525 if (_socketService == null) { |
| 526 _socketService = _Socket._newServicePort(); |
| 527 } |
| 528 } |
| 529 |
| 480 bool _seenFirstOutEvent = false; | 530 bool _seenFirstOutEvent = false; |
| 481 bool _closedRead = false; | 531 bool _closedRead = false; |
| 482 bool _closedWrite = false; | 532 bool _closedWrite = false; |
| 483 bool _pipe = false; | 533 bool _pipe = false; |
| 484 Function _clientConnectHandler; | 534 Function _clientConnectHandler; |
| 485 Function _clientWriteHandler; | 535 Function _clientWriteHandler; |
| 486 SocketInputStream _inputStream; | 536 SocketInputStream _inputStream; |
| 487 SocketOutputStream _outputStream; | 537 SocketOutputStream _outputStream; |
| 538 static SendPort _socketService; |
| 488 } | 539 } |
| 489 | |
| OLD | NEW |