summaryrefslogtreecommitdiff
path: root/wrappers/python/eduvpn_common
diff options
context:
space:
mode:
authorjwijenbergh <jeroenwijenbergh@protonmail.com>2023-04-13 15:25:42 +0200
committerJeroen Wijenbergh <46386452+jwijenbergh@users.noreply.github.com>2023-09-25 09:43:37 +0200
commitf6f4396a81ce662eb5fb50c4f9fef92ffaadb333 (patch)
tree3e6b1c3ecc049c1aa377c8ca813f00b96437d2f3 /wrappers/python/eduvpn_common
parent5610dca6c5e391ee62874c4d6cb25072d9c3c1d9 (diff)
All: Implement a token handler
This implements a token handler for OAuth tokens. Clients can use the SetTokenHandler function in exports to set a token handler. It needs two arguments, a getter and a setter. The getter is a callback with three arguments: - The server to get the tokens for, in types.server.current as JSON - The output buffer - The output buffer maximum length The tokens should be written to the output buffer with maximum length. The type should be types.server.Tokens and be marshalled as JSON. If no tokens are available, leave the output buffer intact The token setter is a callback with two arguments: - The server for which to set the tokens for, in types.server.Current as JSON - The tokens, defined in types.server.Tokens as JSON Breaking changes: - No more tokens as arguments, was already deprecated in previous commits - Tokens are no longer returned in types.server.Configuration
Diffstat (limited to 'wrappers/python/eduvpn_common')
-rw-r--r--wrappers/python/eduvpn_common/loader.py3
-rw-r--r--wrappers/python/eduvpn_common/main.py56
-rw-r--r--wrappers/python/eduvpn_common/types.py7
3 files changed, 54 insertions, 12 deletions
diff --git a/wrappers/python/eduvpn_common/loader.py b/wrappers/python/eduvpn_common/loader.py
index 961b569..1a172af 100644
--- a/wrappers/python/eduvpn_common/loader.py
+++ b/wrappers/python/eduvpn_common/loader.py
@@ -4,7 +4,7 @@ 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, VPNStateChange
+from eduvpn_common.types import BoolError, DataError, ReadRxBytes, TokenGetter, TokenSetter, VPNStateChange
def load_lib() -> CDLL:
@@ -88,6 +88,7 @@ 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.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
diff --git a/wrappers/python/eduvpn_common/main.py b/wrappers/python/eduvpn_common/main.py
index b10e641..5d08ba9 100644
--- a/wrappers/python/eduvpn_common/main.py
+++ b/wrappers/python/eduvpn_common/main.py
@@ -1,8 +1,9 @@
+import ctypes
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, VPNStateChange, decode_res, encode_args
+from eduvpn_common.types import ReadRxBytes, TokenGetter, TokenSetter, VPNStateChange, decode_res, encode_args
class WrappedError(Exception):
@@ -56,6 +57,9 @@ 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
# Load the library
self.lib = load_lib()
@@ -88,8 +92,8 @@ class EduVPN(object):
This removes the object from internal bookkeeping and saves the configuration
"""
self.go_function(self.lib.Deregister)
- global callback_object
- callback_object = None
+ global global_object
+ global_object = None
def register(self, handler: Optional[Callable] = None, debug: bool = False) -> None:
"""Register the Go shared library.
@@ -99,10 +103,11 @@ class EduVPN(object):
:param debug: bool: (Default value = False): Whether or not we want to enable debug logging
"""
- global callback_object
- if callback_object is not None:
+ global global_object
+ if global_object is not None:
raise Exception("Already registered")
- callback_object = handler
+ self.callback = handler
+ global_object = self
register_err = self.go_function(
self.lib.Register,
self.name,
@@ -244,6 +249,14 @@ class EduVPN(object):
if location_err:
forwardError(location_err)
+ 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)
+
+ if handler_err:
+ forwardError(handler_err)
+
def cookie_reply(self, cookie: int, data: str) -> None:
"""Reply with the given cookie and data"""
cookie_err = self.go_function(self.lib.CookieReply, cookie, data)
@@ -289,8 +302,30 @@ class EduVPN(object):
self.jar.cancel()
-callback_object: Optional[Callable] = None
+global_object: Optional[EduVPN] = None
+@TokenSetter
+def token_setter(server: ctypes.c_char_p, tokens: ctypes.c_char_p):
+ global global_object
+ if global_object is None:
+ return
+ if global_object.token_setter is None:
+ 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
+ if global_object is None:
+ return
+ if global_object.token_getter is None:
+ return
+ got = global_object.token_getter(server.decode())
+ if got is None:
+ return
+
+ 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:
@@ -302,9 +337,12 @@ def state_callback(old_state: int, new_state: int, data: str) -> int:
:meta private:
"""
- if callback_object is None:
+ global global_object
+ if global_object is None:
+ return 0
+ if global_object.callback is None:
return 0
- handled = callback_object(old_state, new_state, data.decode("utf-8"))
+ handled = global_object.callback(old_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 1eba468..f83e710 100644
--- a/wrappers/python/eduvpn_common/types.py
+++ b/wrappers/python/eduvpn_common/types.py
@@ -1,10 +1,13 @@
from ctypes import (
CDLL,
CFUNCTYPE,
+ POINTER,
Structure,
+ c_char,
c_char_p,
c_int,
c_ulonglong,
+ c_size_t,
c_void_p,
cast,
)
@@ -32,8 +35,8 @@ class BoolError(Structure):
# The type for a Go state change callback
VPNStateChange = CFUNCTYPE(c_int, c_int, c_int, c_char_p)
ReadRxBytes = CFUNCTYPE(c_ulonglong)
-UpdateToken = CFUNCTYPE(None, c_char_p, c_void_p, c_void_p)
-
+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