summaryrefslogtreecommitdiff
path: root/apidocs.html
diff options
context:
space:
mode:
Diffstat (limited to 'apidocs.html')
-rw-r--r--apidocs.html935
1 files changed, 935 insertions, 0 deletions
diff --git a/apidocs.html b/apidocs.html
new file mode 100644
index 0000000..0a6a36e
--- /dev/null
+++ b/apidocs.html
@@ -0,0 +1,935 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" href="css/simple.css">
+ <link rel="stylesheet" href="css/screen.css">
+ <title>API Docs - Documentation</title>
+</head>
+<body>
+ <header>
+ <h1>Documentation</h1>
+
+ <p>eduVPN for Linux</p>
+
+
+ <nav>
+
+ <a href="index.html">About</a>
+
+ <a href="building.html">Building</a>
+
+ <a href="testing.html">Testing</a>
+
+ <a href="building-client.html">Building a client</a>
+
+ <a href="apidocs.html">API Docs</a>
+
+ </nav>
+
+ </header>
+ <main>
+
+ <aside>
+
+ <ul>
+
+ <li class="nav-item" data-level="2"><a href="#addserver" class="nav-link">AddServer</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#calculategateway" class="nav-link">CalculateGateway</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#cleanup" class="nav-link">Cleanup</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#cookiecancel" class="nav-link">CookieCancel</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#cookiedelete" class="nav-link">CookieDelete</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#cookienew" class="nav-link">CookieNew</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#cookiereply" class="nav-link">CookieReply</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#currentserver" class="nav-link">CurrentServer</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#deregister" class="nav-link">Deregister</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#discoorganizations" class="nav-link">DiscoOrganizations</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#discoservers" class="nav-link">DiscoServers</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#expirytimes" class="nav-link">ExpiryTimes</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#freestring" class="nav-link">FreeString</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#getconfig" class="nav-link">GetConfig</a>
+ <ul class="nav flex-column">
+ <li class="nav-item" data-level="3"><a href="#ask_profile" class="nav-link">ASK_PROFILE</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+ <li class="nav-item" data-level="3"><a href="#ask_location" class="nav-link">ASK_LOCATION</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+ <li class="nav-item" data-level="3"><a href="#oauth_started" class="nav-link">OAUTH_STARTED</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#instate" class="nav-link">InState</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#newproxyguard" class="nav-link">NewProxyguard</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#proxyguardpeerips" class="nav-link">ProxyguardPeerIPs</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#proxyguardrestart" class="nav-link">ProxyguardRestart</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#proxyguardtunnel" class="nav-link">ProxyguardTunnel</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#register" class="nav-link">Register</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#removeserver" class="nav-link">RemoveServer</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#renewsession" class="nav-link">RenewSession</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#serverlist" class="nav-link">ServerList</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#setprofileid" class="nav-link">SetProfileID</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#setsecurelocation" class="nav-link">SetSecureLocation</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#setstate" class="nav-link">SetState</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#settokenhandler" class="nav-link">SetTokenHandler</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+
+ <li class="nav-item" data-level="2"><a href="#startfailover" class="nav-link">StartFailover</a>
+ <ul class="nav flex-column">
+ </ul>
+ </li>
+ </ul>
+ </aside>
+
+ <p>This document was automatically generated from the exports/exports.go file</p>
+<h1 id="about-the-api">About the API<a class="headerlink" href="#about-the-api" title="Permanent link">#</a></h1>
+<p>Some notes:</p>
+<ul>
+<li>
+<p>Errors are returned as JSON c strings. The JSON type is defined in
+<code>types/error/error.go Error</code>. Free them using <code>FreeString</code>. Same is the case for
+other string types, you should also free them. The errors are always localized</p>
+</li>
+<li>
+<p>Types are converted from the Go representation to C using JSON strings</p>
+</li>
+<li>
+<p>Cookies are used for cancellation, just fancy contexts. Create a cookie using
+<code>CookieNew</code>, pass it to the function that needs one as the first argument. To
+cancel the function, call <code>CookieCancel</code>, passing in the same cookie as argument</p>
+</li>
+<li>
+<p>Cookies must also be freed, by using the CookieDelete function if the cookie
+is no longer needed</p>
+</li>
+<li>
+<p>The state machine is used to track the state of a client. It is mainly used
+for asking for certain data from the client, e.g. asking for profiles and
+locations. But a client may also wish to build upon this state machine to build
+the whole UI around it. The SetState and InState functions are useful for this</p>
+</li>
+</ul>
+<h1 id="functions">Functions<a class="headerlink" href="#functions" title="Permanent link">#</a></h1>
+<h2 id="addserver">AddServer<a class="headerlink" href="#addserver" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func AddServer(c C.uintptr_t, _type C.int, id *C.char, ot *C.longlong) *C.char
+</code></pre>
+<p>AddServer adds a server to the eduvpn-common server list <code>c</code> is the cookie
+that is used for cancellation. Create a cookie first with CookieNew.
+This same cookie is also used for replying to state transitions.</p>
+<p><code>_type</code> is the type of server that needs to be added. This type is defined
+in <code>types/server/server.go Type</code></p>
+<p><code>id</code> is the identifier of the string:</p>
+<ul>
+<li>In case of secure internet: The organization ID</li>
+<li>In case of custom server: The base URL</li>
+<li>In case of institute access: The base URL</li>
+</ul>
+<p><code>ni</code> stands for non-interactive. If non-zero, any state transitions will not
+be run.</p>
+<p>This <code>ot</code> flag is useful for preprovisioned servers; set this to non-null to
+non-interactively add a server. This flag represents the Unix time OAuth was
+last triggered, if the server needs to be added non-interactively but there
+is no token structure, set this to zero (integer) or the current Unix time.
+This value will be overwritten once OAuth is triggered.</p>
+<p>If the server cannot be added it returns the error as <code>types/error/error.go
+Error</code>. Note that the server is removed when an error has occured</p>
+<p>The following state callbacks are mandatory to handle:</p>
+<ul>
+<li>OAUTH_STARTED: This indicates that the OAuth procedure has been started,
+ it returns the URL as the data. The client should open the webbrowser
+ with this URL and continue the authorization process. Note: For mobile
+ platforms this returns a Cookie and data (json: <code>{"cookie": x, "data":
+ url}</code>). This <code>url</code> should also be opened in the browser like desktop
+ platforms. But these platforms also need to reply to the library to give
+ back the full authorization code URI with <code>CookieReply(x, uri)</code>. E.g.
+ <code>CookieReply(x, "/callback?code=...&amp;state=...&amp;iss=...")</code> this is the
+ path of the request that the apps get back when the user clicks approve.
+ For this, apps need to register an app url or sorts. For the valid
+ values for app URLs, see the redirect URIs for mobile platforms here
+ https://git.sr.ht/~fkooman/vpn-user-portal/tree/v3/item/src/OAuth/VpnClientDb.php</li>
+</ul>
+<p>Example Input (3=custom server): <code>AddServer(mycookie, 3,
+"https://demo.eduvpn.nl", 0)</code></p>
+<p>Example Output:</p>
+<pre><code>{
+ "message": {
+ "en": "failed to add server"
+ },
+ "misc": false
+}
+</code></pre>
+<h2 id="calculategateway">CalculateGateway<a class="headerlink" href="#calculategateway" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func CalculateGateway(subnet *C.char) (*C.char, *C.char)
+</code></pre>
+<p>CalculateGateway calculates the gateway for a subnet, it can take IPv4 or
+IPv6 networks with CIDR notation as inputs and returns the gateway address.</p>
+<p>This is useful to pass to <code>StartFailover</code>.
+It returns an error if it fails to calculate a gateway.
+The function is implemented according to: <a href="https://docs.eduvpn.org/server/v3/client-implementation-notes.html#fail-over">the eduVPN
+docs</a>.</p>
+<p>Example Input: <code>CalculateGateway("10.10.0.5/24")</code></p>
+<p>Example Output: <code>"10.10.0.1", null</code></p>
+<h2 id="cleanup">Cleanup<a class="headerlink" href="#cleanup" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func Cleanup(c C.uintptr_t) *C.char
+</code></pre>
+<p>Cleanup sends a <code>/disconnect</code> to cleanup the connection.</p>
+<p>This MUST be called when disconnecting, see <a href="https://docs.eduvpn.org/server/v3/api.html#application-flow">the eduVPN
+docs</a>. <code>c</code> is
+the Cookie that needs to be passed. Create a new Cookie using <code>CookieNew</code>.</p>
+<p>If it was unsuccessful, it returns an error.</p>
+<p>Example Input: <code>Cleanup(myCookie)</code></p>
+<p>Example Output:</p>
+<pre><code>{
+ "message": {
+ "en": "cleanup was not successful"
+ },
+ "misc": false
+}
+</code></pre>
+<h2 id="cookiecancel">CookieCancel<a class="headerlink" href="#cookiecancel" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func CookieCancel(c C.uintptr_t) *C.char
+</code></pre>
+<p>CookieCancel cancels the cookie.</p>
+<p>This means that functions which take this as first argument,
+return if they&rsquo;re still running. The error cause is always
+<code>context.Canceled</code> for that cancelled function: <a href="https://pkg.go.dev/context#pkg-variables">see the Go
+docs</a>.</p>
+<p>This CookieCancel function can also return an error if cancelling was
+unsuccessful. Example Input: <code>CookieCancel(myCookie)</code></p>
+<p>Example Output: null</p>
+<h2 id="cookiedelete">CookieDelete<a class="headerlink" href="#cookiedelete" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func CookieDelete(c C.uintptr_t) *C.char
+</code></pre>
+<p>CookieDelete deletes the cookie by cancelling it and deleting the underlying
+cgo handle.</p>
+<p>This function MUST be called when the cookie that is created using
+<code>CookieNew</code> is no longer needed. Example Input: <code>CookieDelete(myCookie)</code></p>
+<p>Example Output: null</p>
+<h2 id="cookienew">CookieNew<a class="headerlink" href="#cookienew" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func CookieNew() C.uintptr_t
+</code></pre>
+<p>CookieNew creates a new cookie and returns it. Functions that take a cookie
+have it as the first argument.</p>
+<p>This value should not be parsed or converted somehow by the client. This
+value is simply to pass back to the Go library. This value has two purposes:</p>
+<ul>
+<li>Cancel a long running function</li>
+<li>Send a reply to a state transition (ASK_PROFILE and ASK_LOCATION)</li>
+</ul>
+<p>Example Input: <code>CookieNew()</code></p>
+<p>Example Output: <code>5</code></p>
+<h2 id="cookiereply">CookieReply<a class="headerlink" href="#cookiereply" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func CookieReply(c C.uintptr_t, data *C.char) *C.char
+</code></pre>
+<p>CookieReply replies to a state transition using the cookie.</p>
+<ul>
+<li><code>c</code> is the Cookie</li>
+<li><code>data</code> is the data to send, e.g. a profile ID</li>
+</ul>
+<p>Example Input: <code>CookieReply(myCookie, "split-tunnel-profile")</code></p>
+<p>Example Output: <code>null</code></p>
+<h2 id="currentserver">CurrentServer<a class="headerlink" href="#currentserver" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func CurrentServer() (*C.char, *C.char)
+</code></pre>
+<p>CurrentServer gets the current server from eduvpn-common</p>
+<p>In eduvpn-common, a server is marked as &lsquo;current&rsquo; if you have gotten a VPN
+configuration for it</p>
+<p>It returns the server as JSON, defined in <code>types/server/server.go Current</code>.</p>
+<p>If there is no current server or some other, e.g. there is no current state,
+an error is returned with a nil string.</p>
+<p>Example Input: <code>CurrentServer()</code></p>
+<p>Example Output:</p>
+<pre><code>{
+ "institute_access_server": {
+ "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"
+ },
+ "support_contacts": [
+ "mailto:eduvpn@surf.nl"
+ ],
+ "delisted": false
+ },
+ "server_type": 1
+}, null
+</code></pre>
+<h2 id="deregister">Deregister<a class="headerlink" href="#deregister" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func Deregister() *C.char
+</code></pre>
+<p>Deregister cleans up the state for the client.</p>
+<p>This function SHOULD be called when the application exits such that the
+configuration file is saved correctly. Note that saving of the configuration
+file also happens in other cases, such as after getting a VPN configuration.
+Thus it is often not problematic if this function cannot be called due to a
+client crash.</p>
+<p>If no client is available or deregistering fails, it returns an error.</p>
+<p>Example Input: <code>Deregister()</code></p>
+<p>Example Output:</p>
+<pre><code>{
+ "message": {
+ "en": "failed to deregister"
+ },
+ "misc": false
+}
+</code></pre>
+<h2 id="discoorganizations">DiscoOrganizations<a class="headerlink" href="#discoorganizations" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func DiscoOrganizations(c C.uintptr_t, cache C.int, search *C.char) (*C.char, *C.char)
+</code></pre>
+<p>DiscoOrganizations gets the organizations from discovery, returned as
+<code>types/discovery/discovery.go Organizations</code> marshalled as JSON.</p>
+<ul>
+<li><code>c</code> is the Cookie that needs to be passed. Create a new Cookie using
+ <code>CookieNew</code></li>
+<li><code>cache</code> indicates whether or not the cache should only be used, meaning
+ no network call</li>
+<li><code>search</code> is the search string for filtering the list.</li>
+</ul>
+<p>If any of the words in the <code>search</code> query is not contained in
+any of the display names or keywords, the candidate is filtered.
+Otherwise they are ranked based on the levenshtein distance: <a href="https://en.wikipedia.org/wiki/Levenshtein_distance">Levenshtein
+Wikipedia</a>. If <code>search</code>
+is empty it returns ALL organizations currently known in common</p>
+<p>If it was unsuccessful, it returns an error. Note that when the lib was
+built in release mode the data is almost always non-nil, even when an error
+has occurred This means it has just returned the cached list, the error
+should then not be handled in a fatal way. E.g. show the returned cache list
+but log the error or show the error with a warning.</p>
+<p>Example Input: <code>DiscoOrganizations(myCookie, "")</code></p>
+<p>Example Output:</p>
+<pre><code>{
+ "organization_list": [
+ {
+ "display_name": {
+ "en": "Academic Network of Albania - RASH"
+ },
+ "org_id": "https://idp.rash.al/simplesaml/saml2/idp/metadata.php",
+ },
+ {
+ "display_name": {
+ "da": "Dansk Sprognævn",
+ "en": "Danish Language Council"
+ },
+ "org_id": "http://idp.dsn.dk/adfs/services/trust",
+ },
+ {
+ "display_name": {
+ "da": "Erhvervsakademi Aarhus",
+ "en": "Business Academy Aarhus"
+ },
+ "org_id": "http://adfs.eaaa.dk/adfs/services/trust",
+}, null
+</code></pre>
+<p>Example Input: <code>DiscoOrganizations(myCookie, "rash")</code></p>
+<p>Example Output:</p>
+<pre><code> {
+ "organization_list": [
+ {
+ "display_name": {
+ "en": "Academic Network of Albania - RASH"
+ },
+ "org_id": "https://idp.rash.al/simplesaml/saml2/idp/metadata.php",
+ },
+ ]
+ }, null
+</code></pre>
+<h2 id="discoservers">DiscoServers<a class="headerlink" href="#discoservers" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func DiscoServers(c C.uintptr_t, cache C.int, search *C.char) (*C.char, *C.char)
+</code></pre>
+<p>DiscoServers gets the servers from discovery, returned as
+<code>types/discovery/discovery.go Servers</code> marshalled as JSON</p>
+<ul>
+<li><code>c</code> is the Cookie that needs to be passed. Create a new Cookie using
+ <code>CookieNew</code></li>
+<li><code>cache</code> indicates whether or not the cache should only be used, meaning
+ no network call</li>
+<li><code>search</code> is the search string for filtering the list.</li>
+</ul>
+<p>If any of the words in the search query is not contained in any of
+the display names or keywords, the candidate is filtered. Otherwise
+they are ranked based on the levenshtein distance: <a href="https://en.wikipedia.org/wiki/Levenshtein_distance">Levenshtein
+Wikipedia</a>. If <code>search</code>
+is empty it returns ALL servers currently known in common</p>
+<p>If it was unsuccessful, it returns an error. Note that when the lib was
+built in release mode the data is almost always non-nil, even when an error
+has occurred. This means it has just returned the cached list, the error
+should then not be handled in a fatal way. E.g. show the returned cache list
+but log the error or show the error with a warning.</p>
+<p>Example Input: <code>DiscoServers(myCookie, "")</code></p>
+<p>Example Output:</p>
+<pre><code> {
+ "server_list": [
+ {
+ "base_url": "https://eduvpn.rash.al/",
+ "country_code": "AL",
+ "server_type": "secure_internet",
+ },
+ {
+ "base_url": "https://eduvpn.deic.dk/",
+ "country_code": "DK",
+ "server_type": "secure_internet",
+ } , null
+</code></pre>
+<p>Example Input: <code>DiscoServers(myCookie, "heanet")</code></p>
+<p>Example Output:</p>
+<pre><code> {
+ "server_list": [
+ {
+ "base_url": "https://eduvpn.heanet.ie/",
+ "display_name": {
+ "en": "HEAnet Staff"
+ },
+ "server_type": "institute_access",
+ },
+ ]
+ } , null
+</code></pre>
+<h2 id="expirytimes">ExpiryTimes<a class="headerlink" href="#expirytimes" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func ExpiryTimes() (*C.char, *C.char)
+</code></pre>
+<p>ExpiryTimes gets the expiry times for the current server</p>
+<p>Expiry times are just fields that represent unix timestamps at which to
+do certain events regarding expiry, e.g. when to show the renew button,
+when to show expiry notifications</p>
+<p>The expiry times structure is defined in <code>types/server/server.go Expiry</code> If
+some error occurs, it is returned as <code>types/error/error.go Error</code></p>
+<p>Example Input: <code>ExpiryTimes()</code></p>
+<p>Example Output (1&hellip;4 are unix timestamps):</p>
+<pre><code>{
+ "start_time": 1,
+ "end_time": 2,
+ "button_time": 3,
+ "countdown_time": 4,
+ "notification_times": [
+ 1,
+ 2,
+ ],
+}, null
+</code></pre>
+<h2 id="freestring">FreeString<a class="headerlink" href="#freestring" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func FreeString(addr *C.char)
+</code></pre>
+<p>FreeString frees a string that was allocated by the eduvpn-common Go
+library.</p>
+<p>This happens when we return strings, such as errors from the Go lib back to
+the client. The client MUST thus ensure that this memory is freed using this
+function. Simply pass the pointer to the string in here.</p>
+<p>Example Input: <code>FreeString(strPtr)</code></p>
+<h2 id="getconfig">GetConfig<a class="headerlink" href="#getconfig" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func GetConfig(c C.uintptr_t, _type C.int, id *C.char, pTCP C.int, startup C.int) (*C.char, *C.char)
+</code></pre>
+<p>GetConfig gets a configuration for the server.</p>
+<p><code>c</code> is the cookie that is used for cancellation. Create a cookie first with
+CookieNew, this same cookie is also used for replying to state transitions</p>
+<p><code>_type</code> is the type of server that needs to be added. This type is defined
+in <code>types/server/server.go Type</code></p>
+<p><code>id</code> is the identifier of the string</p>
+<ul>
+<li>In case of secure internet: The organization ID</li>
+<li>In case of custom server: The base URL</li>
+<li>In case of institute access: The base URL</li>
+</ul>
+<p><code>pTCP</code> is if we prefer TCP or not to get the configuration, non-zero means
+yes</p>
+<p><code>startup</code> is if the client is just starting up, set this to true (non-zero)
+if you autoconnect to a server on startup. If this startup value is true
+(non-zero) then any authorization or other callacks (profile/location) are
+not triggered</p>
+<p>After getting a configuration, the FSM moves to the GOT_CONFIG state
+The return data is the configuration, marshalled as JSON and defined in
+<code>types/server/server.go Configuration</code></p>
+<p>If the config cannot be retrieved it returns an error as
+<code>types/error/error.go Error</code>.</p>
+<p>The current state callbacks MUST be handled:</p>
+<h3 id="ask_profile">ASK_PROFILE<a class="headerlink" href="#ask_profile" title="Permanent link">#</a></h3>
+<p>This asks the client for profile.</p>
+<p>This is called when the user/client has not set a profile for this server
+before, or the current profile is invalid</p>
+<p>When the user has selected a profile, reply with the choice using the
+<code>CookieReply</code> function and the profile ID e.g. CookieReply(cookie,
+&ldquo;wireguard&rdquo;). CookieReply can be done in the background as the Go library
+waits for a reply</p>
+<p>The data for this transition is defined in <code>types/server/server.go
+RequiredAskTransition</code> with embedded data <code>Profiles</code> in
+<code>types/server/server.go</code>. Note that <code>RequiredAskTransition</code> contains the
+cookie to be used for the <code>CookieReply</code>.</p>
+<p>So a client would:</p>
+<ul>
+<li>Parse the data to get the cookie and data</li>
+<li>get the cookie</li>
+<li>get the profiles from the data</li>
+<li>show it in the UI and then reply with CookieReply using the choice</li>
+</ul>
+<h3 id="ask_location">ASK_LOCATION<a class="headerlink" href="#ask_location" title="Permanent link">#</a></h3>
+<p>This asks the client for a location. Note that under normal circumstances,
+this callback is not actually called as the home organization for the
+secure internet server is set as the current if for some reason, an invalid
+location has been configured, the library will ask the client for a new one</p>
+<p>When the user has selected a location, reply with the choice using the
+<code>CookieReply</code> function and the location ID e.g. CookieReply(cookie, &ldquo;nl&rdquo;)</p>
+<p>CookieReply can be done in the background as the Go library waits for a
+reply The data for this transition is defined in <code>types/server/server.go
+RequiredAskTransition</code> with embedded data a list of strings (<code>[]string</code>)</p>
+<p>Note that <code>RequiredAskTransition</code> contains the cookie to be used for the
+<code>CookieReply</code> function,</p>
+<p>So a client would:</p>
+<ul>
+<li>Parse the data to get the cookie and data</li>
+<li>get the cookie</li>
+<li>get the list of locations from the data</li>
+<li>show it in the UI and then reply with CookieReply using the choice</li>
+</ul>
+<h3 id="oauth_started">OAUTH_STARTED<a class="headerlink" href="#oauth_started" title="Permanent link">#</a></h3>
+<ul>
+<li>OAUTH_STARTED: This indicates that the OAuth procedure has been started,
+ it returns the URL as the data. The client should open the webbrowser
+ with this URL and continue the authorization process. Note: For mobile
+ platforms this returns a Cookie and data (json: <code>{"cookie": x, "data":
+ url}</code>). This <code>url</code> should also be opened in the browser like desktop
+ platforms. But these platforms also need to reply to the library to give
+ back the full authorization code URI with <code>CookieReply(x, uri)</code>. E.g.
+ <code>CookieReply(x, "/callback?code=...&amp;state=...&amp;iss=...")</code> this is the
+ path of the request that the apps get back when the user clicks approve.
+ For this, apps need to register an app url or sorts. For the valid
+ values for app URLs, see the redirect URIs for mobile platforms here
+ https://git.sr.ht/~fkooman/vpn-user-portal/tree/v3/item/src/OAuth/VpnClientDb.php</li>
+</ul>
+<p>The client should open the webbrowser with this URL and continue the
+authorization process. This is only called if authorization needs to be
+retriggered</p>
+<p>Example Input (3=custom server): <code>GetConfig(myCookie, 3,
+"https://demo.eduvpn.nl/", 0, 0)</code></p>
+<p>Example Output (2=WireGuard):</p>
+<pre><code>{
+ "config": "[Interface]\nPrivateKey = ...\nAddress = ...\nDNS = ...\n\n[Peer]\nPublicKey = ...=\nAllowedIPs = 0.0.0.0/0,::/0\nEndpoint = ...",
+ "protocol": 2,
+ "default_gateway": true,
+ "should_failover": true, &lt;- whether or not the failover procedure should happen
+}
+</code></pre>
+<h2 id="instate">InState<a class="headerlink" href="#instate" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func InState(fsmState C.int) (C.int, *C.char)
+</code></pre>
+<p>InState checks if the FSM is in <code>fsmState</code>.</p>
+<p>Example Input: <code>InState(5)</code></p>
+<p>Example Output: <code>1, null</code></p>
+<h2 id="newproxyguard">NewProxyguard<a class="headerlink" href="#newproxyguard" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func NewProxyguard(c C.uintptr_t, lp C.int, tcpsp C.int, peer *C.char, proxySetup C.ProxySetup) (C.uintptr_t, *C.char)
+</code></pre>
+<p>NewProxyguard creates the &lsquo;proxyguard&rsquo; procedure in eduvpn-common. If the
+proxy cannot be created it returns an error.</p>
+<p>This function proxies WireGuard UDP connections over HTTP: <a href="https://codeberg.org/eduvpn/proxyguard">ProxyGuard on
+Codeberg</a>.</p>
+<p>These input variables can be gotten from the configuration that is retrieved
+using the <code>proxy</code> JSON key</p>
+<ul>
+<li><code>c</code> is the cookie. Note that if you cancel/delete the cookie,
+ ProxyGuard gets cleaned up. Common automatically cleans up ProxyGuard
+ when <code>Cleanup</code> is called, but it is good to cleanup yourself too.</li>
+<li><code>lp</code> is the <code>port</code> of the local udp ProxyGuard connection, this is what
+ is set to the WireGuard endpoint</li>
+<li><code>tcpsp</code> is the TCP source port. Pass 0 if you do not route based on
+ source port, so far only the Linux client has to pass non-zero.</li>
+<li><code>peer</code> is the <code>ip:port</code> of the remote server</li>
+<li><code>proxySetup</code> is a callback which is called when the socket is setting
+ up, this can be used for configuring routing in the client. It takes
+ two arguments: the file descriptor (integer) and a JSON list of IPs the
+ client connects to</li>
+</ul>
+<p>Example Input: <code>NewProxyguard(myCookie, 1337, 0, "5.5.5.5:51820",
+proxySetupCB)</code></p>
+<p>Example Output: <code>null</code></p>
+<h2 id="proxyguardpeerips">ProxyguardPeerIPs<a class="headerlink" href="#proxyguardpeerips" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func ProxyguardPeerIPs(proxyH C.uintptr_t) (*C.char, *C.char)
+</code></pre>
+<p>ProxyguardPeerIPs gets the Peer IPs configured by ProxyGuard Example Input:
+<code>ProxyguardPeerIPs(handle)</code></p>
+<p>Example Output: <code>["1.1.1.1"], null</code></p>
+<h2 id="proxyguardrestart">ProxyguardRestart<a class="headerlink" href="#proxyguardrestart" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func ProxyguardRestart(proxyH C.uintptr_t) *C.char
+</code></pre>
+<p>ProxyguardRestart restarts ProxyGuard, call this when a network change
+happens</p>
+<p>Example Input: <code>ProxyguardRestart(proxyHandle)</code></p>
+<p>Example Output: <code>"failed restarting ProxyGuard"</code></p>
+<h2 id="proxyguardtunnel">ProxyguardTunnel<a class="headerlink" href="#proxyguardtunnel" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func ProxyguardTunnel(c C.uintptr_t, proxyH C.uintptr_t, wglisten C.int) *C.char
+</code></pre>
+<p>ProxyguardTunnel starts the tunneling for ProxyGuard <code>c</code> is the cookie
+<code>proxyH</code> is the proxy handle <code>wglisten</code> is the port WireGuard is listening
+on</p>
+<h2 id="register">Register<a class="headerlink" href="#register" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func Register(
+ name *C.char,
+ version *C.char,
+ configDirectory *C.char,
+ cb C.StateCB,
+) *C.char
+</code></pre>
+<p>Register creates a new client and also registers the FSM to go to the
+initial state</p>
+<p><code>Name</code> is the name of the client, must be a valid client ID.</p>
+<p><code>Version</code> is the version of the client. This version field is used for the
+user agent in all HTTP requests.</p>
+<p><code>cb</code> is the state callback. It takes three arguments: The old state, the new
+state and the data for the state as JSON.</p>
+<ul>
+<li>
+<p>Note that the states are defined in client/fsm.go, e.g. <code>Main</code> (in Go:
+ <code>StateMain</code>), <code>ASK_PROFILE</code> (in Go: <code>StateAskProfile</code>)</p>
+</li>
+<li>
+<p>This callback returns non-zero if the state transition is handled.
+ This is used to check if the client handles the needed transitions</p>
+</li>
+</ul>
+<p>After registering, the FSM is initialized and the state transition <code>MAIN</code>
+should have been completed If some error occurs during registering, it is
+returned as a <code>types/error/error.go Error</code></p>
+<p>Example Input: <code>Register("org.eduvpn.app.linux", "0.0.1",
+"/tmp/eduvpn-common", myCallbackFunc, 1)</code></p>
+<p>Example Output:</p>
+<pre><code>{
+ "message": {
+ "en": "failed to register, a VPN state is already present"
+ },
+ "misc": false
+}
+</code></pre>
+<h2 id="removeserver">RemoveServer<a class="headerlink" href="#removeserver" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func RemoveServer(_type C.int, id *C.char) *C.char
+</code></pre>
+<p>RemoveServer removes a server from the eduvpn-common server list</p>
+<p><code>_type</code> is the type of server that needs to be added. This type is defined
+in <code>types/server/server.go Type</code></p>
+<p><code>id</code> is the identifier of the string:</p>
+<ul>
+<li>In case of secure internet: The organization ID</li>
+<li>In case of custom server: The base URL</li>
+<li>In case of institute access: The base URL</li>
+</ul>
+<p>If the server cannot be removed it returns the error <code>types/error/error.go
+Error</code>.</p>
+<p>Example Input (3=custom server): <code>RemoveServer(3, "bogus")</code></p>
+<p>Example Output:</p>
+<pre><code>{
+ "message": {
+ "en": "failed to remove server"
+ },
+ "misc": false
+}
+</code></pre>
+<h2 id="renewsession">RenewSession<a class="headerlink" href="#renewsession" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func RenewSession(c C.uintptr_t) *C.char
+</code></pre>
+<p>RenewSession renews the session of the VPN</p>
+<p>This essentially means that the OAuth tokens are deleted. And it also
+possibly re-runs every state callback you need when getting a config.
+So least you MUST handle the OAuth started transition</p>
+<p>It returns an error if unsuccessful. Example Input:
+<code>RenewSession(myCookie)</code></p>
+<p>Example Output:</p>
+<pre><code>{
+ "message": {
+ "en": "could not renew session"
+ },
+ "misc": false
+}
+</code></pre>
+<h2 id="serverlist">ServerList<a class="headerlink" href="#serverlist" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func ServerList() (*C.char, *C.char)
+</code></pre>
+<p>ServerList gets the list of servers that are currently added</p>
+<p>This is NOT the discovery list, but the servers that have previously been
+added with <code>AddServer</code>.</p>
+<p>It returns the server list as a JSON string defined in
+<code>types/server/server.go List</code>. If the server list cannot be retrieved it
+returns a nil string and an error.</p>
+<p>Example Input: <code>ServerList()</code></p>
+<p>Example Output (current profile here is empty as none has been chosen yet):</p>
+<pre><code>{
+ "institute_access_servers": [
+ {
+ "display_name": {
+ "en": "Demo"
+ },
+ "identifier": "https://demo.eduvpn.nl/",
+ "profiles": {
+ "current": ""
+ },
+ "support_contacts": [
+ "mailto:eduvpn@surf.nl"
+ ],
+ "delisted": false
+ }
+ ]
+}, null
+</code></pre>
+<h2 id="setprofileid">SetProfileID<a class="headerlink" href="#setprofileid" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func SetProfileID(data *C.char) *C.char
+</code></pre>
+<p>SetProfileID sets the profile ID of the current serrver.</p>
+<p>This MUST only be called if the user/client wishes to manually set a profile
+instead of the common lib asking for one using a transition.</p>
+<ul>
+<li><code>data</code> is the profile ID.</li>
+</ul>
+<p>It returns an error if unsuccessful. Example Input:
+<code>SetProfileID("splittunnel")</code></p>
+<p>Example Output:</p>
+<pre><code>{
+ "message": {
+ "en": "profile does not exist"
+ },
+ "misc": false
+}
+</code></pre>
+<h2 id="setsecurelocation">SetSecureLocation<a class="headerlink" href="#setsecurelocation" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func SetSecureLocation(orgID *C.char, cc *C.char) *C.char
+</code></pre>
+<p>SetSecureLocation sets the location for the secure internet server if it
+exists.</p>
+<p>This MUST only be called if the user/client wishes to manually set a
+location instead of the common lib asking for one using a transition.</p>
+<ul>
+<li><code>orgID</code> is the organisation ID for the secure internet server</li>
+<li><code>cc</code> is the location ID/country code</li>
+</ul>
+<p>It returns an error if unsuccessful. Example Input:
+<code>SetSecureLocation("http://idp.geant.org/", "nl")</code></p>
+<p>Example Output:</p>
+<pre><code>{
+ "message": {
+ "en": "location does not exist"
+ },
+ "misc": false
+}
+</code></pre>
+<h2 id="setstate">SetState<a class="headerlink" href="#setstate" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func SetState(fsmState C.int) *C.char
+</code></pre>
+<p>SetState sets the state of the state machine.</p>
+<p>Note: this transitions the FSM into the new state without passing any data
+to it. Example Input: <code>SetState(5)</code></p>
+<p>Example Output: <code>null</code></p>
+<h2 id="settokenhandler">SetTokenHandler<a class="headerlink" href="#settokenhandler" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func SetTokenHandler(getter C.TokenGetter, setter C.TokenSetter) *C.char
+</code></pre>
+<p>SetTokenHandler sets the token getters and token setters for OAuth.</p>
+<p>Because the data that is saved does not contain OAuth tokens for server,
+the common lib asks and sets the tokens using these callback functions.
+The client can thus pass callbacks to this function so that the tokens can
+be securely stored in a keyring.</p>
+<p>The client must pass two callback arguments to this function:</p>
+<ol>
+<li>
+<p><code>getter</code> is the void function that gets tokens from the client. It takes
+three arguments:
+ - The <code>server</code> for which to get the tokens for, marshalled as JSON and
+ defined in <code>types/server/server.go Current</code>
+ - The <code>output</code> buffer
+ - The <code>length</code> of the output buffer. This &lsquo;output buffer&rsquo; must contain the
+ tokens, marshalled as JSON that is defined in <code>types/server/server.go
+ Tokens</code></p>
+</li>
+<li>
+<p><code>setter</code> is the void function that sets tokens. It takes two arguments:</p>
+</li>
+</ol>
+<ul>
+<li>The <code>server</code> for which to get the tokens for, marshalled as JSON and
+ defined in <code>types/server/server.go Current</code></li>
+<li>The <code>tokens</code>, defined in <code>types/server/server.go Tokens</code> marshalled as
+ JSON</li>
+</ul>
+<p>It returns an error when the tokens cannot be set. Example Input:
+<code>SetTokenHandler(getterFunc, setterFunc)</code></p>
+<p>Example Output: <code>null</code></p>
+<h2 id="startfailover">StartFailover<a class="headerlink" href="#startfailover" title="Permanent link">#</a></h2>
+<p>Signature:</p>
+<pre><code class="language-go">func StartFailover(c C.uintptr_t, gateway *C.char, mtu C.int, readRxBytes C.ReadRxBytes) (C.int, *C.char)
+</code></pre>
+<p>StartFailover starts the &lsquo;failover&rsquo; procedure in eduvpn-common.</p>
+<p>Failover has one primary goal: check if the VPN can reach the gateway.
+This can be used to check whether or not the client needs to &lsquo;failover&rsquo; to
+prefer TCP (if currently using UDP). Which is useful to go from a broken
+WireGuard connection to OpenVPN over TCP.</p>
+<ul>
+<li><code>c</code> is the cookie that is passed for cancellation. To create a cookie,
+ use the <code>CookieNew</code> function</li>
+<li><code>gateway</code> is the gateway IP of the VPN. You MAY calculate this with the
+ <code>CalculateGateway</code> function</li>
+<li><code>readRxBytes</code> is a function that returns the current rx bytes of the VPN
+ interface, this should return a <code>long long int</code> in c</li>
+</ul>
+<p>It returns a boolean whether or not the common lib has determined
+that it cannot reach the gateway. Non-zero=dropped, zero=not dropped.
+It also returns an error, if it fails to indicate if it has dropped or not.
+In this case, dropped is also set to zero.</p>
+<p>Example Input: <code>StartFailover(myCookie, "10.10.10.1", 1400,
+myRxBytesReader)</code></p>
+<p>Example Output: <code>1, null</code></p>
+ </main>
+
+ <footer>
+ <p>Documentation - eduVPN for Linux</p>
+ </footer>
+</body>
+</html> \ No newline at end of file