| 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 |