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

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

Issue 169383003: Make event-handlers edge-triggered and move socket-state to Dart. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 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
« no previous file with comments | « runtime/bin/socket_linux.cc ('k') | sdk/lib/io/secure_socket.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « runtime/bin/socket_linux.cc ('k') | sdk/lib/io/secure_socket.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698