MobileMeshSession

Struct MobileMeshSession 

Source
pub struct MobileMeshSession { /* private fields */ }
Expand description

Long-lived Rust protocol engine used by the mobile app.

ping is the only ping operation exposed to Swift. The existing Rust node layer owns its nonce, authenticated echo request, counter reservation, response matching, and timeout.

Implementations§

Source§

impl MobileMeshSession

Source

pub async fn new( identity: Arc<MobileIdentity>, counter_store: Arc<MobileCounterStore>, ) -> Result<Arc<Self>, MobileMeshError>

Source

pub fn ping( &self, peer_address: String, timeout_ms: u64, ) -> Result<u64, MobileMeshError>

Source

pub fn node_public_key(&self) -> Vec<u8>

This phone’s own node public key, which is what a device lists in PROP_DEV_ADMINS to let this phone manage it over the mesh.

Handing this to a radio the phone is attached to — MobileUlcpSession::insert_device_admin — is the whole of making this phone an administrator of that radio. Nothing else is exchanged: the session both ends derive comes from their two identities.

Source

pub fn begin_management_get( &self, peer_address: String, property_id: u32, ) -> Result<u64, MobileMeshError>

Read one property from a device across the mesh.

Every begin_management_* call returns immediately with an operation identifier, and reports through poll_update — the same shape as ping, because it is the same kind of thing: a round-trip over a network that promises nothing. One operation runs at a time; starting another while one is outstanding fails it.

Source

pub fn begin_management_set( &self, peer_address: String, property_id: u32, value: Vec<u8>, ) -> Result<u64, MobileMeshError>

Write one property on a device across the mesh.

The answer echoes what the property is now worth, which is what the device kept rather than what was sent. The change is live and unsaved; begin_management_save is what makes it survive a reboot.

Source

pub fn begin_management_insert( &self, peer_address: String, property_id: u32, item: Vec<u8>, ) -> Result<u64, MobileMeshError>

Add one item to a multiple-value property on a device across the mesh — a peer key, an administrator key, a channel key.

Source

pub fn begin_management_remove( &self, peer_address: String, property_id: u32, selector: Vec<u8>, ) -> Result<u64, MobileMeshError>

Take one item out of a multiple-value property on a device across the mesh.

Source

pub fn begin_management_insert_admin( &self, peer_address: String, public_key: Vec<u8>, ) -> Result<u64, MobileMeshError>

Let one more node manage this device over the mesh, by adding its public key to PROP_DEV_ADMINS.

Named rather than left to Self::begin_management_insert for the same reason MobileUlcpSession::insert_device_admin is: this is a decision about who may configure a node, and a caller should not have to name the property — or be able to reach a different one by naming it wrong. The device holds it live until a save.

Source

pub fn begin_management_remove_admin( &self, peer_address: String, public_key: Vec<u8>, ) -> Result<u64, MobileMeshError>

Take a node’s authority to manage this device away again.

A device that removes the administrator it is answering keeps answering this exchange — the reply is already authorized — and refuses the next one.

Source

pub fn begin_management_insert_peer( &self, peer_address: String, public_key: Vec<u8>, ) -> Result<u64, MobileMeshError>

Store one more peer public key on a device’s identity (PROP_DEV_PEERS), so it can hold a secure session with that node on its own.

Named for the same reason the administrator pair is: the caller is deciding who a device talks to, not writing to a numbered property. Live until a save.

Source

pub fn begin_management_remove_peer( &self, peer_address: String, public_key: Vec<u8>, ) -> Result<u64, MobileMeshError>

Drop a peer public key from a device’s identity.

Source

pub fn begin_management_set_alert( &self, peer_address: String, state: UlcpAlertState, ) -> Result<u64, MobileMeshError>

Tell a device to make itself conspicuous, or to stop (PROP_ALERT).

Live state, never saved: an alert is a thing happening now, and one restored at boot would be a device that woke up beeping. The device ends it on its own deadline as well, so a search that outlasts that is kept alive by asking again — the same contract as the local link, with the round trip of the mesh in front of it.

Source

pub fn begin_management_get_many( &self, peer_address: String, property_ids: Vec<u32>, ) -> Result<u64, MobileMeshError>

Read several properties in one exchange.

A device answers as many as fit and stops; the answers that arrive are the ones it sent, and the rest are simply absent. Requires CAP_CMD_MULTI on the device — one that lacks it refuses the whole request rather than answering part of it.

Source

pub fn begin_management_set_many( &self, peer_address: String, writes: Vec<MobileMeshPropertyWriteRecord>, ) -> Result<u64, MobileMeshError>

Write several properties in one exchange, in order.

A device applies them until the next answer would not fit and stops there, so a short answer means the remainder was never attempted. Each position echoes what that property is now worth.

Source

pub fn begin_management_save( &self, peer_address: String, ) -> Result<u64, MobileMeshError>

Persist a device’s live configuration across the mesh.

Source

pub fn begin_management_ble_clear_bonds( &self, peer_address: String, ) -> Result<u64, MobileMeshError>

Clear a device’s Bluetooth bonds across the mesh (CMD_BLE_CLEAR_BONDS): forget every paired host, the pairing PIN, and the pairing lockout, then open a pairing window.

The command answers with a status rather than silence: it is not reset-class, and what it did is the whole of what it reports. STATUS_UNIMPLEMENTED is a device that does not manage its own bonds.

Clearing bonds over the mesh does not touch this exchange — the administrator is addressing the device’s node, not one of its Bluetooth hosts — so unlike the same command over Bluetooth, the reply arrives on a link that survives it.

Source

pub fn begin_management_reset( &self, peer_address: String, scope: MobileMeshResetScope, ) -> Result<u64, MobileMeshError>

Reset a device across the mesh.

A device answers a reset with nothing — it is busy doing what was asked — so the operation ends Acknowledged on the MAC acknowledgment. Restore on a device holding no snapshot resets nothing and answers like any other command, which arrives as an ordinary Replied status.

Source

pub fn begin_management_fetch( &self, peer_address: String, property_ids: Vec<u32>, multi_hint: bool, ) -> Result<u64, MobileMeshError>

Read a named set of properties across the mesh.

The caller names what it wants, in as many exchanges as the answers need — a screenful of settings is normally one. Every property comes back answered, refusals included, so a caller can tell “the device would not say” from “nobody asked”.

multi_hint says whether to open with a batched request. A device that declines one is asked again a property at a time, so the hint costs a round trip when wrong rather than an answer. Pass what CAP_CMD_MULTI last said, or true before anything has.

Every exchange is airtime over a link that may be several hops deep. Ask for what a screen needs and no more.

Source

pub async fn advertise_identity( &self, name: Option<String>, timestamp: Option<u32>, ) -> Result<(), MobileMeshError>

Broadcast a signed node-identity advertisement describing this phone.

The bundle always carries the standalone EdDSA signature because a broadcast frame has no MIC to authenticate it.

Source

pub async fn advertise_identity_scheduled( &self, name: Option<String>, timestamp: Option<u32>, ) -> Result<(), MobileMeshError>

The same advertisement, sent because the phone’s own interval came round rather than because someone asked for it.

Reaches only direct neighbours. A repeated statement of who this phone is does not need to cross the mesh every time; introducing it, which is what the manual send does, is the case that does.

Source

pub async fn send_beacon(&self) -> Result<(), MobileMeshError>

Broadcast an empty beacon: no payload, so what it publishes is the path back to this phone rather than who this phone is. Costs a fraction of an advertisement.

Source

pub async fn request_identity( &self, peer_address: String, ) -> Result<(), MobileMeshError>

Solicit a specific peer’s current node identity by sending a targeted MAC Identity Request (command 1). This resolves once the request has been handed to the transport; the peer’s identity response arrives later as a NodeIdentity advertisement on the normal receive path (surfaced through poll_update’s advertisement events).

Source

pub async fn discover_identities( &self, role_code: Option<u8>, capability_bits: Option<u8>, node_hint: Option<Vec<u8>>, source_route: Vec<Vec<u8>>, ) -> Result<(), MobileMeshError>

Solicit identities with one broadcast MAC Identity Request, either from this node’s own neighbors or from a remote vantage point.

With an empty source_route the request goes out as a direct broadcast with no flood budget, so repeaters never carry it — the blast radius is exactly the nodes in radio range. Given a route, the request is steered along it instead: each repeater consumes its hint, so the request arrives with an empty Route option in the neighborhood the route ends at, and the nodes there are the ones that answer. A steered request also carries a trace route, which is what gives the answering strangers a path back — without it their replies would have no route and no flood budget, and would die on their own transmitter.

Either way it carries this phone’s full source address, so a matching node can reply with a targeted unicast without any prior contact; replies arrive as ordinary NodeIdentity advertisements on the receive path. role_code and capability_bits narrow which nodes respond (AND-combined when both are given); None for all three filters asks every node the request reaches.

node_hint narrows the ask to one node by the leading bytes of its node hint. Two bytes is a router hint, which is all a route reveals about the hops it crosses: pair it with a route ending at the hop before the one in question, since a repeater consumes its own hint only when forwarding and drops a request that still names it.

