distributed-state-network 0.0.3__tar.gz → 0.0.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 (31) hide show
  1. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/PKG-INFO +1 -1
  2. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/documentation/ds-node-server.md +3 -1
  3. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/documentation/ds-node.md +2 -1
  4. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/documentation/usage.md +16 -0
  5. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/pyproject.toml +1 -1
  6. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/src/distributed_state_network/dsnode.py +6 -1
  7. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/src/distributed_state_network/handler.py +5 -4
  8. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/tests/connections.py +22 -8
  9. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/.github/workflows/publish.yml +0 -0
  10. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/.gitignore +0 -0
  11. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/LICENSE +0 -0
  12. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/README.md +0 -0
  13. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/coverage.sh +0 -0
  14. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/documentation/ds-node-config.md +0 -0
  15. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/documentation/protocol.md +0 -0
  16. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/src/distributed_state_network/__init__.py +0 -0
  17. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/src/distributed_state_network/create_key.py +0 -0
  18. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/src/distributed_state_network/objects/config.py +0 -0
  19. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/src/distributed_state_network/objects/endpoint.py +0 -0
  20. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/src/distributed_state_network/objects/hello_packet.py +0 -0
  21. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/src/distributed_state_network/objects/peers_packet.py +0 -0
  22. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/src/distributed_state_network/objects/signed_packet.py +0 -0
  23. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/src/distributed_state_network/objects/state_packet.py +0 -0
  24. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/src/distributed_state_network/util/__init__.py +0 -0
  25. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/src/distributed_state_network/util/aes.py +0 -0
  26. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/src/distributed_state_network/util/byte_helper.py +0 -0
  27. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/src/distributed_state_network/util/ecdsa.py +0 -0
  28. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/src/distributed_state_network/util/https.py +0 -0
  29. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/src/distributed_state_network/util/key_manager.py +0 -0
  30. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/technical.md +0 -0
  31. {distributed_state_network-0.0.3 → distributed_state_network-0.0.4}/test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: distributed-state-network
3
- Version: 0.0.3
3
+ Version: 0.0.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
@@ -18,10 +18,11 @@ class DSNodeServer(HTTPServer):
18
18
  **Parameters:**
19
19
  - `config` (`DSNodeConfig`): Node configuration
20
20
  - `disconnect_callback` (`Optional[Callable]`): Callback for disconnect events
21
+ - `update_callback` (`Optional[Callable]`): Callback for state update events
21
22
 
22
23
  ### Static Methods
23
24
 
24
- ### `start(config: DSNodeConfig, disconnect_callback: Optional[Callable] = None) -> DSNodeServer`
25
+ ### `start(config: DSNodeConfig, disconnect_callback: Optional[Callable] = None, update_callback: Optional[Callable] = None) -> DSNodeServer`
25
26
  Creates and starts a new DSNodeServer instance with SSL configuration.
26
27
  ```python
27
28
  server = DSNodeServer.start(config)
@@ -30,6 +31,7 @@ server = DSNodeServer.start(config)
30
31
  **Parameters:**
31
32
  - `config` (`DSNodeConfig`): Node configuration
32
33
  - `disconnect_callback` (`Optional[Callable]`): Callback for disconnect events
34
+ - `update_callback` (`Optional[Callable]`): Callback for state update events
33
35
 
34
36
  **Returns:**
35
37
  - `DSNodeServer`: Running server instance
@@ -18,13 +18,14 @@ class DSNode:
18
18
  ### Constructor
19
19
 
20
20
  ```python
21
- node = DSNode(config, "0.0.3", disconnect_callback=on_disconnect)
21
+ node = DSNode(config, "0.0.3", disconnect_callback=on_disconnect, update_callback=on_update)
22
22
  ```
23
23
 
24
24
  **Parameters:**
25
25
  - `config` (`DSNodeConfig`): Node configuration
26
26
  - `version` (`str`): Protocol version string for compatibility checking
27
27
  - `disconnect_callback` (`Optional[Callable]`): Callback function invoked when a peer disconnects
28
+ - `update_callback` (`Optional[Callable]`): Callback function invoked when the state of node updates
28
29
 
29
30
  ### Key Methods
30
31
 
@@ -65,4 +65,20 @@ config = DSNodeConfig(
65
65
  )
66
66
 
67
67
  server = DSNodeServer.start(config, disconnect_callback=handle_disconnect)
68
+ ```
69
+
70
+ ### With Update Callback
71
+
72
+ ```python
73
+ def handle_update():
74
+ print("A peer has updated!")
75
+
76
+ config = DSNodeConfig(
77
+ node_id="node3",
78
+ port=8002,
79
+ aes_key_file="/path/to/shared.key",
80
+ bootstrap_nodes=[Endpoint("127.0.0.1", 8000)]
81
+ )
82
+
83
+ server = DSNodeServer.start(config, update_callback=handle_update)
68
84
  ```
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "distributed-state-network"
7
- version = "0.0.3"
7
+ version = "0.0.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"]
@@ -29,7 +29,8 @@ class DSNode:
29
29
  self,
30
30
  config: DSNodeConfig,
31
31
  version: str,
