Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Side by Side Diff: runtime/bin/socket_impl.dart

Issue 9699017: Start better error reporting for sockets (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Added tests Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698