Chromium Code Reviews| 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("")); | |
|
Mads Ager (google)
2012/03/14 12:51:51
I suppose next step is to find a way to actually p
Søren Gjesse
2012/03/19 10:05:43
Yes.
| |
| 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 { |
| 263 static final kSuccessResponse = 0; | |
| 264 static final kIllegalArgumentResponse = 1; | |
| 265 static final kOSErrorResponse = 2; | |
| 266 | |
| 258 // Constructor for socket. First a socket object is allocated | 267 // Constructor for socket. First a socket object is allocated |
| 259 // in which the native socket is stored. After that _createConnect is | 268 // in which the native socket is stored. After that _createConnect is |
| 260 // called which creates a file discriptor and connects to the given | 269 // called which creates a file discriptor and connects to the given |
| 261 // host on the given port. Null is returned if file descriptor creation | 270 // host on the given port. Null is returned if file descriptor creation |
|
Mads Ager (google)
2012/03/14 12:51:51
Update description. Maybe in the public API as wel
Søren Gjesse
2012/03/19 10:05:43
Done.
| |
| 262 // or connect failed. | 271 // or connect failed. |
| 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] = 0; |
|
Mads Ager (google)
2012/03/14 12:51:51
Maybe create a kHostLookup constant?
Søren Gjesse
2012/03/19 10:05:43
Done.
| |
| 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 return null; | |
|
Mads Ager (google)
2012/03/14 12:51:51
No need for the null return here.
We should proba
Søren Gjesse
2012/03/19 10:05:43
Good catch. Changed to do an onError callback when
| |
| 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")); | |
|
Mads Ager (google)
2012/03/14 12:51:51
End the default case with a break as well.
Søren Gjesse
2012/03/19 10:05:43
Done.
| |
| 411 } | |
| 412 } else { | |
| 413 onError(new SocketIOException(message)); | |
| 414 } | |
| 374 } | 415 } |
| 375 } | 416 } |
| 376 | 417 |
| 377 bool _createConnect(String host, int port) native "Socket_CreateConnect"; | 418 bool _createConnect(String host, int port) native "Socket_CreateConnect"; |
| 378 | 419 |
| 379 void set onWrite(void callback()) { | 420 void set onWrite(void callback()) { |
| 380 if (_outputStream != null) throw new StreamException( | 421 if (_outputStream != null) throw new StreamException( |
| 381 "Cannot set write handler when output stream is used"); | 422 "Cannot set write handler when output stream is used"); |
| 382 _clientWriteHandler = callback; | 423 _clientWriteHandler = callback; |
| 383 _updateOutHandler(); | 424 _updateOutHandler(); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 397 } | 438 } |
| 398 | 439 |
| 399 void set onData(void callback()) { | 440 void set onData(void callback()) { |
| 400 if (_inputStream != null) throw new StreamException( | 441 if (_inputStream != null) throw new StreamException( |
| 401 "Cannot set data handler when input stream is used"); | 442 "Cannot set data handler when input stream is used"); |
| 402 _onData = callback; | 443 _onData = callback; |
| 403 } | 444 } |
| 404 | 445 |
| 405 void set onClosed(void callback()) { | 446 void set onClosed(void callback()) { |
| 406 if (_inputStream != null) throw new StreamException( | 447 if (_inputStream != null) throw new StreamException( |
| 407 "Cannot set close handler when input stream is used"); | 448 "Cannot set close handler when input stream is used"); |
| 408 _onClosed = callback; | 449 _onClosed = callback; |
| 409 } | 450 } |
| 410 | 451 |
| 411 bool _isListenSocket() => false; | 452 bool _isListenSocket() => false; |
| 412 | 453 |
| 413 bool _isPipe() => _pipe; | 454 bool _isPipe() => _pipe; |
| 414 | 455 |
| 415 InputStream get inputStream() { | 456 InputStream get inputStream() { |
| 416 if (_inputStream === null) { | 457 if (_inputStream === null) { |
| 417 if (_handlerMap[_IN_EVENT] !== null || | 458 if (_handlerMap[_IN_EVENT] !== null || |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 470 _onWrite = null; | 511 _onWrite = null; |
| 471 } else { | 512 } else { |
| 472 if (_seenFirstOutEvent) { | 513 if (_seenFirstOutEvent) { |
| 473 _onWrite = _clientWriteHandler; | 514 _onWrite = _clientWriteHandler; |
| 474 } else { | 515 } else { |
| 475 _onWrite = firstWriteHandler; | 516 _onWrite = firstWriteHandler; |
| 476 } | 517 } |
| 477 } | 518 } |
| 478 } | 519 } |
| 479 | 520 |
| 521 static SendPort _newServicePort() native "Socket_NewServicePort"; | |
| 522 | |
| 523 static void _ensureSocketService() { | |
| 524 if (_socketService == null) { | |
| 525 _socketService = _Socket._newServicePort(); | |
| 526 } | |
| 527 } | |
| 528 | |
| 480 bool _seenFirstOutEvent = false; | 529 bool _seenFirstOutEvent = false; |
| 481 bool _closedRead = false; | 530 bool _closedRead = false; |
| 482 bool _closedWrite = false; | 531 bool _closedWrite = false; |
| 483 bool _pipe = false; | 532 bool _pipe = false; |
| 484 Function _clientConnectHandler; | 533 Function _clientConnectHandler; |
| 485 Function _clientWriteHandler; | 534 Function _clientWriteHandler; |
| 486 SocketInputStream _inputStream; | 535 SocketInputStream _inputStream; |
| 487 SocketOutputStream _outputStream; | 536 SocketOutputStream _outputStream; |
| 537 static SendPort _socketService; | |
| 488 } | 538 } |
| 489 | |
| OLD | NEW |