distributed-state-network 0.5.2__tar.gz → 0.5.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/PKG-INFO +1 -1
  2. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/pyproject.toml +1 -1
  3. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/src/distributed_state_network/dsnode.py +18 -16
  4. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/src/distributed_state_network/handler.py +1 -1
  5. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/src/distributed_state_network/objects/config.py +3 -1
  6. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/tests/connections.py +1 -0
  7. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/.github/workflows/publish.yml +0 -0
  8. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/.gitignore +0 -0
  9. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/LICENSE +0 -0
  10. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/README.md +0 -0
  11. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/coverage.sh +0 -0
  12. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/documentation/ds-node-config.md +0 -0
  13. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/documentation/ds-node-server.md +0 -0
  14. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/documentation/ds-node.md +0 -0
  15. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/documentation/protocol.md +0 -0
  16. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/documentation/usage.md +0 -0
  17. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/src/distributed_state_network/__init__.py +0 -0
  18. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/src/distributed_state_network/create_key.py +0 -0
  19. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/src/distributed_state_network/objects/endpoint.py +0 -0
  20. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/src/distributed_state_network/objects/hello_packet.py +0 -0
  21. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/src/distributed_state_network/objects/msg_types.py +0 -0
  22. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/src/distributed_state_network/objects/peers_packet.py +0 -0
  23. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/src/distributed_state_network/objects/signed_packet.py +0 -0
  24. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/src/distributed_state_network/objects/state_packet.py +0 -0
  25. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/src/distributed_state_network/util/__init__.py +0 -0
  26. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/src/distributed_state_network/util/aes.py +0 -0
  27. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/src/distributed_state_network/util/byte_helper.py +0 -0
  28. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/src/distributed_state_network/util/ecdsa.py +0 -0
  29. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/src/distributed_state_network/util/https.py +0 -0
  30. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/src/distributed_state_network/util/key_manager.py +0 -0
  31. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/technical.md +0 -0
  32. {distributed_state_network-0.5.2 → distributed_state_network-0.5.4}/tests/test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: distributed-state-network
3
- Version: 0.5.2
3
+ Version: 0.5.4
4
4
  Summary: A tool to distribute the state of a network device to other devices on the network
5
5
  Project-URL: Homepage, https://github.com/erinclemmer/distributed_state_network
6
6
  Project-URL: Issues, https://github.com/erinclemmer/distributed_state_network/issues
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "distributed-state-network"
7
- version = "0.5.2"
7
+ version = "0.5.4"
8
8
  authors = [{name="Erin Clemmer", email="erin.c.clemmer@gmail.com"}]
9
9
  description = "A tool to distribute the state of a network device to other devices on the network"
10
10
  keywords = ["distributed", "networking"]
@@ -56,10 +56,8 @@ class DSNode:
56
56
  self.config.node_id: StatePacket.create(self.config.node_id, time.time(), self.cred_manager.my_private(), { })
57
57
  }
58
58
 
59
- # Determine initial IP - use 127.0.0.1 for localhost, will be updated when connecting to remote nodes
60
- initial_ip = "127.0.0.1"
61
59
  self.address_book = {
62
- self.config.node_id: Endpoint(initial_ip, config.port)
60
+ self.config.node_id: Endpoint(self.config.network_ip, config.port)
63
61
  }
64
62
 
65
63
  self.logger = logging.getLogger("DSN: " + config.node_id)
@@ -74,6 +72,12 @@ class DSNode:
74
72
  def get_aes_key(self) -> bytes:
75
73
  return bytes.fromhex(self.config.aes_key)
76
74
 
75
+ def write_address_book(self, node_id: str, conn: Endpoint):
76
+ if conn.address == "127.0.0.1":
77
+ return
78
+ self.logger.info(f"Address set: {node_id} -> {conn.address}:{conn.port}")
79
+ self.address_book[node_id] = conn
80
+
77
81
  def network_tick(self):
78
82
  time.sleep(TICK_INTERVAL)
79
83
  if self.shutting_down:
@@ -96,6 +100,7 @@ class DSNode:
96
100
  return
97
101
  self.send_ping(node_id)
98
102
  except Exception:
103
+ self.logger.error(f"PING Failure for {node_id}")
99
104
  if node_id in self.node_states: # double check if something has changed since the ping request started
100
105
  remove(node_id)
101
106
  if self.disconnect_cb is not None:
@@ -185,11 +190,11 @@ class DSNode:
185
190
  if key == self.config.node_id:
186
191
  continue
187
192
 
188
- self.address_book[key] = pkt.connections[key]
193
+ self.write_address_book(key, pkt.connections[key])
189
194
 
190
195
  if key not in self.node_states:
191
196
  self.send_hello(self.address_book[key])
192
-
197
+
193
198
  node_state = self.send_update(key)
194
199
  self.handle_update(node_state)
195
200
 
@@ -203,6 +208,8 @@ class DSNode:
203
208
 
204
209
  peers = { }
205
210
  for key in self.address_book.keys():
211
+ if key == self.config.node_id:
212
+ continue
206
213
  peers[key] = self.address_book[key]
207
214
 
208
215
  pkt = PeersPacket(self.config.node_id, None, peers)
