model.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. # This file is part of DarkFi (https://dark.fi)
  2. #
  3. # Copyright (C) 2020-2023 Dyne.org foundation
  4. #
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU Affero General Public License as
  7. # published by the Free Software Foundation, either version 3 of the
  8. # License, or (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU Affero General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU Affero General Public License
  16. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. import logging, time
  18. import datetime as dt
  19. from collections import defaultdict as dd
  20. class Model:
  21. def __init__(self):
  22. self.nodes = {}
  23. def add_node(self, node):
  24. channel_lookup = {}
  25. name = list(node.keys())[0]
  26. values = list(node.values())[0]
  27. info = values["result"]
  28. channels = info["channels"]
  29. self.nodes[name] = {}
  30. self.nodes[name]['outbound'] = {}
  31. self.nodes[name]['inbound'] = {}
  32. self.nodes[name]['manual'] = {}
  33. self.nodes[name]['event'] = {}
  34. self.nodes[name]['seed'] = {}
  35. self.nodes[name]['msgs'] = dd(list)
  36. for channel in channels:
  37. id = channel["id"]
  38. channel_lookup[id] = channel
  39. for channel in channels:
  40. if channel["session"] != "inbound":
  41. continue
  42. id = channel["id"]
  43. url = channel_lookup[id]["url"]
  44. self.nodes[name]['inbound'][f"{id}"] = url
  45. for i, id in enumerate(info["outbound_slots"]):
  46. if id == 0:
  47. outbounds = self.nodes[name]['outbound'][f"{i}"] = "none"
  48. continue
  49. assert id in channel_lookup
  50. url = channel_lookup[id]["url"]
  51. outbounds = self.nodes[name]['outbound'][f"{i}"] = url
  52. for channel in channels:
  53. if channel["session"] != "seed":
  54. continue
  55. id = channel["id"]
  56. url = channel["url"]
  57. self.nodes[name]['seed'][f"{id}"] = url
  58. for channel in channels:
  59. if channel["session"] != "manual":
  60. continue
  61. id = channel["id"]
  62. url = channel["url"]
  63. self.nodes[name]['manual'][f"{id}"] = url
  64. def add_offline(self, node):
  65. name = list(node.keys())[0]
  66. values = list(node.values())[0]
  67. self.nodes[name] = values
  68. def add_event(self, event):
  69. name = list(event.keys())[0]
  70. values = list(event.values())[0]
  71. params = values.get("params")
  72. event = params[0].get("event")
  73. info = params[0].get("info")
  74. t = time.localtime()
  75. current_time = time.strftime("%H:%M:%S", t)
  76. match event:
  77. case "send":
  78. nano = info.get("time")
  79. cmd = info.get("cmd")
  80. chan = info.get("chan")
  81. addr = chan.get("addr")
  82. t = (dt.datetime
  83. .fromtimestamp(int(nano)/1000000000)
  84. .strftime('%H:%M:%S'))
  85. msgs = self.nodes[name]['msgs']
  86. msgs[addr].append((t, event, cmd))
  87. case "recv":
  88. nano = info.get("time")
  89. cmd = info.get("cmd")
  90. chan = info.get("chan")
  91. addr = chan.get("addr")
  92. t = (dt.datetime
  93. .fromtimestamp(int(nano)/1000000000)
  94. .strftime('%H:%M:%S'))
  95. msgs = self.nodes[name]['msgs']
  96. msgs[addr].append((t, event, cmd))
  97. case "inbound_connected":
  98. addr = info["addr"]
  99. id = info.get("channel_id")
  100. self.nodes[name]['inbound'][f"{id}"] = addr
  101. logging.debug(f"{current_time} inbound (connect): {addr}")
  102. case "inbound_disconnected":
  103. addr = info["addr"]
  104. id = info.get("channel_id")
  105. inbound = self.nodes[name]['inbound']
  106. self.nodes[name]['inbound'][f"{id}"] = {}
  107. logging.debug(f"{current_time} inbound (disconnect): {addr}")
  108. case "outbound_slot_sleeping":
  109. slot = info["slot"]
  110. logging.debug(f"{current_time} slot {slot}: sleeping")
  111. self.nodes[name]['event'][(f"{name}", f"{slot}")] = "sleeping"
  112. case "outbound_slot_connecting":
  113. slot = info["slot"]
  114. addr = info["addr"]
  115. event = self.nodes[name]['event']
  116. event[(f"{name}", f"{slot}")] = f"connecting: addr={addr}"
  117. logging.debug(f"{current_time} slot {slot}: connecting addr={addr}")
  118. case "outbound_slot_connected":
  119. slot = info["slot"]
  120. addr = info["addr"]
  121. channel_id = info["channel_id"]
  122. event = self.nodes[name]['event']
  123. event[(f"{name}", f"{slot}")] = f"connected: addr={addr}"
  124. logging.debug(f"{current_time} slot {slot}: connected addr={addr}")
  125. case "outbound_slot_disconnected":
  126. slot = info["slot"]
  127. err = info["err"]
  128. event = self.nodes[name]['event']
  129. event[(f"{name}", f"{slot}")] = f"disconnected: {err}"
  130. logging.debug(f"{current_time} slot {slot}: disconnected err='{err}'")
  131. case "outbound_peer_discovery":
  132. attempt = info["attempt"]
  133. state = info["state"]
  134. event = self.nodes[name]['event']
  135. key = (f"{name}", "outbound")
  136. event[key] = f"peer discovery: {state} (attempt {attempt})"
  137. logging.debug(f"{current_time} peer_discovery: {state} (attempt {attempt})")
  138. def __repr__(self):
  139. return f"{self.nodes}"