From 8b875cb03ac00a08a99c152c6149ed12c096e00a Mon Sep 17 00:00:00 2001 From: mario4tier Date: Sun, 25 Feb 2024 23:19:44 -0500 Subject: [PATCH] (#12) Add dtp::api layer --- crates/dtp-core/src/network/host_internal.rs | 8 +- .../src/network/transport_control_internal.rs | 10 +- crates/dtp-core/src/types/stats.rs | 16 +- move/Move.lock | 2 +- move/sources/api.move | 54 +++++++ move/sources/api_impl.move | 61 ++++++++ move/sources/conn_objects.move | 71 +++++++++ move/sources/events.move | 20 +-- move/sources/host.move | 73 ++++++--- move/sources/kvalues.move | 92 +++++++++++ move/sources/pipe.move | 55 ++++--- move/sources/stats.move | 124 +++++++++++---- move/sources/transport_control.move | 147 ++++++++---------- 13 files changed, 537 insertions(+), 196 deletions(-) create mode 100644 move/sources/api.move create mode 100644 move/sources/api_impl.move create mode 100644 move/sources/conn_objects.move create mode 100644 move/sources/kvalues.move diff --git a/crates/dtp-core/src/network/host_internal.rs b/crates/dtp-core/src/network/host_internal.rs index 5d277e6..95db835 100644 --- a/crates/dtp-core/src/network/host_internal.rs +++ b/crates/dtp-core/src/network/host_internal.rs @@ -26,10 +26,10 @@ pub struct HostMoveRaw { id: UID, flgs: u8, adm: SuiAddress, - con_req: u64, - con_sdd: u64, - con_del: u64, - con_rcy: u64, + conn_req: u64, + conn_sdd: u64, + conn_del: u64, + conn_rcy: u64, max_con: u16, } diff --git a/crates/dtp-core/src/network/transport_control_internal.rs b/crates/dtp-core/src/network/transport_control_internal.rs index f036d67..fdd852d 100644 --- a/crates/dtp-core/src/network/transport_control_internal.rs +++ b/crates/dtp-core/src/network/transport_control_internal.rs @@ -29,7 +29,7 @@ pub(crate) async fn create_best_effort_transport_control_on_network( rpc: &SuiSDKParamsRPC, txn: &SuiSDKParamsTxn, localhost: &LocalhostInternal, - server_host: &HostInternal, + srv_host: &HostInternal, _server_protocol: u16, _server_port: Option, _return_port: Option, @@ -39,14 +39,14 @@ pub(crate) async fn create_best_effort_transport_control_on_network( None => bail!(DTPError::DTPMissingSuiClient), }; - let server_adm = match server_host.admin_address() { + let server_adm = match srv_host.admin_address() { Some(x) => x, None => bail!(DTPError::DTPMissingServerAdminAddress), }; /* Params must match. See tranport_control.move - client_host: ID, - server_host: ID, + cli_host: ID, + srv_host: ID, server_adm: address, protocol: u16, port: u16, @@ -55,7 +55,7 @@ pub(crate) async fn create_best_effort_transport_control_on_network( let call_args = vec![ SuiJsonValue::from_object_id(localhost.object_id()), - SuiJsonValue::from_object_id(server_host.object_id()), + SuiJsonValue::from_object_id(srv_host.object_id()), SuiJsonValue::from_str(&server_adm.to_string()).unwrap(), SuiJsonValue::from_str("0").unwrap(), SuiJsonValue::from_str("0").unwrap(), diff --git a/crates/dtp-core/src/types/stats.rs b/crates/dtp-core/src/types/stats.rs index cda0121..76f47a8 100644 --- a/crates/dtp-core/src/types/stats.rs +++ b/crates/dtp-core/src/types/stats.rs @@ -3,12 +3,12 @@ pub struct PingStats { pub ping_count_attempted: u8, pub success_request: u8, pub success_reply: u8, - pub connection_creation_time: u64, // milliseconds (can be zero) - pub min_round_trip_time: u64, // milliseconds - pub max_round_trip_time: u64, // milliseconds - pub avg_round_trip_time: u64, // milliseconds - pub min_gas_cost: u32, // Mist - pub avg_gas_cost: u32, // Mist - pub max_gas_cost: u32, // Mist - pub total_gas_cost: u32, // Mist + pub conn_creation_time: u64, // milliseconds (can be zero) + pub min_round_trip_time: u64, // milliseconds + pub max_round_trip_time: u64, // milliseconds + pub avg_round_trip_time: u64, // milliseconds + pub min_gas_cost: u32, // Mist + pub avg_gas_cost: u32, // Mist + pub max_gas_cost: u32, // Mist + pub total_gas_cost: u32, // Mist } diff --git a/move/Move.lock b/move/Move.lock index 8151262..8ec6e72 100644 --- a/move/Move.lock +++ b/move/Move.lock @@ -23,6 +23,6 @@ dependencies = [ ] [move.toolchain-version] -compiler-version = "1.18.0" +compiler-version = "1.18.1" edition = "legacy" flavor = "sui" diff --git a/move/sources/api.move b/move/sources/api.move new file mode 100644 index 0000000..b1af451 --- /dev/null +++ b/move/sources/api.move @@ -0,0 +1,54 @@ +module dtp::api { + + // === Imports === + use sui::tx_context::{TxContext}; + + use dtp::kvalues::{Self}; + use dtp::host::{Host}; + use dtp::conn_objects::{ConnObjects}; + + // === Friends === + + // === Errors === + + // === Constants === + + // === Structs === + + // === Public-Mutative Functions === + + // === Public-View Functions === + + // === Admin Functions === + + // === Public-Friend Functions === + + // Functions to add services to an Host. + public entry fun add_service_ping(host: &mut Host, args: vector, ctx: &mut TxContext) : vector + { + let kvargs = kvalues::from_bytes(&args); + let ret_value = dtp::api_impl::add_service_ping(host, &kvargs, ctx); + kvalues::to_bytes(&ret_value) + } + + // JSON-RPC 2.0 service + public entry fun add_service_json_rpc(host: &mut Host, args: vector, ctx: &mut TxContext) : vector + { + let kvargs = kvalues::from_bytes(&args); + let ret_value = dtp::api_impl::add_service_json_rpc(host, &kvargs, ctx); + kvalues::to_bytes(&ret_value) + } + + // Returns IDs of objects needed to start exchanging data (TransportControl, Pipes, InnerPipes...). + public entry fun open_connection(service_idx: u8, cli_host: &mut Host, srv_host: &mut Host, args: vector, ctx: &mut TxContext): (ConnObjects, vector) + { + let kvargs = kvalues::from_bytes(&args); + let (conn_objects, ret_value) = dtp::api_impl::open_connection(service_idx, cli_host, srv_host, &kvargs, ctx); + (conn_objects, kvalues::to_bytes(&ret_value)) + } + + // === Private Functions === + + // === Test Functions === + +} \ No newline at end of file diff --git a/move/sources/api_impl.move b/move/sources/api_impl.move new file mode 100644 index 0000000..4ecfc99 --- /dev/null +++ b/move/sources/api_impl.move @@ -0,0 +1,61 @@ +module dtp::api_impl { + + // === Imports === + use sui::tx_context::{TxContext}; + + use dtp::host::{Host}; + use dtp::transport_control::{Self}; + use dtp::conn_objects::{Self,ConnObjects}; + use dtp::kvalues::{Self,KValues}; + + // === Friends === + friend dtp::api; + + // === Errors === + + // === Constants === + + // === Structs === + + // === Public-Mutative Functions === + + // === Public-View Functions === + + // === Admin Functions === + + // === Public-Friend Functions === + + + // Functions to add services to an Host. + public(friend) fun add_service_ping(_host: &mut Host, _kvargs: &KValues, _ctx: &mut TxContext) : KValues + { + kvalues::new() + } + + // JSON-RPC 2.0 service + public(friend) fun add_service_json_rpc(_host: &mut Host, _kvargs: &KValues, _ctx: &mut TxContext) : KValues + { + kvalues::new() + } + + + // Returns IDs of objects needed to start exchanging data (TransportControl, Pipes, InnerPipes...). + public(friend) fun open_connection(service_idx: u8, cli_host: &mut Host, srv_host: &mut Host, _kvargs: &KValues, ctx: &mut TxContext): (ConnObjects, KValues) + { + let conn = conn_objects::new(); + + // Create the connection. Will emit an event on success + transport_control::create_best_effort(service_idx, cli_host, srv_host, &mut conn, ctx); + + // TODO Add references in Host object for slow discovery. + //host::add_connection(cli_host, &conn.transport_control); + //host::add_connection(srv_host, &conn.transport_control); + + (conn, kvalues::new()) + } + + // === Private Functions === + + // === Test Functions === + +} \ No newline at end of file diff --git a/move/sources/conn_objects.move b/move/sources/conn_objects.move new file mode 100644 index 0000000..2081467 --- /dev/null +++ b/move/sources/conn_objects.move @@ -0,0 +1,71 @@ +module dtp::conn_objects { + // === Imports === + use std::vector; + + // === Friends === + friend dtp::api_impl; + friend dtp::host; + friend dtp::transport_control; + friend dtp::pipe; + friend dtp::inner_pipe; + + // === Errors === + + // === Constants === + + // === Structs === + struct ConnObjects has drop, copy, store { + // References to all objects needed to exchange data + // through a connection. + // + // If an end-point loose these references, they can be + // re-discovered using one of the related Host object. + tc: address, // TransportControl + cli_tx_pipe: address, + srv_tx_pipe: address, + cli_tx_ipipes: vector
, + srv_tx_ipipes: vector
, + } + + // === Public-Mutative Functions === + + // === Public-View Functions === + + // === Admin Functions === + + // === Public-Friend Functions === + public(friend) fun new(): ConnObjects { + ConnObjects{ + tc: @0x0, + cli_tx_pipe: @0x0, + srv_tx_pipe: @0x0, + cli_tx_ipipes: vector::empty(), + srv_tx_ipipes: vector::empty(), + } + } + + public(friend) fun set_tc(self: &mut ConnObjects, tc: address) { + self.tc = tc; + } + + public(friend) fun set_cli_tx_pipe(self: &mut ConnObjects, cli_tx_pipe: address) { + self.cli_tx_pipe = cli_tx_pipe; + } + + public(friend) fun set_srv_tx_pipe(self: &mut ConnObjects, srv_tx_pipe: address) { + self.srv_tx_pipe = srv_tx_pipe; + } + + public(friend) fun add_cli_tx_ipipe(self: &mut ConnObjects, cli_tx_ipipe: address) { + vector::push_back(&mut self.cli_tx_ipipes, cli_tx_ipipe); + } + + public(friend) fun add_srv_tx_ipipe(self: &mut ConnObjects, srv_tx_ipipe: address) { + vector::push_back(&mut self.srv_tx_ipipes, srv_tx_ipipe); + } + + // === Private Functions === + + // === Test Functions === + +} \ No newline at end of file diff --git a/move/sources/events.move b/move/sources/events.move index c7694c5..862938f 100644 --- a/move/sources/events.move +++ b/move/sources/events.move @@ -3,6 +3,8 @@ module dtp::events { // === Imports === use sui::event; + use dtp::conn_objects::ConnObjects; + // === Friends === friend dtp::host; friend dtp::inner_pipe; @@ -15,19 +17,7 @@ module dtp::events { // === Structs === struct ConReq has copy, drop { service_idx: u8, // Service Type - cli_haddr: address, // Client Host address (requester of the connection). - srv_haddr: address, // Server Host address - tc_addr: address, // Transport Control - - // Address of the first inner pipe addresses to use. - // - // This is for faster initial response time - // for some services (e.g. first ping). - // - // The server should find out about additional - // inner pipes with a tc_addr object read. - client_tx_ipipe: address, - server_tx_ipipe: address, + conn: ConnObjects, // All Connection Objects (TransportControl, Pipe etc...) } @@ -38,8 +28,8 @@ module dtp::events { // === Admin Functions === // === Public-Friend Functions === - public(friend) fun emit_con_req( service_idx: u8, cli_haddr: address, srv_haddr: address, tc_addr: address, client_tx_ipipe: address, server_tx_ipipe: address ) { - event::emit(ConReq { service_idx, cli_haddr, srv_haddr, tc_addr, client_tx_ipipe, server_tx_ipipe}); + public(friend) fun emit_conn_req( service_idx: u8, conn: ConnObjects ) { + event::emit(ConReq { service_idx, conn }); } // === Private Functions === diff --git a/move/sources/host.move b/move/sources/host.move index 3898c45..1034722 100644 --- a/move/sources/host.move +++ b/move/sources/host.move @@ -11,19 +11,27 @@ module dtp::host { // === Imports === use sui::object::{Self, UID, ID, uid_to_address}; + use sui::table::{Self,Table}; use sui::transfer::{Self}; use sui::tx_context::{Self,TxContext}; - use sui::linked_table::{LinkedTable}; + use sui::linked_table::{Self,LinkedTable}; - //use dtp::service_type::{ServiceType}; - use dtp::stats::{ConnectionAcceptedStats, ConnectionRejectedStats, ConnectionClosedStats}; + // To avoid circular reference, this Host module *must* not use: + // dtp::transport_control + // dtp::pipe + // dtp::inner_pipe + + use dtp::stats::{Self,ConnAcceptedStats, ConnRejectedStats, ConnClosedStats}; use dtp::weak_ref::{Self,WeakRef}; use dtp::consts::{Self}; + use dtp::kvalues::{KValues}; + //use dtp::errors::{Self}; + // === Friends === - friend dtp::transport_control; + friend dtp::transport_control; #[test_only] friend dtp::test_host; @@ -38,29 +46,29 @@ module dtp::host { // === Structs === // Public Shared Object - struct Connection has store { - tctrl_id: WeakRef, + struct Connection has copy, drop, store { + tx: WeakRef, // Reference on the TransportControl (for slow discovery). } struct Service has store { service_idx: u8, - // Each connection requested increments one member of either con_accepted or con_rejected. - con_accepted: ConnectionAcceptedStats, - con_rejected: ConnectionRejectedStats, + // Each connection requested increments one member of either conn_accepted or conn_rejected. + conn_accepted: ConnAcceptedStats, + conn_rejected: ConnRejectedStats, - // Every con_accepted are either represented in cons container or - // an increment of one member of con_closed. - con_closed: ConnectionClosedStats, + // Every conn_accepted are either represented in 'conns' + // container or an increment of one member of conn_closed. + conn_closed: ConnClosedStats, // Active connections - cons: LinkedTable, + conns: LinkedTable, // Recently closed connections (for debug purpose). - cons_recent_closed: LinkedTable, + conns_recent_closed: LinkedTable, } - struct HostConfig has store { + struct HostConfig has copy, drop, store { // Configurations that can be changed only by the AdminCap. // Maximum number of connection allowed for the whole host. @@ -107,8 +115,13 @@ module dtp::host { // Service Level Agreements // TODO + + // Services provided by this Host. + // key is a service idx [1..253] ( See service_type.move ) + services: Table, } + // === Public-Mutative Functions === // === Public-View Functions === @@ -117,26 +130,44 @@ module dtp::host { // === Public-Friend Functions === - public(friend) fun new(creator: address, ctx: &mut TxContext) : Host { + public(friend) fun new(ctx: &mut TxContext) : Host { Host { id: object::new(ctx), flgs: 0, - creator, + creator: tx_context::sender(ctx), config: HostConfig { max_con: consts::MAX_CONNECTION_PER_HOST(), }, + services: table::new(ctx), } } #[allow(lint(share_owned))] - public(friend) fun new_transfered( creator: address, ctx: &mut TxContext ): WeakRef + public(friend) fun new_transfered( ctx: &mut TxContext ): WeakRef { - let new_obj = new(creator,ctx); + let new_obj = dtp::host::new(ctx); let new_obj_ref = weak_ref::new_from_address(uid_to_address(&new_obj.id)); transfer::share_object(new_obj); new_obj_ref } + public(friend) fun upsert_service(self: &mut Host, service_idx: u8, _args: &KValues, ctx: &mut TxContext ) + { + if (!table::contains(&self.services, service_idx )) { + //assert!(table::contains(&self.services, service_idx) == false, 1); + table::add(&mut self.services, service_idx, Service{ + service_idx: service_idx, + conn_accepted: stats::new_conn_accepted_stats(), + conn_rejected: stats::new_conn_rejected_stats(), + conn_closed: stats::new_conn_closed_stats(), + conns: linked_table::new(ctx), + conns_recent_closed: linked_table::new(ctx), + }); + } + + // TODO Update/replace when already in table. + } + public(friend) fun creator(host: &Host): address { host.creator } @@ -154,7 +185,7 @@ module dtp::host { #[test_only, allow(unused_field, unused_use)] module dtp::test_host { - use sui::transfer; + //use sui::transfer; use sui::test_scenario::{Self}; use dtp::host::{Self}; // DUT @@ -169,7 +200,7 @@ module dtp::test_host { { let ctx = test_scenario::ctx(scenario); - let _new_host_ref = host::new_transfered( creator, ctx ); + let _new_host_ref = host::new_transfered( ctx ); // admnistrator address must be the creator. //assert!(host::creator(&new_host) == creator, 1); diff --git a/move/sources/kvalues.move b/move/sources/kvalues.move new file mode 100644 index 0000000..6f29591 --- /dev/null +++ b/move/sources/kvalues.move @@ -0,0 +1,92 @@ +module dtp::kvalues { + // === Imports === + use std::string::{String}; + use std::option::{Self, Option}; + use std::vector; + + // use dtp::errors::{Self}; + + // === Friends === + friend dtp::api; + + // === Errors === + + // === Constants === + + // === Structs === + + // TODO Consider BCS + typescript and rust codec (helpers). + // TODO Consider TLV bytes encoding --> {type: u8, length: u8, vector} + struct KValues has copy, store, drop { + keys_bool: vector, + + keys_u64: vector, + values_u64: vector, + + keys_str: vector, + values_str: vector, + } + + // === Public-Mutative Functions === + + // === Public-View Functions === + + // === Admin Functions === + + // === Public-Friend Functions === + public fun new(): KValues { + KValues { + keys_bool: vector::empty(), + + keys_u64: vector::empty(), + values_u64: vector::empty(), + + keys_str: vector::empty(), + values_str: vector::empty(), + } + } + + public fun from_bytes(_bytes: &vector ): KValues { + // TODO Not implemented + dtp::kvalues::new() + } + + public fun to_bytes(_self: &KValues): vector { + // TODO Not implemented + vector::empty() + } + + public fun get_bool( self: &KValues, key: &String ): bool { + let i: u64 = 0; + let ret_value = false; + let length = vector::length( &self.keys_bool ); + while (i < length) { + if (vector::borrow(&self.keys_bool, i) == key) { + ret_value = true; + break + }; + i = i + 1; + }; + ret_value + } + + public fun get_u64( self: &KValues, key: &String ): Option { + let i: u64 = 0; + let ret_value = option::none(); + let length = vector::length( &self.keys_u64 ); + while (i < length) { + if (vector::borrow(&self.keys_u64, i) == key) { + let value = vector::borrow(&self.values_u64, i); + ret_value = option::some(*value); + break + }; + i = i + 1; + }; + ret_value + } + + // === Private Functions === + + // === Test Functions === + +} \ No newline at end of file diff --git a/move/sources/pipe.move b/move/sources/pipe.move index a627cf9..3a944d6 100644 --- a/move/sources/pipe.move +++ b/move/sources/pipe.move @@ -17,6 +17,8 @@ module dtp::pipe { use dtp::pipe_sync_data::{Self,PipeSyncData}; use dtp::inner_pipe::{Self}; + use dtp::conn_objects::{Self,ConnObjects}; + // === Friends === friend dtp::host; friend dtp::transport_control; @@ -36,8 +38,8 @@ module dtp::pipe { sync_data: PipeSyncData, // Merged of all InnerPipe sync_data. - tctl_id: WeakRef, - inner_pipes: vector, + tc: WeakRef, // TransportControl + ipipes: vector, // InnerPipe(s) } // === Public-Mutative Functions === @@ -48,44 +50,53 @@ module dtp::pipe { // === Public-Friend Functions === - public(friend) fun new_transfered( tctl_id: &ID, inner_pipe_count: u8, recipient: address, ctx: &mut TxContext ): (WeakRef,WeakRef) { - assert!(inner_pipe_count > 0, errors::EInvalidPipeCount()); + public(friend) fun new_transfered( tc: &ID, ipipe_count: u8, recipient: address, is_cli_tx_pipe: bool, conn: &mut ConnObjects, ctx: &mut TxContext ): WeakRef { + assert!(ipipe_count > 0, errors::EInvalidPipeCount()); let new_pipe = Pipe { id: object::new(ctx), flgs: 0, sync_data: pipe_sync_data::new(), - tctl_id: weak_ref::new(tctl_id), - inner_pipes: vector::empty(), + tc: weak_ref::new(tc), + ipipes: vector::empty(), }; - let pipe_address = uid_to_address(&new_pipe.id); - - // First InnerPipe created is "special" because the caller gets a WeakRef on it. - let ipipe_ref = inner_pipe::new_transfered(&pipe_address, recipient, ctx); - let ipipe_addr = weak_ref::get_address(&ipipe_ref); - vector::push_back(&mut new_pipe.inner_pipes, ipipe_ref); - // Create additional InnerPipes. - inner_pipe_count = inner_pipe_count - 1; + let pipe_addr = uid_to_address(&new_pipe.id); + if (is_cli_tx_pipe) { + conn_objects::set_cli_tx_pipe(conn, pipe_addr); + } else { + conn_objects::set_srv_tx_pipe(conn, pipe_addr); + }; + + // Create InnerPipes. let i: u8 = 0; - while (i < inner_pipe_count) { - let ipipe_ref = inner_pipe::new_transfered(&pipe_address, recipient, ctx); - vector::push_back(&mut new_pipe.inner_pipes, ipipe_ref); + while (i < ipipe_count) { + let ipipe_ref = inner_pipe::new_transfered(&pipe_addr, recipient, ctx); + let ipipe_addr = weak_ref::get_address(&ipipe_ref); + + // Save WeakRef in the Pipe object (for slow discovery), and the addresses in + // the ConnObjects (to be return/emitted to the end-points). + vector::push_back(&mut new_pipe.ipipes, ipipe_ref); + if (is_cli_tx_pipe) { + conn_objects::add_cli_tx_ipipe(conn, ipipe_addr); + } else { + conn_objects::add_srv_tx_ipipe(conn, ipipe_addr); + }; }; transfer::transfer(new_pipe, recipient); - (weak_ref::new_from_address(pipe_address), weak_ref::new_from_address(ipipe_addr)) + weak_ref::new_from_address(pipe_addr) } /* TODO - public(friend) fun delete( self: Pipe, inner_pipes: vector ) { - let Pipe { id, flgs: _, sync_data: _, tctl_id: _, inner_pipes } = self; + public(friend) fun delete( self: Pipe, ipipes: vector ) { + let Pipe { id, flgs: _, sync_data: _, tc: _, ipipes } = self; // Delete all the inner pipes. // For tracking/debugging purpose, the weak ref is not removed from vector (only cleared). let i: u64 = 0; - while (i < vector::length(&inner_pipes)) { - let inner_pipe_ref = vector::borrow_mut(&mut inner_pipes, i); + while (i < vector::length(&ipipes)) { + let inner_pipe_ref = vector::borrow_mut(&mut ipipes, i); let inner_pipe_id = weak_ref::id(inner_pipe_ref); weak_ref::clear(inner_pipe_ref); object::delete(inner_pipe_id); diff --git a/move/sources/stats.move b/move/sources/stats.move index bed3979..52f3bff 100644 --- a/move/sources/stats.move +++ b/move/sources/stats.move @@ -1,47 +1,103 @@ module dtp::stats { - struct ConnectionAcceptedStats has store { - con_accepted: u64, // Normally accepted connection. - con_accepted_lru: u64, // Accepted after LRU eviction of another connection. + // === Imports === + + // === Friends === + friend dtp::host; + + // === Errors === + + // === Constants === + + // === Structs === + + struct ConnAcceptedStats has copy, drop, store { + conn_accepted: u64, // Normally accepted connection. + conn_accepted_lru: u64, // Accepted after LRU eviction of another connection. + } + + struct ConnClosedStats has copy, drop, store { + conn_closed_srv: u64, // Successful close initiated by server. + conn_closed_cli: u64, // Successful close initiated by client. + conn_closed_exp: u64, // Normal expiration initiated by protocol (e.g. Ping Connection iddle). + conn_closed_lru: u64, // Close initiated by least-recently-used (LRU) algo when cons limit reach. + conn_closed_srv_sync_err: u64, // Server caused a sync protocol error. + conn_closed_clt_sync_err: u64, // Client caused a sync protocol error. + } + + struct ConnRejectedStats has copy, drop, store { + conn_rej_host_max_con: u64, // Max Host connection limit reached. + conn_rej_srv_max_con: u64, // Max Service connection limit reached. + conn_rej_firewall: u64, // Firewall rejected. TODO more granular reasons. + conn_rej_srv_down: u64, // Connection requested while server is down. + conn_rej_cli_err: u64, // Error in client request. + conn_rej_cli_no_fund: u64, // Client not respecting funding SLA. + } + + // === Public-Mutative Functions === + + // === Public-View Functions === + + // === Admin Functions === + + // === Public-Friend Functions === + + + // Constructors + public(friend) fun new_conn_accepted_stats(): ConnAcceptedStats { + ConnAcceptedStats { + conn_accepted: 0, + conn_accepted_lru: 0, + } } - public(friend) fun connection_accepted_stats_sum(stats: &ConnectionAcceptedStats) : u64 { - stats.con_accepted + - stats.con_accepted_lru + public(friend) fun new_conn_closed_stats(): ConnClosedStats { + ConnClosedStats { + conn_closed_srv: 0, + conn_closed_cli: 0, + conn_closed_exp: 0, + conn_closed_lru: 0, + conn_closed_srv_sync_err: 0, + conn_closed_clt_sync_err: 0, + } } - struct ConnectionClosedStats has store { - con_closed_srv: u64, // Successful close initiated by server. - con_closed_cli: u64, // Successful close initiated by client. - con_closed_exp: u64, // Normal expiration initiated by protocol (e.g. Ping Connection iddle). - con_closed_lru: u64, // Close initiated by least-recently-used (LRU) algo when cons limit reach. - con_closed_srv_sync_err: u64, // Server caused a sync protocol error. - con_closed_clt_sync_err: u64, // Client caused a sync protocol error. + public(friend) fun new_conn_rejected_stats(): ConnRejectedStats { + ConnRejectedStats { + conn_rej_host_max_con: 0, + conn_rej_srv_max_con: 0, + conn_rej_firewall: 0, + conn_rej_srv_down: 0, + conn_rej_cli_err: 0, + conn_rej_cli_no_fund: 0, + } } - public(friend) fun connection_closed_stats_sum(stats: &ConnectionClosedStats) : u64 { - stats.con_closed_srv + - stats.con_closed_cli + - stats.con_closed_exp + - stats.con_closed_lru + - stats.con_closed_srv_sync_err + - stats.con_closed_clt_sync_err + public(friend) fun conn_accepted_stats_sum(stats: &ConnAcceptedStats) : u64 { + stats.conn_accepted + + stats.conn_accepted_lru } - struct ConnectionRejectedStats has store { - con_rej_host_max_con: u64, // Max Host connection limit reached. - con_rej_srv_max_con: u64, // Max Service connection limit reached. - con_rej_firewall: u64, // Firewall rejected. TODO more granular reasons. - con_rej_srv_down: u64, // Connection requested while server is down. - con_rej_cli_err: u64, // Error in client request. - con_rej_cli_no_fund: u64, // Client not respecting funding SLA. + public(friend) fun conn_closed_stats_sum(stats: &ConnClosedStats) : u64 { + stats.conn_closed_srv + + stats.conn_closed_cli + + stats.conn_closed_exp + + stats.conn_closed_lru + + stats.conn_closed_srv_sync_err + + stats.conn_closed_clt_sync_err } - public(friend) fun connection_rejected_stats_sum(stats: &ConnectionRejectedStats) : u64 { - stats.con_rej_host_max_con + - stats.con_rej_srv_max_con + - stats.con_rej_firewall + - stats.con_rej_srv_down + - stats.con_rej_cli_err + - stats.con_rej_cli_no_fund + public(friend) fun conn_rejected_stats_sum(stats: &ConnRejectedStats) : u64 { + stats.conn_rej_host_max_con + + stats.conn_rej_srv_max_con + + stats.conn_rej_firewall + + stats.conn_rej_srv_down + + stats.conn_rej_cli_err + + stats.conn_rej_cli_no_fund } + + + // === Private Functions === + + // === Test Functions === + } \ No newline at end of file diff --git a/move/sources/transport_control.move b/move/sources/transport_control.move index e703c1a..c187792 100644 --- a/move/sources/transport_control.move +++ b/move/sources/transport_control.move @@ -21,10 +21,10 @@ module dtp::transport_control { // ================ Tests ===================== // Unit Tests - use std::option::{Self, Option}; + use std::option::{Option}; - use sui::object::{Self, ID, UID}; - use sui::tx_context::{Self,TxContext}; + use sui::object::{Self, UID}; + use sui::tx_context::{TxContext}; use sui::transfer; @@ -32,6 +32,7 @@ module dtp::transport_control { use dtp::errors::{Self}; use dtp::weak_ref::{Self,WeakRef}; use dtp::host::{Self,Host}; + use dtp::conn_objects::{Self,ConnObjects}; #[test_only] friend dtp::test_transport_control; @@ -53,12 +54,12 @@ module dtp::transport_control { service_idx: u8, // UDP, Ping, HTTPS etc... // Hosts involved in the connection. - client_host: WeakRef, - server_host: WeakRef, + cli_host: WeakRef, + srv_host: WeakRef, - // Authorization verified by sender ID address. - client_addr: address, - server_addr: address, + // Some call authorization verified with sender ID address. + cli_addr: address, + srv_addr: address, // Connection Type. // @@ -69,27 +70,17 @@ module dtp::transport_control { // Intended for slow discovery. // // It is expected that DTP off-chain will cache these IDs. - client_tx_pipe: WeakRef, - server_tx_pipe: WeakRef, - - // Inner Pipe to be used for first request/response. - // - // This is an optimization for faster first interactions - // after connection creation. - // - // The endpoints can get all the inner pipe addresses with - // read of the client_tx_pipe and server_tx_pipe objects. - client_tx_ipipe: WeakRef, - server_tx_ipipe: WeakRef, - + cli_tx_pipe: WeakRef, + srv_tx_pipe: WeakRef, } // Constructors public(friend) fun new( service_idx: u8, - client_host: &mut Host, - server_host: &Host, + cli_host: &Host, + srv_host: &Host, + conn: &mut ConnObjects, ctx: &mut TxContext): TransportControl { // Check service_idx is in-range. @@ -97,24 +88,24 @@ module dtp::transport_control { // If address are same, then the host ID must be the same, else the host ID must be different. /* - if (client_addr == server_addr) { - assert!(client_host == server_host, errors::EHostAddressMismatch1()); + if (cli_addr == srv_addr) { + assert!(cli_host == srv_host, errors::EHostAddressMismatch1()); } else { - assert!(client_host != server_host, errors::EHostAddressMismatch2()); + assert!(cli_host != srv_host, errors::EHostAddressMismatch2()); };*/ // Verify that at least one pipe is provided._ /* - let is_client_tx_pipe_set = weak_ref::is_set(&client_tx_pipe); - let is_server_tx_pipe_set = weak_ref::is_set(&server_tx_pipe); + let is_client_tx_pipe_set = weak_ref::is_set(&cli_tx_pipe); + let is_server_tx_pipe_set = weak_ref::is_set(&srv_tx_pipe); assert!(is_client_tx_pipe_set || is_server_tx_pipe_set, errors::EOnePipeRequired()); */ // If two pipes are provided, they must be different objects. /* if (is_client_tx_pipe_set && is_server_tx_pipe_set) { - let pipe1 = weak_ref::get_address(&client_tx_pipe); - let pipe2 = weak_ref::get_address(&server_tx_pipe); + let pipe1 = weak_ref::get_address(&cli_tx_pipe); + let pipe2 = weak_ref::get_address(&srv_tx_pipe); assert!(pipe1 != pipe2, errors::EPipeInstanceSame()); };*/ @@ -122,23 +113,23 @@ module dtp::transport_control { id: object::new(ctx), flags: 0, service_idx, - client_host: weak_ref::new_from_obj(client_host), - server_host: weak_ref::new_from_obj(server_host), - client_addr: host::creator(client_host), - server_addr: host::creator(server_host), - client_tx_pipe: weak_ref::new_empty(), - server_tx_pipe: weak_ref::new_empty(), - client_tx_ipipe: weak_ref::new_empty(), - server_tx_ipipe: weak_ref::new_empty(), + cli_host: weak_ref::new_from_obj(cli_host), + srv_host: weak_ref::new_from_obj(srv_host), + cli_addr: host::creator(cli_host), + srv_addr: host::creator(srv_host), + cli_tx_pipe: weak_ref::new_empty(), + srv_tx_pipe: weak_ref::new_empty() }; - // Initialize all the Weak references (for slow discovery). - let (a,b) = dtp::pipe::new_transfered(object::borrow_id(&tc), 2, tc.client_addr, ctx); - tc.client_tx_pipe = a; - tc.client_tx_ipipe= b; - (a,b) = dtp::pipe::new_transfered(object::borrow_id(&tc), 2, tc.server_addr, ctx); - tc.server_tx_pipe = a; - tc.server_tx_ipipe= b; + // Initialize the Weak references (for slow discovery). + tc.cli_tx_pipe = dtp::pipe::new_transfered(object::borrow_id(&tc), + 2, tc.cli_addr, true, conn, ctx); + tc.srv_tx_pipe = dtp::pipe::new_transfered(object::borrow_id(&tc), + 2, tc.srv_addr, false, conn, ctx); + + // Update the ConnObjects (returned to the end-points when a connection is completed). + conn_objects::set_cli_tx_pipe(conn, weak_ref::get_address(&tc.cli_tx_pipe)); + conn_objects::set_srv_tx_pipe(conn, weak_ref::get_address(&tc.srv_tx_pipe)); tc } @@ -147,10 +138,9 @@ module dtp::transport_control { public(friend) fun delete( self: TransportControl ) { let TransportControl { id, flags: _, service_idx: _, - client_host: _, server_host: _, - client_addr: _, server_addr: _, - client_tx_pipe: _, server_tx_pipe: _, - client_tx_ipipe: _, server_tx_ipipe: _ + cli_host: _, srv_host: _, + cli_addr: _, srv_addr: _, + cli_tx_pipe: _, srv_tx_pipe: _, } = self; @@ -158,18 +148,18 @@ module dtp::transport_control { } // Read accessors - public(friend) fun server_addr(self: &TransportControl): address { - self.server_addr + public(friend) fun srv_addr(self: &TransportControl): address { + self.srv_addr } - public(friend) fun client_addr(self: &TransportControl): address { - self.client_addr + public(friend) fun cli_addr(self: &TransportControl): address { + self.cli_addr } // Initial Inner Pipe address. // This is for the first response toward the client. public(friend) fun ipipe_addr(self: &TransportControl): address { - weak_ref::get_address(&self.server_tx_pipe) + weak_ref::get_address(&self.srv_tx_pipe) } // The TransportControl is the shared object for the @@ -206,17 +196,18 @@ module dtp::transport_control { // // Returns: // - tc_address: TransportControl address. Most other addresses can be learn from it. - // - client_tx_ipipe: First InnerPipe used by client to TX to server. + // - cli_tx_ipipe: First InnerPipe used by client to TX to server. // - server_tx_ipipe: First InnerPipe used by server to TX to client. #[allow(lint(share_owned))] - public entry fun create_best_effort( service_idx: u8, - client_host: &mut Host, - server_host: &Host, - ctx: &mut TxContext ): (address,address,address) + public fun create_best_effort( service_idx: u8, + cli_host: &mut Host, + srv_host: &Host, + conn: &mut ConnObjects, + ctx: &mut TxContext ) { - // Sender must be the owner of the client_host. - assert!(host::is_caller_creator(client_host, ctx), errors::EHostNotOwner()); + // Sender must be the owner of the cli_host. + assert!(host::is_caller_creator(cli_host, ctx), errors::EHostNotOwner()); // Create the TransportControl/Pipes/InnerPipes // @@ -225,21 +216,15 @@ module dtp::transport_control { // refuse the request (which is relatively nice since it save the // client some storage fee by allowing to delete the object created). // - let tc = dtp::transport_control::new(service_idx, client_host, server_host, ctx); + let tc = dtp::transport_control::new(service_idx, cli_host, srv_host, conn, ctx); + conn_objects::set_tc(conn, object::id_to_address( object::borrow_id(&tc) )); // Emit the "Connection Request" Move event. - // The server will see the sender address therefore will know the TC and plenty of info! - let tc_address = object::id_to_address( object::borrow_id(&tc) ); - dtp::events::emit_con_req( service_idx, - client_address(&tc), server_address(&tc), - tc_address, client_tx_ipipe(&tc), server_tx_ipipe(&tc)); - let client_tx_ipipe = client_tx_ipipe(&tc); - let server_tx_ipipe = server_tx_ipipe(&tc); + // The server will see the sender address therefore will know the TC and plenty of info! + dtp::events::emit_conn_req( service_idx, *conn ); transfer::share_object(tc); - // TODO Add the connection to the Client Host object registry (for slow discovery). - - (tc_address, client_tx_ipipe, server_tx_ipipe) + // TODO Add the TC address to the Client Host object registry (for slow discovery). } public entry fun create_preapproved( _ctx: &mut TxContext ) @@ -248,19 +233,11 @@ module dtp::transport_control { } public(friend) fun client_address(self: &TransportControl): address { - self.client_addr + self.cli_addr } public(friend) fun server_address(self: &TransportControl): address { - self.server_addr - } - - public(friend) fun client_tx_ipipe(self: &TransportControl): address { - weak_ref::get_address(&self.client_tx_ipipe) - } - - public(friend) fun server_tx_ipipe(self: &TransportControl): address { - weak_ref::get_address(&self.server_tx_ipipe) + self.srv_addr } // Connection State Machine (work-in-progress): @@ -308,16 +285,14 @@ module dtp::test_transport_control { fun create_hosts(scenario: &mut Scenario) { ts::next_tx(scenario, @0x10); { - let sender = ts::sender(scenario); let ctx = ts::ctx(scenario); - let _client_host = host::new_transfered(sender, ctx); + let _client_host = host::new_transfered(ctx); }; ts::next_tx(scenario, @0x20); { - let sender = ts::sender(scenario); let ctx = ts::ctx(scenario); - let _server_host = host::new_transfered(sender,ctx); + let _server_host = host::new_transfered(ctx); }; }