Module Upsycle_router

This is the top-level entrypoint module for Upsycle_router.

The entire Commons module is re-exported through the top level.

Commons re-exports.

module Commons : sig ... end

Contains shared types and values which are used throughout the application.

Convenience types.
type result_msg = Rresult.R.msg
type 'a rresult = ('a, result_msg) Stdlib.result
type 'a to_yaml = 'a -> Yaml.value
type 'a of_yaml = Yaml.value -> 'a rresult
type 'a sencode = 'a -> Seaboar.Encode.value
type 'a sdecode = 'a Seaboar.Decode.t
Basic types.
type privkey_25519 = Mirage_crypto_ec.Ed25519.priv

These are the base types we use for private and public keys; no need to try and hide the implementation.

type pubkey_25519 = Mirage_crypto_ec.Ed25519.pub
type privkey
type pubkey
type ip
type port
type ip_port
type host_port
type command
type multicast_group_pubkey
type multicast_group_privkey
type multicast_group_rw

A multicast group for which we have both a public and private key.

type multicast_group_ro

A multicast group for which we only have a public key.

type multicast_group = [
  1. | `Rw of multicast_group_rw
  2. | `Ro of multicast_group_ro
]
Types used for configuration and choices. *
type msg_id_hash_function = [
  1. | `Blake2b_256
  2. | `Blake2b_32
  3. | `Blake2s_128
  4. | `Blake2s_32
]

Used for choosing the Blake2 hash function for calculating message IDs.

type multicast_requestor = [
  1. | `Peerkey
  2. | `Src
]

When the message router receives a JOIN request whose src field doesn't match the actual public key of the peer, it needs to decide which one to actually add to the group. By default this is set to `Src in the configurations, but `Peerkey can be useful for testing or experimenting.

type print_messages_on_console = [
  1. | `Long
  2. | `None
  3. | `Short
]

Configures whether or not to dump the contents of every message received by the message router to the console.

type multicast_subscriber

Types used for configuring the initial state of the message router.

type multicast_table = (multicast_group_pubkey, multicast_subscriber BatSet.t) BatMap.t
type remote_router = private {
  1. pubkey : pubkey;
  2. ip : ip;
  3. port : port;
  4. routername : string;
}

The functions in T are just function versions of the constructors of various types, which provides a convenient way of constructing types in many situations.

module T : sig ... end
module Pp : sig ... end
module Encode : sig ... end
module Decode : sig ... end
module Crypto : sig ... end
module Yaml : sig ... end
module Mk : sig ... end
module Acc : sig ... end
val keys_common : string -> char -> unit Lwt.t

Provides handlers for the keys 'q', '\n', and an unknown key press, to be used in the key thread.

Miscellaneous helpers.
val mk_random_ttl : [< `Medium | `Short ] -> int

Returns a random integer for use in the `ttl` field.

mk_random_ttl `Short produces an integer in the range [3, 10].

mk_random_ttl `Medium produces an integer in the range [10, 30].

val mk_random_expiry : unit -> int

Returns a random integer representing minutes elapsed since 2020-01-01 00:00 UTC, for use in the `expiry` field.

val mk_random_revision : unit -> int

Returns a random integer in the range [0, 19], for use in the `revision` field.

val ip_of_string_result : string -> ip rresult

Converts a string to our internal ip type.

val to_yaml_noop : 'a Util_yaml.to_yaml

ppx_deriving_yaml requires both an x_to_yaml and x_of_yaml function for a type x in order to be able produce derivations for types which include x. However the 'of_yaml' variant is never used in this library so there's no sense in writing it; this function can be provided instead to satisfy the requirements.

val error_msg : string -> string rresult

Convenience for generating Error (`Msg s) from a string s.

val pubkey_of_multicast_group : multicast_group -> pubkey
val string_list_of_command : command -> string list
val pp_comma_list : 'a Fmt.t -> 'a list Fmt.t

Message_router_config and Service_config are used for configuring an executable which uses this library code. See the code for upsycle-router.exe and upsycle-service.exe in the bin directory for usage.

module Message_router_config : sig ... end
module Service_config : sig ... end

Re-exported configuration types from modules other than Commons.

type message_router_route

Aliases used in this interface.

type timer_handler := expired:bool -> ([ `Multi | `Uni ] * Commons.pubkey * Message.Base.t) -> unit
type join_leave_return := [
  1. | `No_groups
  2. | `Ok of int
]
type publish_return := [
  1. | `No_groups
  2. | `Ok of int
]
type pull_seen_return := [
  1. | `No_seen
  2. | `Ok of int
]
val init_crypto : unit -> unit

Initialize the cryptography functions in Mirage_crypto_rng (calls Mirage_crypto_rng_lwt.initialize underneath). It's important to call this during initialization, before using any of those functions.

Starting / using a message router.

Note that the message router keeps track of its own mutable state as a singleton, which saves us from having to manually keep track of the state and pass it to all the functions. It also means that you can only start one message router per process.

val start_message_router : ?threads: (Message_router_config.t -> (Upsycle_router__.Message_router_stream.stream_msg option -> unit) -> unit Lwt.t) list -> Message_router_config.t -> unit Lwt.t
val serialize_message_router_state : Message_router_config.t -> unit Lwt.t
val deserialize_and_set_message_router_state : timer_handler -> int -> int -> string -> unit Lwt.t
val send_peer_advertisement_about_us : Message_router_config.t -> addr_type:[ `Tcp ] -> rev:int -> ttl_multicast:int -> ttl_pa:int -> exp_multicast:int -> exp_pa:int -> string -> pubkey -> [> `No_groups | `Ok of int ] Lwt.t
val get_connection : Commons.pubkey -> Upsycle_router__.Message_router_route.connection option
val get_groups_from_multicast_table : unit -> multicast_group_pubkey list
val unqueue_message : expired:bool -> Commons.msg_id_hash_function -> ([ `Multi | `Uni ] * pubkey * Message.Base.t) -> unit
val reset_message_queue : unit -> unit
val reset_message_cache : unit -> unit
val clear_routing_table : unit -> unit
val clear_multicast_table : unit -> unit

Common functions for message router clients.

This refers to either message routers or services who want to communicate with a remote message router.

val send_message_to_peer : ttl:int -> exp:int -> body:string -> pubkey Util_conduit.connection -> privkey -> pubkey -> pubkey -> unit Lwt.t
val send_join_to_message_router : ttl:int -> exp:int -> 'a Util_conduit.connection -> privkey -> pubkey -> pubkey -> pubkey -> unit Lwt.t
val send_message_to_topic : ttl:int -> exp:int -> seen:Message.Com.seen -> 'a Util_conduit.connection -> multicast_group_rw -> string -> unit Lwt.t
val send_message_to_topic_of_remote_router : ttl:int -> exp:int -> seen:Message.Com.seen -> pubkey:pubkey -> multicast_group_rw -> string -> unit Lwt.t

Starting / using a service.

In the case of services the caller is responsible for keeping track of the state and most functions accept a state reference which they will mutate or query.

val start_service : ?threads: (Service_config.t -> Upsycle_router__.Service.State.state Stdlib.ref -> pubkey Util_conduit.Connection.t -> unit Lwt.t) list -> Service_config.t -> unit Lwt.t
val join_groups : ?prepend:string -> ttl:int -> exp:int -> Service_config.t -> Upsycle_router__.Service.State.state Stdlib.ref -> 'a Util_conduit.Connection.t -> multicast_group list -> join_leave_return Lwt.t
val leave_all_groups : ?prepend:string -> ttl:int -> exp:int -> Service_config.t -> Upsycle_router__.Service.State.state Stdlib.ref -> 'a Util_conduit.Connection.t -> join_leave_return Lwt.t
val publish_to_subscribed_groups : ?prepend:string -> ttl:int -> exp:int -> Service_config.t -> Upsycle_router__.Service.State.state Stdlib.ref -> 'a Util_conduit.Connection.t -> publish_return Lwt.t
val pull_seen : ?prepend:string -> ttl:int -> exp:int -> Service_config.t -> Upsycle_router__.Service.State.state Stdlib.ref -> 'a Util_conduit.Connection.t -> pull_seen_return Lwt.t
val service_show_state : Service_config.t -> Upsycle_router__.Service.State.state Stdlib.ref -> string -> unit Lwt.t
val service_clear_multicast_table : Upsycle_router__.Service.State.state Stdlib.ref -> unit

Creating CBOR-encoded strings with various types of messages.

val mk_encoded_unicast_message : ttl:int -> exp:int -> ?via:pubkey -> (privkey * pubkey) -> pubkey -> string -> string
val mk_encoded_multicast_message : ttl:int -> exp:int -> seen:Message.Com.seen -> multicast_group_rw -> string -> string
val mk_unicast_message : ?test_tamper:bool -> ttl:int -> exp:int -> ?via:pubkey -> (privkey * pubkey) -> pubkey -> string -> Message.Base.t
val mk_multicast_message : ?test_tamper:bool -> ttl:int -> exp:int -> ?via:pubkey -> seen:Message.Com.seen -> multicast_group_rw -> string -> Message.Base.t
val mk_encoded_peer_advertisement_message : ?test_tamper:bool -> id:pubkey -> (Commons.ip * port * [ `Tcp ]) -> (pubkey option * pubkey option) -> grps:multicast_group_pubkey list -> rev:int -> ttl:int -> exp:int -> priv_key:privkey -> string

