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 if (result >= 0 && result < bytes) { | |
508 writeAvailable = false; | |
509 } | |
510 if (result < 0) result = -result; | |
Søren Gjesse
2014/02/18 14:28:00
If the negative result is needed please explain it
Anders Johnsen
2014/02/19 09:43:03
Done.
| |
513 return result; | 511 return result; |
514 } | 512 } |
515 | 513 |
516 int send(List<int> buffer, int offset, int bytes, | 514 int send(List<int> buffer, int offset, int bytes, |
517 InternetAddress address, int port) { | 515 InternetAddress address, int port) { |
518 if (isClosing || isClosed) return 0; | 516 if (isClosing || isClosed) return 0; |
519 _BufferAndStart bufferAndStart = | 517 _BufferAndStart bufferAndStart = |
520 _ensureFastAndSerializableByteData( | 518 _ensureFastAndSerializableByteData( |
521 buffer, offset, bytes); | 519 buffer, offset, bytes); |
522 var result = nativeSendTo( | 520 var result = nativeSendTo( |
(...skipping 24 matching lines...) Expand all Loading... | |
547 int get remotePort { | 545 int get remotePort { |
548 return nativeGetRemotePeer()[1]; | 546 return nativeGetRemotePeer()[1]; |
549 } | 547 } |
550 | 548 |
551 InternetAddress get remoteAddress { | 549 InternetAddress get remoteAddress { |
552 var result = nativeGetRemotePeer()[0]; | 550 var result = nativeGetRemotePeer()[0]; |
553 var type = new InternetAddressType._from(result[0]); | 551 var type = new InternetAddressType._from(result[0]); |
554 return new _InternetAddress(result[1], null, result[2]); | 552 return new _InternetAddress(result[1], null, result[2]); |
555 } | 553 } |
556 | 554 |
555 void issueReadEvent() { | |
556 if (readEventIssued) return; | |
557 readEventIssued = true; | |
558 void issue() { | |
559 readEventIssued = false; | |
560 if (isClosing) return; | |
561 if (!sendReadEvents) return; | |
562 if (available == 0) { | |
563 if (isClosedRead) { | |
564 if (isClosedWrite) close(); | |
565 var handler = eventHandlers[CLOSED_EVENT]; | |
566 if (handler == null) return; | |
567 handler(); | |
568 } | |
569 return; | |
570 } | |
571 var handler = eventHandlers[READ_EVENT]; | |
572 if (handler == null) return; | |
573 readEventIssued = true; | |
574 handler(); | |
575 scheduleMicrotask(issue); | |
576 } | |
577 scheduleMicrotask(issue); | |
578 } | |
579 | |
580 void issueWriteEvent({bool delayed: true}) { | |
581 if (writeEventIssued) return; | |
582 if (!writeAvailable) return; | |
583 void issue() { | |
584 writeEventIssued = false; | |
585 if (!writeAvailable) return; | |
586 if (isClosing) return; | |
587 if (!sendWriteEvents) return; | |
588 sendWriteEvents = false; | |
589 var handler = eventHandlers[WRITE_EVENT]; | |
590 if (handler == null) return; | |
591 handler(); | |
592 } | |
593 if (delayed) { | |
594 writeEventIssued = true; | |
595 scheduleMicrotask(issue); | |
596 } else { | |
597 issue(); | |
598 } | |
599 } | |
600 | |
557 // Multiplexes socket events to the socket handlers. | 601 // Multiplexes socket events to the socket handlers. |
558 void multiplex(int events) { | 602 void multiplex(int events) { |
559 canActivateEvents = false; | |
560 for (int i = FIRST_EVENT; i <= LAST_EVENT; i++) { | 603 for (int i = FIRST_EVENT; i <= LAST_EVENT; i++) { |
561 if (((events & (1 << i)) != 0)) { | 604 if (((events & (1 << i)) != 0)) { |
562 if ((i == CLOSED_EVENT || i == READ_EVENT) && isClosedRead) continue; | 605 if ((i == CLOSED_EVENT || i == READ_EVENT) && isClosedRead) continue; |
606 if (isClosing && i != DESTROYED_EVENT) continue; | |
563 if (i == CLOSED_EVENT && | 607 if (i == CLOSED_EVENT && |
564 typeFlags != TYPE_LISTENING_SOCKET && | 608 typeFlags != TYPE_LISTENING_SOCKET && |
565 !isClosing && | 609 !isClosing && |
566 !isClosed) { | 610 !isClosed) { |
567 isClosedRead = true; | 611 isClosedRead = true; |
612 issueReadEvent(); | |
613 continue; | |
614 } | |
615 | |
616 if (i == WRITE_EVENT) { | |
617 writeAvailable = true; | |
618 issueWriteEvent(delayed: false); | |
619 continue; | |
620 } | |
621 | |
622 if (i == READ_EVENT && | |
623 typeFlags != TYPE_LISTENING_SOCKET) { | |
624 var avail = nativeAvailable(); | |
625 if (avail is int) { | |
626 available = avail; | |
627 } else { | |
628 // Available failed. Mark socket as having data, to ensure read | |
629 // events, and thus reporting of this error. | |
630 available = 1; | |
631 } | |
632 issueReadEvent(); | |
Søren Gjesse
2014/02/18 14:28:00
Why is there no "delayed: false" for this as well?
Anders Johnsen
2014/02/19 09:43:03
It's always delayed. If it wasn't I was having tro
| |
633 continue; | |
568 } | 634 } |
569 | 635 |
570 var handler = eventHandlers[i]; | 636 var handler = eventHandlers[i]; |
571 if (i == DESTROYED_EVENT) { | 637 if (i == DESTROYED_EVENT) { |
572 assert(!isClosed); | 638 assert(!isClosed); |
573 isClosed = true; | 639 isClosed = true; |
574 closeCompleter.complete(); | 640 closeCompleter.complete(); |
575 disconnectFromEventHandler(); | 641 disconnectFromEventHandler(); |
576 if (handler != null) handler(); | 642 if (handler != null) handler(); |
577 continue; | 643 continue; |
578 } | 644 } |
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 | 645 |
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) { | 646 if (i == ERROR_EVENT) { |
598 if (!isClosing) { | 647 if (!isClosing) { |
599 reportError(nativeGetError(), ""); | 648 reportError(nativeGetError(), ""); |
600 } | 649 } |
601 } else if (!isClosed) { | 650 } else if (!isClosed) { |
602 // If the connection is closed right after it's accepted, there's a | 651 // If the connection is closed right after it's accepted, there's a |
603 // chance the close-handler is not set. | 652 // chance the close-handler is not set. |
604 if (handler != null) handler(); | 653 if (handler != null) handler(); |
605 } | 654 } |
606 } | 655 } |
607 } | 656 } |
608 if (isClosedRead && isClosedWrite) close(); | |
609 canActivateEvents = true; | |
610 activateHandlers(); | |
611 } | 657 } |
612 | 658 |
613 void setHandlers({read, write, error, closed, destroyed}) { | 659 void setHandlers({read, write, error, closed, destroyed}) { |
614 eventHandlers[READ_EVENT] = read; | 660 eventHandlers[READ_EVENT] = read; |
615 eventHandlers[WRITE_EVENT] = write; | 661 eventHandlers[WRITE_EVENT] = write; |
616 eventHandlers[ERROR_EVENT] = error; | 662 eventHandlers[ERROR_EVENT] = error; |
617 eventHandlers[CLOSED_EVENT] = closed; | 663 eventHandlers[CLOSED_EVENT] = closed; |
618 eventHandlers[DESTROYED_EVENT] = destroyed; | 664 eventHandlers[DESTROYED_EVENT] = destroyed; |
619 } | 665 } |
620 | 666 |
621 void setListening({read: true, write: true}) { | 667 void setListening({read: true, write: true}) { |
622 eventMask = (1 << CLOSED_EVENT) | (1 << ERROR_EVENT); | 668 sendReadEvents = read; |
623 if (read) eventMask |= (1 << READ_EVENT); | 669 sendWriteEvents = write; |
624 if (write) eventMask |= (1 << WRITE_EVENT); | 670 if (read) issueReadEvent(); |
625 activateHandlers(); | 671 if (write) issueWriteEvent(); |
626 } | 672 if (eventPort == null) { |
627 | 673 int flags = typeFlags; |
628 | 674 if (!isClosedRead) flags |= 1 << READ_EVENT; |
629 void activateHandlers() { | 675 if (!isClosedWrite) flags |= 1 << WRITE_EVENT; |
630 if (canActivateEvents && !isClosing && !isClosed) { | 676 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 } | 677 } |
643 } | 678 } |
644 | 679 |
645 Future close() { | 680 Future close() { |
646 if (!isClosing && !isClosed) { | 681 if (!isClosing && !isClosed) { |
647 sendToEventHandler(1 << CLOSE_COMMAND); | 682 sendToEventHandler(1 << CLOSE_COMMAND); |
648 isClosing = true; | 683 isClosing = true; |
649 } | 684 } |
650 return closeCompleter.future; | 685 return closeCompleter.future; |
651 } | 686 } |
(...skipping 14 matching lines...) Expand all Loading... | |
666 throw new ArgumentError(direction); | 701 throw new ArgumentError(direction); |
667 } | 702 } |
668 } | 703 } |
669 } | 704 } |
670 | 705 |
671 void shutdownWrite() { | 706 void shutdownWrite() { |
672 if (!isClosing && !isClosed) { | 707 if (!isClosing && !isClosed) { |
673 if (isClosedRead) { | 708 if (isClosedRead) { |
674 close(); | 709 close(); |
675 } else { | 710 } else { |
676 bool connected = eventPort != null; | |
677 sendToEventHandler(1 << SHUTDOWN_WRITE_COMMAND); | 711 sendToEventHandler(1 << SHUTDOWN_WRITE_COMMAND); |
678 if (!connected) disconnectFromEventHandler(); | |
679 } | 712 } |
680 isClosedWrite = true; | 713 isClosedWrite = true; |
681 } | 714 } |
682 } | 715 } |
683 | 716 |
684 void shutdownRead() { | 717 void shutdownRead() { |
685 if (!isClosing && !isClosed) { | 718 if (!isClosing && !isClosed) { |
686 if (isClosedWrite) { | 719 if (isClosedWrite) { |
687 close(); | 720 close(); |
688 } else { | 721 } else { |
689 bool connected = eventPort != null; | |
690 sendToEventHandler(1 << SHUTDOWN_READ_COMMAND); | 722 sendToEventHandler(1 << SHUTDOWN_READ_COMMAND); |
691 if (!connected) disconnectFromEventHandler(); | |
692 } | 723 } |
693 isClosedRead = true; | 724 isClosedRead = true; |
694 } | 725 } |
695 } | 726 } |
696 | 727 |
697 void sendToEventHandler(int data) { | 728 void sendToEventHandler(int data) { |
729 assert(!isClosed); | |
698 connectToEventHandler(); | 730 connectToEventHandler(); |
699 assert(!isClosed); | |
700 _EventHandler._sendData(this, eventPort, data); | 731 _EventHandler._sendData(this, eventPort, data); |
701 } | 732 } |
702 | 733 |
703 void connectToEventHandler() { | 734 void connectToEventHandler() { |
704 if (eventPort == null) { | 735 if (eventPort == null) { |
705 eventPort = new RawReceivePort(multiplex); | 736 eventPort = new RawReceivePort(multiplex); |
706 } | 737 } |
707 } | 738 } |
708 | 739 |
709 void disconnectFromEventHandler() { | 740 void disconnectFromEventHandler() { |
710 if (eventPort != null) { | 741 assert(eventPort != null); |
711 eventPort.close(); | 742 eventPort.close(); |
712 eventPort = null; | 743 eventPort = null; |
713 } | |
714 } | 744 } |
715 | 745 |
716 // Check whether this is an error response from a native port call. | 746 // Check whether this is an error response from a native port call. |
717 static bool isErrorResponse(response) { | 747 static bool isErrorResponse(response) { |
718 return response is List && response[0] != _SUCCESS_RESPONSE; | 748 return response is List && response[0] != _SUCCESS_RESPONSE; |
719 } | 749 } |
720 | 750 |
721 // Create the appropriate error/exception from different returned | 751 // Create the appropriate error/exception from different returned |
722 // error objects. | 752 // error objects. |
723 static createError(error, | 753 static createError(error, |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
861 | 891 |
862 _RawServerSocket(this._socket) { | 892 _RawServerSocket(this._socket) { |
863 var zone = Zone.current; | 893 var zone = Zone.current; |
864 _controller = new StreamController(sync: true, | 894 _controller = new StreamController(sync: true, |
865 onListen: _onSubscriptionStateChange, | 895 onListen: _onSubscriptionStateChange, |
866 onCancel: _onSubscriptionStateChange, | 896 onCancel: _onSubscriptionStateChange, |
867 onPause: _onPauseStateChange, | 897 onPause: _onPauseStateChange, |
868 onResume: _onPauseStateChange); | 898 onResume: _onPauseStateChange); |
869 _socket.setHandlers( | 899 _socket.setHandlers( |
870 read: zone.bindCallback(() { | 900 read: zone.bindCallback(() { |
871 var socket = _socket.accept(); | 901 do { |
872 if (socket != null) _controller.add(new _RawSocket(socket)); | 902 var socket = _socket.accept(); |
903 if (socket == null) return; | |
904 _controller.add(new _RawSocket(socket)); | |
905 } while (!_controller.isPaused); | |
873 }), | 906 }), |
874 error: zone.bindUnaryCallback((e) { | 907 error: zone.bindUnaryCallback((e) { |
875 _controller.addError(e); | 908 _controller.addError(e); |
876 _controller.close(); | 909 _controller.close(); |
877 }), | 910 }), |
878 destroyed: _controller.close | 911 destroyed: _controller.close |
879 ); | 912 ); |
880 } | 913 } |
881 | 914 |
882 StreamSubscription<RawSocket> listen(void onData(RawSocket event), | 915 StreamSubscription<RawSocket> listen(void onData(RawSocket event), |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
985 {Function onError, | 1018 {Function onError, |
986 void onDone(), | 1019 void onDone(), |
987 bool cancelOnError}) { | 1020 bool cancelOnError}) { |
988 return _controller.stream.listen( | 1021 return _controller.stream.listen( |
989 onData, | 1022 onData, |
990 onError: onError, | 1023 onError: onError, |
991 onDone: onDone, | 1024 onDone: onDone, |
992 cancelOnError: cancelOnError); | 1025 cancelOnError: cancelOnError); |
993 } | 1026 } |
994 | 1027 |
995 int available() => _socket.available(); | 1028 int available() => _socket.available; |
996 | 1029 |
997 List<int> read([int len]) { | 1030 List<int> read([int len]) { |
998 if (_isMacOSTerminalInput) { | 1031 if (_isMacOSTerminalInput) { |
999 var available = this.available(); | 1032 var available = this.available(); |
1000 if (available == 0) return null; | 1033 if (available == 0) return null; |
1001 var data = _socket.read(len); | 1034 var data = _socket.read(len); |
1002 if (data == null || data.length < available) { | 1035 if (data == null || data.length < available) { |
1003 // Reading less than available from a Mac OS terminal indicate Ctrl-D. | 1036 // Reading less than available from a Mac OS terminal indicate Ctrl-D. |
1004 // This is interpreted as read closed. | 1037 // This is interpreted as read closed. |
1005 scheduleMicrotask(() => _controller.add(RawSocketEvent.READ_CLOSED)); | 1038 scheduleMicrotask(() => _controller.add(RawSocketEvent.READ_CLOSED)); |
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1550 | 1583 |
1551 Datagram _makeDatagram(List<int> data, | 1584 Datagram _makeDatagram(List<int> data, |
1552 String address, | 1585 String address, |
1553 List<int> in_addr, | 1586 List<int> in_addr, |
1554 int port) { | 1587 int port) { |
1555 return new Datagram( | 1588 return new Datagram( |
1556 data, | 1589 data, |
1557 new _InternetAddress(address, null, in_addr), | 1590 new _InternetAddress(address, null, in_addr), |
1558 port); | 1591 port); |
1559 } | 1592 } |
OLD | NEW |