diff options
Diffstat (limited to 'wrappers/python/eduvpn_common')
| -rw-r--r-- | wrappers/python/eduvpn_common/discovery.py | 12 | ||||
| -rw-r--r-- | wrappers/python/eduvpn_common/error.py | 1 | ||||
| -rw-r--r-- | wrappers/python/eduvpn_common/event.py | 3 | ||||
| -rw-r--r-- | wrappers/python/eduvpn_common/loader.py | 8 | ||||
| -rw-r--r-- | wrappers/python/eduvpn_common/main.py | 80 | ||||
| -rw-r--r-- | wrappers/python/eduvpn_common/server.py | 25 | ||||
| -rw-r--r-- | wrappers/python/eduvpn_common/state.py | 2 | ||||
| -rw-r--r-- | wrappers/python/eduvpn_common/types.py | 26 |
8 files changed, 135 insertions, 22 deletions
diff --git a/wrappers/python/eduvpn_common/discovery.py b/wrappers/python/eduvpn_common/discovery.py index aa5a667..1d59c00 100644 --- a/wrappers/python/eduvpn_common/discovery.py +++ b/wrappers/python/eduvpn_common/discovery.py @@ -16,7 +16,14 @@ class DiscoOrganization: :param: secure_internet_home: str: Indicating which server is the secure internet home server :param: keyword_list: The list of strings that the users gets to search on to find the server """ - def __init__(self, display_name: str, org_id: str, secure_internet_home: str, keyword_list: List[str]): + + def __init__( + self, + display_name: str, + org_id: str, + secure_internet_home: str, + keyword_list: List[str], + ): self.display_name = display_name self.org_id = org_id self.secure_internet_home = secure_internet_home @@ -33,6 +40,7 @@ class DiscoOrganizations: :param: version: int: The version of the list as returned by Discovery :param: organizations: List[DiscoOrganization]: The actual list of discovery organizations """ + def __init__(self, version: int, organizations: List[DiscoOrganization]): self.version = version self.organizations = organizations @@ -50,6 +58,7 @@ class DiscoServer: :param: server_type: str: The server type as a string :param: support_contacts: List[str]: The list of support contacts """ + def __init__( self, authentication_url_template: str, @@ -81,6 +90,7 @@ class DiscoServers: :param: version: int: The version of the list as returned by Discovery :param: servers: List[DiscoServers]: The list of discovery servers """ + def __init__(self, version: int, servers: List[DiscoServer]): self.version = version self.servers = servers diff --git a/wrappers/python/eduvpn_common/error.py b/wrappers/python/eduvpn_common/error.py index a642a70..3d84331 100644 --- a/wrappers/python/eduvpn_common/error.py +++ b/wrappers/python/eduvpn_common/error.py @@ -7,6 +7,7 @@ class WrappedError(Exception): :param: traceback: str: The traceback of the error including newlines :param: cause: str: The cause of the error as a message """ + def __init__(self, traceback: str, cause: str): super(WrappedError, self).__init__(cause) self.traceback = traceback diff --git a/wrappers/python/eduvpn_common/event.py b/wrappers/python/eduvpn_common/event.py index 4387222..746a0c9 100644 --- a/wrappers/python/eduvpn_common/event.py +++ b/wrappers/python/eduvpn_common/event.py @@ -23,6 +23,7 @@ def class_state_transition(state: int, state_type: StateType) -> Callable: :meta private: """ + def wrapper(func): """ @@ -65,6 +66,7 @@ def convert_data(lib: CDLL, state: int, data: Any) -> None: class EventHandler(object): """The class that neatly handles event callbacks from the internal Go FSM""" + def __init__(self, lib: CDLL): self.handlers: Dict[Tuple[int, StateType], List[Callable]] = {} self.lib = lib @@ -134,6 +136,7 @@ class EventHandler(object): :meta private: """ + def wrapped_f(func): """ diff --git a/wrappers/python/eduvpn_common/loader.py b/wrappers/python/eduvpn_common/loader.py index 202e2da..036c201 100644 --- a/wrappers/python/eduvpn_common/loader.py +++ b/wrappers/python/eduvpn_common/loader.py @@ -108,6 +108,7 @@ def initialize_functions(lib: CDLL) -> None: c_char_p, c_char_p, c_char_p, + c_char_p, VPNStateChange, c_int, ], c_void_p @@ -157,5 +158,10 @@ def initialize_functions(lib: CDLL) -> None: c_int, ], c_void_p lib.ShouldRenewButton.argtypes, lib.ShouldRenewButton.restype = [], int - lib.StartFailover.argtypes, lib.StartFailover.restype = [c_char_p, c_char_p, c_int, ReadRxBytes], DataError + lib.StartFailover.argtypes, lib.StartFailover.restype = [ + c_char_p, + c_char_p, + c_int, + ReadRxBytes, + ], DataError lib.CancelFailover.argtypes, lib.CancelFailover.restype = [c_char_p], c_void_p diff --git a/wrappers/python/eduvpn_common/main.py b/wrappers/python/eduvpn_common/main.py index e27ec55..3ca26fe 100644 --- a/wrappers/python/eduvpn_common/main.py +++ b/wrappers/python/eduvpn_common/main.py @@ -2,12 +2,34 @@ import threading from ctypes import cast, c_void_p, c_int, pointer from typing import Any, Callable, Dict, Iterator, List, Optional, Tuple -from eduvpn_common.discovery import DiscoOrganizations, DiscoServers, get_disco_organizations, get_disco_servers +from eduvpn_common.discovery import ( + DiscoOrganizations, + DiscoServers, + get_disco_organizations, + get_disco_servers, +) from eduvpn_common.event import EventHandler from eduvpn_common.loader import initialize_functions, load_lib -from eduvpn_common.server import Profiles, Config, Token, encode_tokens, get_config, Server, get_transition_server, get_servers +from eduvpn_common.server import ( + Profiles, + Config, + Token, + encode_tokens, + get_config, + Server, + get_transition_server, + get_servers, +) from eduvpn_common.state import State, StateType -from eduvpn_common.types import VPNStateChange, ReadRxBytes, cToken, decode_res, encode_args, get_data_error, get_bool +from eduvpn_common.types import ( + VPNStateChange, + ReadRxBytes, + cToken, + decode_res, + encode_args, + get_data_error, + get_bool, +) class EduVPN(object): @@ -15,12 +37,15 @@ class EduVPN(object): It registers the client with the library and then calls the needed appropriate functions :param name: str: The name of the client. For commonly used names, see https://git.sr.ht/~fkooman/vpn-user-portal/tree/v3/item/src/OAuth/ClientDb.php. E.g. org.eduvpn.app.linux, if this name has "letsconnect" in it, then it is a Let's Connect! variant + :param version: str: The version number of the client as a string, max 10 characters :param config_directory: str: The directory (absolute/relative) where to store the files :param language: str: The language of the client, e.g. en """ - def __init__(self, name: str, config_directory: str, language: str): + + def __init__(self, name: str, version: str, config_directory: str, language: str): self.name = name + self.version = version self.config_directory = config_directory self.language = language @@ -59,7 +84,9 @@ class EduVPN(object): if self.location_event: self.location_event.wait() - def go_function(self, func: Any, *args: Iterator, decode_func: Optional[Callable] = None) -> Any: + def go_function( + self, func: Any, *args: Iterator, decode_func: Optional[Callable] = None + ) -> Any: """Call an internal go function and properly forward the arguments. Also handles decoding the result @@ -103,6 +130,7 @@ class EduVPN(object): register_err = self.go_function( self.lib.Register, + self.version, self.config_directory, self.language, state_callback, @@ -213,7 +241,13 @@ class EduVPN(object): if remove_err: raise remove_err - def get_config(self, identifier: str, func: Any, prefer_tcp: bool = False, tokens: Optional[Token] = None) -> Optional[Config]: + def get_config( + self, + identifier: str, + func: Any, + prefer_tcp: bool = False, + tokens: Optional[Token] = None, + ) -> Optional[Config]: """Get an OpenVPN/WireGuard configuration from the server :param identifier: str: The identifier of the server, e.g. URL or ORG ID @@ -233,7 +267,13 @@ class EduVPN(object): # The event is set in self.set_profile self.profile_event = threading.Event() - config, config_err = self.go_function(func, identifier, prefer_tcp, encode_tokens(tokens), decode_func=lambda lib, x: get_data_error(lib, x, get_config)) + config, config_err = self.go_function( + func, + identifier, + prefer_tcp, + encode_tokens(tokens), + decode_func=lambda lib, x: get_data_error(lib, x, get_config), + ) self.profile_event = None self.location_event = None @@ -273,7 +313,9 @@ class EduVPN(object): :return: The configuration and configuration type ('openvpn' or 'wireguard') :rtype: Config """ - return self.get_config(url, self.lib.GetConfigInstituteAccess, prefer_tcp, tokens) + return self.get_config( + url, self.lib.GetConfigInstituteAccess, prefer_tcp, tokens + ) def get_config_secure_internet( self, org_id: str, prefer_tcp: bool = False, tokens: Optional[Token] = None @@ -289,7 +331,9 @@ class EduVPN(object): :return: The configuration and configuration type ('openvpn' or 'wireguard') :rtype: Config """ - return self.get_config(org_id, self.lib.GetConfigSecureInternet, prefer_tcp, tokens) + return self.get_config( + org_id, self.lib.GetConfigSecureInternet, prefer_tcp, tokens + ) def go_back(self) -> None: """Go back in the FSM""" @@ -338,7 +382,9 @@ class EduVPN(object): if cleanup_err: raise cleanup_err - def set_disconnected(self, ) -> None: + def set_disconnected( + self, + ) -> None: """Set the FSM to disconnected :param cleanup: bool: (Default value = True): Whether or not to call /disconnect to the server. This invalidates the OpenVPN/WireGuard configuration @@ -516,9 +562,14 @@ class EduVPN(object): return servers - def start_failover(self, gateway: str, wg_mtu: int, readrxbytes: ReadRxBytes) -> bool: + def start_failover( + self, gateway: str, wg_mtu: int, readrxbytes: ReadRxBytes + ) -> bool: dropped, dropped_err = self.go_function( - self.lib.StartFailover, gateway, wg_mtu, readrxbytes, + self.lib.StartFailover, + gateway, + wg_mtu, + readrxbytes, decode_func=lambda lib, x: get_data_error(lib, x, get_bool), ) if dropped_err: @@ -548,11 +599,14 @@ def state_callback(name: bytes, old_state: int, new_state: int, data: Any) -> in name_decoded = name.decode() if name_decoded not in eduvpn_objects: return 0 - handled = eduvpn_objects[name_decoded].callback(State(old_state), State(new_state), data) + handled = eduvpn_objects[name_decoded].callback( + State(old_state), State(new_state), data + ) if handled: return 1 return 0 + def add_as_global_object(eduvpn: EduVPN) -> bool: """Add the provided parameter to the global objects lists so we can call the callback diff --git a/wrappers/python/eduvpn_common/server.py b/wrappers/python/eduvpn_common/server.py index d10584e..068dc61 100644 --- a/wrappers/python/eduvpn_common/server.py +++ b/wrappers/python/eduvpn_common/server.py @@ -2,7 +2,14 @@ from ctypes import CDLL, POINTER, c_void_p, cast from datetime import datetime from typing import List, Optional, Type -from eduvpn_common.types import cConfig, cServer, cServerLocations, cServerProfiles, cServers, cToken +from eduvpn_common.types import ( + cConfig, + cServer, + cServerLocations, + cServerProfiles, + cServers, + cToken, +) class Profile: @@ -12,6 +19,7 @@ class Profile: :param: display_name: str: The display name of the profile :param: default_gateway: str: Whether or not this profile should have the default gateway set """ + def __init__(self, identifier: str, display_name: str, default_gateway: bool): self.identifier = identifier self.display_name = display_name @@ -20,6 +28,7 @@ class Profile: def __str__(self): return self.display_name + class Token: """The class that represents oauth Tokens @@ -27,6 +36,7 @@ class Token: :param: refresh: str: The refresh token :param: expired: int: The expire unix time """ + def __init__(self, access: str, refresh: str, expired: int): self.access = access self.refresh = refresh @@ -40,6 +50,7 @@ class Config: :param: config_type: str: The type of config, openvpn/wireguard :param: tokens: Optional[Token]: The tokens """ + def __init__(self, config: str, config_type: str, tokens: Optional[Token]): self.config = config self.config_type = config_type @@ -55,6 +66,7 @@ class Profiles: :param: profiles: List[Profile]: A list of profiles :param: current: int: The current profile index """ + def __init__(self, profiles: List[Profile], current: int): self.profiles = profiles self.current_index = current @@ -79,6 +91,7 @@ class Server: :param: profiles: Optional[Profiles]: The profiles if there are any already obtained, defaults to None :param: expire_time: int: The expiry time in a Unix timestamp, defaults to 0 """ + def __init__( self, url: str, @@ -113,6 +126,7 @@ class InstituteServer(Server): :param: profiles: Profiles: The profiles of the server :param: expire_time: int: The expiry time in a Unix timestamp """ + def __init__( self, url: str, @@ -145,6 +159,7 @@ class SecureInternetServer(Server): :param: expire_time: int: The expiry time in a Unix timestamp :param: country_code: str: The country code of the server """ + def __init__( self, org_id: str, @@ -396,15 +411,19 @@ def get_config(lib: CDLL, ptr: c_void_p) -> Optional[Config]: tokens = None if config.token: token_struct = config.token.contents - tokens = Token(token_struct.access.decode("utf-8"), token_struct.refresh.decode("utf-8"), token_struct.expired) + tokens = Token( + token_struct.access.decode("utf-8"), + token_struct.refresh.decode("utf-8"), + token_struct.expired, + ) config_class = Config(cfg, cfg_type, tokens) lib.FreeConfig(ptr) return config_class return None + def encode_tokens(arg: Optional[Token]) -> cToken: if arg is None: return cToken("".encode("utf-8"), "".encode("utf-8"), 0) return cToken(arg.access.encode("utf-8"), arg.refresh.encode("utf-8"), arg.expires) - diff --git a/wrappers/python/eduvpn_common/state.py b/wrappers/python/eduvpn_common/state.py index 227d3c2..21573f7 100644 --- a/wrappers/python/eduvpn_common/state.py +++ b/wrappers/python/eduvpn_common/state.py @@ -5,6 +5,7 @@ class StateType(IntEnum): """ The State Type enum. Wait types are mostly used for internal code """ + ENTER = 1 LEAVE = 2 WAIT = 3 @@ -14,6 +15,7 @@ class State(IntEnum): """ The State enum. Each state here also exists in the Go library """ + DEREGISTERED = 0 NO_SERVER = 1 ASK_LOCATION = 2 diff --git a/wrappers/python/eduvpn_common/types.py b/wrappers/python/eduvpn_common/types.py index c1d9848..4bc5a85 100644 --- a/wrappers/python/eduvpn_common/types.py +++ b/wrappers/python/eduvpn_common/types.py @@ -15,11 +15,13 @@ from typing import Any, Callable, Iterator, List, Optional, Tuple from eduvpn_common.error import WrappedError + class cToken(Structure): """The C type that represents the Token as forwarded to the Go library :meta private: """ + _fields_ = [ ("access", c_char_p), ("refresh", c_char_p), @@ -32,13 +34,20 @@ class cConfig(Structure): :meta private: """ - _fields_ = [("config", c_char_p), ("config_type", c_char_p), ("token", POINTER(cToken))] + + _fields_ = [ + ("config", c_char_p), + ("config_type", c_char_p), + ("token", POINTER(cToken)), + ] + class cError(Structure): """The C type that represents the Error as returned by the Go library :meta private: """ + _fields_ = [ ("traceback", c_char_p), ("cause", c_char_p), @@ -50,6 +59,7 @@ class cServerLocations(Structure): :meta private: """ + _fields_ = [("locations", POINTER(c_char_p)), ("total_locations", c_size_t)] @@ -58,6 +68,7 @@ class cDiscoveryOrganization(Structure): :meta private: """ + _fields_ = [ ("display_name", c_char_p), ("org_id", c_char_p), @@ -71,6 +82,7 @@ class cDiscoveryOrganizations(Structure): :meta private: """ + _fields_ = [ ("version", c_ulonglong), ("organizations", POINTER(POINTER(cDiscoveryOrganization))), @@ -83,6 +95,7 @@ class cDiscoveryServer(Structure): :meta private: """ + _fields_ = [ ("authentication_url_template", c_char_p), ("base_url", c_char_p), @@ -102,6 +115,7 @@ class cDiscoveryServers(Structure): :meta private: """ + _fields_ = [ ("version", c_ulonglong), ("servers", POINTER(POINTER(cDiscoveryServer))), @@ -114,6 +128,7 @@ class cServerProfile(Structure): :meta private: """ + _fields_ = [ ("identifier", c_char_p), ("display_name", c_char_p), @@ -126,6 +141,7 @@ class cServerProfiles(Structure): :meta private: """ + _fields_ = [ ("current", c_int), ("profiles", POINTER(POINTER(cServerProfile))), @@ -138,6 +154,7 @@ class cServer(Structure): :meta private: """ + _fields_ = [ ("identifier", c_char_p), ("display_name", c_char_p), @@ -156,6 +173,7 @@ class cServers(Structure): :meta private: """ + _fields_ = [ ("custom_servers", POINTER(POINTER(cServer))), ("total_custom", c_size_t), @@ -170,6 +188,7 @@ class DataError(Structure): :meta private: """ + _fields_ = [("data", c_void_p), ("error", c_void_p)] @@ -177,6 +196,7 @@ class DataError(Structure): VPNStateChange = CFUNCTYPE(c_int, c_char_p, c_int, c_int, c_void_p) ReadRxBytes = CFUNCTYPE(c_ulonglong) + def encode_args(args: List[Any], types: List[Any]) -> Iterator[Any]: """Encode the arguments ready to be used by the Go library @@ -271,9 +291,7 @@ def get_error(lib: CDLL, ptr: c_void_p) -> Optional[WrappedError]: if not ptr: return None err = cast(ptr, POINTER(cError)).contents - wrapped = WrappedError( - err.traceback.decode("utf-8"), err.cause.decode("utf-8") - ) + wrapped = WrappedError(err.traceback.decode("utf-8"), err.cause.decode("utf-8")) lib.FreeError(ptr) return wrapped |
