| Index: runtime/bin/socket_patch.dart
|
| diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
|
| index 94285aaaa02ed59b6eb0905770a60a066762bdf3..be459ba164dd2c653ae3b0e4ee2d8175db0d197e 100644
|
| --- a/runtime/bin/socket_patch.dart
|
| +++ b/runtime/bin/socket_patch.dart
|
| @@ -280,9 +280,6 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
| static const Duration _RETRY_DURATION_LOOPBACK =
|
| const Duration(milliseconds: 25);
|
|
|
| - // Use default Map so we keep order.
|
| - static Map<int, _NativeSocket> _sockets = new Map<int, _NativeSocket>();
|
| -
|
| // Socket close state
|
| bool isClosed = false;
|
| bool isClosing = false;
|
| @@ -317,13 +314,9 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
| bool writeAvailable = false;
|
|
|
| static final Stopwatch sw = new Stopwatch()..start();
|
| - // Statistics.
|
| - int totalRead = 0;
|
| - int totalWritten = 0;
|
| - int readCount = 0;
|
| - int writeCount = 0;
|
| - double lastRead;
|
| - double lastWrite;
|
| +
|
| + static bool connectedResourceHandler = false;
|
| + _ReadWriteResourceInfo resourceInfo;
|
|
|
| // The owner object is the object that the Socket is being used by, e.g.
|
| // a HttpServer, a WebSocket connection, a process pipe, etc.
|
| @@ -441,6 +434,8 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
| _RETRY_DURATION_LOOPBACK :
|
| _RETRY_DURATION;
|
| var timer = new Timer(duration, connectNext);
|
| + setupResourceInfo(socket);
|
| +
|
| connecting[socket] = timer;
|
| // Setup handlers for receiving the first write event which
|
| // indicate that the socket is fully connected.
|
| @@ -492,7 +487,6 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
| .then((address) {
|
| var socket = new _NativeSocket.listen();
|
| socket.localAddress = address;
|
| -
|
| var result = socket.nativeCreateBindListen(address._in_addr,
|
| port,
|
| backlog,
|
| @@ -505,11 +499,16 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
| port: port);
|
| }
|
| if (port != 0) socket.localPort = port;
|
| + setupResourceInfo(socket);
|
| socket.connectToEventHandler();
|
| return socket;
|
| });
|
| }
|
|
|
| + static void setupResourceInfo(_NativeSocket socket) {
|
| + socket.resourceInfo = new _SocketResourceInfo(socket);
|
| + }
|
| +
|
| static Future<_NativeSocket> bindDatagram(
|
| host, int port, bool reuseAddress) {
|
| return new Future.value(host)
|
| @@ -534,6 +533,7 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
| port: port);
|
| }
|
| if (port != 0) socket.localPort = port;
|
| + setupResourceInfo(socket);
|
| return socket;
|
| });
|
| }
|
| @@ -575,10 +575,18 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
| }
|
| if (result != null) {
|
| available -= result.length;
|
| - totalRead += result.length;
|
| + // TODO(ricow): Remove when we track internal and pipe uses.
|
| + assert(resourceInfo != null || isPipe || isInternal);
|
| + if (resourceInfo != null) {
|
| + resourceInfo.totalRead += result.length;
|
| + }
|
| + }
|
| + // TODO(ricow): Remove when we track internal and pipe uses.
|
| + assert(resourceInfo != null || isPipe || isInternal);
|
| + if (resourceInfo != null) {
|
| + resourceInfo.readCount++;
|
| + resourceInfo.lastRead = timestamp;
|
| }
|
| - readCount++;
|
| - lastRead = timestamp;
|
| return result;
|
| }
|
|
|
| @@ -595,10 +603,18 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
| // receive. If available becomes > 0, the _NativeSocket will continue to
|
| // emit read events.
|
| available = nativeAvailable();
|
| - totalRead += result.data.length;
|
| + // TODO(ricow): Remove when we track internal and pipe uses.
|
| + assert(resourceInfo != null || isPipe || isInternal);
|
| + if (resourceInfo != null) {
|
| + resourceInfo.totalRead += result.data.length;
|
| + }
|
| + }
|
| + // TODO(ricow): Remove when we track internal and pipe uses.
|
| + assert(resourceInfo != null || isPipe || isInternal);
|
| + if (resourceInfo != null) {
|
| + resourceInfo.readCount++;
|
| + resourceInfo.lastRead = timestamp;
|
| }
|
| - readCount++;
|
| - lastRead = timestamp;
|
| return result;
|
| }
|
|
|
| @@ -637,9 +653,13 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
| }
|
| // Negate the result, as stated above.
|
| if (result < 0) result = -result;
|
| - totalWritten += result;
|
| - writeCount++;
|
| - lastWrite = timestamp;
|
| + // TODO(ricow): Remove when we track internal and pipe uses.
|
| + assert(resourceInfo != null || isPipe || isInternal);
|
| + if (resourceInfo != null) {
|
| + resourceInfo.totalWritten += result;
|
| + resourceInfo.writeCount++;
|
| + resourceInfo.lastWrite = timestamp;
|
| + }
|
| return result;
|
| }
|
|
|
| @@ -656,9 +676,13 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
| scheduleMicrotask(() => reportError(result, "Send failed"));
|
| result = 0;
|
| }
|
| - totalWritten += result;
|
| - writeCount++;
|
| - lastWrite = timestamp;
|
| + // TODO(ricow): Remove when we track internal and pipe uses.
|
| + assert(resourceInfo != null || isPipe || isInternal);
|
| + if (resourceInfo != null) {
|
| + resourceInfo.totalWritten += result;
|
| + resourceInfo.writeCount++;
|
| + resourceInfo.lastWrite = timestamp;
|
| + }
|
| return result;
|
| }
|
|
|
| @@ -673,8 +697,13 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
| if (nativeAccept(socket) != true) return null;
|
| socket.localPort = localPort;
|
| socket.localAddress = address;
|
| - totalRead += 1;
|
| - lastRead = timestamp;
|
| + setupResourceInfo(socket);
|
| + // TODO(ricow): Remove when we track internal and pipe uses.
|
| + assert(resourceInfo != null || isPipe || isInternal);
|
| + if (resourceInfo != null) {
|
| + resourceInfo.totalRead += 1;
|
| + resourceInfo.lastRead = timestamp;
|
| + }
|
| return socket;
|
| }
|
|
|
| @@ -787,6 +816,11 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
| if (i == DESTROYED_EVENT) {
|
| assert(isClosing);
|
| assert(!isClosed);
|
| + // TODO(ricow): Remove/update when we track internal and pipe uses.
|
| + assert(resourceInfo != null || isPipe || isInternal);
|
| + if (resourceInfo != null) {
|
| + _SocketResourceInfo.SocketClosed(resourceInfo);
|
| + }
|
| isClosed = true;
|
| closeCompleter.complete();
|
| disconnectFromEventHandler();
|
| @@ -904,7 +938,14 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
| assert(!isClosed);
|
| if (eventPort == null) {
|
| eventPort = new RawReceivePort(multiplex);
|
| - _sockets[_serviceId] = this;
|
| + }
|
| + if (!connectedResourceHandler) {
|
| + registerExtension('__getOpenSockets',
|
| + _SocketResourceInfo.getOpenSockets);
|
| + registerExtension('__getSocketByID',
|
| + _SocketResourceInfo.getSocketInfoMapByID);
|
| +
|
| + connectedResourceHandler = true;
|
| }
|
| }
|
|
|
| @@ -912,7 +953,6 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
| assert(eventPort != null);
|
| eventPort.close();
|
| eventPort = null;
|
| - _sockets.remove(_serviceId);
|
| // Now that we don't track this Socket anymore, we can clear the owner
|
| // field.
|
| owner = null;
|
| @@ -1017,123 +1057,6 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
| if (result is OSError) throw result;
|
| }
|
|
|
| - String get _serviceTypePath => 'io/sockets';
|
| - String get _serviceTypeName => 'Socket';
|
| -
|
| - String _JSONKind() {
|
| - return isListening ? "Listening" :
|
| - isPipe ? "Pipe" :
|
| - isInternal ? "Internal" : "Normal";
|
| - }
|
| -
|
| - Map _toJSONPipe(bool ref) {
|
| - var name = 'Anonymous Pipe';
|
| - var r = {
|
| - 'id': _servicePath,
|
| - 'type': _serviceType(ref),
|
| - 'name': name,
|
| - 'user_name': name,
|
| - 'kind': _JSONKind(),
|
| - };
|
| - if (ref) {
|
| - return r;
|
| - }
|
| - r['readClosed'] = isClosedRead;
|
| - r['writeClosed'] = isClosedWrite;
|
| - r['closing'] = isClosing;
|
| - r['fd'] = nativeGetSocketId();
|
| - if (owner != null) {
|
| - r['owner'] = owner._toJSON(true);
|
| - }
|
| - return r;
|
| - }
|
| -
|
| - Map _toJSONInternal(bool ref) {
|
| - var name = 'Internal';
|
| - var r = {
|
| - 'id': _servicePath,
|
| - 'type': _serviceType(ref),
|
| - 'name': name,
|
| - 'user_name': name,
|
| - 'kind': _JSONKind(),
|
| - };
|
| - if (ref) {
|
| - return r;
|
| - }
|
| - r['closing'] = isClosing;
|
| - r['fd'] = nativeGetSocketId();
|
| - if (owner != null) {
|
| - r['owner'] = owner._toJSON(true);
|
| - }
|
| - return r;
|
| - }
|
| -
|
| - Map _toJSONNetwork(bool ref) {
|
| - var name = '${address.host}:$port';
|
| - if (isTcp && !isListening) name += " <-> ${remoteAddress.host}:$remotePort";
|
| - var r = {
|
| - 'id': _servicePath,
|
| - 'type': _serviceType(ref),
|
| - 'name': name,
|
| - 'user_name': name,
|
| - 'kind': _JSONKind(),
|
| - };
|
| - if (ref) {
|
| - return r;
|
| - }
|
| - var protocol = isTcp ? "TCP" : isUdp ? "UDP" : null;
|
| - var localAddress;
|
| - var localPort;
|
| - var rAddress;
|
| - var rPort;
|
| - try {
|
| - localAddress = address.address;
|
| - } catch (e) { }
|
| - try {
|
| - localPort = port;
|
| - } catch (e) { }
|
| - try {
|
| - rAddress = this.remoteAddress.address;
|
| - } catch (e) { }
|
| - try {
|
| - rPort = remotePort;
|
| - } catch (e) { }
|
| - r['localAddress'] = localAddress;
|
| - r['localPort'] = localPort;
|
| - r['remoteAddress'] = rAddress;
|
| - r['remotePort'] = rPort;
|
| - r['protocol'] = protocol;
|
| - r['readClosed'] = isClosedRead;
|
| - r['writeClosed'] = isClosedWrite;
|
| - r['closing'] = isClosing;
|
| - r['listening'] = isListening;
|
| - r['fd'] = nativeGetSocketId();
|
| - if (owner != null) {
|
| - r['owner'] = owner._toJSON(true);
|
| - }
|
| - return r;
|
| - }
|
| -
|
| - Map _toJSON(bool ref) {
|
| - var map;
|
| - if (isPipe) {
|
| - map = _toJSONPipe(ref);
|
| - } else if (isInternal) {
|
| - map = _toJSONInternal(ref);
|
| - } else {
|
| - map = _toJSONNetwork(ref);
|
| - }
|
| - if (!ref) {
|
| - map['available'] = available;
|
| - map['totalRead'] = totalRead;
|
| - map['totalWritten'] = totalWritten;
|
| - map['readCount'] = totalWritten;
|
| - map['writeCount'] = writeCount;
|
| - map['lastRead'] = lastRead;
|
| - map['lastWrite'] = lastWrite;
|
| - }
|
| - return map;
|
| - }
|
|
|
| void nativeSetSocketId(int id) native "Socket_SetSocketId";
|
| nativeAvailable() native "Socket_Available";
|
| @@ -1286,8 +1209,6 @@ class _RawServerSocket extends Stream<RawSocket>
|
| return new _RawServerSocketReference(_referencePort.sendPort);
|
| }
|
|
|
| - Map _toJSON(bool ref) => _socket._toJSON(ref);
|
| -
|
| void set _owner(owner) { _socket.owner = owner; }
|
| }
|
|
|
| @@ -1465,7 +1386,6 @@ class _RawSocket extends Stream<RawSocketEvent>
|
| }
|
| }
|
|
|
| - Map _toJSON(bool ref) => _socket._toJSON(ref);
|
| void set _owner(owner) { _socket.owner = owner; }
|
| }
|
|
|
| @@ -1528,8 +1448,6 @@ class _ServerSocket extends Stream<Socket>
|
| return new _ServerSocketReference(_socket.reference);
|
| }
|
|
|
| - Map _toJSON(bool ref) => _socket._toJSON(ref);
|
| -
|
| void set _owner(owner) { _socket._owner = owner; }
|
| }
|
|
|
| @@ -1843,7 +1761,6 @@ class _Socket extends Stream<List<int>> implements Socket {
|
| }
|
| }
|
|
|
| - Map _toJSON(bool ref) => _raw._toJSON(ref);
|
| void set _owner(owner) { _raw._owner = owner; }
|
| }
|
|
|
| @@ -1999,4 +1916,3 @@ Datagram _makeDatagram(List<int> data,
|
| port);
|
| }
|
|
|
| -String _socketsStats() => _SocketsObservatory.toJSON();
|
|
|