Each entry of source_route is one 2-byte router hint in send order.

Source

pub async fn request_identity_by_hint( &self, conversation_address: String, hint: Vec<u8>, ) -> Result<(), MobileMeshError>

Ask a channel member who is known only by their claimed hint to send their identity.

A group message carries a 3-byte hint and nothing else, so there is no address to unicast a request to. This goes out over the channel itself, filtered to that hint, and only the member it names answers — with a targeted unicast, since the request carries this phone’s full address.

The request is routed by what that member’s own frames have shown: their observed trace route if one is known, otherwise a flood budget bounded by the hops their last message took rather than a default.

Source

pub async fn request_peer_repeaters( &self, peer: Vec<u8>, ) -> Result<Vec<MobileMeshPeerRepeaterRecord>, MobileMeshError>

Ask one repeater which repeaters it knows of, and return the whole listing.

Unlike discover_identities, which scatters a request and lets the answers arrive as events, this is one node’s own account of its neighborhood: a single addressed exchange, paged when it does not fit one frame, so it resolves to a list rather than a stream. Pages are followed here; the caller sees only the finished listing.

Source

pub async fn set_chat_display_name( &self, name: String, ) -> Result<(), MobileMeshError>

Set whether this phone answers Identity Requests with its own identity — the passive counterpart of [discover_identities]: discoverable phones show up in other people’s Discover sessions.

name is the display name carried in replies (truncated to the 24-byte wire limit). The session starts discoverable with no name; the app pushes the stored preference and name right after install and again whenever either changes. Replies are targeted authenticated unicasts, never broadcasts. Set the name carried on this phone’s own group messages.

A multicast reaches members holding no identity for us, so a group message says who sent it or arrives anonymous. Direct messages never carry it: the recipient authenticated us by key. Empty clears it.

Source

pub async fn set_discoverable( &self, enabled: bool, name: Option<String>, ) -> Result<(), MobileMeshError>

Source

pub async fn set_advertised_location( &self, location: Option<MobileMeshSharedLocationRecord>, ) -> Result<(), MobileMeshError>

Set the position this phone’s identity carries, or None to stop sharing one.

Reaches every live identity payload — advertisements, manual and scheduled, and Identity Request replies while discoverable — but never the shareable QR/URI bundle: that bundle is durable, and a position frozen into it would go stale and then travel wherever the QR is pasted. The coordinate is reduced to the cell named by precision_bytes before it is stored, so nothing finer ever sits in this session, whatever later reads it.

Source

pub async fn peer_route( &self, peer_address: String, ) -> Result<MobileMeshRouteRecord, MobileMeshError>

Report the route the MAC will use for the next frame sent to peer.

Read-only: an unregistered peer reads as Unknown rather than being registered as a side effect of being inspected.

Source

pub async fn clear_peer_route( &self, peer_address: String, ) -> Result<bool, MobileMeshError>

Forget the route cached for peer, returning whether one was held.

The peer, its keys, and its counters are untouched; only the learned path is discarded, so the next send starts over from flood delivery.

Source

pub async fn sign_identity_bundle( &self, name: Option<String>, timestamp: Option<u32>, ) -> Result<Vec<u8>, MobileMeshError>

Build and sign this phone’s node-identity bundle without transmitting it, for embedding in the shareable umsh:n: URI and QR code.

Source

pub async fn register_peers( &self, peer_addresses: Vec<String>, ) -> Result<(), MobileMeshError>

Source

pub async fn remove_peers( &self, peer_addresses: Vec<String>, ) -> Result<(), MobileMeshError>

Remove peers from the live MAC. Idempotent: a peer that was never registered is already in the requested state, so it is not an error. A removed peer that transmits again may be auto-re-registered (unpinned) by the MAC — removal here tracks the app’s stored peer list, it is not a block list.

Source

pub async fn register_channels( &self, keys: Vec<Vec<u8>>, ) -> Result<(), MobileMeshError>

Register channel keys with the live MAC so their traffic is accepted.

Membership itself is persisted by the platform, which replays the whole joined set through this call when a session starts. Re-registering a channel already held is harmless.

Source

pub async fn remove_channels( &self, keys: Vec<Vec<u8>>, ) -> Result<(), MobileMeshError>

Drop channel keys from the live MAC, so its traffic is no longer decrypted. Idempotent, like Self::remove_peers.

Source

pub fn receive(&self, frame: MobileMeshRxRecord) -> Result<(), MobileMeshError>

Source

pub fn complete_outbound_frame( &self, frame_id: u64, transmitted: bool, ) -> Result<(), MobileMeshError>