@@ -213,7 +220,6 @@ class DSNode:
213
220
  self.logger.info(f"HELLO => {con.to_string()}")
214
221
 
215
222
  pkt = self.my_hello_packet()
216
- pkt.detected_address = con.address
217
223
  payload = pkt.to_bytes()
218
224
  content = self.send_http_request(con, MSG_HELLO, payload)
219
225
 
@@ -234,18 +240,16 @@ class DSNode:
234
240
  if pkt.detected_address:
235
241
  self.logger.info(f"Server detected our IP as: {pkt.detected_address}")
236
242
  # Update our own connection in the address book with the detected IP
237
- self.address_book[self.config.node_id] = Endpoint(pkt.detected_address, self.config.port)
243
+ self.write_address_book(self.config.node_id, pkt.detected_address, self.config.port)
238
244
 
239
- # Store the peer's connection info
240
- if pkt.node_id not in self.address_book:
241
- self.address_book[pkt.node_id] = pkt.connection
245
+ self.write_address_book(pkt.node_id, con)
242
246
 
243
247
  if pkt.node_id not in self.node_states:
244
248
  self.node_states[pkt.node_id] = StatePacket(pkt.node_id, 0, b'', { })
245
249
 
246
250
  return pkt.node_id
247
251
 
248
- def handle_hello(self, data: bytes, detected_address: str = None) -> bytes | None:
252
+ def handle_hello(self, data: bytes, detected_address: str) -> bytes:
249
253
  pkt = HelloPacket.from_bytes(data)
250
254
  self.logger.info(f"Received HELLO from {pkt.node_id}")
251
255
  if pkt.version != self.version:
@@ -254,9 +258,7 @@ class DSNode:
254
258
  raise Exception(505) # Version not supported
255
259
 
256
260
  self.cred_manager.ensure_public(pkt.node_id, pkt.ecdsa_public_key)
257
-
258
- if pkt.node_id not in self.address_book:
259
- self.address_book[pkt.node_id] = pkt.connection
261
+ self.write_address_book(pkt.node_id, Endpoint(detected_address, pkt.connection.port))
260
262
 
261
263
  if pkt.node_id not in self.node_states:
262
264
  self.node_states[pkt.node_id] = StatePacket(pkt.node_id, 0, b'', { })
@@ -280,6 +282,8 @@ class DSNode:
280
282
 
281
283
  def send_ping(self, node_id: str):
282
284
  try:
285
+ conn = self.connection_from_node(node_id)
286
+ self.logger.debug(f"PING => {node_id} ({conn.address}:{conn.port})")
283
287
  self.send_request_to_node(node_id, MSG_PING, b' ')
284
288
  except Exception as e:
285
289
  raise Exception(f'PING => {node_id}: {e}')
@@ -306,7 +310,6 @@ class DSNode:
306
310
 
307
311
  if pkt.node_id not in self.node_states:
308
312
  self.node_states[pkt.node_id] = pkt
309
- return
310
313
 
311
314
  if get_dict_hash(self.node_states[pkt.node_id].state_data) != get_dict_hash(pkt.state_data):
312
315
  self.node_states[pkt.node_id] = pkt
@@ -325,7 +328,6 @@ class DSNode:
325
328
 
326
329
  def bootstrap(self, con: Endpoint):
327
330
  bootstrap_id = self.send_hello(con)
328
- self.address_book[bootstrap_id] = con
329
331
  content = self.send_update(bootstrap_id)
330
332
  self.handle_update(content)
331
333
  self.request_peers(bootstrap_id)
@@ -8,7 +8,7 @@ from distributed_state_network.objects.config import DSNodeConfig
8
8
  from distributed_state_network.util.aes import generate_aes_key
9
9
  from distributed_state_network.util import stop_thread
10
10
 
11
- VERSION = "0.5.2"
11
+ VERSION = "0.5.4"
12
12
  logging.basicConfig(level=logging.INFO)
13
13
 
14
14
  # Silence Flask and Werkzeug logging
@@ -8,6 +8,7 @@ class DSNodeConfig:
8
8
  node_id: str
9
9
  credential_dir: str
10
10
  port: int
11
+ network_ip: str
11
12
  aes_key: str | None
12
13
  bootstrap_nodes: List[Endpoint]
13
14
 
@@ -16,7 +17,8 @@ class DSNodeConfig:
16
17
  return DSNodeConfig(
17
18
  data["node_id"],
18
19
  data["credential_dir"] if "credential_dir" in data else "credentials",
19
- data["port"],
20
+ data["port"],
21
+ data["network_ip"] if "network_ip" in data else "127.0.0.1",
20
22
  data["aes_key"] if "aes_key" in data else None,
21
23
  [Endpoint.from_json(e) for e in data["bootstrap_nodes"]]
22
24
  )
@@ -20,6 +20,7 @@ def start_node(node_id: str, bootstrap_port: int = None, disconnect_cb: Optional
20
20
  "node_id": node_id,
21
21
  "port": current_port,
22
22
  "aes_key": aes_key,
23
+ "network_ip": "127.0.0.1",
23
24
  "credential_dir": "credentials"
24
25
  }
25
26
  current_port += 1