Creating data structures and values.

val mk_privkey_base64_exn : string -> privkey
val mk_pubkey_base64_exn : string -> pubkey
val mk_seen : int -> Message.Com.seen

Pretty printers.

val pp_message_router_state : Stdlib.Format.formatter -> Upsycle_router__.Message_router_state.state -> unit
val pp_message_router_state' : [ `Short | `Long ] -> Stdlib.Format.formatter -> 'a -> unit

Time.

val now : unit -> int
val now_f : unit -> float

Stream manipulation and parsing.

val parse_conduit_stream : 'a Util_conduit.Connection.t -> int -> (Message.Base.t -> bool Lwt.t) -> (unit -> bool Lwt.t) -> (string -> [< `Fail | `Scrub of int ] Lwt.t) -> (string -> unit Lwt.t) -> unit Lwt.t
val stream_msg : Upsycle_router__.Message_router_route.connection -> Util_conduit.info -> pubkey -> pubkey -> Message.Base.t -> Upsycle_router__.Message_router_stream.stream_msg
val test_stream_msg : Util_conduit.info -> pubkey -> pubkey -> Message.Base.t -> Upsycle_router__.Message_router_stream.stream_msg

Helper functions for dealing with certificates and keys.

val pubkey_of_certfile_exn : ?quiet:bool -> command -> string -> pubkey
val pubkey_of_keyfile_exn : ?quiet:bool -> command -> string -> pubkey
val privkey_of_keyfile_exn : ?quiet:bool -> command -> string -> privkey
val generate_key_pair : ?g:Mirage_crypto_rng.g -> unit -> privkey * pubkey

We flatten this module so that [@@deriving yaml] works transparently from the outside.

include module type of Commons.Yaml
type string_or_string_list
val host_port_to_yaml : Commons.host_port Commons.to_yaml
val host_port_of_yaml : Commons.host_port Commons.of_yaml
val ip_of_yaml : Commons.ip Commons.of_yaml
val ip_to_yaml : Commons.ip Commons.to_yaml
val port_of_yaml : Commons.port Commons.of_yaml
val port_to_yaml : Commons.port Commons.to_yaml
val ip_port_of_yaml : Commons.ip_port Commons.of_yaml
val ip_port_to_yaml : Commons.ip_port Commons.to_yaml
val print_messages_on_console_of_yaml : [ `Long | `None | `Short ] Commons.of_yaml
val print_messages_on_console_to_yaml : 'a Commons.to_yaml
val pubkey_of_file_of_yaml : Commons.pubkey Commons.of_yaml
val multicast_requestor_of_yaml : Commons.multicast_requestor Commons.of_yaml
val multicast_requestor_to_yaml : Commons.multicast_requestor Commons.to_yaml
val msg_id_hash_function_of_yaml : Commons.msg_id_hash_function Commons.of_yaml
val msg_id_hash_function_to_yaml : Commons.msg_id_hash_function Commons.to_yaml
val multicast_group_to_yaml : 'a -> [> `String of string ]
val multicast_group_of_yaml : Commons.multicast_group Commons.of_yaml
val string_of_file_of_yaml : string Commons.of_yaml
val command_of_yaml : Commons.command Commons.of_yaml
val command_to_yaml : Commons.command Commons.to_yaml
val string_or_string_list_of_yaml : string_or_string_list Commons.of_yaml
val string_or_string_list_to_yaml : string_or_string_list Commons.to_yaml

Message API.

We export the Message module here, which may be useful for constructing and understanding the various kinds of messages. It's generally not necessary to use this module directly.

module Message : sig ... end

“Basic” (implicit imports) and utilities.

We export Basic and all the utils here for convenience and for better documentation, though they are also available directly as libraries. Basic is imported using open by nearly every module.

module Basic : sig ... end
module Util_cache : sig ... end
module Util_conduit : sig ... end
module Util_crypto_io : sig ... end
module Util_crypto : sig ... end
module Util_encode_decode_io : sig ... end
module Util_encode_decode : sig ... end
module Util_io : sig ... end
module Util_lwt : sig ... end
module Util_lwt_seaboar : sig ... end
module Util_pure : sig ... end
module Util_yaml_io : sig ... end
module Util_yaml : sig ... end