BootstrapperPlugin.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import time
  2. from Plugin import PluginManager
  3. from BootstrapperDb import BootstrapperDb
  4. from Crypt import CryptRsa
  5. if "db" not in locals().keys(): # Share durin reloads
  6. db = BootstrapperDb()
  7. @PluginManager.registerTo("FileRequest")
  8. class FileRequestPlugin(object):
  9. def actionAnnounce(self, params):
  10. hashes = params["hashes"]
  11. if "onion_signs" in params and len(params["onion_signs"]) == len(hashes):
  12. # Check if all sign is correct
  13. if time.time() - float(params["onion_sign_this"]) < 3*60: # Peer has 3 minute to sign the message
  14. onions_signed = []
  15. # Check onion signs
  16. for onion_publickey, onion_sign in params["onion_signs"].items():
  17. if CryptRsa.verify(params["onion_sign_this"], onion_publickey, onion_sign):
  18. onions_signed.append(CryptRsa.publickeyToOnion(onion_publickey))
  19. else:
  20. break
  21. # Check if the same onion addresses signed as the announced onces
  22. if sorted(onions_signed) == sorted(params["onions"]):
  23. all_onions_signed = True
  24. else:
  25. all_onions_signed = False
  26. else:
  27. # Onion sign this out of 3 minute
  28. all_onions_signed = False
  29. else:
  30. # Incorrect signs number
  31. all_onions_signed = False
  32. if "ip4" in params["add"] and self.connection.ip != "127.0.0.1" and not self.connection.ip.endswith(".onion"):
  33. ip4 = self.connection.ip
  34. else:
  35. ip4 = None
  36. # Separatley add onions to sites or at once if no onions present
  37. hashes_changed = 0
  38. i = 0
  39. for onion in params.get("onions", []):
  40. hashes_changed += db.peerAnnounce(
  41. onion=onion,
  42. port=params["port"],
  43. hashes=[hashes[i]],
  44. onion_signed=all_onions_signed
  45. )
  46. i += 1
  47. # Announce all sites if ip4 defined
  48. if ip4:
  49. hashes_changed += db.peerAnnounce(
  50. ip4=ip4,
  51. port=params["port"],
  52. hashes=hashes,
  53. delete_missing_hashes=params.get("delete")
  54. )
  55. # Query sites
  56. back = {}
  57. peers = []
  58. if params.get("onions") and not all_onions_signed and hashes_changed:
  59. back["onion_sign_this"] = "%.0f" % time.time() # Send back nonce for signing
  60. for hash in hashes:
  61. hash_peers = db.peerList(
  62. hash,
  63. ip4=self.connection.ip, onions=params.get("onions"), port=params["port"],
  64. limit=min(30, params["need_num"]), need_types=params["need_types"]
  65. )
  66. peers.append(hash_peers)
  67. back["peers"] = peers
  68. self.response(back)
  69. @PluginManager.registerTo("UiRequest")
  70. class UiRequestPlugin(object):
  71. def actionStatsBootstrapper(self):
  72. self.sendHeader()
  73. # Style
  74. yield """
  75. <style>
  76. * { font-family: monospace; white-space: pre }
  77. table td, table th { text-align: right; padding: 0px 10px }
  78. </style>
  79. """
  80. hash_rows = db.execute("SELECT * FROM hash").fetchall()
  81. for hash_row in hash_rows:
  82. peer_rows = db.execute(
  83. "SELECT * FROM peer LEFT JOIN peer_to_hash USING (peer_id) WHERE hash_id = :hash_id",
  84. {"hash_id": hash_row["hash_id"]}
  85. ).fetchall()
  86. yield "<br>%s (added: %s, peers: %s)<br>" % (
  87. str(hash_row["hash"]).encode("hex"), hash_row["date_added"], len(peer_rows)
  88. )
  89. for peer_row in peer_rows:
  90. yield " - {ip4: <30} {onion: <30} added: {date_added}, announced: {date_announced}<br>".format(**dict(peer_row))