|
@@ -1,6 +1,7 @@
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
import random
|
|
|
+import pickle
|
|
|
from enum import Enum
|
|
|
|
|
|
class WOMode(Enum):
|
|
@@ -17,6 +18,44 @@ class SNIPAuthMode(Enum):
|
|
|
THRESHSIG = 2 # Threshold signatures
|
|
|
|
|
|
|
|
|
+class EntType(Enum):
|
|
|
+ """The different types of entities in the system."""
|
|
|
+ NONE = 0
|
|
|
+ DIRAUTH = 1
|
|
|
+ RELAY = 2
|
|
|
+ CLIENT = 3
|
|
|
+
|
|
|
+
|
|
|
+class PerfStats:
|
|
|
+ """A class to store performance statistics for a relay or client.
|
|
|
+ We keep track of bytes sent, bytes received, and counts of
|
|
|
+ public-key operations of various types. We will reset these every
|
|
|
+ epoch."""
|
|
|
+
|
|
|
+ def __init__(self, ent_type):
|
|
|
+ # Which type of entity is this for (DIRAUTH, RELAY, CLIENT)
|
|
|
+ self.ent_type = ent_type
|
|
|
+ # A printable name for the entity
|
|
|
+ self.name = None
|
|
|
+ # True if bootstrapping this epoch
|
|
|
+ self.is_bootstrapping = False
|
|
|
+ # Bytes sent and received
|
|
|
+ self.bytes_sent = 0
|
|
|
+ self.bytes_received = 0
|
|
|
+ # Public-key operations: key generation, signing, verification,
|
|
|
+ # Diffie-Hellman
|
|
|
+ self.keygens = 0
|
|
|
+ self.sigs = 0
|
|
|
+ self.verifs = 0
|
|
|
+ self.dhs = 0
|
|
|
+
|
|
|
+ def __str__(self):
|
|
|
+ return "%s: type=%s boot=%s sent=%d recv=%d keygen=%d sig=%d verif=%d dh=%d" % \
|
|
|
+ (self.name, self.ent_type.name, self.is_bootstrapping, \
|
|
|
+ self.bytes_sent, self.bytes_received, self.keygens, \
|
|
|
+ self.sigs, self.verifs, self.dhs)
|
|
|
+
|
|
|
+
|
|
|
class NetAddr:
|
|
|
"""A class representing a network address"""
|
|
|
nextaddr = 1
|
|
@@ -114,14 +153,16 @@ class Network:
|
|
|
server.bound(addr, lambda: self.servers.pop(addr))
|
|
|
return addr
|
|
|
|
|
|
- def connect(self, client, srvaddr):
|
|
|
+ def connect(self, client, srvaddr, perfstats):
|
|
|
"""Connect the given client to the server bound to addr. Throw
|
|
|
an exception if there is no server bound to that address."""
|
|
|
try:
|
|
|
server = self.servers[srvaddr]
|
|
|
except KeyError:
|
|
|
raise NetNoServer()
|
|
|
- return server.connected(client)
|
|
|
+ conn = server.connected(client)
|
|
|
+ conn.perfstats = perfstats
|
|
|
+ return conn
|
|
|
|
|
|
def setfallbackrelays(self, fallbackrelays):
|
|
|
"""Set the list of globally known fallback relays. Clients use
|
|
@@ -157,6 +198,16 @@ class NetMsg:
|
|
|
"""The parent class of network messages. Subclass this class to
|
|
|
implement specific kinds of network messages."""
|
|
|
|
|
|
+ def size(self):
|
|
|
+ """Return the size of this network message. For now, just
|
|
|
+ pickle it and return the length of that. There's some
|
|
|
+ unnecessary overhead in this method; if you want specific
|
|
|
+ messages to have more accurate sizes, override this method in
|
|
|
+ the subclass."""
|
|
|
+ sz = len(pickle.dumps(self))
|
|
|
+ print('size',sz,type(self))
|
|
|
+ return sz
|
|
|
+
|
|
|
|
|
|
class StringNetMsg(NetMsg):
|
|
|
"""Send an arbitratry string as a NetMsg."""
|
|
@@ -193,17 +244,22 @@ class ClientConnection(Connection):
|
|
|
"""Create a ClientConnection object with the given peer. The
|
|
|
peer must have a received(client, msg) method."""
|
|
|
self.peer = peer
|
|
|
+ self.perfstats = None
|
|
|
|
|
|
def sendmsg(self, netmsg):
|
|
|
assert(isinstance(netmsg, NetMsg))
|
|
|
+ msgsize = netmsg.size()
|
|
|
+ self.perfstats.bytes_sent += msgsize
|
|
|
self.peer.received(self, netmsg)
|
|
|
|
|
|
def reply(self, netmsg):
|
|
|
assert(isinstance(netmsg, NetMsg))
|
|
|
+ msgsize = netmsg.size()
|
|
|
+ self.perfstats.bytes_received += msgsize
|
|
|
self.receivedfromserver(netmsg)
|
|
|
|
|
|
- def received(self, netmsg):
|
|
|
- print("received", netmsg, "from server")
|
|
|
+ #def received(self, netmsg):
|
|
|
+ #print("received", netmsg, "from server")
|
|
|
|
|
|
|
|
|
class ServerConnection(Connection):
|