OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 patch class RawServerSocket { | 5 patch class RawServerSocket { |
6 /* patch */ static Future<RawServerSocket> bind(address, | 6 /* patch */ static Future<RawServerSocket> bind(address, |
7 int port, | 7 int port, |
8 {int backlog: 0, | 8 {int backlog: 0, |
9 bool v6Only: false}) { | 9 bool v6Only: false}) { |
10 return _RawServerSocket.bind(address, port, backlog, v6Only); | 10 return _RawServerSocket.bind(address, port, backlog, v6Only); |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 static const int PROTOCOL_IPV6 = 1 << 1; | 249 static const int PROTOCOL_IPV6 = 1 << 1; |
250 | 250 |
251 // Socket close state | 251 // Socket close state |
252 bool isClosed = false; | 252 bool isClosed = false; |
253 bool isClosing = false; | 253 bool isClosing = false; |
254 bool isClosedRead = false; | 254 bool isClosedRead = false; |
255 bool isClosedWrite = false; | 255 bool isClosedWrite = false; |
256 Completer closeCompleter = new Completer.sync(); | 256 Completer closeCompleter = new Completer.sync(); |
257 | 257 |
258 // Handlers and receive port for socket events from the event handler. | 258 // Handlers and receive port for socket events from the event handler. |
259 int eventMask = 0; | 259 final List eventHandlers = new List(EVENT_COUNT + 1); |
260 List eventHandlers; | |
261 RawReceivePort eventPort; | 260 RawReceivePort eventPort; |
262 | 261 |
263 // Indicates if native interrupts can be activated. | |
264 bool canActivateEvents = true; | |
265 | |
266 // The type flags for this socket. | 262 // The type flags for this socket. |
267 final int typeFlags; | 263 final int typeFlags; |
268 | 264 |
269 // Holds the port of the socket, 0 if not known. | 265 // Holds the port of the socket, 0 if not known. |
270 int localPort = 0; | 266 int localPort = 0; |
271 | 267 |
272 // Holds the address used to connect or bind the socket. | 268 // Holds the address used to connect or bind the socket. |
273 InternetAddress address; | 269 InternetAddress address; |
274 | 270 |
| 271 int available = 0; |
| 272 |
| 273 bool sendReadEvents = false; |
| 274 bool readEventIssued = false; |
| 275 |
| 276 bool sendWriteEvents = false; |
| 277 bool writeEventIssued = false; |
| 278 bool writeAvailable = false; |
| 279 |
275 static Future<List<InternetAddress>> lookup( | 280 static Future<List<InternetAddress>> lookup( |
276 String host, {InternetAddressType type: InternetAddressType.ANY}) { | 281 String host, {InternetAddressType type: InternetAddressType.ANY}) { |
277 return _IOService.dispatch(_SOCKET_LOOKUP, [host, type._value]) | 282 return _IOService.dispatch(_SOCKET_LOOKUP, [host, type._value]) |
278 .then((response) { | 283 .then((response) { |
279 if (isErrorResponse(response)) { | 284 if (isErrorResponse(response)) { |
280 throw createError(response, "Failed host lookup: '$host'"); | 285 throw createError(response, "Failed host lookup: '$host'"); |
281 } else { | 286 } else { |
282 return response.skip(1).map((result) { | 287 return response.skip(1).map((result) { |
283 var type = new InternetAddressType._from(result[0]); | 288 var type = new InternetAddressType._from(result[0]); |
284 return new _InternetAddress(result[1], host, result[2]); | 289 return new _InternetAddress(result[1], host, result[2]); |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 throw new SocketException("Failed to create datagram socket", | 424 throw new SocketException("Failed to create datagram socket", |
420 osError: result, | 425 osError: result, |
421 address: address, | 426 address: address, |
422 port: port); | 427 port: port); |
423 } | 428 } |
424 if (port != 0) socket.localPort = port; | 429 if (port != 0) socket.localPort = port; |
425 return socket; | 430 return socket; |
426 }); | 431 }); |
427 } | 432 } |
428 | 433 |
429 _NativeSocket.datagram(this.address) | 434 _NativeSocket.datagram(this.address) : typeFlags = TYPE_NORMAL_SOCKET; |
430 : typeFlags = TYPE_NORMAL_SOCKET { | |
431 eventHandlers = new List(EVENT_COUNT + 1); | |
432 } | |
433 | 435 |
434 _NativeSocket.normal() : typeFlags = TYPE_NORMAL_SOCKET { | 436 _NativeSocket.normal() : typeFlags = TYPE_NORMAL_SOCKET; |
435 eventHandlers = new List(EVENT_COUNT + 1); | |
436 } | |
437 | 437 |
438 _NativeSocket.listen() : typeFlags = TYPE_LISTENING_SOCKET { | 438 _NativeSocket.listen() : typeFlags = TYPE_LISTENING_SOCKET; |
439 eventHandlers = new List(EVENT_COUNT + 1); | |
440 } | |
441 | 439 |
442 _NativeSocket.pipe() : typeFlags = TYPE_PIPE { | 440 _NativeSocket.pipe() : typeFlags = TYPE_PIPE; |
443 eventHandlers = new List(EVENT_COUNT + 1); | |
444 } | |
445 | 441 |
446 _NativeSocket.watch(int id) : typeFlags = TYPE_NORMAL_SOCKET { | 442 _NativeSocket.watch(int id) : typeFlags = TYPE_NORMAL_SOCKET { |
447 eventHandlers = new List(EVENT_COUNT + 1); | |
448 isClosedWrite = true; | 443 isClosedWrite = true; |
449 nativeSetSocketId(id); | 444 nativeSetSocketId(id); |
450 } | 445 } |
451 | 446 |
452 int available() { | |
453 if (isClosing || isClosed) return 0; | |
454 var result = nativeAvailable(); | |
455 if (result is OSError) { | |
456 reportError(result, "Available failed"); | |
457 return 0; | |
458 } else { | |
459 return result; | |
460 } | |
461 } | |
462 | |
463 List<int> read(int len) { | 447 List<int> read(int len) { |
464 if (len != null && len <= 0) { | 448 if (len != null && len <= 0) { |
465 throw new ArgumentError("Illegal length $len"); | 449 throw new ArgumentError("Illegal length $len"); |
466 } | 450 } |
467 if (isClosing || isClosed) return null; | 451 if (isClosing || isClosed) return null; |
468 var result = nativeRead(len == null ? -1 : len); | 452 var result = nativeRead(min(available, len == null ? available : len)); |
469 if (result is OSError) { | 453 if (result is OSError) { |
470 reportError(result, "Read failed"); | 454 reportError(result, "Read failed"); |
471 return null; | 455 return null; |
472 } | 456 } |
| 457 if (result != null) available -= result.length; |
473 return result; | 458 return result; |
474 } | 459 } |
475 | 460 |
476 Datagram receive() { | 461 Datagram receive() { |
477 if (isClosing || isClosed) return null; | 462 if (isClosing || isClosed) return null; |
478 var result = nativeRecvFrom(); | 463 var result = nativeRecvFrom(); |
479 if (result is OSError) { | 464 if (result is OSError) { |
480 reportError(result, "Receive failed"); | 465 reportError(result, "Receive failed"); |
481 return null; | 466 return null; |
482 } | 467 } |
| 468 if (result != null) { |
| 469 if (Platform.isMacOS) { |
| 470 // Mac includes the header size, so we need to query the actual |
| 471 // available. |
| 472 available = nativeAvailable(); |
| 473 } else { |
| 474 available -= result.data.length; |
| 475 } |
| 476 } |
483 return result; | 477 return result; |
484 } | 478 } |
485 | 479 |
486 int write(List<int> buffer, int offset, int bytes) { | 480 int write(List<int> buffer, int offset, int bytes) { |
487 if (buffer is! List) throw new ArgumentError(); | 481 if (buffer is! List) throw new ArgumentError(); |
488 if (offset == null) offset = 0; | 482 if (offset == null) offset = 0; |
489 if (bytes == null) { | 483 if (bytes == null) { |
490 if (offset > buffer.length) { | 484 if (offset > buffer.length) { |
491 throw new RangeError.value(offset); | 485 throw new RangeError.value(offset); |
492 } | 486 } |
(...skipping 10 matching lines...) Expand all Loading... |
503 if (isClosing || isClosed) return 0; | 497 if (isClosing || isClosed) return 0; |
504 if (bytes == 0) return 0; | 498 if (bytes == 0) return 0; |
505 _BufferAndStart bufferAndStart = | 499 _BufferAndStart bufferAndStart = |
506 _ensureFastAndSerializableByteData(buffer, offset, offset + bytes); | 500 _ensureFastAndSerializableByteData(buffer, offset, offset + bytes); |
507 var result = | 501 var result = |
508 nativeWrite(bufferAndStart.buffer, bufferAndStart.start, bytes); | 502 nativeWrite(bufferAndStart.buffer, bufferAndStart.start, bytes); |
509 if (result is OSError) { | 503 if (result is OSError) { |
510 scheduleMicrotask(() => reportError(result, "Write failed")); | 504 scheduleMicrotask(() => reportError(result, "Write failed")); |
511 result = 0; | 505 result = 0; |
512 } | 506 } |
| 507 // The result may be negative, if we forced a short write for testing |
| 508 // purpose. In such case, don't mark writeAvailable as false, as we don't |
| 509 // know if we'll receive an event. It's better to just retry. |
| 510 if (result >= 0 && result < bytes) { |
| 511 writeAvailable = false; |
| 512 } |
| 513 // Negate the result, as stated above. |
| 514 if (result < 0) result = -result; |
513 return result; | 515 return result; |
514 } | 516 } |
515 | 517 |
516 int send(List<int> buffer, int offset, int bytes, | 518 int send(List<int> buffer, int offset, int bytes, |
517 InternetAddress address, int port) { | 519 InternetAddress address, int port) { |
518 if (isClosing || isClosed) return 0; | 520 if (isClosing || isClosed) return 0; |
519 _BufferAndStart bufferAndStart = | 521 _BufferAndStart bufferAndStart = |
520 _ensureFastAndSerializableByteData( | 522 _ensureFastAndSerializableByteData( |
521 buffer, offset, bytes); | 523 buffer, offset, bytes); |
522 var result = nativeSendTo( | 524 var result = nativeSendTo( |
(...skipping 24 matching lines...) Expand all Loading... |
547 int get remotePort { | 549 int get remotePort { |
548 return nativeGetRemotePeer()[1]; | 550 return nativeGetRemotePeer()[1]; |
549 } | 551 } |
550 | 552 |
551 InternetAddress get remoteAddress { | 553 InternetAddress get remoteAddress { |
552 var result = nativeGetRemotePeer()[0]; | 554 var result = nativeGetRemotePeer()[0]; |
553 var type = new InternetAddressType._from(result[0]); | 555 var type = new InternetAddressType._from(result[0]); |
554 return new _InternetAddress(result[1], null, result[2]); | 556 return new _InternetAddress(result[1], null, result[2]); |
555 } | 557 } |
556 | 558 |
| 559 void issueReadEvent() { |
| 560 if (readEventIssued) return; |
| 561 readEventIssued = true; |
| 562 void issue() { |
| 563 readEventIssued = false; |
| 564 if (isClosing) return; |
| 565 if (!sendReadEvents) return; |
| 566 if (available == 0) { |
| 567 if (isClosedRead) { |
| 568 if (isClosedWrite) close(); |
| 569 var handler = eventHandlers[CLOSED_EVENT]; |
| 570 if (handler == null) return; |
| 571 handler(); |
| 572 } |
| 573 return; |
| 574 } |
| 575 var handler = eventHandlers[READ_EVENT]; |
| 576 if (handler == null) return; |
| 577 readEventIssued = true; |
| 578 handler(); |
| 579 scheduleMicrotask(issue); |
| 580 } |
| 581 scheduleMicrotask(issue); |
| 582 } |
| 583 |
| 584 void issueWriteEvent({bool delayed: true}) { |
| 585 if (writeEventIssued) return; |
| 586 if (!writeAvailable) return; |
| 587 void issue() { |
| 588 writeEventIssued = false; |
| 589 if (!writeAvailable) return; |
| 590 if (isClosing) return; |
| 591 if (!sendWriteEvents) return; |
| 592 sendWriteEvents = false; |
| 593 var handler = eventHandlers[WRITE_EVENT]; |
| 594 if (handler == null) return; |
| 595 handler(); |
| 596 } |
| 597 if (delayed) { |
| 598 writeEventIssued = true; |
| 599 scheduleMicrotask(issue); |
| 600 } else { |
| 601 issue(); |
| 602 } |
| 603 } |
| 604 |
557 // Multiplexes socket events to the socket handlers. | 605 // Multiplexes socket events to the socket handlers. |
558 void multiplex(int events) { | 606 void multiplex(int events) { |
559 canActivateEvents = false; | |
560 for (int i = FIRST_EVENT; i <= LAST_EVENT; i++) { | 607 for (int i = FIRST_EVENT; i <= LAST_EVENT; i++) { |
561 if (((events & (1 << i)) != 0)) { | 608 if (((events & (1 << i)) != 0)) { |
562 if ((i == CLOSED_EVENT || i == READ_EVENT) && isClosedRead) continue; | 609 if ((i == CLOSED_EVENT || i == READ_EVENT) && isClosedRead) continue; |
| 610 if (isClosing && i != DESTROYED_EVENT) continue; |
563 if (i == CLOSED_EVENT && | 611 if (i == CLOSED_EVENT && |
564 typeFlags != TYPE_LISTENING_SOCKET && | 612 typeFlags != TYPE_LISTENING_SOCKET && |
565 !isClosing && | 613 !isClosing && |
566 !isClosed) { | 614 !isClosed) { |
567 isClosedRead = true; | 615 isClosedRead = true; |
| 616 issueReadEvent(); |
| 617 continue; |
| 618 } |
| 619 |
| 620 if (i == WRITE_EVENT) { |
| 621 writeAvailable = true; |
| 622 issueWriteEvent(delayed: false); |
| 623 continue; |
| 624 } |
| 625 |
| 626 if (i == READ_EVENT && |
| 627 typeFlags != TYPE_LISTENING_SOCKET) { |
| 628 var avail = nativeAvailable(); |
| 629 if (avail is int) { |
| 630 available = avail; |
| 631 } else { |
| 632 // Available failed. Mark socket as having data, to ensure read |
| 633 // events, and thus reporting of this error. |
| 634 available = 1; |
| 635 } |
| 636 issueReadEvent(); |
| 637 continue; |
568 } | 638 } |
569 | 639 |
570 var handler = eventHandlers[i]; | 640 var handler = eventHandlers[i]; |
571 if (i == DESTROYED_EVENT) { | 641 if (i == DESTROYED_EVENT) { |
572 assert(!isClosed); | 642 assert(!isClosed); |
573 isClosed = true; | 643 isClosed = true; |
574 closeCompleter.complete(); | 644 closeCompleter.complete(); |
575 disconnectFromEventHandler(); | 645 disconnectFromEventHandler(); |
576 if (handler != null) handler(); | 646 if (handler != null) handler(); |
577 continue; | 647 continue; |
578 } | 648 } |
579 assert(handler != null); | |
580 if (i == WRITE_EVENT) { | |
581 // If the event was disabled before we had a chance to fire the event, | |
582 // discard it. If we register again, we'll get a new one. | |
583 if ((eventMask & (1 << i)) == 0) continue; | |
584 // Unregister the out handler before executing it. There is | |
585 // no need to notify the eventhandler as handlers are | |
586 // disabled while the event is handled. | |
587 eventMask &= ~(1 << i); | |
588 } | |
589 | 649 |
590 // Don't call the in handler if there is no data available | |
591 // after all. | |
592 if (i == READ_EVENT && | |
593 typeFlags != TYPE_LISTENING_SOCKET && | |
594 available() == 0) { | |
595 continue; | |
596 } | |
597 if (i == ERROR_EVENT) { | 650 if (i == ERROR_EVENT) { |
598 if (!isClosing) { | 651 if (!isClosing) { |
599 reportError(nativeGetError(), ""); | 652 reportError(nativeGetError(), ""); |
600 } | 653 } |
601 } else if (!isClosed) { | 654 } else if (!isClosed) { |
602 // If the connection is closed right after it's accepted, there's a | 655 // If the connection is closed right after it's accepted, there's a |
603 // chance the close-handler is not set. | 656 // chance the close-handler is not set. |
604 if (handler != null) handler(); | 657 if (handler != null) handler(); |
605 } | 658 } |
606 } | 659 } |
607 } | 660 } |
608 if (isClosedRead && isClosedWrite) close(); | |
609 canActivateEvents = true; | |
610 activateHandlers(); | |
611 } | 661 } |
612 | 662 |
613 void setHandlers({read, write, error, closed, destroyed}) { | 663 void setHandlers({read, write, error, closed, destroyed}) { |
614 eventHandlers[READ_EVENT] = read; | 664 eventHandlers[READ_EVENT] = read; |
615 eventHandlers[WRITE_EVENT] = write; | 665 eventHandlers[WRITE_EVENT] = write; |
616 eventHandlers[ERROR_EVENT] = error; | 666 eventHandlers[ERROR_EVENT] = error; |
617 eventHandlers[CLOSED_EVENT] = closed; | 667 eventHandlers[CLOSED_EVENT] = closed; |
618 eventHandlers[DESTROYED_EVENT] = destroyed; | 668 eventHandlers[DESTROYED_EVENT] = destroyed; |
619 } | 669 } |
620 | 670 |
621 void setListening({read: true, write: true}) { | 671 void setListening({read: true, write: true}) { |
622 eventMask = (1 << CLOSED_EVENT) | (1 << ERROR_EVENT); | 672 sendReadEvents = read; |
623 if (read) eventMask |= (1 << READ_EVENT); | 673 sendWriteEvents = write; |
624 if (write) eventMask |= (1 << WRITE_EVENT); | 674 if (read) issueReadEvent(); |
625 activateHandlers(); | 675 if (write) issueWriteEvent(); |
626 } | 676 if (eventPort == null) { |
627 | 677 int flags = typeFlags; |
628 | 678 if (!isClosedRead) flags |= 1 << READ_EVENT; |
629 void activateHandlers() { | 679 if (!isClosedWrite) flags |= 1 << WRITE_EVENT; |
630 if (canActivateEvents && !isClosing && !isClosed) { | 680 sendToEventHandler(flags); |
631 if ((eventMask & ((1 << READ_EVENT) | (1 << WRITE_EVENT))) == 0) { | |
632 // If we don't listen for either read or write, disconnect as we won't | |
633 // get close and error events anyway. | |
634 if (eventPort != null) disconnectFromEventHandler(); | |
635 } else { | |
636 int data = eventMask; | |
637 if (isClosedRead) data &= ~(1 << READ_EVENT); | |
638 if (isClosedWrite) data &= ~(1 << WRITE_EVENT); | |
639 data |= typeFlags; | |
640 sendToEventHandler(data); | |
641 } | |
642 } | 681 } |
643 } | 682 } |
644 | 683 |
645 Future close() { | 684 Future close() { |
646 if (!isClosing && !isClosed) { | 685 if (!isClosing && !isClosed) { |
647 sendToEventHandler(1 << CLOSE_COMMAND); | 686 sendToEventHandler(1 << CLOSE_COMMAND); |
648 isClosing = true; | 687 isClosing = true; |
649 } | 688 } |
650 return closeCompleter.future; | 689 return closeCompleter.future; |
651 } | 690 } |
(...skipping 14 matching lines...) Expand all Loading... |
666 throw new ArgumentError(direction); | 705 throw new ArgumentError(direction); |
667 } | 706 } |
668 } | 707 } |
669 } | 708 } |
670 | 709 |
671 void shutdownWrite() { | 710 void shutdownWrite() { |
672 if (!isClosing && !isClosed) { | 711 if (!isClosing && !isClosed) { |
673 if (isClosedRead) { | 712 if (isClosedRead) { |
674 close(); | 713 close(); |
675 } else { | 714 } else { |
676 bool connected = eventPort != null; | |
677 sendToEventHandler(1 << SHUTDOWN_WRITE_COMMAND); | 715 sendToEventHandler(1 << SHUTDOWN_WRITE_COMMAND); |
678 if (!connected) disconnectFromEventHandler(); | |
679 } | 716 } |
680 isClosedWrite = true; | 717 isClosedWrite = true; |
681 } | 718 } |
682 } | 719 } |
683 | 720 |
684 void shutdownRead() { | 721 void shutdownRead() { |
685 if (!isClosing && !isClosed) { | 722 if (!isClosing && !isClosed) { |
686 if (isClosedWrite) { | 723 if (isClosedWrite) { |
687 close(); | 724 close(); |
688 } else { | 725 } else { |
689 bool connected = eventPort != null; | |
690 sendToEventHandler(1 << SHUTDOWN_READ_COMMAND); | 726 sendToEventHandler(1 << SHUTDOWN_READ_COMMAND); |
691 if (!connected) disconnectFromEventHandler(); | |
692 } | 727 } |
693 isClosedRead = true; | 728 isClosedRead = true; |
694 } | 729 } |
695 } | 730 } |
696 | 731 |
697 void sendToEventHandler(int data) { | 732 void sendToEventHandler(int data) { |
| 733 assert(!isClosed); |
698 connectToEventHandler(); | 734 connectToEventHandler(); |
699 assert(!isClosed); | |
700 _EventHandler._sendData(this, eventPort, data); | 735 _EventHandler._sendData(this, eventPort, data); |
701 } | 736 } |
702 | 737 |
703 void connectToEventHandler() { | 738 void connectToEventHandler() { |
704 if (eventPort == null) { | 739 if (eventPort == null) { |
705 eventPort = new RawReceivePort(multiplex); | 740 eventPort = new RawReceivePort(multiplex); |
706 } | 741 } |
707 } | 742 } |
708 | 743 |
709 void disconnectFromEventHandler() { | 744 void disconnectFromEventHandler() { |
710 if (eventPort != null) { | 745 assert(eventPort != null); |
711 eventPort.close(); | 746 eventPort.close(); |
712 eventPort = null; | 747 eventPort = null; |
713 } | |
714 } | 748 } |
715 | 749 |
716 // Check whether this is an error response from a native port call. | 750 // Check whether this is an error response from a native port call. |
717 static bool isErrorResponse(response) { | 751 static bool isErrorResponse(response) { |
718 return response is List && response[0] != _SUCCESS_RESPONSE; | 752 return response is List && response[0] != _SUCCESS_RESPONSE; |
719 } | 753 } |
720 | 754 |
721 // Create the appropriate error/exception from different returned | 755 // Create the appropriate error/exception from different returned |
722 // error objects. | 756 // error objects. |
723 static createError(error, | 757 static createError(error, |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
861 | 895 |
862 _RawServerSocket(this._socket) { | 896 _RawServerSocket(this._socket) { |
863 var zone = Zone.current; | 897 var zone = Zone.current; |
864 _controller = new StreamController(sync: true, | 898 _controller = new StreamController(sync: true, |
865 onListen: _onSubscriptionStateChange, | 899 onListen: _onSubscriptionStateChange, |
866 onCancel: _onSubscriptionStateChange, | 900 onCancel: _onSubscriptionStateChange, |
867 onPause: _onPauseStateChange, | 901 onPause: _onPauseStateChange, |
868 onResume: _onPauseStateChange); | 902 onResume: _onPauseStateChange); |
869 _socket.setHandlers( | 903 _socket.setHandlers( |
870 read: zone.bindCallback(() { | 904 read: zone.bindCallback(() { |
871 var socket = _socket.accept(); | 905 do { |
872 if (socket != null) _controller.add(new _RawSocket(socket)); | 906 var socket = _socket.accept(); |
| 907 if (socket == null) return; |
| 908 _controller.add(new _RawSocket(socket)); |
| 909 } while (!_controller.isPaused); |
873 }), | 910 }), |
874 error: zone.bindUnaryCallback((e) { | 911 error: zone.bindUnaryCallback((e) { |
875 _controller.addError(e); | 912 _controller.addError(e); |
876 _controller.close(); | 913 _controller.close(); |
877 }), | 914 }), |
878 destroyed: _controller.close | 915 destroyed: _controller.close |
879 ); | 916 ); |
880 } | 917 } |
881 | 918 |
882 StreamSubscription<RawSocket> listen(void onData(RawSocket event), | 919 StreamSubscription<RawSocket> listen(void onData(RawSocket event), |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
985 {Function onError, | 1022 {Function onError, |
986 void onDone(), | 1023 void onDone(), |
987 bool cancelOnError}) { | 1024 bool cancelOnError}) { |
988 return _controller.stream.listen( | 1025 return _controller.stream.listen( |
989 onData, | 1026 onData, |
990 onError: onError, | 1027 onError: onError, |
991 onDone: onDone, | 1028 onDone: onDone, |
992 cancelOnError: cancelOnError); | 1029 cancelOnError: cancelOnError); |
993 } | 1030 } |
994 | 1031 |
995 int available() => _socket.available(); | 1032 int available() => _socket.available; |
996 | 1033 |
997 List<int> read([int len]) { | 1034 List<int> read([int len]) { |
998 if (_isMacOSTerminalInput) { | 1035 if (_isMacOSTerminalInput) { |
999 var available = this.available(); | 1036 var available = this.available(); |
1000 if (available == 0) return null; | 1037 if (available == 0) return null; |
1001 var data = _socket.read(len); | 1038 var data = _socket.read(len); |
1002 if (data == null || data.length < available) { | 1039 if (data == null || data.length < available) { |
1003 // Reading less than available from a Mac OS terminal indicate Ctrl-D. | 1040 // Reading less than available from a Mac OS terminal indicate Ctrl-D. |
1004 // This is interpreted as read closed. | 1041 // This is interpreted as read closed. |
1005 scheduleMicrotask(() => _controller.add(RawSocketEvent.READ_CLOSED)); | 1042 scheduleMicrotask(() => _controller.add(RawSocketEvent.READ_CLOSED)); |
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1550 | 1587 |
1551 Datagram _makeDatagram(List<int> data, | 1588 Datagram _makeDatagram(List<int> data, |
1552 String address, | 1589 String address, |
1553 List<int> in_addr, | 1590 List<int> in_addr, |
1554 int port) { | 1591 int port) { |
1555 return new Datagram( | 1592 return new Datagram( |
1556 data, | 1593 data, |
1557 new _InternetAddress(address, null, in_addr), | 1594 new _InternetAddress(address, null, in_addr), |
1558 port); | 1595 port); |
1559 } | 1596 } |
OLD | NEW |