32
- disconnect_callback: Optional[Callable] = None
32
+ disconnect_callback: Optional[Callable] = None,
33
+ update_callback: Optional[Callable] = None
33
34
  ):
34
35
  self.config = config
35
36
  self.version = version
@@ -50,6 +51,7 @@ class DSNode:
50
51
 
51
52
  self.logger = logging.getLogger("DSN: " + config.node_id)
52
53
  self.disconnect_cb = disconnect_callback
54
+ self.update_cb = update_callback
53
55
  if not os.path.exists(config.aes_key_file):
54
56
  raise Exception(f"Could not find aes key file in {config.aes_key_file}")
55
57
  threading.Thread(target=self.network_tick).start()
@@ -231,6 +233,9 @@ class DSNode:
231
233
  if get_dict_hash(self.node_states[pkt.node_id].state_data) != get_dict_hash(pkt.state_data):
232
234
  self.node_states[pkt.node_id] = pkt
233
235
 
236
+ if self.update_cb is not None:
237
+ self.update_cb()
238
+
234
239
  return self.my_state().to_bytes()
235
240
 
236
241
  def my_state(self):
@@ -70,11 +70,12 @@ class DSNodeServer(HTTPServer):
70
70
  def __init__(
71
71
  self,
72
72
  config: DSNodeConfig,
73
- disconnect_callback: Optional[Callable] = None
73
+ disconnect_callback: Optional[Callable] = None,
74
+ update_callback: Optional[Callable] = None
74
75
  ):
75
76
  super().__init__(("127.0.0.1", config.port), DSNodeHandler)
76
77
  self.config = config
77
- self.node = DSNode(config, VERSION, disconnect_callback)
78
+ self.node = DSNode(config, VERSION, disconnect_callback, update_callback)
78
79
  self.node.logger.info(f'Started DSNode on port {config.port}')
79
80
 
80
81
  def stop(self):
@@ -90,8 +91,8 @@ class DSNodeServer(HTTPServer):
90
91
  f.write(key)
91
92
 
92
93
  @staticmethod
93
- def start(config: DSNodeConfig, disconnect_callback: Optional[Callable] = None) -> 'NodeServer':
94
- n = DSNodeServer(config, disconnect_callback)
94
+ def start(config: DSNodeConfig, disconnect_callback: Optional[Callable] = None, update_callback: Optional[Callable] = None) -> 'NodeServer':
95
+ n = DSNodeServer(config, disconnect_callback, update_callback)
95
96
  ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
96
97
  public_path = n.node.cert_manager.public_path(n.config.node_id)
97
98
  ssl_context.load_cert_chain(
@@ -13,11 +13,11 @@ KEY_FILE = "network.key"
13
13
  if not os.path.exists(KEY_FILE):
14
14
  DSNodeServer.generate_key("network.key")
15
15
 
16
- d_cb_test = 0
16
+ cb_test = 0
17
17
 
18
18
  current_port = 5000
19
19
 
20
- def start_node(node_id: str, bootstrap_port: int = None, disconnect_cb: Optional[Callable] = None):
20
+ def start_node(node_id: str, bootstrap_port: int = None, disconnect_cb: Optional[Callable] = None, update_cb: Optional[Callable] = None):
21
21
  global current_port
22
22
  args = {
23
23
  "node_id": node_id,
@@ -33,7 +33,7 @@ def start_node(node_id: str, bootstrap_port: int = None, disconnect_cb: Optional
33
33
  else:
34
34
  args["bootstrap_nodes"] = []
35
35
 
36
- return DSNodeServer.start(DSNodeConfig(**args), disconnect_cb)
36
+ return DSNodeServer.start(DSNodeConfig(**args), disconnect_cb, update_cb)
37
37
 
38
38
  class ConnectionsTest(unittest.TestCase):
39
39
  def test_one(self):
@@ -75,17 +75,31 @@ class ConnectionsTest(unittest.TestCase):
75
75
  self.assertEqual(["node-1", "node-3", "node-4"], sorted(node4.node.peers()))
76
76
 
77
77
  def test_disconnect_cb(self):
78
- global d_cb_test
79
- d_cb_test = 0
78
+ global cb_test
79
+ cb_test = 0
80
80
  def inc():
81
- global d_cb_test
82
- d_cb_test = 1
81
+ global cb_test
82
+ cb_test = 1
83
83
  node1 = start_node("node-1", None, inc)
84
84
  node2 = start_node("node-2", node1.config.port)
85
85
  time.sleep(1)
86
86
  node2.stop()
87
87
  time.sleep(5)
88
- self.assertEqual(d_cb_test, 1)
88
+ self.assertEqual(cb_test, 1)
89
+
90
+ def test_update_cb(self):
91
+ global cb_test
92
+ cb_test = 0
93
+ def inc():
94
+ global cb_test
95
+ cb_test = 1
96
+ node1 = start_node("node-1", None, None, inc)
97
+ node2 = start_node("node-2", node1.config.port)
98
+
99
+ node2.node.update_data("key", "value")
100
+ time.sleep(1)
101
+
102
+ self.assertEqual(cb_test, 1)
89
103
 
90
104
  if __name__ == '__main__':
91
105
  unittest.main()