Report the actual physical radio result for an outbound frame. This is intentionally distinct from accepting the frame into the BLE/CRP queue: the MAC starts ACK and retry timing only after success.

Source

pub async fn restore_chat( &self, checkpoints: Vec<MobileChatCheckpointRecord>, ) -> Result<(), MobileMeshError>

Source

pub async fn compose_text( &self, conversation_address: String, client_token: u32, body: String, ) -> Result<MobileChatComposeBatchRecord, MobileMeshError>

Compose a message into a conversation, addressed either by a peer’s address or by a channel’s conversation address.

Source

pub async fn compose_edit( &self, conversation_address: String, client_token: u32, original: MobileChatOriginalRef, body: String, ) -> Result<MobileChatComposeBatchRecord, MobileMeshError>

Compose an edit of a previously sent message. The original may come from an earlier app launch: its persisted (wire_id, epoch) is used when the facade session no longer holds a live handle, and the engine rejects it (ChatComposeFailed) if stream continuity was lost since.

Source

pub async fn compose_delete( &self, conversation_address: String, client_token: u32, original: MobileChatOriginalRef, ) -> Result<MobileChatComposeBatchRecord, MobileMeshError>

Compose a deletion (empty edit on the wire) of a previously sent message. Same original-reference rules as Self::compose_edit.

Source

pub async fn compose_reaction( &self, conversation_address: String, client_token: u32, target: MobileChatRegardingRef, body: String, ) -> Result<MobileChatComposeBatchRecord, MobileMeshError>

React to a message with a short emote body, or withdraw an earlier reaction by passing an empty body. A sender has at most one live reaction per message: sending another simply supersedes it, so there is nothing to edit or delete.

Unlike an edit, the target may be a message the peer sent, and usually one persisted before this launch; the reference carries the direction and (for channel groups) the sender hint needed to name it.

Source

pub async fn commit_chat_batch( &self, batch_id: u64, ) -> Result<(), MobileMeshError>

Source

pub async fn reject_chat_batch( &self, batch_id: u64, checkpoints: Vec<MobileChatCheckpointRecord>, ) -> Result<(), MobileMeshError>

Source

pub fn apply_chat_archive_result( &self, request_id: u32, kind: MobileChatArchiveResultKind, payload: Vec<u8>, ) -> Result<(), MobileMeshError>

Source

pub fn acknowledge_chat_batch( &self, batch_id: u64, ) -> Result<(), MobileMeshError>

Source

pub fn fail_outbound_transmissions(&self) -> Result<(), MobileMeshError>

Fail every chat transmission currently owned by the mobile radio bridge. The platform calls this when ULCP-link delivery failed after the MAC had accepted the frames, ensuring optimistic UI rows do not remain in Sending indefinitely.

Source

pub fn set_wake_listener(&self, listener: Arc<dyn MobileMeshWakeListener>)

Register (or replace) the listener that is told when this session has new data for poll_update. If data is already pending, the listener fires immediately.

Source

pub fn clear_wake_listener(&self)

Source

pub fn poll_update(&self) -> MobileMeshSessionUpdateRecord

Trait Implementations§

Source§

impl Drop for MobileMeshSession

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl<UT> LiftRef<UT> for MobileMeshSession

Source§

impl<UT> LowerError<UT> for MobileMeshSession

Source§

fn lower_error(obj: Self) -> RustBuffer

Lower this value for scaffolding function return Read more
Source§

impl<UT> LowerReturn<UT> for MobileMeshSession

Source§

type ReturnType = <Arc<MobileMeshSession> as LowerReturn<UniFfiTag>>::ReturnType

The type that should be returned by scaffolding functions for this type. Read more
Source§

fn lower_return(obj: Self) -> Result<Self::ReturnType, RustCallError>

Lower the return value from an scaffolding call Read more
Source§

fn handle_failed_lift( error: LiftArgsError, ) -> Result<Self::ReturnType, RustCallError>

Lower the return value for failed argument lifts Read more
Source§

impl<UT> TypeId<UT> for MobileMeshSession

Auto Trait Implementations§

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, UT> HandleAlloc<UT> for T
where T: Send + Sync,

Source§

fn new_handle(value: Arc<T>) -> Handle

Create a new handle for an Arc value Read more
Source§

unsafe fn clone_handle(handle: Handle) -> Handle

Clone a handle Read more
Source§

unsafe fn consume_handle(handle: Handle) -> Arc<T>

Consume a handle, getting back the initial Arc<> Read more
Source§

unsafe fn get_arc(handle: Handle) -> Arc<Self>

Get a clone of the Arc<> using a “borrowed” handle. Read more
§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.