mobile

package module
v0.0.0-...-5197356 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 25, 2022 License: Apache-2.0 Imports: 17 Imported by: 0

README

Mobile bindings

This contains a simple API which is capable of being automatically converted into mobile libraries (e.g Java). For Android:

gomobile bind -target=android

Then copy mobile-sources.jar and mobile.aar to a suitable Android project.

The main API shape is:

func SendRequest(method, hsURL, token, body string) *Response

For example, in Kotlin:

import okhttp3.Response
import okhttp3.Request
import mobile.Mobile

private fun init() {
    // First time setup for development
    val cp = Mobile.params()
    cp.insecureSkipVerify = true
    Mobile.setParams(cp)
}

// call this function in an okhttp3.Interceptor
// if <null> is returned then fallback to HTTP APIs
private fun doRequest(request: Request): Response? {
    val method = request.method
    val url = request.url.toString()
    val token = request.headers.get("Authorization")?.removePrefix("Bearer ")
    val body = this.stringifyRequestBody(request)
    // call out to the Go code
    val result = Mobile.sendRequest(method, url, token, body)
    if (result == null) {
        return null
    }
    return Response.Builder()
            .request(request)
            .code(result.getCode().toInt())
            .protocol(Protocol.HTTP_1_1)
            .message(result.getBody())
            .body(result.getBody().toByteArray().toResponseBody("application/json".toMediaTypeOrNull()))
            .addHeader("content-type", "application/json")
            .build()
}

private fun stringifyRequestBody(request: Request): String? {
    return try {
        val copy: Request = request.newBuilder().build()
        val buffer = Buffer()
        copy.body?.writeTo(buffer)
        buffer.readUtf8()
    } catch (e: IOException) {
        ""
    }
}

There are many connection parameters which can be configured, and it is important developers understand what they do. There are sensible defaults, but this is only sensible for Element clients running over the public internet. If you are running in a different network environment or with a different client, there may be better configurations. The parameters are well explained in the code, along with the trade-offs of setting them too high/low.

Documentation

Overview

Package mobile contains a gomobile friendly API for creating low bandwidth mobile clients

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SetParams

func SetParams(cp *ConnectionParams)

SetParams changes the connection parameters to those given. Closes all DTLS connections.

Types

type ConnectionParams

type ConnectionParams struct {
	// If true, skips TLS certificate checks allowing this library to be used with self-signed certificates.
	// This should be false in production!
	InsecureSkipVerify bool
	// The retry rate when sending initial DTLS handshake packets. If this value is too low (lower than the
	// RTT latency) the client will be unable to establish a DTLS session with the server because the client
	// will always send another handshake before the server can respond. If this value is too high, the
	// client will take longer than required to establish a DTLS session when under high packet
	// loss network conditions.
	FlightIntervalSecs int
	// How frequently to send CoAP heartbeat packets (Empty messages). This adds bandwidth costs when no
	// traffic is flowing but is required in order to keep NAT bindings active.
	HeartbeatTimeoutSecs int
	KeepAliveMaxRetries  int
	KeepAliveTimeoutSecs int
	// The max number of simultaneous outstanding requests to the server. Important for congestion control.
	// If this value is too high then the client may flood the network with traffic and cause network problems.
	// If this value is too low then sending many requests in a row will be queued, resulting in head-of-line
	// blocking problems.
	// The CoAP RFC recommends a value of 1. https://datatracker.ietf.org/doc/html/rfc7252#section-4.8
	// XXX FIXME: This option is broken in go-coap: https://github.com/plgd-dev/go-coap/issues/226
	TransmissionNStart int
	// How long to wait after having sent a CoAP message for an ACK from the server. It is important that
	// any CoAP server sends an ACK back before this timeout is hit. Servers which implement long poll /sync
	// MUST NOT piggyback the ACK with the sync payload (that is, wait for the sync response before ACKing)
	// or else the ?timeout= value will be the ACK timeout when there are no new events. This will cause
	// clients to retransmit sync requests needlessly.
	// The CoAP RFC recommends a value of 2. https://datatracker.ietf.org/doc/html/rfc7252#section-4.8
	// If this value is too low, clients will retransmit packets needlessly when there are latency spikes.
	// If this value is too high, clients will wait too long before retransmitting when there is packet loss.
	TransmissionACKTimeoutSecs int
	// The max number of times to retry sending a CoAP packet. If this is too high it can add unecessary
	// bandwidth costs when the server is unreachable. If this is too low then the client will not handle
	// packet loss gracefully.
	// The CoAP RFC recommends a value of 4. https://datatracker.ietf.org/doc/html/rfc7252#section-4.8
	TransmissionMaxRetransmits int
	// If set, enables /sync OBSERVE requests, meaning the server will push traffic to the client
	// rather than relying on long-polling. Client implementations need no changes for this feature
	// to work. Using OBSERVE carries risks as client syncing state is now stored server-side. If the
	// server gets restarted, it will lose its OBSERVE subscriptions, meaning clients will not be pushed
	// events. Enabling this will reduce idle bandwidth costs by 50% (~160 bytes CoAP keep-alive packets
	// vs ~320 bytes with long-polling). Therefore, enabling this is most useful when used with very
	// quiet accounts, as there are no savings when the connection is not idle.
	ObserveEnabled bool
	// The channel buffer size for pushed /sync events. The client will be pushed events even without
	// calling SendRequest when OBSERVEing. This value is the size of the buffer to hold pushed events
	// until the client calls SendRequest again. Setting this high will consume more memory but ensure
	// that a flood of traffic can be buffered. Setting this too low will eventually stop the client sending
	// ACK messages back to the server, effectively acting as backpressure.
	ObserveBufferSize int
	// Clients which use long-polling will expect a regular stream of responses when calling /sync. When using
	// OBSERVE this does not happen, as traffic is ONLY sent when there is actual data. This may cause UI elements
	// to display "not connected to the server" or equivalent. To transparently fix this, this library can send
	// back fake /sync responses (with no data and the same sync token) after a certain amount of time when waiting
	// for OBSERVE data.
	ObserveNoResponseTimeoutSecs int
}

ConnectionParams contains parameters for the entire low bandwidth stack, including DTLS, CoAP and OBSERVE.

func Params

func Params() *ConnectionParams

Params returns the current connection parameters.

type Response

type Response struct {
	// Code is the return status code
	Code int
	// Body is the HTTP response body as a string
	Body string
}

Response is a simple HTTP response

func SendRequest

func SendRequest(method, hsURL, token, body string) *Response

SendRequest sends a CoAP request to the target hsURL. All of these parameters should be treated as HTTP parameters (so https:// URL, JSON body), and the returned Response will also contain a JSON body. Returns <nil> if there was an error (e.g network error, failed conversion) in which case clients should use normal Matrix over HTTP to send this request.

This function will block until the response is returned, or the request times out.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL