From 7738b73ff325ccd80779a6c25193dbc29a226a2b Mon Sep 17 00:00:00 2001 From: Michael Woods Date: Fri, 3 Jan 2025 00:34:48 -0500 Subject: [PATCH] Initial commit --- .gitignore | 1 + Readme.md | 22 +++++++++++++++++++ requirements.txt | 4 ++++ src/packetserver/__init__.py | 0 src/packetserver/client/__init__.py | 2 ++ src/packetserver/common/__init__.py | 34 +++++++++++++++++++++++++++++ src/packetserver/server/__init__.py | 22 +++++++++++++++++++ 7 files changed, 85 insertions(+) create mode 100644 .gitignore create mode 100644 Readme.md create mode 100644 requirements.txt create mode 100644 src/packetserver/__init__.py create mode 100644 src/packetserver/client/__init__.py create mode 100644 src/packetserver/common/__init__.py create mode 100644 src/packetserver/server/__init__.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2d4daa4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea* diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..9d8c21b --- /dev/null +++ b/Readme.md @@ -0,0 +1,22 @@ +This whole project is still a major WIP. Details to follow. + +Basically, this is supposed to be a modernized BBS for radio, +but exchanging binary messages (which can be compressed automatically) +rather than human-typed text. + +I'm planning several features like: + +- automatic compression for all RF communication +- messages for other users +- RF beacon +- administration over RF +- object storage/retrieval +- running user-scripts scripts or shell commands on the server in containers with podman/docker +- possibly a cron system (again in containers for safety) +- maybe an e-mail or an sms gateway (though clever user uploaded scripts could do this instead) +- maybe APRS integration through APRS-IS + +I may also add a TCP/IP interface to this later, since that shouldn't be too difficult. We'll see. + +I'm envisioning using a couple of python CLI clients with this for now, or possibly an android or +PC GUI, assuming an AGWPE TNC is available on the network. \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..5c25280 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +pyham_pe +msgpack +pyham_ax25 +ZODB \ No newline at end of file diff --git a/src/packetserver/__init__.py b/src/packetserver/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/packetserver/client/__init__.py b/src/packetserver/client/__init__.py new file mode 100644 index 0000000..5892ab1 --- /dev/null +++ b/src/packetserver/client/__init__.py @@ -0,0 +1,2 @@ +class Client: + pass \ No newline at end of file diff --git a/src/packetserver/common/__init__.py b/src/packetserver/common/__init__.py new file mode 100644 index 0000000..438c837 --- /dev/null +++ b/src/packetserver/common/__init__.py @@ -0,0 +1,34 @@ +from pe.connect import Connection +from threading import Lock +from msgpack import Unpacker + + +class PacketServerConnection(Connection): + + connection_subscribers = [] + receive_subscribers = [] + + def __init__(self, port, call_from, call_to, incoming=False): + super().__init__(port, call_from, call_to, incoming=incoming) + # Now perform any initialization of your own that you might need + self.data = Unpacker() + self.data_lock = Lock() + + def connected(self): + print("connected") + for fn in PacketServerConnection.connection_subscribers: + fn(self) + + def disconnected(self): + pass + + def data_received(self, pid, data): + with self.data_lock: + self.data.feed(data) + for fn in PacketServerConnection.receive_subscribers: + fn(self) + + @classmethod + def query_accept(cls, port, call_from, call_to): + return True + diff --git a/src/packetserver/server/__init__.py b/src/packetserver/server/__init__.py new file mode 100644 index 0000000..d0121ce --- /dev/null +++ b/src/packetserver/server/__init__.py @@ -0,0 +1,22 @@ +import pe +from ..common import PacketServerConnection +import ax25 +from configparser import ConfigParser +from pathlib import Path +import ZODB, transaction + +class Server: + def __init__(self, pe_server: str, port: int, server_callsign: str, data_dir: str = None): + if not ax25.Address.valid_call(server_callsign): + raise ValueError(f"Provided callsign '{server_callsign}' is invalid.") + self.callsign = server_callsign + self.pe_server = pe_server + self.pe_port = port + if data_dir: + if Path.is_dir(data_dir): + self.home_dir = data_dir + + + def server_receiver(self, conn: PacketServerConnection): + pass + pass \ No newline at end of file