summaryrefslogtreecommitdiff
path: root/wrappers/python
diff options
context:
space:
mode:
Diffstat (limited to 'wrappers/python')
-rw-r--r--wrappers/python/eduvpn_common/loader.py12
-rw-r--r--wrappers/python/eduvpn_common/main.py43
-rw-r--r--wrappers/python/eduvpn_common/server.py63
-rw-r--r--wrappers/python/eduvpn_common/types.py54
4 files changed, 118 insertions, 54 deletions
diff --git a/wrappers/python/eduvpn_common/loader.py b/wrappers/python/eduvpn_common/loader.py
index 1090619..f0f31d6 100644
--- a/wrappers/python/eduvpn_common/loader.py
+++ b/wrappers/python/eduvpn_common/loader.py
@@ -5,7 +5,7 @@ from ctypes import CDLL, c_char_p, c_int, c_void_p, cdll
from eduvpn_common import __version__
from eduvpn_common.types import (
- ConfigError,
+ cToken,
DataError,
ReadRxBytes,
VPNStateChange,
@@ -67,6 +67,7 @@ def initialize_functions(lib: CDLL) -> None:
c_char_p
], c_void_p
lib.Deregister.argtypes, lib.Deregister.restype = [c_char_p], None
+ lib.FreeConfig.argtypes, lib.FreeConfig.restype = [c_void_p], None
lib.FreeDiscoOrganizations.argtypes, lib.FreeDiscoOrganizations.restype = [
c_void_p
], None
@@ -81,17 +82,20 @@ def initialize_functions(lib: CDLL) -> None:
c_char_p,
c_char_p,
c_int,
- ], ConfigError
+ cToken,
+ ], DataError
lib.GetConfigInstituteAccess.argtypes, lib.GetConfigInstituteAccess.restype = [
c_char_p,
c_char_p,
c_int,
- ], ConfigError
+ cToken,
+ ], DataError
lib.GetConfigSecureInternet.argtypes, lib.GetConfigSecureInternet.restype = [
c_char_p,
c_char_p,
c_int,
- ], ConfigError
+ cToken,
+ ], DataError
lib.GetDiscoOrganizations.argtypes, lib.GetDiscoOrganizations.restype = [
c_char_p
], DataError
diff --git a/wrappers/python/eduvpn_common/main.py b/wrappers/python/eduvpn_common/main.py
index 3cb45e1..304e2e8 100644
--- a/wrappers/python/eduvpn_common/main.py
+++ b/wrappers/python/eduvpn_common/main.py
@@ -1,13 +1,14 @@
import threading
-from ctypes import c_int
+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.event import EventHandler
from eduvpn_common.loader import initialize_functions, load_lib
-from eduvpn_common.server import Profiles, 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 ReadRxBytes, VPNStateChange, 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):
@@ -219,26 +220,27 @@ class EduVPN(object):
if remove_err:
raise remove_err
- def get_config(self, identifier: str, func: Any, prefer_tcp: bool = False) -> Tuple[str, str]:
+ 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
:param func: Any: The Go function to call
:param prefer_tcp: bool: (Default value = False): Whether or not to prefer TCP
+ :param tokens: Optional[Token] (Default value = None): The OAuth tokens if available
:meta private:
:raises WrappedError: An error by the Go library
:return: The configuration and configuration type ('openvpn' or 'wireguard')
- :rtype: Tuple[str, str]
+ :rtype: Config
"""
# Because it could be the case that a profile callback is started, store a threading event
# In the constructor, we have defined a wait event for Ask_Profile, this waits for this event to be set
# The event is set in self.set_profile
self.profile_event = threading.Event()
- config, config_type, config_err = self.go_function(func, identifier, prefer_tcp)
+ 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
@@ -246,49 +248,55 @@ class EduVPN(object):
if config_err:
raise config_err
- return config, config_type
+ return config
def get_config_custom_server(
- self, url: str, prefer_tcp: bool = False
- ) -> Tuple[str, str]:
+ self, url: str, prefer_tcp: bool = False, tokens: Optional[Token] = None
+ ) -> Optional[Config]:
"""Get an OpenVPN/WireGuard configuration from a custom server
:param url: str: The URL of the custom server
:param prefer_tcp: bool: (Default value = False): Whether or not to prefer TCP
+ :param tokens: Optional[Token] (Default value = None): The OAuth tokens if available
:raises WrappedError: An error by the Go library
:return: The configuration and configuration type ('openvpn' or 'wireguard')
- :rtype: Tuple[str, str]
+ :rtype: Config
"""
- return self.get_config(url, self.lib.GetConfigCustomServer, prefer_tcp)
+ return self.get_config(url, self.lib.GetConfigCustomServer, prefer_tcp, tokens)
def get_config_institute_access(
- self, url: str, prefer_tcp: bool = False
- ) -> Tuple[str, str]:
+ self, url: str, prefer_tcp: bool = False, tokens: Optional[Token] = None
+ ) -> Optional[Config]:
"""Get an OpenVPN/WireGuard configuration from an institute access server
:param url: str: The URL of the institute access server. Use the one from Discovery
:param prefer_tcp: bool: (Default value = False): Whether or not to prefer TCP
+ :param tokens: Optional[Token] (Default value = None): The OAuth tokens if available
:raises WrappedError: An error by the Go library
:return: The configuration and configuration type ('openvpn' or 'wireguard')
- :rtype: Tuple[str, str]
+ :rtype: Config
"""
- return self.get_config(url, self.lib.GetConfigInstituteAccess, prefer_tcp)
+ return self.get_config(url, self.lib.GetConfigInstituteAccess, prefer_tcp, tokens)
def get_config_secure_internet(
- self, org_id: str, prefer_tcp: bool = False
- ) -> Tuple[str, str]:
+ self, org_id: str, prefer_tcp: bool = False, tokens: Optional[Token] = None
+ ) -> Optional[Config]:
"""Get an OpenVPN/WireGuard configuration from a secure internet server
:param org_id: str: The organization ID of the secure internet server. Use the one from Discovery
:param prefer_tcp: bool: (Default value = False): Whether or not to prefer TCP
+ :param tokens: Optional[Token] (Default value = None): The OAuth tokens if available
:raises WrappedError: An error by the Go library
+
+ :return: The configuration and configuration type ('openvpn' or 'wireguard')
+ :rtype: Config
"""
- return self.get_config(org_id, self.lib.GetConfigSecureInternet, prefer_tcp)
+ return self.get_config(org_id, self.lib.GetConfigSecureInternet, prefer_tcp, tokens)
def go_back(self) -> None:
"""Go back in the FSM"""
@@ -539,7 +547,6 @@ def state_callback(name: bytes, old_state: int, new_state: int, data: Any) -> in
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 380623d..d10584e 100644
--- a/wrappers/python/eduvpn_common/server.py
+++ b/wrappers/python/eduvpn_common/server.py
@@ -2,7 +2,7 @@ from ctypes import CDLL, POINTER, c_void_p, cast
from datetime import datetime
from typing import List, Optional, Type
-from eduvpn_common.types import cServer, cServerLocations, cServerProfiles, cServers
+from eduvpn_common.types import cConfig, cServer, cServerLocations, cServerProfiles, cServers, cToken
class Profile:
@@ -20,6 +20,34 @@ class Profile:
def __str__(self):
return self.display_name
+class Token:
+ """The class that represents oauth Tokens
+
+ :param: access: str: The access 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
+ self.expires = expired
+
+
+class Config:
+ """The class that represents an OpenVPN/WireGuard config
+
+ :param: config: str: The config string
+ :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
+ self.tokens = tokens
+
+ def __str__(self):
+ return self.config
+
class Profiles:
"""The class that represents a list of profiles
@@ -347,3 +375,36 @@ def get_locations(lib: CDLL, ptr: c_void_p) -> Optional[List[str]]:
lib.FreeSecureLocations(ptr)
return location_list
return None
+
+
+def get_config(lib: CDLL, ptr: c_void_p) -> Optional[Config]:
+ """Get the config from the Go library as a C structure and return a Python usable structure
+
+ :param lib: CDLL: The Go shared library
+ :param ptr: c_void_p: The C pointer to the confg structure
+
+ :meta private:
+
+ :return: The configuration if there is any
+ :rtype: Optional[Config]
+ """
+ # TODO: FREE
+ if ptr:
+ config = cast(ptr, POINTER(cConfig)).contents
+ cfg = config.config.decode("utf-8")
+ cfg_type = config.config_type.decode("utf-8")
+ 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)
+
+ 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/types.py b/wrappers/python/eduvpn_common/types.py
index 7e3ce9a..e4f8e26 100644
--- a/wrappers/python/eduvpn_common/types.py
+++ b/wrappers/python/eduvpn_common/types.py
@@ -15,6 +15,24 @@ from typing import Any, Callable, Iterator, List, Optional, Tuple
from eduvpn_common.error import ErrorLevel, 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),
+ ("expired", c_ulonglong),
+ ]
+
+
+class cConfig(Structure):
+ """The C type that represents the data that gets by the Go library returned when a config is obtained
+
+ :meta private:
+ """
+ _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
@@ -156,19 +174,10 @@ class DataError(Structure):
_fields_ = [("data", c_void_p), ("error", c_void_p)]
-class ConfigError(Structure):
- """The C type that represents the data that gets by the Go library returned when a config is obtained
-
- :meta private:
- """
- _fields_ = [("config", c_void_p), ("config_type", c_void_p), ("error", c_void_p)]
-
-
# The type for a Go state change callback
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
@@ -182,8 +191,11 @@ def encode_args(args: List[Any], types: List[Any]) -> Iterator[Any]:
"""
for arg, t in zip(args, types):
# c_char_p needs the str to be encoded to bytes
- if t is c_char_p:
- arg = arg.encode("utf-8")
+ encode_map = {
+ c_char_p: lambda x: x.encode("utf-8"),
+ }
+ if t in encode_map:
+ arg = encode_map[t](arg)
yield arg
@@ -201,7 +213,6 @@ def decode_res(res: Any) -> Any:
c_int: get_bool,
c_void_p: get_error,
DataError: get_data_error,
- ConfigError: get_config_error,
}
return decode_map.get(res, lambda lib, x: x)
@@ -268,25 +279,6 @@ def get_error(lib: CDLL, ptr: c_void_p) -> Optional[WrappedError]:
return wrapped
-def get_config_error(
- lib: CDLL, config_error: ConfigError
-) -> Tuple[str, str, Optional[WrappedError]]:
- """Convert a C config structure to a Python usable config structure
-
- :param lib: CDLL: The Go shared library
- :param config_error: ConfigError: The config error structure
-
- :meta private:
-
- :return: The configuration, configuration type ('openvpn'/'wireguard') and an optional error
- :rtype: Tuple[str, str, Optional[WrappedError]]
- """
- config = get_ptr_string(lib, config_error.config)
- config_type = get_ptr_string(lib, config_error.config_type)
- err = get_error(lib, config_error.error)
- return config, config_type, err
-
-
def get_data_error(
lib: CDLL, data_error: DataError, data_conv: Callable = get_ptr_string
) -> Tuple[Any, Optional[WrappedError]]: