Skip to content

Commit 33d2020

Browse files
Patrik-Stasmirgee
andauthored
Make send_message implementation pluggable for Connection FSM (#299)
* Make send_message implementation pluggable for Inviter FSM Signed-off-by: Patrik Stas <patrik.stas@absa.africa> * Make send_message implementation pluggable for Inviter FSM Signed-off-by: Patrik Stas <patrik.stas@absa.africa> * Specify Connection object de/serialization on serde layer Signed-off-by: Patrik Stas <patrik.stas@absa.africa> * Remove unwrap from connection serialization Signed-off-by: Patrik Stas <patrik.stas@absa.africa> * Reformat and optimize imports for connection code Signed-off-by: Patrik Stas <patrik.stas@absa.africa> * Address PR comments Signed-off-by: Patrik Stas <patrik.stas@absa.africa> * Fix compilation errors Signed-off-by: Patrik Stas <patrik.stas@absa.africa> * Remove unnecessary line Signed-off-by: Miroslav Kovar <miroslavkovar@protonmail.com> * Fix after rebase, remove unused variables Signed-off-by: Patrik Stas <patrik.stas@absa.africa> Co-authored-by: Miroslav Kovar <miroslavkovar@protonmail.com>
1 parent 7775022 commit 33d2020

File tree

10 files changed

+266
-147
lines changed

10 files changed

+266
-147
lines changed

libvcx/src/aries/handlers/connection/connection.rs

Lines changed: 82 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,36 @@
1+
use core::fmt;
12
use std::collections::HashMap;
3+
use std::fmt::Formatter;
4+
5+
use serde::{Deserialize, Deserializer, Serialize, Serializer};
6+
use serde::de::{EnumAccess, Error, MapAccess, SeqAccess, Unexpected, Visitor};
7+
use serde_json::Value;
28

39
use agency_client::get_message::{Message, MessageByConnection};
410
use agency_client::MessageStatusCode;
511

612
use crate::aries::handlers::connection::cloud_agent::CloudAgentInfo;
7-
use crate::aries::handlers::connection::invitee::state_machine::{InviteeFullState, SmConnectionInvitee, InviteeState};
8-
use crate::aries::handlers::connection::inviter::state_machine::{InviterFullState, SmConnectionInviter, InviterState};
13+
use crate::aries::handlers::connection::invitee::state_machine::{InviteeFullState, InviteeState, SmConnectionInvitee};
14+
use crate::aries::handlers::connection::inviter::state_machine::{InviterFullState, InviterState, SmConnectionInviter};
915
use crate::aries::handlers::connection::legacy_agent_info::LegacyAgentInfo;
1016
use crate::aries::handlers::connection::pairwise_info::PairwiseInfo;
1117
use crate::aries::messages::a2a::A2AMessage;
1218
use crate::aries::messages::basic_message::message::BasicMessage;
1319
use crate::aries::messages::connection::did_doc::DidDoc;
1420
use crate::aries::messages::connection::invite::Invitation;
1521
use crate::aries::messages::discovery::disclose::ProtocolDescriptor;
22+
use crate::aries::utils::send_message;
1623
use crate::error::prelude::*;
1724
use crate::utils::serialization::SerializableObjectWithState;
1825

19-
#[derive(Debug, Clone, Serialize, Deserialize)]
26+
#[derive(Clone)]
2027
pub struct Connection {
2128
connection_sm: SmConnection,
2229
cloud_agent_info: CloudAgentInfo,
2330
autohop_enabled: bool,
2431
}
2532

26-
#[derive(Debug, Clone, Serialize, Deserialize)]
33+
#[derive(Clone)]
2734
pub enum SmConnection {
2835
Inviter(SmConnectionInviter),
2936
Invitee(SmConnectionInvitee),
@@ -44,7 +51,7 @@ struct ConnectionInfo {
4451
#[derive(Debug, PartialEq)]
4552
pub enum ConnectionState {
4653
Inviter(InviterState),
47-
Invitee(InviteeState)
54+
Invitee(InviteeState),
4855
}
4956

5057

@@ -73,12 +80,9 @@ impl Connection {
7380
trace!("Connection::create >>> source_id: {}", source_id);
7481
let pairwise_info = PairwiseInfo::create()?;
7582
let cloud_agent_info = CloudAgentInfo::create(&pairwise_info)?;
76-
let routing_keys = cloud_agent_info.routing_keys()?;
77-
let agency_endpoint = cloud_agent_info.service_endpoint()?;
78-
7983
Ok(Connection {
8084
cloud_agent_info,
81-
connection_sm: SmConnection::Inviter(SmConnectionInviter::new(source_id, pairwise_info)),
85+
connection_sm: SmConnection::Inviter(SmConnectionInviter::new(source_id, pairwise_info, send_message)),
8286
autohop_enabled: autohop,
8387
})
8488
}
@@ -90,12 +94,9 @@ impl Connection {
9094
trace!("Connection::create_with_invite >>> source_id: {}", source_id);
9195
let pairwise_info = PairwiseInfo::create()?;
9296
let cloud_agent_info = CloudAgentInfo::create(&pairwise_info)?;
93-
let routing_keys = cloud_agent_info.routing_keys()?;
94-
let agency_endpoint = cloud_agent_info.service_endpoint()?;
95-
9697
let mut connection = Connection {
9798
cloud_agent_info,
98-
connection_sm: SmConnection::Invitee(SmConnectionInvitee::new(source_id, pairwise_info)),
99+
connection_sm: SmConnection::Invitee(SmConnectionInvitee::new(source_id, pairwise_info, send_message)),
99100
autohop_enabled,
100101
};
101102
connection.process_invite(invitation)?;
@@ -107,14 +108,14 @@ impl Connection {
107108
SmConnectionState::Inviter(state) => {
108109
Connection {
109110
cloud_agent_info,
110-
connection_sm: SmConnection::Inviter(SmConnectionInviter::from(source_id, pairwise_info, state)),
111+
connection_sm: SmConnection::Inviter(SmConnectionInviter::from(source_id, pairwise_info, state, send_message)),
111112
autohop_enabled,
112113
}
113114
}
114115
SmConnectionState::Invitee(state) => {
115116
Connection {
116117
cloud_agent_info,
117-
connection_sm: SmConnection::Invitee(SmConnectionInvitee::from(source_id, pairwise_info, state)),
118+
connection_sm: SmConnection::Invitee(SmConnectionInvitee::from(source_id, pairwise_info, state, send_message)),
118119
autohop_enabled,
119120
}
120121
}
@@ -577,7 +578,7 @@ Get messages received from connection counterparty.
577578
.ok_or(VcxError::from_msg(VcxErrorKind::NotReady, "Cannot send message: Remote Connection information is not set"))?;
578579
let sender_vk = self.pairwise_info().pw_vk.clone();
579580
return Ok(move |a2a_message: &A2AMessage| {
580-
did_doc.send_message(a2a_message, &sender_vk)
581+
send_message(&sender_vk, &did_doc, a2a_message)
581582
});
582583
}
583584

@@ -677,7 +678,23 @@ Get messages received from connection counterparty.
677678
Ok(msgs)
678679
}
679680

680-
pub fn to_string(&self) -> String {
681+
pub fn to_string(&self) -> VcxResult<String> {
682+
serde_json::to_string(&self)
683+
.map_err(|err| VcxError::from_msg(VcxErrorKind::SerializationError, format!("Cannot serialize Connection: {:?}", err)))
684+
}
685+
686+
pub fn from_string(connection_data: &str) -> VcxResult<Connection> {
687+
serde_json::from_str(connection_data)
688+
.map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize Connection: {:?}", err)))
689+
}
690+
}
691+
692+
impl Serialize for Connection
693+
{
694+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
695+
where
696+
S: Serializer,
697+
{
681698
let (state, pairwise_info, cloud_agent_info, source_id) = self.to_owned().into();
682699
let data = LegacyAgentInfo {
683700
pw_did: pairwise_info.pw_did,
@@ -686,13 +703,31 @@ Get messages received from connection counterparty.
686703
agent_vk: cloud_agent_info.agent_vk,
687704
};
688705
let object = SerializableObjectWithState::V1 { data, state, source_id };
689-
json!(object).to_string()
706+
serializer.serialize_some(&object)
690707
}
708+
}
691709

692-
pub fn from_string(connection_data: &str) -> VcxResult<Connection> {
693-
let object: SerializableObjectWithState<LegacyAgentInfo, SmConnectionState> = serde_json::from_str(connection_data)
694-
.map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize Connection: {:?}", err)))?;
695-
match object {
710+
struct ConnectionVisitor;
711+
712+
impl<'de> Visitor<'de> for ConnectionVisitor {
713+
type Value = Connection;
714+
715+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
716+
formatter.write_str("serialized Connection object")
717+
}
718+
719+
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, <A as MapAccess<'de>>::Error> where
720+
A: MapAccess<'de>, {
721+
let mut map_value = serde_json::Map::new();
722+
while let Some(key) = map.next_key()? {
723+
let k: String = key;
724+
let v: Value = map.next_value()?;
725+
map_value.insert(k, v);
726+
}
727+
let obj = Value::from(map_value);
728+
let ver: SerializableObjectWithState<LegacyAgentInfo, SmConnectionState> = serde_json::from_value(obj)
729+
.map_err(|err| A::Error::custom(err.to_string()))?;
730+
match ver {
696731
SerializableObjectWithState::V1 { data, state, source_id } => {
697732
let pairwise_info = PairwiseInfo { pw_did: data.pw_did, pw_vk: data.pw_vk };
698733
let cloud_agent_info = CloudAgentInfo { agent_did: data.agent_did, agent_vk: data.agent_vk };
@@ -702,6 +737,14 @@ Get messages received from connection counterparty.
702737
}
703738
}
704739

740+
impl<'de> Deserialize<'de> for Connection {
741+
fn deserialize<D>(deserializer: D) -> Result<Connection, D::Error>
742+
where
743+
D: Deserializer<'de>,
744+
{
745+
deserializer.deserialize_map(ConnectionVisitor)
746+
}
747+
}
705748

706749
#[cfg(test)]
707750
pub mod tests {
@@ -743,7 +786,7 @@ pub mod tests {
743786
fn test_deserialize_and_serialize(sm_serialized: &str) {
744787
let original_object: Value = serde_json::from_str(sm_serialized).unwrap();
745788
let connection = Connection::from_string(sm_serialized).unwrap();
746-
let reserialized = connection.to_string();
789+
let reserialized = connection.to_string().unwrap();
747790
let reserialized_object: Value = serde_json::from_str(&reserialized).unwrap();
748791

749792
assert_eq!(original_object, reserialized_object);
@@ -766,14 +809,28 @@ pub mod tests {
766809
let _setup = SetupMocks::init();
767810

768811
let connection = Connection::create("test_serialize_deserialize", true).unwrap();
769-
let first_string = connection.to_string();
812+
let first_string = connection.to_string().unwrap();
770813

771814
let connection2 = Connection::from_string(&first_string).unwrap();
772-
let second_string = connection2.to_string();
815+
let second_string = connection2.to_string().unwrap();
773816

774817
assert_eq!(first_string, second_string);
775818
}
776819

820+
#[test]
821+
#[cfg(feature = "general_test")]
822+
fn test_serialize_deserialize_serde() {
823+
let _setup = SetupMocks::init();
824+
825+
let connection = Connection::create("test_serialize_deserialize", true).unwrap();
826+
let first_string = serde_json::to_string(&connection).unwrap();
827+
828+
let connection: Connection = serde_json::from_str(&first_string).unwrap();
829+
let second_string = serde_json::to_string(&connection).unwrap();
830+
assert_eq!(first_string, second_string);
831+
}
832+
833+
777834
pub fn create_connected_connections(consumer: &mut Alice, institution: &mut Faber) -> (Connection, Connection) {
778835
debug!("Institution is going to create connection.");
779836
institution.activate().unwrap();

0 commit comments

Comments
 (0)