emion 0.2.0__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.
@@ -0,0 +1,3 @@
1
+ include README.md
2
+ include LICENSE
3
+ recursive-include emion/dashboard/static *
emion-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,144 @@
1
+ Metadata-Version: 2.4
2
+ Name: emion
3
+ Version: 0.2.0
4
+ Summary: Professional ION-DTN Mission Control & BPv7 Simulation Framework
5
+ Author: EmION Team
6
+ Author-email: EmION Team <dev@info-gallary.com>
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/info-gallary/emion
9
+ Project-URL: Repository, https://github.com/info-gallary/emion.git
10
+ Keywords: dtn,ion,bpv7,simulation,space,networking
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: POSIX :: Linux
16
+ Classifier: Topic :: Scientific/Engineering
17
+ Requires-Python: >=3.8
18
+ Description-Content-Type: text/markdown
19
+ Provides-Extra: dashboard
20
+ Requires-Dist: fastapi>=0.100.0; extra == "dashboard"
21
+ Requires-Dist: uvicorn>=0.20.0; extra == "dashboard"
22
+ Requires-Dist: websockets>=11.0; extra == "dashboard"
23
+ Dynamic: author
24
+
25
+ # โš›๏ธ EmION โ€” Professional ION-DTN Simulation
26
+
27
+ EmION is an authentic, production-ready Delay-Tolerant Networking (DTN) simulation framework. Unlike other simulators, EmION uses the **real ION-DTN C-engine** and **Contact Graph Routing (CGR)** for 100% protocol authenticity.
28
+
29
+ ---
30
+
31
+ ## ๐Ÿš€ 1. Installation
32
+
33
+ EmION requires **ION-DTN** (C-engine) and **pyion** to be installed on your Linux system.
34
+
35
+ ### One-Click Setup
36
+ We provide a unified installer that checks dependencies and installs the package:
37
+ ```bash
38
+ chmod +x install.sh
39
+ ./install.sh
40
+ ```
41
+
42
+ ### Manual Installation
43
+ ```bash
44
+ pip install -e ".[dashboard]"
45
+ ```
46
+
47
+ ---
48
+
49
+ ## ๐Ÿงช 2. Verification
50
+
51
+ Ensure your environment is correctly configured by running the professional test suite. This verifies real-time bundle transit and CGR routing:
52
+ ```bash
53
+ python3 tests/test_emion.py
54
+ ```
55
+
56
+ ---
57
+
58
+ ## ๐Ÿ›ฐ๏ธ 3. Usage
59
+
60
+ ### Launching Mission Control
61
+ Start the visual dashboard to manage multi-node topologies and view live telemetry:
62
+ ```bash
63
+ emion dashboard
64
+ ```
65
+ - **URL**: `http://localhost:8420`
66
+ - **Telemetry**: Real-time SDR memory and bundle tracking.
67
+ - **Visuals**: Canvas-based topology with bundle animation.
68
+
69
+ ### Command Line Interface
70
+ ```bash
71
+ emion info # Check ION system status
72
+ emion dashboard # Start visual UI
73
+ ```
74
+
75
+ ---
76
+
77
+ ## ๐Ÿ”Œ 4. Connecting Third-Party Modules (API)
78
+
79
+ EmION supports selective attachment of Anomaly Detection or Security modules via a **FastAPI-based Plugin System**.
80
+
81
+ ### Step A: Implement your Plugin
82
+ Your module must be a web service (FastAPI) with these endpoints:
83
+ 1. `GET /health` -> `{"status": "ok"}`
84
+ 2. `POST /analyze` -> Receives bundle `payload` and `metadata`, returns:
85
+ ```json
86
+ {
87
+ "is_anomaly": true,
88
+ "score": 0.95,
89
+ "label": "attack",
90
+ "details": {"reason": "Payload too large"}
91
+ }
92
+ ```
93
+
94
+ ### Step B: Connect to EmION
95
+ In the Dashboard UI (or via API), connect your module:
96
+ - **Module URL**: `http://localhost:8421`
97
+ - **Target Nodes**: Selectively monitor specific nodes (e.g., `1,3`) or `all`.
98
+
99
+ ### Demo Reference
100
+ See `anomaly_detector.py` for a functional sample implementation.
101
+
102
+ ---
103
+
104
+ ## ๐Ÿณ 5. Docker (Self-Contained BPv7)
105
+
106
+ Run the entire EmION environment (ION-DTN + pyion + Dashboard) without local installation.
107
+
108
+ ### Build and Run
109
+ ```bash
110
+ docker build -t emion .
111
+ docker run -p 8420:8420 emion
112
+ ```
113
+ Access Mission Control at `http://localhost:8420`.
114
+
115
+ ---
116
+
117
+ ## ๐Ÿ“ฆ 6. Publishing to PyPI
118
+
119
+ ### Build the Package
120
+ ```bash
121
+ pip install build twine
122
+ python3 -m build
123
+ ```
124
+
125
+ ### Upload to PyPI
126
+ ```bash
127
+ twine upload dist/*
128
+ ```
129
+
130
+ ---
131
+
132
+ ## ๐Ÿ—๏ธ Project Structure
133
+ - `emion/` โ€” Core BPv7 orchestration.
134
+ - `docs/` โ€” [Coding Guide](docs/coding_guide.md) & [Usage Notebook](docs/usage_demo.ipynb).
135
+ - `ION-DTN/` โ€” Authentic NASA-JPL C-Engine.
136
+ - `Dockerfile` โ€” Professional self-contained environment.
137
+ - `README.md` โ€” This guide.
138
+
139
+ ---
140
+
141
+ **Authentic. Professional. Space-Ready.** โš›๏ธ
142
+ - ION-DTN (compiled, with ionadmin/bpadmin in PATH)
143
+ - pyion (built against your ION installation)
144
+ - FastAPI + uvicorn + websockets (for dashboard)
emion-0.2.0/README.md ADDED
@@ -0,0 +1,120 @@
1
+ # โš›๏ธ EmION โ€” Professional ION-DTN Simulation
2
+
3
+ EmION is an authentic, production-ready Delay-Tolerant Networking (DTN) simulation framework. Unlike other simulators, EmION uses the **real ION-DTN C-engine** and **Contact Graph Routing (CGR)** for 100% protocol authenticity.
4
+
5
+ ---
6
+
7
+ ## ๐Ÿš€ 1. Installation
8
+
9
+ EmION requires **ION-DTN** (C-engine) and **pyion** to be installed on your Linux system.
10
+
11
+ ### One-Click Setup
12
+ We provide a unified installer that checks dependencies and installs the package:
13
+ ```bash
14
+ chmod +x install.sh
15
+ ./install.sh
16
+ ```
17
+
18
+ ### Manual Installation
19
+ ```bash
20
+ pip install -e ".[dashboard]"
21
+ ```
22
+
23
+ ---
24
+
25
+ ## ๐Ÿงช 2. Verification
26
+
27
+ Ensure your environment is correctly configured by running the professional test suite. This verifies real-time bundle transit and CGR routing:
28
+ ```bash
29
+ python3 tests/test_emion.py
30
+ ```
31
+
32
+ ---
33
+
34
+ ## ๐Ÿ›ฐ๏ธ 3. Usage
35
+
36
+ ### Launching Mission Control
37
+ Start the visual dashboard to manage multi-node topologies and view live telemetry:
38
+ ```bash
39
+ emion dashboard
40
+ ```
41
+ - **URL**: `http://localhost:8420`
42
+ - **Telemetry**: Real-time SDR memory and bundle tracking.
43
+ - **Visuals**: Canvas-based topology with bundle animation.
44
+
45
+ ### Command Line Interface
46
+ ```bash
47
+ emion info # Check ION system status
48
+ emion dashboard # Start visual UI
49
+ ```
50
+
51
+ ---
52
+
53
+ ## ๐Ÿ”Œ 4. Connecting Third-Party Modules (API)
54
+
55
+ EmION supports selective attachment of Anomaly Detection or Security modules via a **FastAPI-based Plugin System**.
56
+
57
+ ### Step A: Implement your Plugin
58
+ Your module must be a web service (FastAPI) with these endpoints:
59
+ 1. `GET /health` -> `{"status": "ok"}`
60
+ 2. `POST /analyze` -> Receives bundle `payload` and `metadata`, returns:
61
+ ```json
62
+ {
63
+ "is_anomaly": true,
64
+ "score": 0.95,
65
+ "label": "attack",
66
+ "details": {"reason": "Payload too large"}
67
+ }
68
+ ```
69
+
70
+ ### Step B: Connect to EmION
71
+ In the Dashboard UI (or via API), connect your module:
72
+ - **Module URL**: `http://localhost:8421`
73
+ - **Target Nodes**: Selectively monitor specific nodes (e.g., `1,3`) or `all`.
74
+
75
+ ### Demo Reference
76
+ See `anomaly_detector.py` for a functional sample implementation.
77
+
78
+ ---
79
+
80
+ ## ๐Ÿณ 5. Docker (Self-Contained BPv7)
81
+
82
+ Run the entire EmION environment (ION-DTN + pyion + Dashboard) without local installation.
83
+
84
+ ### Build and Run
85
+ ```bash
86
+ docker build -t emion .
87
+ docker run -p 8420:8420 emion
88
+ ```
89
+ Access Mission Control at `http://localhost:8420`.
90
+
91
+ ---
92
+
93
+ ## ๐Ÿ“ฆ 6. Publishing to PyPI
94
+
95
+ ### Build the Package
96
+ ```bash
97
+ pip install build twine
98
+ python3 -m build
99
+ ```
100
+
101
+ ### Upload to PyPI
102
+ ```bash
103
+ twine upload dist/*
104
+ ```
105
+
106
+ ---
107
+
108
+ ## ๐Ÿ—๏ธ Project Structure
109
+ - `emion/` โ€” Core BPv7 orchestration.
110
+ - `docs/` โ€” [Coding Guide](docs/coding_guide.md) & [Usage Notebook](docs/usage_demo.ipynb).
111
+ - `ION-DTN/` โ€” Authentic NASA-JPL C-Engine.
112
+ - `Dockerfile` โ€” Professional self-contained environment.
113
+ - `README.md` โ€” This guide.
114
+
115
+ ---
116
+
117
+ **Authentic. Professional. Space-Ready.** โš›๏ธ
118
+ - ION-DTN (compiled, with ionadmin/bpadmin in PATH)
119
+ - pyion (built against your ION installation)
120
+ - FastAPI + uvicorn + websockets (for dashboard)
@@ -0,0 +1,19 @@
1
+ """
2
+ EmION โ€” Authentic ION-DTN Framework.
3
+ All operations use real ION C-engine + pyion. No dummies.
4
+ """
5
+
6
+ __version__ = "0.1.0"
7
+ __author__ = "EmION Team"
8
+
9
+ from .core.node import EmionNode
10
+ from .core.engine import EmionEngine
11
+ from .plugins.base import APIPlugin
12
+
13
+ ION_AVAILABLE = True
14
+
15
+
16
+ def dashboard(host="0.0.0.0", port=8420):
17
+ """Launch the EmION web dashboard."""
18
+ from .dashboard.server import run
19
+ run(host=host, port=port)
@@ -0,0 +1,67 @@
1
+ """
2
+ EmION CLI โ€” all operations use real ION-DTN.
3
+
4
+ emion dashboard Launch the web dashboard
5
+ emion info Show ION-DTN status
6
+ emion test Run the 2-node communication test
7
+ """
8
+
9
+ import sys
10
+ import argparse
11
+
12
+
13
+ def main():
14
+ parser = argparse.ArgumentParser(
15
+ prog="emion",
16
+ description="EmION โ€” Authentic ION-DTN Framework"
17
+ )
18
+ sub = parser.add_subparsers(dest="cmd")
19
+
20
+ d = sub.add_parser("dashboard", help="Launch the web dashboard")
21
+ d.add_argument("--host", default="0.0.0.0")
22
+ d.add_argument("--port", type=int, default=8420)
23
+
24
+ sub.add_parser("info", help="Show ION-DTN status")
25
+ sub.add_parser("test", help="Run 2-node comm test")
26
+
27
+ args = parser.parse_args()
28
+
29
+ if args.cmd == "dashboard":
30
+ from emion.dashboard.server import run
31
+ run(host=args.host, port=args.port)
32
+ elif args.cmd == "info":
33
+ _info()
34
+ elif args.cmd == "test":
35
+ _test()
36
+ else:
37
+ parser.print_help()
38
+
39
+
40
+ def _info():
41
+ import shutil
42
+ import emion
43
+ print(f"\n โš› EmION v{emion.__version__}")
44
+ for cmd in ["ionadmin", "bpadmin", "ionsecadmin", "bprecvfile", "bpsendfile"]:
45
+ path = shutil.which(cmd)
46
+ print(f" {cmd}: {'โœ… ' + path if path else 'โŒ not found'}")
47
+ try:
48
+ import pyion
49
+ print(f" pyion: โœ…")
50
+ except ImportError:
51
+ print(f" pyion: โŒ not found")
52
+ try:
53
+ import fastapi
54
+ print(f" fastapi: v{fastapi.__version__}")
55
+ except ImportError:
56
+ print(f" fastapi: โŒ (pip install fastapi uvicorn websockets)")
57
+ print()
58
+
59
+
60
+ def _test():
61
+ from tests.test_emion import test_two_node_communication
62
+ ok = test_two_node_communication()
63
+ sys.exit(0 if ok else 1)
64
+
65
+
66
+ if __name__ == "__main__":
67
+ main()
@@ -0,0 +1,3 @@
1
+ from .node import EmionNode
2
+ from .engine import EmionEngine
3
+ from . import network
@@ -0,0 +1,74 @@
1
+ """
2
+ EmionEngine โ€” Python interface to ION-DTN via pyion C-bindings.
3
+ Handles memory attachment, bundle send/receive.
4
+ No dummies โ€” requires a running ION node.
5
+ """
6
+
7
+ import os
8
+ import time
9
+ import pyion
10
+
11
+
12
+ class EmionEngine:
13
+ """
14
+ High-level Python wrapper over pyion C-bindings for a single ION node.
15
+ Must be used after EmionNode.start() has booted the C daemons.
16
+ """
17
+
18
+ def __init__(self, node_id: int, base_dir: str = "/tmp/emion_nodes"):
19
+ self.node_id = node_id
20
+ self.node_dir = os.path.join(base_dir, str(node_id))
21
+ self.proxy = None
22
+
23
+ def attach(self, retries=5, delay=2):
24
+ """Attach to the ION shared-memory region via pyion."""
25
+ print(f"[EmION] Attaching engine to Node {self.node_id}...")
26
+
27
+ # Ensure ION_NODE_LIST_DIR is unset โ€” we use cwd instead
28
+ os.environ.pop("ION_NODE_LIST_DIR", None)
29
+ pyion.ION_NODE_LIST_DIR = None
30
+ os.environ["ION_NODE_NUMBER"] = str(self.node_id)
31
+
32
+ saved_dir = os.getcwd()
33
+ os.chdir(self.node_dir)
34
+
35
+ try:
36
+ for attempt in range(1, retries + 1):
37
+ try:
38
+ self.proxy = pyion.get_bp_proxy(self.node_id)
39
+ print(f" โœ… Attached (attempt {attempt})")
40
+ return True
41
+ except Exception as e:
42
+ print(f" [!] Attempt {attempt}/{retries}: {e}")
43
+ time.sleep(delay)
44
+ finally:
45
+ os.chdir(saved_dir)
46
+
47
+ raise RuntimeError(
48
+ f"Cannot attach to ION Node {self.node_id}. "
49
+ f"Is the node running? Check {self.node_dir}/node_boot.log"
50
+ )
51
+
52
+ def send(self, src_eid: str, dst_eid: str, payload: bytes):
53
+ """Send a bundle via the real ION Bundle Protocol engine."""
54
+ if not self.proxy:
55
+ self.attach()
56
+ with self.proxy.bp_open(src_eid) as ep:
57
+ result = ep.bp_send(dst_eid, payload)
58
+ print(f" ๐Ÿ“ก Sent {len(payload)}B {src_eid} โ†’ {dst_eid}")
59
+ return result
60
+
61
+ def receive(self, eid: str, timeout: int = 10):
62
+ """Receive a bundle from the ION BP engine."""
63
+ if not self.proxy:
64
+ self.attach()
65
+ with self.proxy.bp_open(eid) as ep:
66
+ data = ep.bp_receive(timeout=timeout)
67
+ if data:
68
+ print(f" ๐Ÿ“ฅ Received {len(data)}B on {eid}")
69
+ return data
70
+
71
+ def detach(self):
72
+ """Detach from the ION proxy."""
73
+ if self.proxy:
74
+ self.proxy = None
@@ -0,0 +1,101 @@
1
+ """
2
+ Emion Network - High-level orchestration API for ION-DTN.
3
+ Provides simple functional interface for notebooks and scripts.
4
+ """
5
+
6
+ import time
7
+ import subprocess
8
+ from typing import List, Dict, Optional
9
+ from emion.core.node import EmionNode
10
+ from emion.core.engine import EmionEngine
11
+ from emion.plugins.base import APIPlugin
12
+
13
+ _nodes: Dict[int, EmionNode] = {}
14
+ _engines: Dict[int, EmionEngine] = {}
15
+ _plugins: Dict[str, APIPlugin] = {}
16
+
17
+
18
+ def register_node(node_id: int):
19
+ """Register an authentic ION-DTN node."""
20
+ if node_id in _nodes:
21
+ return _nodes[node_id]
22
+
23
+ n = EmionNode(node_id)
24
+ # auto-connect routing
25
+ for existing_id, existing_node in _nodes.items():
26
+ n.connect_to(existing_id)
27
+ existing_node.connect_to(node_id)
28
+
29
+ _nodes[node_id] = n
30
+ return n
31
+
32
+
33
+ def start_core(cleanup: bool = True):
34
+ """
35
+ Boot all registered ION nodes.
36
+ Minimum 2 nodes recommended for routing verification.
37
+ """
38
+ if cleanup:
39
+ print("[EmION] Cleaning up existing ION processes (killm)...")
40
+ subprocess.run(["killm"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
41
+ time.sleep(2)
42
+
43
+ print(f"[EmION] Initializing {len(_nodes)} nodes...")
44
+ for nid, node in _nodes.items():
45
+ node.start(cleanup=False)
46
+
47
+ # Wait for shared memory regions to stabilize
48
+ time.sleep(6)
49
+
50
+ print("[EmION] Attaching bundle engines...")
51
+ for nid in _nodes:
52
+ eng = EmionEngine(nid)
53
+ eng.attach()
54
+ _engines[nid] = eng
55
+
56
+
57
+ def stop_core():
58
+ """Shut down all ION nodes and engines."""
59
+ for nid, node in _nodes.items():
60
+ try:
61
+ node.stop()
62
+ except:
63
+ pass
64
+ _engines.clear()
65
+ subprocess.run(["killm"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
66
+
67
+
68
+ def send_bundle(src: int, dst: int, payload: str):
69
+ """Send a real BPv7 bundle via IPN."""
70
+ if src not in _engines:
71
+ raise RuntimeError(f"Engine for Node {src} not initialized. Call start_core() first.")
72
+
73
+ src_eid = f"ipn:{src}.1"
74
+ dst_eid = f"ipn:{dst}.1"
75
+ data = payload.encode()
76
+
77
+ res = _engines[src].send(src_eid, dst_eid, data)
78
+
79
+ # Analyze with plugins
80
+ module_results = {}
81
+ for name, plugin in _plugins.items():
82
+ module_results[name] = plugin.analyze(data, {"src": src_eid, "dst": dst_eid})
83
+
84
+ return {
85
+ "status": "sent",
86
+ "bundle_id": res,
87
+ "src": src_eid,
88
+ "dst": dst_eid,
89
+ "size": len(data),
90
+ "analyzer_results": module_results
91
+ }
92
+
93
+
94
+ def attach_plugin(url: str, target_nodes: str = "all"):
95
+ """Attach an external anomaly/security module."""
96
+ plugin = APIPlugin(base_url=url, name=url)
97
+ if plugin.health_check():
98
+ _plugins[url] = plugin
99
+ return {"status": "ok", "url": url}
100
+ else:
101
+ raise ConnectionError(f"Could not reach plugin at {url}/health")