From d4939e8694a6762dc9de2f4027266850f49790ac Mon Sep 17 00:00:00 2001 From: jwijenbergh Date: Mon, 1 May 2023 14:19:32 +0200 Subject: Docs: Update API section for V2 --- docs/src/api/README.md | 2 +- docs/src/api/architecture.md | 11 ++ docs/src/api/codeexamples.md | 16 ++ docs/src/api/go/README.md | 12 -- docs/src/api/go/example.md | 17 -- docs/src/api/go/functions.md | 76 -------- docs/src/api/languageinterop.md | 12 ++ docs/src/api/letsbuildaclient.md | 296 +++++++++++++++++++++++++++++++ docs/src/api/overview/README.md | 363 --------------------------------------- docs/src/api/overview/flow.md | 8 - docs/src/api/python/README.md | 2 - docs/src/api/python/example.md | 7 - docs/src/api/typicalflow.md | 13 ++ docs/src/api/wheretofinddocs.md | 6 + 14 files changed, 355 insertions(+), 486 deletions(-) create mode 100644 docs/src/api/architecture.md create mode 100644 docs/src/api/codeexamples.md delete mode 100644 docs/src/api/go/README.md delete mode 100644 docs/src/api/go/example.md delete mode 100644 docs/src/api/go/functions.md create mode 100644 docs/src/api/languageinterop.md create mode 100644 docs/src/api/letsbuildaclient.md delete mode 100644 docs/src/api/overview/README.md delete mode 100644 docs/src/api/overview/flow.md delete mode 100644 docs/src/api/python/README.md delete mode 100644 docs/src/api/python/example.md create mode 100644 docs/src/api/typicalflow.md create mode 100644 docs/src/api/wheretofinddocs.md (limited to 'docs/src/api') diff --git a/docs/src/api/README.md b/docs/src/api/README.md index 0b7ec55..8684c9c 100644 --- a/docs/src/api/README.md +++ b/docs/src/api/README.md @@ -1,2 +1,2 @@ # API -This section gives the documentation for the API. We first give an overview of the API in a language-agnostic way. Afterwards, we continue with the language specific documentation. We recommend to read both to get a complete picture, regardless of the language you're using. +This chapter is an introduction to the eduvpn-common API. It is meant as a high-level overview on how to use API and build your own eduVPN/Let's Connect! client. In this chapter, we *go* over the basics of how the interop between Go and language x works, say something about the architecture, explain where to find detailed API documentation, give a typical flow for a client and give a follow along tutorial on building an eduVPN client using Python code. diff --git a/docs/src/api/architecture.md b/docs/src/api/architecture.md new file mode 100644 index 0000000..72f63ef --- /dev/null +++ b/docs/src/api/architecture.md @@ -0,0 +1,11 @@ +# Architecture +In the previous section, we have already hinted a bit on the exact architecture. This section will expand upon it by giving a figure of the basic structure + +```mermaid +graph TD; +A[Go]-- Compiles to -->B[C shared library .so/.dll]; +C[Language wrapper]-- Loads -->B +Client -- Uses --> C; +``` + +As can be seen by this architecture, there is an intermediate layer between the client and the *shared* library. This wrapper eases the way of loading this library and then defining a more language specific API for it. In the eduvpn-common repo, we currently only support a Python wrapper. Clients themselves can define their own wrapper diff --git a/docs/src/api/codeexamples.md b/docs/src/api/codeexamples.md new file mode 100644 index 0000000..b3bcdc3 --- /dev/null +++ b/docs/src/api/codeexamples.md @@ -0,0 +1,16 @@ +# Code examples +This chapter contains code examples that use the API + +## Go command line client +The following is an example [in the repository](https://github.com/eduvpn/eduvpn-common/blob/v2/cmd/cli/main.go). It is a command line client with the following flags +``` + -get-custom string + The url of a custom server to connect to + -get-institute string + The url of an institute to connect to + -get-secure string + Gets secure internet servers +``` +```go +{{#include ../../../cmd/cli/main.go}} +``` diff --git a/docs/src/api/go/README.md b/docs/src/api/go/README.md deleted file mode 100644 index 2b71f99..0000000 --- a/docs/src/api/go/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Go -The API that has no additional wrapper code is the Go API. To begin to use the Go library in a Go client you first need to import it: - -```go -import "github.com/eduvpn/eduvpn-common/client" -``` - -This brings the client library into scope using the client prefix. - -The documentation to then use this API and the rest is online at [pkg.go.dev](https://pkg.go.dev/github.com/eduvpn/eduvpn-common). - -[We also provide an example](./example.md). diff --git a/docs/src/api/go/example.md b/docs/src/api/go/example.md deleted file mode 100644 index a7f293b..0000000 --- a/docs/src/api/go/example.md +++ /dev/null @@ -1,17 +0,0 @@ -# Example with comments -The following is an example [in the repository](https://github.com/eduvpn/eduvpn-common/blob/main/cmd/cli/main.go). It is a command line client with the following flags -``` - -get-custom string - The url of a custom server to connect to - -get-institute string - The url of an institute to connect to - -get-secure string - Gets secure internet servers -``` -```go -{{#include ../../../../cmd/cli/main.go}} -``` - -The documentation to then use this API is online at [pkg.go.dev](https://pkg.go.dev/github.com/eduvpn/eduvpn-common). - -[We also provide an example](./example.md). diff --git a/docs/src/api/go/functions.md b/docs/src/api/go/functions.md deleted file mode 100644 index 2cbab78..0000000 --- a/docs/src/api/go/functions.md +++ /dev/null @@ -1,76 +0,0 @@ -# Functions -## Registering -See [Overview](../overview/registering.html) -```go -func Register(name string, directory string, stateCallback func, debug bool) error -``` -- `name`: The name of the client -- `directory`: The directory where the configs and logging should be stored -- `stateCallback`: function with three arguments, full type: - ```go - func StateCallback(oldState string, newState string, data string) - ``` -- `debug`: Whether or not we want to enable debugging - -Returns an `error` type, nil if no error - -## Discovery -See [Overview](../overview/discovery.html) -```go -func GetDiscoServers() (string, error) -func GetDiscoOrganizations() (string, error) -``` - -Returns a string of JSON data with the servers/organizations and an `error`, nil if no error - -## OpenVPN/Wireguard config -See [Overview](../overview/getconfig.html) -```go -func GetConfigInstituteAccess(url string, preferTCP bool) (string, string, error) -func GetConfigSecureInternet(url string, preferTCP bool) (string, string, error) -``` -- `url`: The URL of the Institute Access or Secure Internet server to get a connect config for -- `preferTCP`: Whether or not we want to prefer TCP - -Returns: -- A `string` of the OpenVPN/Wireguard config -- A `string`, `openvpn` or `wireguard` indicating if it is an OpenVPN or Wireguard config -- An `error` (can be nil) - -### Cancelling OAuth -```go -func CancelOAuth() error -``` -Returns an `error`, can be nil indicating no error - -### Setting a profile ID -```go -func SetProfileID(profileID string) error -``` -- `profileID`: The profile ID to connect to - -Returns an `error`, can be nil indicating no error - -## Connecting/Disconnecting -See [Overview](../overview/connecting.html) -```go -func SetConnected() error -func SetDisconnected() error -``` - -Returns an `error`, can be nil indicating no error - -## Deregister -See [Overview](../overview/deregistering.html) -```go -func Deregister() error -``` - -Returns an `error`, can be nil indicating no error - -# Note on Callbacks -Some functions (e.g. [the API for getting an OpenVPN/Wireguard config](http://localhost:3000/api/overview/getconfig.html)) need a (or multiple) callback(s) set. In Go, the callback function is given in the [Register function](#registering). The signature of this function is the following: -```go -func StateCallback(oldState string, newState string, data string) -``` -Because certain callbacks need to be set, you can simply compare against `oldState` and `newState`. To show how this can be done in practice, we will give an example in the next section. diff --git a/docs/src/api/languageinterop.md b/docs/src/api/languageinterop.md new file mode 100644 index 0000000..7321874 --- /dev/null +++ b/docs/src/api/languageinterop.md @@ -0,0 +1,12 @@ +# Go <-> language X interop +Because this library is meant to be a *general* library for other clients to use that are written in different programming languages, we need to find a way to make this Go library available on each platform and codebase. The approach that we take is to build a C library from the Go library using Cgo. Cgo can have its disadvantages with performance and the constant conversion between Go and C types. To overcome those barriers, this library has the following goals (with some others noted here): +- **Be high-level**. Functions should do as much as possible in Go. The exported API should fit in one file. Lots of low-level functions would be a constant conversion between C and Go which adds overhead +- **Move as much state to Go as possible**. For example, Go keeps track of the servers you have configured and discovery. This makes the arguments to functions simple, clients should pass simple identifiers that Go can look up in the state +- **Easy type conversion**: to convert between C and Go types, JSON is used. Whereas Protobuf, Cap'n'proto or flatbuffers are more performant, they are harder to debug, add thousands of lines of autogenerated code and are not human friendly. Using JSON, the clients can approach it the same way they would use with a server using a REST API. Another approach is to just convert from Go -> C types -> language types. This was tried in version 1 of the library, but this ended up being too much work and manual memory management +- **Make it as easy as possible for clients to manage UI and internal state**: we use a state machine that gives the clients information in which state the Go library is in, e.g. we're selecting a server profile, we're loading the server endpoints. This library is not only a layer to talk to eduVPN servers, but the whole engine for a client +- **Implement features currently not present in existing clients**: WireGuard to OpenVPN failover, WireGuard over TCP +- **Follow the official eduVPN specification** and also contribute changes when needed +- **Secure**: We aim to follow the latest OAuth recommendations, to not store secret data and e.g. disable OpenVPN scripts from being ran by default + +And finally the most important goal: +- **The advantages that this library brings for clients should outweigh the cost of incorporating it into the codebase**. Initial versions would take more work than we get out of it. However, when each eduVPN/Let's Connect! client uses this library we should expect a net gain. New features should be easier to implement for clients by simply requiring a new eduvpn-common version and using the necessary functions diff --git a/docs/src/api/letsbuildaclient.md b/docs/src/api/letsbuildaclient.md new file mode 100644 index 0000000..bfb9258 --- /dev/null +++ b/docs/src/api/letsbuildaclient.md @@ -0,0 +1,296 @@ +# Let's build a client using Python +To begin, let's follow the flow and see if we can figure out how it works. + +## Registering + +> The client starts up. It calls the Register function that communicates with the library that it has initialized + +In Python, this works like the following: +- First import the library +```python +import eduvpn_common.main as edu + +# we will come back to this later +def handler(common: edu.EduVPN, old: int, old: int, data: str): + return False + +# These arguments can be found in the docstring +# But also in the exports.go file +# For Python it's a bit different, we have split the arguments into the constructor and register +# Here we pass the client ID for OAuth, the version of the client and the directory where config files should be found +common=edu.EduVPN("org.eduvpn.app.linux", "0.0.1", "/tmp/test") + +# Here we create a state handler with the class passed to it +state_handler = lambda old, new, data: handler(common, old, new, data) + +common.register(handler=state_handler, debug=True) +``` + +Now after registering, we know that we have no servers configured (unless you're following this tutorial again with an existing `/tmp/test`). So we continue with step 4 + +## Discovery + +> If the client has no servers, or it wants to add a new server, the client calls `DiscoOrganizations` and `DiscoServers` to get the discovery files from the library. + +```python +# Let's get them and print them +print(common.get_disco_organizations()) +print(common.get_disco_servers()) +``` + +We get a big JSON blob, so which format is this? From the Go documentation: + +> DiscoOrganizations gets the organizations from discovery, returned as types/discovery/discovery.go Organizations marshalled as JSON + +> DiscoServers gets the servers from discovery, returned as types/discovery/discovery.go Servers marshalled as JSON + +If you follow these files, you see two structs, Servers and Organizations. These structs have json tags associated with them. You can use this structure to figure out how to parse the returned data. In case of discovery, it's very similar to the discovery files from https://disco.eduvpn.org/v2 + +## Adding a server + +The next bullet point that we will do in the folow is: + +> From this discovery list, it calls AddServer to add the server to the internal server list of eduvpn-common. This also calls necessary state transitions, e.g. for authorizing the server. The next call to ServerList then has this server included + +The discovery servers contains a server called the demo server. Let's try to add it. To add it we need to pass the type of server we're adding. From discovery we can deduce that this is an institute access server as the JSON looks like the following: + +```json +{ + "authentication_url_template": "", + "base_url": "https://demo.eduvpn.nl/", + "display_name": { + "en": "Demo" + }, + "server_type": "institute_access", # this is why we know it is Institute Access + "support_contact": [ + "mailto:eduvpn@surf.nl" + ] +}, +``` + +From the Go documentation, we know that the identifier must be the Base URL: + +> id is the identifier of the string +> - In case of secure internet: The organization ID +> - In case of custom server: The base URL +> - In case of institute access: The base URL + + +```python +# Compare this to the Go version, the non-interactive field is optional here as it is default False +common.add_server(edu.ServerType.INSTITUTE_ACCESS, "https://demo.eduvpn.nl/") +``` + +But we get an error! +```bash +eduvpn_common.main.WrappedError: fsm failed transition from 'Chosen_Server' to 'OAuth_Started', is this required transition handled? +``` + +This is the state machine we briefly mentioned before. Some functions require that you handle certain transitions. From the Go documentation, we can find this in the documentation as well that you must handle this transition. Let's handle it in Python to open the webbrowser for the OAuth process. + +In the registering code, we previously defined a handler that does nothing. Let's extend it to handle the OAuth state transition: +```python +import webbrowser + +def handler(common: edu.EduVPN, old: int, new: int, data: str): + # you would define an enumeration with all the states so that you can also extend them + # it's 6 because https://github.com/eduvpn/eduvpn-common/blob/b660911b5db000b43970f3754b5767bb50741360/client/fsm.go#L33 + if new == 6: + webbrowser.open(data) + return True + return False +``` + +Now if you re-rerun the whole code with this handler added, your webbrowser should open. + +After you have authorized the application through the portal using the webbrowser, the server should have been added: + +```python +print(common.get_servers()) +``` + +Returns: + +```json +{ + "institute_access_servers": [ + { + "display_name": { + "en": "Demo" + }, + "identifier": "https://demo.eduvpn.nl/", + "profiles": { + "current": "" + }, + "delisted": false + } + ] +} +``` + +The format of this JSON is specified in the Go documentation: + +`(in exports/exports.go)` +> It returns the server list as a JSON string defined in types/server/server.go List + +## Obtaining a VPN configuration from the server + +The next part of the flow is: + +> When the user selects a server to connect to in the UI, it calls the GetConfig to get a VPN configuration for this server. This function transitions the state machine multiple times. The client uses these state transitions for logging or even updating the UI. The client then connects + +Let's try it, the required arguments are the same for adding a config in the Python wrapper: + +```python +print(common.get_config(edu.ServerType.INSTITUTE_ACCESS, "https://demo.eduvpn.nl")) +``` + +However, this gives an exception: + +```bash +eduvpn_common.main.WrappedError: fsm failed transition from 'Request_Config' to 'Ask_Profile', is this required transition handled? +``` + +A similar error to the OAuth error we had before. This `Ask_Profile` transition is there for the client/user to choose a profile as this server has multiple profiles defined. + +To handle this transition and thus choose a profile to continue, we must do multiple steps: +- Add the condition to the handler to return true +- Parse the data that we get back +- Reply with a choice for the profile + +If we add the condition and print the data: + +```python +if new == 9: + print(f"profiles received: {data}") + return True +``` + +we get back the following JSON (from the Go docs: `The data for this transition is defined in types/server/server.go RequiredAskTransition with embedded data Profiles in types/server/server.go`): + +```python +{ + "cookie": 4, + "data": { + "map": { + "internet": { + "display_name": { + "en": "Internet" + }, + "supported_protocols": [ + 1, + 2 + ] + }, + "internet-split": { + "display_name": { + "en": "No rfc1918 routes" + }, + "supported_protocols": [ + 1, + 2 + ] + } + }, + "current": "" + } +} +``` + +This thus gives you the list of profiles with a so-called "cookie". This *cookie* is used to confirm the choice to the Go library. To do so we must do the following in the handler: + +```python +if new == 9: + json_dict = json.loads(data) + common.cookie_reply(json_dict["cookie"], "internet") + return True +``` + +If we then re-run the code, we get back the following JSON (from the Go docs: `The return data is the configuration, marshalled as JSON and defined in types/server/server.go Configuration`) + +```python +{ + "config": "the WireGuard config", + "protocol": 2, # 2 specifies WireGuard + "default_gateway": true +} +``` + +## Cleanup +The flow also mentioned: + +> When the client is done, it calls `Deregister` such that the most up to date internal state is saved to disk. Note that eduvpn-common also saves the internal state .e.g. after obtaining a VPN configuration + +Let's be a nice client and do this: + +```python +common.deregister() +``` + +If we then call any function, we get an error, so it is important that you do this on exit: + +```python +print(common.get_servers()) +>>> eduvpn_common.main.WrappedError: No state available, did you register the client? +``` + +But when we register again and then get the list of servers, the servers are retrieved from disk: + +```python +common=edu.EduVPN("org.eduvpn.app.linux", "0.0.1", "/tmp/test") +common.register(handler=state_handler, debug=True) +print(common.get_servers()) +``` + +gives + +```json +{ + "institute_access_servers": [ + { + "display_name": { + "en": "Demo" + }, + "identifier": "https://demo.eduvpn.nl/", + "profiles": { + "map": { + "internet": { + "display_name": { + "en": "Internet" + }, + "supported_protocols": [ + 1, + 2 + ] + }, + "internet-split": { + "display_name": { + "en": "No rfc1918 routes" + }, + "supported_protocols": [ + 1, + 2 + ] + } + }, + "current": "internet" + }, + "delisted": false + } + ] +} +``` + +Note the difference with the previous JSON, the profiles are now initialized because we have gotten a configuration before. + +If the `/tmp/test` directory is removed (the argument that was passed to register), we get no servers again: + +```python +import shutil +shutil.rmtree("/tmp/test") +common=edu.EduVPN("org.eduvpn.app.linux", "0.0.1", "/tmp/test") +common.register(handler=state_handler, debug=True) +print(common.get_servers()) +``` + +gives `"{}"`, an empty JSON object string diff --git a/docs/src/api/overview/README.md b/docs/src/api/overview/README.md deleted file mode 100644 index 32e0893..0000000 --- a/docs/src/api/overview/README.md +++ /dev/null @@ -1,363 +0,0 @@ -# API overview - -This chapter defines the API that is used to build an eduVPN/Let's Connect! client. We explain what functions there are, what their use is and what a typical flow is for creating an eduVPN client with this library. The extensive language specific documentation will be given in separate sections. - -## Table of contents -1. [Types](#types) - - [JSON](#json) - - [Errors](#errors) - - [States](#states) -2. [Functions](#functions) - - [Registering](#registering) - - [Add a server](#add-a-server) - - [Remove a server](#remove-a-server) - - [List of servers](#list-of-servers) - - [Current server](#current-server) - - [Get VPN config](#get-vpn-config) - - [Expiry Times](#expiry-times) - - [Set Profile ID](#set-profile-id) - - [Set Secure Location](#set-profile-id) - - [Discovery Servers](#discovery-servers) - - [Discovery Organizations](#discovery-organizations) - - [Cancel OAuth](#cancel-oauth) - - [Set Support WireGuard](#set-support-wireguard) - - [Cleanup](#cleanup) - - [Renew Session](#renew-session) - - [Secure Location List](#secure-location-list) - - [Start Failover](#start-failover) - - [Cancel Failover](#cancel-failover) - - [Deregistering](#deregistering) - - [Free String](#free-string) - -## Types -This section describes a few types that are either used as arguments or return values - -### JSON - -The message passing between language X and Go is done using JSON. This means that every type that we mention here is converted to JSON. For a list of public types that are returned and their JSON representation see: . So for example, if we say that we return `types.server.Expiry` (meaning the `Expiry` struct defined in the [types/server](https://github.com/eduvpn/eduvpn-common/blob/v2/types/server/server.go)), we will return the following json representation: - -```json -{ - "start_time": 5, - "end_time": 6, - "button_time": 7, - "countdown_time": 8, - "notification_times": [1, 2], -} -``` - -But in the Go API, this means that we actually return the struct `types.server.Expiry`, so e.g. - -```Go -// Get the return type -rt := somefunction() -fmt.Println(rt.start_time) -``` - -If we for example have an enumeration, e.g. `types.protocol.Protocol`, this is converted as an integer. E.g. `Unknown` translates to `0`, `OpenVPN` to `1` and `WireGuard` to `2`. - -You can also see this when reading the source code. In Go this was denoted with the `iota` keyword, meaning start at 0 and increment on following const declarations. - -> **_NOTE:_** strings returned by CGO (`*C.char`) MUST be freed by the [FreeString](#free-string) function. - -### Errors -Errors are encoded as error messages (`*C.char`) in the CGO API. For regular Go, this is just `error`. Errors are *hard-fail* unless otherwise defined. Hard-fail means that the associated data that is returned will be nil/default value if an error is returned. - -> **_NOTE:_** In case of CGO this error (a `*C.char`) MUST be freed by the [FreeString](#free-string) function. - -### States - -The `states` is an enumeration of the possible states that the state machine has defined. Starting at 0: - -- `Deregistered`: the client is not yet registered -- `No Server`: the client has registered and we're about to choose a server -- `Ask Location`: eduvpn-common is asking the client for a secure internet location - - A slice/list `[]string` of locations (country codes). For the C API: a JSON list e.g. - ```json - ["nl", "de"] - ``` -- `Chosen Location`: a secure internet location has been chosen -- `Loading Server`: the server is loading, e.g. doing a request -- `Chosen Server`: the server has been chosen -- `OAuth Started`: the OAuth procedure has started - - Data with this transition: the URL to open in the browser as a string -- `Authorized`: authorization is finished, OAuth process is done -- `Request Config`: eduvpn-common is requesting a config from the server -- `Ask Profile`: eduvpn-common is asking the client for a profile - - Data with this transition: `types.server.Profiles`. -- `Chosen Profile`: A profile has been chosen by the client -- `Got Config`: A VPN Configuration has been obtained for the current server and the client should be ready to connect - -The states with data are required transitions, handle them by returning True/non-zero (e.g. 1) in your callback function. We will discuss this callback function later. - -## Functions -For each function, we define it by giving a small description and then the arguments and return types that follows. We will also describe which type of state transitions must be handled by the client in order to call this function. - -The functions are defined, more or less, in the order that you might call them. - -### Registering -The first function that a client calls is the `register` -function. This function is meant as a registration/constructor of the -library and can only be called once during the lifetime of the library -(until `deregister` is called). - -The arguments are: -- The name of the client as a ClientID (`string`), e.g. `org.eduvpn.app.linux` -- The version field that is used in the HTTP User agent (`string`), e.g. `1.0.0` -- The directory where config files are stored, absolute or relative (`string`), e.g. `/home/eduvpn/.config/eduvpn` -- A boolean that indicates whether or not debugging is enabled, debugging means log more verbose -- The callback function which is used for state transitions. Takes three arguments, old state (integer), new state (integer), data (string, JSON) - -Return type: -- An error - -
- Python - -```python -from eduvpn_common.main import EduVPN - -# These integers are an enumeration under the hood -# See https://github.com/eduvpn/eduvpn-common/blob/v2/client/fsm.go#L17 -def callback(old_state: int, new_state: int, data: str): - pass - -# Some arguments are in the class constructor -eduvpn = EduVPN("org.eduvpn.app.linux", "1.0.0", "/home/eduvpn/.config/eduvpn") -eduvpn.register(handler=callback, debug=True) -``` -
-
-Go - -```go -import "github.com/eduvpn/eduvpn-common/client" - -// Note: these integer types may also be defined as client.FSMStateID -// See: https://github.com/eduvpn/eduvpn-common/blob/v2/client/fsm.go#L17 -// The data here is an interface as we do not convert anything to JSON for the Go API -// You would type check depending on the state transition, e.g. https://github.com/eduvpn/eduvpn-common/blob/85aec7dbe5ba18b1b1e2ea3cd35b0d5797c404c3/cmd/cli/main.go#L101 -func stateCallback(oldState int, newState int, data interface{}) { - // do something -} - -c, err := client.New("org.eduvpn.app.linux", "1.0.0", "/home/eduvpn/.config/eduvpn", stateCallback, true) -if err != nil { - // handle error -} -err := c.Register() -if err != nil { - // handle error -} -``` -
- -### Add a server - -Eduvpn-common keeps track of the servers that the user/client has defined. To add a server, the `add server` function must be called. - -Arguments: -- The type of server (`types.server.Type`) -- The identifier of the server (`string`), in case of secure internet the Org ID, otherwise the base URL - -State transitions that must be handled: -- `OAuth_Started`: If the server needs authorization. Open the URL in the browser -- `Ask_Profile`: For choosing the correct profile. Acknowledge the request with [SetProfileID](#set-profile-id) -- `Ask_Location`: For asking the secure internet location. Acknowledge the request with [SetSecureLocationID](#set-secure-location-id) - - -Return type: -- An error message (`string`). Empty string if no error - -### Remove a server -You can also remove a server again, using the `remove server` function. - -Arguments: -- The type of server (`types.server.Type`) -- The identifier of the server (`string`), in case of secure internet the Org ID, otherwise the base URL - -Return type: -- An error - -### List of servers -To get all the currently configured servers and some of their associated data, the `server list` function is used. - -Arguments: -- None - -Return type: -- The list of servers (`types.server.List`) -- An error - - -### Current server -After adding or getting a configuration for a server, the Go library sets that server as the `current` server internally. This is so that EduVPN clients do not even have to keep track of which server is currently configured. - -Arguments: -- None - -Return type: -- The current server (`types.server.Current`) -- An error - - -### Get VPN config -To get a VPN configuration (`WireGuard` or `OpenVPN`) for a server, the `get config` function is used. Note that the server must first have been added before calling this function. - -Arguments: -- The type of server (`types.server.Type`) -- The identifier of the server (`string`), in case of secure internet the Org ID, otherwise the base URL -- A boolean which indicates whether or not prefer TCP should be set -- Tokens used for authorization `types.server.Tokens`. If no tokens, pass a default struct or "{}" with the C JSON API - -State transitions that must be handled: -- `OAuth_Started`: If the server needs to trigger re-authorization. Open the URL in the browser -- `Ask_Profile`: For choosing the correct profile. Acknowledge the request with [SetProfileID](#set-profile-id) -- `Ask_Location`: For asking the secure internet location. Acknowledge the request with [SetSecureLocation](#set-secure-location) - -Return type: -- The VPN configuration with associated data (`types.server.Configuration`). Note that this also contains Tokens that can be saved by the client. Note that the VPN configuration itself has "script-security 0" added to the end if it's an OpenVPN config. This is to disable OpenVPN scripts from being run by default. A client may override this if it has a good reason to. -- An error - -### Expiry Times -To get the different times regarding expiry, the function `expiry times` is used. - -Arguments: -- None - -Return type: -- The expiry times (`types.server.Expiry`) -- An error - -### Set Profile ID -Set the profile ID for the current server. To be used as a reply to `Ask_Location` or just to change the current profile before getting a configuration - -Arguments: -- The profile ID (`string`) - -Return type: -- An error message (`string`). Empty string if no error - -### Set Secure Location -Set the secure internet location for the current server. To be used as a reply to `Ask_Location` or just to change the current location before getting a configuration - -Arguments: -- The location as a country code (`string`) - -Return type: -- An error - - -### Discovery servers -Get the discovery servers from . This returns a cached list if the server should not be contacted according to the eduvpn spec at . So you do not have to worry about when to call this function. However, clients may cache further to prevent parsing this data every time. - -Arguments: -- None - -Return type: -- The servers (`types.discovery.Servers`) -- An error message (`string`). Empty string if no error. Note that if an error is returned, when building this library in [release mode](/gettingstarted/building/release.md) this function is guaranteed to return a result for the servers, unless there is an issue with parsing the internal data representation. So the error can be used for logging instead of being a hard-fail - -### Discovery organizations -Get the discovery organizations from . This returns a cached list if the server should not be contacted according to the eduvpn spec at . So you do not have to worry about when to call this functions. Clients may cache further to prevent parsing this data every time. - -Arguments: -- None - -Return type: -- The organizations (`types.discovery.Organizations`) -- An error. Note that if an error is returned, when building this library in [release mode](/gettingstarted/building/release.md) this function is guaranteed to return a result for the organizations, unless there is an issue with parsing the internal data representation. So the error can be used for logging instead of being a hard-fail - -### Cancel OAuth -Cancel the current OAuth process. - -Arguments: -- None - -Return type: -- An error - -### Set Support WireGuard -> **_NOTE:_** This function might be removed in the future. This is currently here for the Linux client and also for the failover procedure. - -WireGuard is by default enabled. To indicate that the client does not support WireGuard, you can use the `SetSupportWireGuard` function. - -Arguments: -- A boolean that indicates whether or not WireGuard should be enabled or disabled - -Return type: -- An error - -### Cleanup -Cleans up the VPN connection by sending a /disconnect - -Arguments: -- None - -### Renew Session -Renew session is used for renewing the VPN. This does not give you a configuration, but merely deletes the OAuth tokens from the current server. - -Arguments: -- None - -State transitions that must be handled: -- `OAuth_Started`: If the server needs authorization. Open the URL in the browser - -Return type: -- An error - -### Secure Location List -> **_NOTE:_** This function might be removed in the future as clients can parse this out of discovery themselves - -This gets the list of secure internet locations that are available in discovery. - -Arguments: -- None - -Return type: -- A slice/list of country codes (`[]string`) -- An error - - -### Start Failover -Eduvpn-common also has a `failover` implementation that can be started with `start failover`. This is used to check whether or not the VPN can reach the internet. Useful when connecting to WireGuard or OpenVPN over UDP. This function sends ICMP echo pings for a maximum of 10 seconds up until it is dropped. If a ping can be send and a pong returns within a timeout of 2 seconds, it returns after this pong is received. - -If this functions tells you that the VPN is dropped, it might be wise to get a configuration again using Prefer TCP (see [Get VPN Config](#get-vpn-config)) and disabling WireGuard (see [Set Support Wireguard](#set-support-wireguard)). Note that this `start failover` function also checks if the current profile supports OpenVPN and will return an error if it doesn't. - -Arguments: -- Gateway (`string`), the IP endpoint to ping to check if the VPN can reach the internet. As the name suggests, this should be the gateway -- MTU (`int`), the packet size to send for each ping. As the name suggests, this should be the MTU of the connection -- `readRxBytes`, a function that returns the current Rx bytes counter (`int64` in Go, `long long int` in CGO api) for the connection. Used to check if any bytes have been received in an interval of maximum 10 seconds - -Return type: -- Dropped: a boolean that indicates whether or not the connection is dropped according to eduvpn-common. This means that the VPN is unable to reach the gateway -- An error - -### Cancel Failover -To cancel the current failover process, e.g. due to disconnecting, you should call `cancel failover`. This makes the original failover function return dropped `false` and an error indicating cancellation. - -Arguments: -- None - -Return type: -- An error - -### Deregistering -When the client is done, e.g. on application close, it can call the `deregister` function to save the internal state to disk and afterwards empty out this state. This can also be used to re-register, but this is probably not something you have to do. - -Arguments: -- None - -Return type: -- An error - -### Free String -> **_NOTE:_** This does not apply for the pure Go API - -With the Go <-> X language API (using CGO), there is a function to free a string (`*C.char`). This is called `free string` - -Arguments: -- The pointer to the string - -Return type: -- None diff --git a/docs/src/api/overview/flow.md b/docs/src/api/overview/flow.md deleted file mode 100644 index 14b5a72..0000000 --- a/docs/src/api/overview/flow.md +++ /dev/null @@ -1,8 +0,0 @@ -# Typical flow -A typical flow of creating a client is calling the methods that we talked about in order that we introduced them: - -- The client starts, it registers with the library -- A list of discovery servers/organizations is obtained using the library -- The client selects an URL to connect to and calls the function to get an OpenVPN/Wireguard config from the library -- The client uses the OS specific libraries and programs to use the OpenVPN/Wireguard config to establish a tunnel and calls the function to connect or disconnect -- When the client is done it calls the deregister method to save all configuration and clean up diff --git a/docs/src/api/python/README.md b/docs/src/api/python/README.md deleted file mode 100644 index 6bc66b6..0000000 --- a/docs/src/api/python/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Python -As the Go library is build as a *shared* library, it can be loaded by other languages. We have created wrapper code for Python to use this library. The api documentation can be found [here](./rtd/index.html). In the next chapter we will give a similar example to the Go example. diff --git a/docs/src/api/python/example.md b/docs/src/api/python/example.md deleted file mode 100644 index d4f6c08..0000000 --- a/docs/src/api/python/example.md +++ /dev/null @@ -1,7 +0,0 @@ -# Example with comments - -This is an example that can also be found [in the repository](https://github.com/eduvpn/eduvpn-common/blob/main/wrappers/python/main.py). It gets a config from an Institute Access server with support for multiple profiles. - -```python -{{#include ../../../../wrappers/python/example/main.py}} -``` diff --git a/docs/src/api/typicalflow.md b/docs/src/api/typicalflow.md new file mode 100644 index 0000000..2260352 --- /dev/null +++ b/docs/src/api/typicalflow.md @@ -0,0 +1,13 @@ +# Typical flow for a client +> **_NOTE:_** This uses the function names that are defined in the exports file in Go. For your own wrapper/the Python wrapper they are different. But the general flow is the same +1. The client starts up. It calls the `Register` function that communicates with the library that it has initialized +2. It gets the list of servers using `ServerList` +3. When the user selects a server to connect to in the UI, it calls the `GetConfig` to get a VPN configuration for this server. This function transitions the state machine multiple times. The client uses these state transitions for logging or even updating the UI. The client then connects + - New feature in eduvpn-common: Check if the VPN can reach the gateway after the client is connected by calling `StartFailover` +4. If the client has no servers, or it wants to add a new server, the client calls `DiscoOrganizations` and `DiscoServers` to get the discovery files from the library. This even returns cached copies if the organizations or servers should not have been updated [according to the documentation](https://docs.eduvpn.org/server/v3/server-discovery.html) + - From this discovery list, it calls `AddServer` to add the server to the internal server list of eduvpn-common. This also calls necessary state transitions, e.g. for authorizing the server. The next call to `ServerList` then has this server included + - It can then get a configuration for this server like we have explained in *step 3* +5. When a configuration has been obtained, the internal state has changed and the client can get the current server that was configured using `CurrentServer`. `CurrentServer` can also be called after startup if a server was previously set as the current server. +6. When the VPN disconnects, the client calls `Cleanup` so that the server resources are cleaned up by calling the `/disconnect` endpoint +7. A server can be removed with the `RemoveServer` function +8. When the client is done, it calls `Deregister` such that the most up to date internal state is saved to disk. Note that eduvpn-common also saves the internal state .e.g. after obtaining a VPN configuration diff --git a/docs/src/api/wheretofinddocs.md b/docs/src/api/wheretofinddocs.md new file mode 100644 index 0000000..cbf4a67 --- /dev/null +++ b/docs/src/api/wheretofinddocs.md @@ -0,0 +1,6 @@ +# Where to find API docs +The API documentation, depends on which wrapper you are using. If you're writing a wrapper yourself, or want some background information on how it works internally, you can find function docs in the [exports/exports.go](https://github.com/eduvpn/eduvpn-common/blob/v2/exports/exports.go) file. + +This file is commented using Go comment style. It gives a basic of what the function does, what it returns and what type of arguments you should pass to it. The API documentation for the Python wrapper can be [found here](https://eduvpn.github.io/eduvpn-common/api/python/rtd/index.html). + +There is also a Go API that is defined in the [client package](https://github.com/eduvpn/eduvpn-common/tree/v2/client). However, this is not the primary use case for the library. -- cgit v1.2.3