summaryrefslogtreecommitdiff
path: root/wrappers
diff options
context:
space:
mode:
authorjwijenbergh <jeroenwijenbergh@protonmail.com>2023-05-08 16:20:00 +0200
committerJeroen Wijenbergh <46386452+jwijenbergh@users.noreply.github.com>2023-09-25 09:43:37 +0200
commitb7f86c83fffc221e654048e6e55c3f130c9fd308 (patch)
tree89c629982651bff51e50b8bd26fda1580dd2b87d /wrappers
parentbf2cef5150b630b2964b9025d3a63c34803a4db1 (diff)
Client: Use a mutex for state transitions
Diffstat (limited to 'wrappers')
-rw-r--r--wrappers/python/eduvpn_common/loader.py17
-rw-r--r--wrappers/python/eduvpn_common/main.py42
-rw-r--r--wrappers/python/eduvpn_common/types.py1
3 files changed, 49 insertions, 11 deletions
diff --git a/wrappers/python/eduvpn_common/loader.py b/wrappers/python/eduvpn_common/loader.py
index afad569..75a6a0a 100644
--- a/wrappers/python/eduvpn_common/loader.py
+++ b/wrappers/python/eduvpn_common/loader.py
@@ -4,7 +4,14 @@ from collections import defaultdict
from ctypes import CDLL, c_char_p, c_int, c_void_p, cdll
from eduvpn_common import __version__
-from eduvpn_common.types import BoolError, DataError, ReadRxBytes, TokenGetter, TokenSetter, VPNStateChange
+from eduvpn_common.types import (
+ BoolError,
+ DataError,
+ ReadRxBytes,
+ TokenGetter,
+ TokenSetter,
+ VPNStateChange,
+)
def load_lib() -> CDLL:
@@ -88,7 +95,10 @@ def initialize_functions(lib: CDLL) -> None:
c_int,
], c_void_p
lib.RenewSession.argtypes, lib.RenewSession.restype = [c_int], c_void_p
- lib.SetTokenHandler.argtypes, lib.SetTokenHandler.restype = [TokenGetter, TokenSetter], c_void_p
+ lib.SetTokenHandler.argtypes, lib.SetTokenHandler.restype = [
+ TokenGetter,
+ TokenSetter,
+ ], c_void_p
lib.Cleanup.argtypes, lib.Cleanup.restype = [c_int], c_void_p
lib.SetProfileID.argtypes, lib.SetProfileID.restype = [c_char_p], c_void_p
lib.CookieNew.argtypes, lib.CookieNew.restype = [], c_int
@@ -105,6 +115,9 @@ def initialize_functions(lib: CDLL) -> None:
lib.SetState.argtypes, lib.SetState.restype = [
c_int,
], c_void_p
+ lib.InState.argtypes, lib.InState.restype = [
+ c_int,
+ ], BoolError
lib.StartFailover.argtypes, lib.StartFailover.restype = [
c_int,
c_char_p,
diff --git a/wrappers/python/eduvpn_common/main.py b/wrappers/python/eduvpn_common/main.py
index 64fa6ac..f3639e0 100644
--- a/wrappers/python/eduvpn_common/main.py
+++ b/wrappers/python/eduvpn_common/main.py
@@ -3,7 +3,17 @@ from enum import IntEnum
from typing import Any, Callable, Iterator, Optional
from eduvpn_common.loader import initialize_functions, load_lib
-from eduvpn_common.types import ReadRxBytes, TokenGetter, TokenSetter, VPNStateChange, decode_res, encode_args
+from eduvpn_common.types import (
+ ReadRxBytes,
+ TokenGetter,
+ TokenSetter,
+ VPNStateChange,
+ decode_res,
+ encode_args,
+)
+
+from eduvpn_common.event import EventHandler
+from eduvpn_common.state import State
class WrappedError(Exception):
@@ -57,14 +67,20 @@ class EduVPN(object):
self.version = version
self.config_directory = config_directory
self.jar = Jar(lambda x: self.go_function(self.lib.CookieCancel, x))
- self.callback = None
self.token_setter = None
self.token_getter = None
+ self.event_handler = EventHandler()
# Load the library
self.lib = load_lib()
initialize_functions(self.lib)
+ def register_class_callbacks(self, _class):
+ self.event_handler.change_class_callbacks(_class, add=True)
+
+ def deregister_class_callbacks(self, _class):
+ self.event_handler.change_class_callbacks(_class, add=False)
+
def go_cookie_function(self, func: Any, *args: Iterator) -> Any:
cookie = self.lib.CookieNew()
self.jar.add(cookie)
@@ -95,7 +111,7 @@ class EduVPN(object):
global global_object
global_object = None
- def register(self, handler: Optional[Callable] = None, debug: bool = False) -> None:
+ def register(self, debug: bool = False) -> None:
"""Register the Go shared library.
This makes sure the FSM is initialized and that we can call Go functions
@@ -106,7 +122,6 @@ class EduVPN(object):
global global_object
if global_object is not None:
raise Exception("Already registered")
- self.callback = handler
global_object = self
register_err = self.go_function(
self.lib.Register,
@@ -175,11 +190,17 @@ class EduVPN(object):
if remove_err:
forwardError(remove_err)
- def set_state(self, state: int):
+ def set_state(self, state: State):
state_err = self.go_function(self.lib.SetState, state)
if state_err:
forwardError(state_err)
+ def in_state(self, state: State) -> bool:
+ yes, state_err = self.go_function(self.lib.InState, state)
+ if state_err:
+ forwardError(state_err)
+ return yes
+
def get_config(
self, _type: ServerType, identifier: str, prefer_tcp: bool = False
) -> str:
@@ -257,7 +278,9 @@ class EduVPN(object):
def set_token_handler(self, getter: Callable, setter: Callable) -> None:
self.token_setter = setter
self.token_getter = getter
- handler_err = self.go_function(self.lib.SetTokenHandler, token_getter, token_setter)
+ handler_err = self.go_function(
+ self.lib.SetTokenHandler, token_getter, token_setter
+ )
if handler_err:
forwardError(handler_err)
@@ -309,6 +332,7 @@ class EduVPN(object):
global_object: Optional[EduVPN] = None
+
@TokenSetter
def token_setter(server: ctypes.c_char_p, tokens: ctypes.c_char_p):
global global_object
@@ -318,6 +342,7 @@ def token_setter(server: ctypes.c_char_p, tokens: ctypes.c_char_p):
return 0
global_object.token_setter(server.decode(), tokens.decode())
+
@TokenGetter
def token_getter(server: ctypes.c_char_p, buf: ctypes.c_char_p, size: ctypes.c_size_t):
global global_object
@@ -332,6 +357,7 @@ def token_getter(server: ctypes.c_char_p, buf: ctypes.c_char_p, size: ctypes.c_s
outbuf = ctypes.cast(buf, ctypes.POINTER(ctypes.c_char * size))
outbuf.contents.value = got.encode("utf-8")
+
@VPNStateChange
def state_callback(old_state: int, new_state: int, data: str) -> int:
"""The internal callback that is passed to the Go library
@@ -345,9 +371,7 @@ def state_callback(old_state: int, new_state: int, data: str) -> int:
global global_object
if global_object is None:
return 0
- if global_object.callback is None:
- return 0
- handled = global_object.callback(old_state, new_state, data.decode("utf-8"))
+ handled = global_object.event_handler.run(State(old_state), State(new_state), data.decode("utf-8"))
if handled:
return 1
return 0
diff --git a/wrappers/python/eduvpn_common/types.py b/wrappers/python/eduvpn_common/types.py
index f83e710..f1be42c 100644
--- a/wrappers/python/eduvpn_common/types.py
+++ b/wrappers/python/eduvpn_common/types.py
@@ -38,6 +38,7 @@ ReadRxBytes = CFUNCTYPE(c_ulonglong)
TokenGetter = CFUNCTYPE(c_void_p, c_char_p, POINTER(c_char), c_size_t)
TokenSetter = CFUNCTYPE(c_void_p, c_char_p, c_char_p)
+
def encode_args(args: List[Any], types: List[Any]) -> Iterator[Any]:
"""Encode the arguments ready to be used by the Go library