Mina_net2An interface to limited libp2p functionality for Coda to use.
A subprocess is spawned to run the go-libp2p code. This module communicates with that subprocess over an ad-hoc RPC protocol.
TODO: separate internal helper errors from underlying libp2p errors.
In general, functions in this module return 'a Deferred.Or_error.t. Unless otherwise mentioned, the deferred is resolved immediately once the RPC action to the libp2p helper is finished. Unless otherwise mentioned, everything can throw an exception due to an internal helper error. These indicate a bug in this module/the helper, and not misuse.
Some errors can arise from calling certain functions before configure has been called. In general, anything that returns an Or_error can fail in this manner.
A Mina_net2.t has the following lifecycle:
Mina_net2.create. This spawns the helper process but does not connect to any network. Few operations can be done on fresh nets, only Keypair.random for now.Mina_net2.configure. Configure creates the libp2p objects and can start listening on network sockets. This doesn't join any DHT or attempt peer connections. Configured networks can do everything but any pubsub messages may have very limited reach without being in the DHT.Mina_net2.begin_advertising. This joins the DHT, announcing our existence to our peers and initiating local mDNS discovery.Mina_net2.shutdown. This flushes all the pending RPCTODO: consider encoding the network state in the types.
A note about connection limits:
In the original coda_net, connection limits were enforced synchronously on every received connection. Right now with mina_net2, connection management is asynchronous and post-hoc. In the background, once per minute it checks the connection count. If it is above the "high water mark", it will close ("trim") eligible connections until it reaches the "low water mark". All connections start with a "grace period" where they won't be closed. Peer IDs can be marked as "protected" which prevents them being trimmed. Ember believes this is vulnerable to resource exhaustion by opening many new connections.
module Multiaddr : sig ... endA "multiaddr" is libp2p's extensible encoding for network addresses.
module Keypair : sig ... endmodule Validation_callback : sig ... endmodule Sink : sig ... endmodule For_tests : sig ... endval create :
?allow_multiple_instances:bool ->
all_peers_seen_metric:bool ->
logger:Logger.t ->
pids:Child_processes.Termination.t ->
conf_dir:string ->
on_peer_connected:( Network_peer.Peer.Id.t -> unit ) ->
on_peer_disconnected:( Network_peer.Peer.Id.t -> unit ) ->
unit ->
t Async.Deferred.Or_error.tcreate ~logger ~conf_dir starts a new net storing its state in conf_dir * * The optional allow_multiple_instances defaults to `false`. A `true` value * allows spawning multiple subprocesses, which can be useful for tests. * * The new net isn't connected to any network until configure is called. * * This can fail for a variety of reasons related to spawning the subprocess.
type connection_gating = {banned_peers : Network_peer.Peer.t list; |
trusted_peers : Network_peer.Peer.t list; |
isolate : bool; |
}State for the connection gateway. It will disallow connections from IPs or peer IDs in banned_peers, except for those listed in trusted_peers. If isolate is true, only connections to trusted_peers are allowed.
val configure :
t ->
me:Keypair.t ->
external_maddr:Multiaddr.t ->
maddrs:Multiaddr.t list ->
network_id:string ->
metrics_port:int option ->
unsafe_no_trust_ip:bool ->
flooding:bool ->
direct_peers:Multiaddr.t list ->
peer_exchange:bool ->
peer_protection_ratio:float ->
seed_peers:Multiaddr.t list ->
initial_gating_config:connection_gating ->
min_connections:int ->
max_connections:int ->
validation_queue_size:int ->
known_private_ip_nets:Core.Unix.Cidr.t list ->
topic_config:string list list ->
unit Async.Deferred.Or_error.tConfigure the network connection. * * Listens on each address in maddrs. * * This will only connect to peers that share the same network_id. on_new_peer, if present, * will be called for each peer we connect to. unsafe_no_trust_ip, if true, will not attempt to * report trust actions for the IPs of observed connections. * * Whenever the connection list gets too small, seed_peers will be * candidates for reconnection for peer discovery. * * This fails if initializing libp2p fails for any reason.
The keypair the network was configured with. * * Resolved once configuration succeeds.
val peers : t -> Network_peer.Peer.t list Async.Deferred.tList of all peers we know about.
val bandwidth_info :
t ->
([ `Input of float ] * [ `Output of float ] * [ `Cpu_usage of float ])
Async.Deferred.Or_error.tval set_node_status : t -> string -> unit Async.Deferred.Or_error.tSet node status to be served to peers requesting node status.
val get_peer_node_status : t -> Multiaddr.t -> string Async.Deferred.Or_error.tGet node status from given peer.
module Pubsub : sig ... endmodule Libp2p_stream : sig ... endAn open stream.
val open_stream :
t ->
protocol:string ->
peer:Network_peer.Peer.Id.t ->
Libp2p_stream.t Async.Deferred.Or_error.tOpens a stream with a peer on a particular protocol.
Close the write pipe when you are done. This won't close the reading end. The reading end will be closed when the remote peer closes their writing end. Once both write ends are closed, the connection terminates.
This can fail if the peer isn't reachable, doesn't implement the requested protocol, and probably for other reasons.
val reset_stream : t -> Libp2p_stream.t -> unit Async.Deferred.Or_error.treset_stream t informs the other peer to close the stream.
The returned Deferred.Or_error.t is fulfilled with Ok () immediately once the reset is performed. It does not wait for the other host to acknowledge.
val open_protocol :
t ->
on_handler_error:
[ `Raise | `Ignore | `Call of Libp2p_stream.t -> exn -> unit ] ->
protocol:string ->
( Libp2p_stream.t -> unit Async.Deferred.t ) ->
unit Async.Deferred.Or_error.tHandle incoming streams for a protocol.
on_handler_error determines what happens if the handler throws an exception. If an exception is raised by on_handler_error (either explicitly via `Raise, or in the function passed via `Call), Protocol_handler.close will be called.
The function in `Call will be passed the stream that faulted.
val close_protocol :
?reset_existing_streams:bool ->
t ->
protocol:string ->
unit Async.Deferred.tStop handling new streams on this protocol.
reset_existing_streams controls whether open streams for this protocol will be reset, and defaults to false.
val listen_on : t -> Multiaddr.t -> Multiaddr.t list Async.Deferred.Or_error.tTry listening on a multiaddr. * * If successful, returns the list of all addresses this net is listening on * For example, if listening on "/ip4/127.0.0.1/tcp/0", it might return * "/ip4/127.0.0.1/tcp/35647" after the OS selects an available listening * port. * * This can be called many times.
val listening_addrs : t -> Multiaddr.t list Async.Deferred.Or_error.tThe list of addresses this net is listening on.
This returns the same thing that listen_on does, without listening on an address.
val add_peer :
t ->
Multiaddr.t ->
is_seed:bool ->
unit Async.Deferred.Or_error.tConnect to a peer, ensuring it enters our peerbook and DHT.
This can fail if the connection fails.
val begin_advertising : t -> unit Async.Deferred.Or_error.tJoin the DHT and announce our existence. Call this after using add_peer to add any bootstrap peers.
val shutdown : t -> unit Async.Deferred.tStop listening, close all connections and subscription pipes, and kill the subprocess.
val set_connection_gating_config :
t ->
connection_gating ->
connection_gating Async.Deferred.tConfigure the connection gateway.
This will fail if any of the trusted or banned peers are on IPv6.
val connection_gating_config : t -> connection_gatingval banned_ips : t -> Async.Unix.Inet_addr.t listList of currently banned IPs.
val send_heartbeat : t -> Network_peer.Peer.Id.t -> unit