Index: runtime/bin/socket_patch.dart |
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart |
index be459ba164dd2c653ae3b0e4ee2d8175db0d197e..94285aaaa02ed59b6eb0905770a60a066762bdf3 100644 |
--- a/runtime/bin/socket_patch.dart |
+++ b/runtime/bin/socket_patch.dart |
@@ -280,6 +280,9 @@ 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; |
@@ -314,9 +317,13 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { |
bool writeAvailable = false; |
static final Stopwatch sw = new Stopwatch()..start(); |
- |
- static bool connectedResourceHandler = false; |
- _ReadWriteResourceInfo resourceInfo; |
+ // Statistics. |
+ int totalRead = 0; |
+ int totalWritten = 0; |
+ int readCount = 0; |
+ int writeCount = 0; |
+ double lastRead; |
+ double lastWrite; |
// The owner object is the object that the Socket is being used by, e.g. |
// a HttpServer, a WebSocket connection, a process pipe, etc. |
@@ -434,8 +441,6 @@ 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. |
@@ -487,6 +492,7 @@ 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, |
@@ -499,16 +505,11 @@ 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) |
@@ -533,7 +534,6 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { |
port: port); |
} |
if (port != 0) socket.localPort = port; |
- setupResourceInfo(socket); |
return socket; |
}); |
} |
@@ -575,18 +575,10 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { |
} |
if (result != null) { |
available -= 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; |
+ totalRead += result.length; |
} |
+ readCount++; |
+ lastRead = timestamp; |
return result; |
} |
@@ -603,18 +595,10 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { |
// receive. If available becomes > 0, the _NativeSocket will continue to |
// emit read events. |
available = nativeAvailable(); |
- // 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; |
+ totalRead += result.data.length; |
} |
+ readCount++; |
+ lastRead = timestamp; |
return result; |
} |
@@ -653,13 +637,9 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { |
} |
// Negate the result, as stated above. |
if (result < 0) result = -result; |
- // 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; |
- } |
+ totalWritten += result; |
+ writeCount++; |
+ lastWrite = timestamp; |
return result; |
} |
@@ -676,13 +656,9 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { |
scheduleMicrotask(() => reportError(result, "Send failed")); |
result = 0; |
} |
- // 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; |
- } |
+ totalWritten += result; |
+ writeCount++; |
+ lastWrite = timestamp; |
return result; |
} |
@@ -697,13 +673,8 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { |
if (nativeAccept(socket) != true) return null; |
socket.localPort = localPort; |
socket.localAddress = address; |
- 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; |
- } |
+ totalRead += 1; |
+ lastRead = timestamp; |
return socket; |
} |
@@ -816,11 +787,6 @@ 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(); |
@@ -938,14 +904,7 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { |
assert(!isClosed); |
if (eventPort == null) { |
eventPort = new RawReceivePort(multiplex); |
- } |
- if (!connectedResourceHandler) { |
- registerExtension('__getOpenSockets', |
- _SocketResourceInfo.getOpenSockets); |
- registerExtension('__getSocketByID', |
- _SocketResourceInfo.getSocketInfoMapByID); |
- |
- connectedResourceHandler = true; |
+ _sockets[_serviceId] = this; |
} |
} |
@@ -953,6 +912,7 @@ 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; |
@@ -1057,6 +1017,123 @@ 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"; |
@@ -1209,6 +1286,8 @@ class _RawServerSocket extends Stream<RawSocket> |
return new _RawServerSocketReference(_referencePort.sendPort); |
} |
+ Map _toJSON(bool ref) => _socket._toJSON(ref); |
+ |
void set _owner(owner) { _socket.owner = owner; } |
} |
@@ -1386,6 +1465,7 @@ class _RawSocket extends Stream<RawSocketEvent> |
} |
} |
+ Map _toJSON(bool ref) => _socket._toJSON(ref); |
void set _owner(owner) { _socket.owner = owner; } |
} |
@@ -1448,6 +1528,8 @@ class _ServerSocket extends Stream<Socket> |
return new _ServerSocketReference(_socket.reference); |
} |
+ Map _toJSON(bool ref) => _socket._toJSON(ref); |
+ |
void set _owner(owner) { _socket._owner = owner; } |
} |
@@ -1761,6 +1843,7 @@ class _Socket extends Stream<List<int>> implements Socket { |
} |
} |
+ Map _toJSON(bool ref) => _raw._toJSON(ref); |
void set _owner(owner) { _raw._owner = owner; } |
} |
@@ -1916,3 +1999,4 @@ Datagram _makeDatagram(List<int> data, |
port); |
} |
+String _socketsStats() => _SocketsObservatory.toJSON(); |