1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
45use crate::message::action_fuse::{ActionFuse, ActionFuseHandle};
6use crate::message::base::{
7 Attribution, Audience, Message, MessageAction, MessageClientId, MessageType, Signature, Status,
8};
9use crate::message::beacon::BeaconBuilder;
10use crate::message::messenger::Messenger;
11use crate::message::receptor::Receptor;
1213/// MessageClient provides a subset of Messenger functionality around a specific
14/// delivered message. The client may duplicate/move the MessageClient as
15/// desired. Once all MessageClient instances go out of scope, the original
16/// message is forwarded to the next Messenger if no interaction preceded it.
17#[derive(Clone, Debug)]
18pub struct MessageClient {
19// A unique identifier that identifies this client within the parent message
20 // hub.
21id: MessageClientId,
22// The "source" message for the client. Any replies or action are done in the
23 // context of this message.
24message: Message,
25// The messenger to receive any actions.
26messenger: Messenger,
27// Auto-trigger for automatically forwarding the message to the next
28 // recipient.
29forwarder: ActionFuseHandle,
30}
3132impl PartialEq for MessageClient {
33fn eq(&self, other: &MessageClient) -> bool {
34 other.id == self.id
35 }
36}
3738impl MessageClient {
39pub(super) fn new(
40 id: MessageClientId,
41 message: Message,
42 messenger: Messenger,
43 ) -> MessageClient {
44let fuse_messenger_clone = messenger.clone();
45let fuse_message_clone = message.clone();
46 MessageClient {
47 id,
48 message,
49 messenger,
50 forwarder: ActionFuse::create(Box::new(move || {
51 fuse_messenger_clone.forward(fuse_message_clone.clone(), None);
52 })),
53 }
54 }
5556#[cfg(test)]
57pub(crate) fn get_modifiers(&self) -> Vec<Signature> {
58self.message.get_modifiers()
59 }
6061/// Returns the Signature of the original author of the associated Message.
62 /// This value can be used to communicate with the author at top-level
63 /// communication.
64pub(crate) fn get_author(&self) -> Signature {
65self.message.get_author()
66 }
6768/// Returns the audience associated with the underlying [`Message`]. If it
69 /// is a new [`Message`] (origin), it will be the target audience.
70 /// Otherwise it is the author of the reply.
71pub(crate) fn get_audience(&self) -> Audience {
72match self.message.get_type() {
73 MessageType::Origin(audience) => audience.clone(),
74 MessageType::Reply(message) => Audience::Messenger(message.get_author()),
75 }
76 }
7778/// Creates a dedicated receptor for receiving future communication on this message thread.
79pub(crate) fn spawn_observer(&mut self) -> Receptor {
80let (beacon, receptor) = BeaconBuilder::new(self.messenger.clone()).build();
81self.messenger.forward(self.message.clone(), Some(beacon));
82 ActionFuse::defuse(self.forwarder.clone());
8384 receptor
85 }
8687/// Sends a reply to this message.
88pub(crate) fn reply(&self, payload: crate::Payload) -> Receptor {
89self.send(payload, Attribution::Source(MessageType::Reply(Box::new(self.message.clone()))))
90 }
9192/// Propagates a derived message on the path of the original message.
93#[cfg(test)]
94pub(crate) fn propagate(&self, payload: crate::Payload) -> Receptor {
95self.send(
96 payload,
97 Attribution::Derived(Box::new(self.message.clone()), self.messenger.get_signature()),
98 )
99 }
100101/// Report back to the clients that the message has been acknowledged.
102pub(crate) async fn acknowledge(&self) {
103self.message.report_status(Status::Acknowledged).await;
104 }
105106/// Tracks the lifetime of the reply listener, firing the fuse when it
107 /// goes out of scope.
108pub(crate) async fn bind_to_recipient(&mut self, fuse: ActionFuseHandle) {
109self.message.bind_to_author(fuse).await;
110 }
111112fn send(&self, payload: crate::Payload, attribution: Attribution) -> Receptor {
113let (beacon, receptor) = BeaconBuilder::new(self.messenger.clone()).build();
114self.messenger.transmit(MessageAction::Send(payload, attribution), Some(beacon));
115116 ActionFuse::defuse(self.forwarder.clone());
117118 receptor
119 }
120}