summaryrefslogtreecommitdiff
path: root/wrappers/python
diff options
context:
space:
mode:
authorjwijenbergh <jeroenwijenbergh@protonmail.com>2022-03-23 10:42:49 +0100
committerjwijenbergh <jeroenwijenbergh@protonmail.com>2022-03-23 10:42:49 +0100
commited6073f2c2c6600063f2e5062937b7a2a1162eb2 (patch)
treed43109bb55546fc4815824579c4879b51e4c3605 /wrappers/python
parente9597dc652e8ca99141b0d66bfca3e24f233d430 (diff)
Python: Implement state callbacks using decorators
Diffstat (limited to 'wrappers/python')
-rw-r--r--wrappers/python/eduvpncommon/__init__.py28
-rw-r--r--wrappers/python/eduvpncommon/error.py1
-rw-r--r--wrappers/python/eduvpncommon/main.py67
-rw-r--r--wrappers/python/main.py11
4 files changed, 87 insertions, 20 deletions
diff --git a/wrappers/python/eduvpncommon/__init__.py b/wrappers/python/eduvpncommon/__init__.py
index ff329a0..073af39 100644
--- a/wrappers/python/eduvpncommon/__init__.py
+++ b/wrappers/python/eduvpncommon/__init__.py
@@ -3,14 +3,20 @@ from collections import defaultdict
import pathlib
import platform
-_lib_prefixes = defaultdict(lambda: "lib", {
- "windows": "",
-})
-
-_lib_suffixes = defaultdict(lambda: ".so", {
- "windows": ".dll",
- "darwin": ".dylib",
-})
+_lib_prefixes = defaultdict(
+ lambda: "lib",
+ {
+ "windows": "",
+ },
+)
+
+_lib_suffixes = defaultdict(
+ lambda: ".so",
+ {
+ "windows": ".dll",
+ "darwin": ".dylib",
+ },
+)
_os = platform.system().lower()
@@ -19,9 +25,10 @@ _libfile = f"{_lib_prefixes[_os]}{_libname}{_lib_suffixes[_os]}"
# Library should have been copied to the lib/ folder
lib = cdll.LoadLibrary(str(pathlib.Path(__file__).parent / "lib" / _libfile))
+
class DataError(Structure):
- _fields_ = [('data', c_void_p),
- ('error', c_void_p)]
+ _fields_ = [("data", c_void_p), ("error", c_void_p)]
+
VPNStateChange = CFUNCTYPE(None, c_char_p, c_char_p, c_char_p)
@@ -33,6 +40,7 @@ lib.GetServersList.argtypes, lib.GetServersList.restype = [], DataError
# See https://stackoverflow.com/questions/13445568/python-ctypes-how-to-free-memory-getting-invalid-pointer-error
lib.FreeString.argtypes, lib.FreeString.restype = [c_void_p], None
+
def GetPtrString(ptr):
if ptr:
string = cast(ptr, c_char_p).value
diff --git a/wrappers/python/eduvpncommon/error.py b/wrappers/python/eduvpncommon/error.py
index ce0cec1..59f0607 100644
--- a/wrappers/python/eduvpncommon/error.py
+++ b/wrappers/python/eduvpncommon/error.py
@@ -1,5 +1,6 @@
from enum import Enum
+
class GoError(Exception):
message_dict: dict
code: Enum
diff --git a/wrappers/python/eduvpncommon/main.py b/wrappers/python/eduvpncommon/main.py
index ac13344..9a4931f 100644
--- a/wrappers/python/eduvpncommon/main.py
+++ b/wrappers/python/eduvpncommon/main.py
@@ -1,21 +1,72 @@
-from . import lib, VPNStateChange, GetDataError
+from . import lib, VPNStateChange, GetDataError, GetPtrString
from ctypes import *
+from enum import Enum
+import functools
-@VPNStateChange
-def state_change(old, new, data):
- print(f"Python: State change {old.decode()} {new.decode()} DATA {data.decode()}")
+class StateType(Enum):
+ Enter = 1
+ Leave = 2
# Registers the python app with the Go code
# name: The name of the app to be registered
# url: The url of the server to connect to, FIXME: To be removed
# state_callback: The callback to trigger whenever a state is changed, FIXME: Remove whenever this wrapper has implemented callbacks using function decorations
def Register(name, config_directory, state_callback):
- name_bytes = name.encode('utf-8')
- dir_bytes = config_directory.encode('utf-8')
- lib.Register(name_bytes, dir_bytes, state_callback)
+ name_bytes = name.encode("utf-8")
+ dir_bytes = config_directory.encode("utf-8")
+ ptr_err = lib.Register(name_bytes, dir_bytes, state_callback)
+ err_string = GetPtrString(ptr_err)
+ return err_string
+
+
+class EduVPN(object):
+ def __init__(self, name, config_directory):
+ self.event_handler = EventHandler()
+ self.name = name
+ self.config_directory = config_directory
+
+ def register(self) -> bool:
+ closure = VPNStateChange(
+ lambda old_state, new_state, data: self.callback(
+ old_state.decode(), new_state.decode(), data.decode()
+ )
+ )
+ return Register(self.name, self.config_directory, closure) == ""
+
+ @property
+ def event(self):
+ return self.event_handler
+
+ def callback(self, old_state, new_state, data):
+ self.event.run(old_state, new_state, data)
+
+
+class EventHandler(object):
+ def __init__(self):
+ self.handlers = {}
+
+ def on(self, state, state_type):
+ def wrapped_f(func):
+ if (state, state_type) not in self.handlers:
+ self.handlers[(state, state_type)] = []
+ self.handlers[(state, state_type)].append(func)
+ return func
+ return wrapped_f
+
+ def run_state(self, state, state_type, data):
+ if (state, state_type) not in self.handlers:
+ return
+ for func in self.handlers[(state, state_type)]:
+ func(data)
+
+ def run(self, old_state, new_state, data):
+ if old_state == new_state:
+ return
+ self.run_state(old_state, StateType.Leave, data)
+ self.run_state(new_state, StateType.Enter, data)
+
def GetDiscoServers():
servers, serversErr = GetDataError(lib.GetServersList())
organizations, organizationsErr = GetDataError(lib.GetOrganizationsList())
return servers, serversErr, organizations, organizationsErr
-
diff --git a/wrappers/python/main.py b/wrappers/python/main.py
index 5383799..a248b71 100644
--- a/wrappers/python/main.py
+++ b/wrappers/python/main.py
@@ -1,5 +1,12 @@
import eduvpncommon.main as eduvpn
-eduvpn.Register("org.eduvpn.app.linux", "configs", eduvpn.state_change)
-print(eduvpn.GetDiscoServers())
+_eduvpn = eduvpn.EduVPN("org.eduvpn.app.linux", "configs")
+
+
+@_eduvpn.event.on("REGISTERED", eduvpn.StateType.Enter)
+def registered(data):
+ print(f"REGISTERED PYTHON WITH DATA {data}")
+
+
+_eduvpn.register()