client.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. #!/usr/bin/env python
  2. import socket
  3. import select
  4. import random
  5. import subprocess
  6. import time
  7. import re
  8. import peerfinder_pb2 as pf
  9. SERVER = ("::1", 9999)
  10. # In seconds
  11. HEARTBEAT_INTERVAL = random.randint(5, 15)
  12. RECONNECT_INTERVAL = random.randint(5, 15)
  13. NB_PINGS = 3
  14. ping_regexp = re.compile(r"time=(.*) ms")
  15. def ping(target, nb_pings=NB_PINGS):
  16. """Returns the list of latencies towards the given target"""
  17. if target.family == pf.IPAddress.IPV4:
  18. ping = "ping"
  19. elif target.family == pf.IPAddress.IPV6:
  20. ping = "ping6"
  21. args = [ping, "-n", "-c", str(nb_pings), str(target.address)]
  22. try:
  23. out = subprocess.check_output(args, shell=False)
  24. except subprocess.CalledProcessError:
  25. return []
  26. data = out.decode("utf8").split("\n")
  27. data = [ping_regexp.search(line) for line in data]
  28. return [float(m.group(1)) for m in data if m != None]
  29. def run_measurements(s):
  30. while True:
  31. try:
  32. data = s.recv(1024)
  33. print(data)
  34. if len(data) == 0:
  35. s.close()
  36. return
  37. msg = pf.Message()
  38. msg.ParseFromString(data)
  39. if msg.type == pf.Message.Pong:
  40. print("Got pong")
  41. else:
  42. target = msg.target
  43. latencies = ping(target.target)
  44. reply = pf.Message()
  45. reply.type = pf.Message.Measurement
  46. reply.measurement.target_id = msg.target.target_id
  47. reply.measurement.probes_sent = NB_PINGS
  48. reply.measurement.probes_received = len(latencies)
  49. reply.measurement.latency_us.extend([int(1000 * l) for l in latencies])
  50. # Debug
  51. #time.sleep(random.randint(1, 5))
  52. print("Sending results")
  53. s.send(reply.SerializeToString())
  54. except socket.timeout:
  55. pass
  56. #print("Not sending heartbeat")
  57. #msg = pf.Message()
  58. #msg.type = pf.Message.Ping
  59. #s.send(msg.SerializeToString())
  60. except ConnectionResetError:
  61. s.close()
  62. return
  63. if __name__ == '__main__':
  64. while True:
  65. sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
  66. sock.settimeout(HEARTBEAT_INTERVAL)
  67. try:
  68. sock.connect(SERVER)
  69. print("Connected to {}".format(SERVER))
  70. run_measurements(sock)
  71. except ConnectionRefusedError:
  72. pass
  73. print("Disconnected, reconnecting in {} seconds".format(RECONNECT_INTERVAL))
  74. time.sleep(RECONNECT_INTERVAL)