From a5ad71199f33c951af779bbc9f2877e6b016dfa2 Mon Sep 17 00:00:00 2001 From: Patrik Stas Date: Fri, 25 Dec 2020 18:15:55 +0100 Subject: [PATCH] Refactor sending Aries messages Signed-off-by: Patrik Stas --- .../aries/handlers/connection/agent_info.rs | 12 +--- .../aries/handlers/connection/connection.rs | 2 +- .../connection/invitee/state_machine.rs | 5 +- .../connection/invitee/states/complete.rs | 7 +-- .../connection/invitee/states/requested.rs | 2 +- .../connection/inviter/state_machine.rs | 4 +- .../connection/inviter/states/complete.rs | 6 +- .../connection/inviter/states/invited.rs | 3 +- libvcx/src/aries/handlers/connection/util.rs | 3 +- .../src/aries/messages/connection/did_doc.rs | 23 ++++++++ libvcx/src/utils/httpclient.rs | 56 +++++++++++++++++++ libvcx/src/utils/mod.rs | 1 + 12 files changed, 98 insertions(+), 26 deletions(-) create mode 100644 libvcx/src/utils/httpclient.rs diff --git a/libvcx/src/aries/handlers/connection/agent_info.rs b/libvcx/src/aries/handlers/connection/agent_info.rs index 3e5c49a301..7997cdfd5c 100644 --- a/libvcx/src/aries/handlers/connection/agent_info.rs +++ b/libvcx/src/aries/handlers/connection/agent_info.rs @@ -11,7 +11,7 @@ use crate::connection::create_agent_keys; use crate::error::prelude::*; use crate::libindy::utils::signus::create_and_store_my_did; use crate::settings; -use crate::agency_client::httpclient; +use crate::utils::httpclient; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct AgentInfo { @@ -149,16 +149,6 @@ impl AgentInfo { EncryptionEnvelope::anon_unpack(message.payload()?) } - /** - Sends authenticated message to connection counterparty - */ - pub fn send_message(&self, message: &A2AMessage, did_dod: &DidDoc) -> VcxResult<()> { - trace!("Agent::send_message >>> message: {:?}, did_doc: {:?}", message, did_dod); - let envelope = EncryptionEnvelope::create(&message, Some(&self.pw_vk), &did_dod)?; - httpclient::post_message(&envelope.0, &did_dod.get_endpoint())?; - Ok(()) - } - /** Sends message to one's agency signalling resources related to this connection agent can be deleted. */ diff --git a/libvcx/src/aries/handlers/connection/connection.rs b/libvcx/src/aries/handlers/connection/connection.rs index 14540a5f25..339be15656 100644 --- a/libvcx/src/aries/handlers/connection/connection.rs +++ b/libvcx/src/aries/handlers/connection/connection.rs @@ -356,7 +356,7 @@ Get messages received from connection counterparty. .ok_or(VcxError::from_msg(VcxErrorKind::NotReady, "Cannot send message: Remote Connection information is not set"))?; warn!("Connection resolved did_doc = {:?}", did_doc); - self.agent_info().send_message(message, &did_doc) + did_doc.send_message(message, &self.agent_info().pw_vk) } fn parse_generic_message(message: &str) -> A2AMessage { diff --git a/libvcx/src/aries/handlers/connection/invitee/state_machine.rs b/libvcx/src/aries/handlers/connection/invitee/state_machine.rs index d4a7543cfe..1f00e3a3aa 100644 --- a/libvcx/src/aries/handlers/connection/invitee/state_machine.rs +++ b/libvcx/src/aries/handlers/connection/invitee/state_machine.rs @@ -216,7 +216,8 @@ impl SmConnectionInvitee { .set_keys(agent_info.recipient_keys(), agent_info.routing_keys()?); trace!("invitation {:?}", state.invitation); - agent_info.send_message(&request.to_a2a_message(), &DidDoc::from(state.invitation.clone()))?; + let ddo = DidDoc::from(state.invitation.clone()); + ddo.send_message(&request.to_a2a_message(), &agent_info.pw_vk)?; InviteeState::Requested((state, request).into()) } DidExchangeMessages::ProblemReportReceived(problem_report) => { @@ -239,7 +240,7 @@ impl SmConnectionInvitee { .set_problem_code(ProblemCode::ResponseProcessingError) .set_explain(err.to_string()) .set_thread_id(&state.request.id.0); - agent_info.send_message(&problem_report.to_a2a_message(), &state.did_doc).ok(); + state.did_doc.send_message(&problem_report.to_a2a_message(), &agent_info.pw_vk).ok(); InviteeState::Null((state, problem_report).into()) } } diff --git a/libvcx/src/aries/handlers/connection/invitee/states/complete.rs b/libvcx/src/aries/handlers/connection/invitee/states/complete.rs index 87fff61d5d..d26eda8a13 100644 --- a/libvcx/src/aries/handlers/connection/invitee/states/complete.rs +++ b/libvcx/src/aries/handlers/connection/invitee/states/complete.rs @@ -59,7 +59,7 @@ impl CompleteState { .request_response() .set_comment(comment); - agent_info.send_message(&ping.to_a2a_message(), &self.did_doc).ok(); + self.did_doc.send_message(&ping.to_a2a_message(), &agent_info.pw_did).ok(); Ok(()) } @@ -72,8 +72,7 @@ impl CompleteState { Query::create() .set_query(query) .set_comment(comment); - - agent_info.send_message(&query_.to_a2a_message(), &self.did_doc) + self.did_doc.send_message(&query_.to_a2a_message(), &agent_info.pw_did) } fn handle_discovery_query(&self, query: Query, agent_info: &AgentInfo) -> VcxResult<()> { @@ -83,6 +82,6 @@ impl CompleteState { .set_protocols(protocols) .set_thread_id(query.id.0.clone()); - agent_info.send_message(&disclose.to_a2a_message(), &self.did_doc) + self.did_doc.send_message(&disclose.to_a2a_message(), &agent_info.pw_did) } } \ No newline at end of file diff --git a/libvcx/src/aries/handlers/connection/invitee/states/requested.rs b/libvcx/src/aries/handlers/connection/invitee/states/requested.rs index a25b0fe8e2..c6fe576686 100644 --- a/libvcx/src/aries/handlers/connection/invitee/states/requested.rs +++ b/libvcx/src/aries/handlers/connection/invitee/states/requested.rs @@ -53,7 +53,7 @@ impl RequestedState { .to_a2a_message() }; - agent_info.send_message(&message, &response.connection.did_doc)?; + response.connection.did_doc.send_message(&message, &agent_info.pw_vk)?; Ok(response) } diff --git a/libvcx/src/aries/handlers/connection/inviter/state_machine.rs b/libvcx/src/aries/handlers/connection/inviter/state_machine.rs index ca491dd598..3a37090e66 100644 --- a/libvcx/src/aries/handlers/connection/inviter/state_machine.rs +++ b/libvcx/src/aries/handlers/connection/inviter/state_machine.rs @@ -261,7 +261,7 @@ impl SmConnectionInviter { .set_explain(err.to_string()) .set_thread_id(&request.id.0); - agent_info.send_message(&problem_report.to_a2a_message(), &request.connection.did_doc).ok(); // IS is possible? + request.connection.did_doc.send_message(&problem_report.to_a2a_message(), &agent_info.pw_vk).ok(); InviterState::Null((state, problem_report).into()) } } @@ -292,7 +292,7 @@ impl SmConnectionInviter { .request_response() .set_comment(comment); - agent_info.send_message(&ping.to_a2a_message(), &state.did_doc).ok(); + state.did_doc.send_message(&ping.to_a2a_message(), &agent_info.pw_vk).ok(); InviterState::Responded(state) } DidExchangeMessages::PingResponseReceived(ping_response) => { diff --git a/libvcx/src/aries/handlers/connection/inviter/states/complete.rs b/libvcx/src/aries/handlers/connection/inviter/states/complete.rs index 41b7d7be05..5514704898 100644 --- a/libvcx/src/aries/handlers/connection/inviter/states/complete.rs +++ b/libvcx/src/aries/handlers/connection/inviter/states/complete.rs @@ -59,7 +59,7 @@ impl CompleteState { .request_response() .set_comment(comment); - agent_info.send_message(&ping.to_a2a_message(), &self.did_doc).ok(); + self.did_doc.send_message(&ping.to_a2a_message(), &agent_info.pw_vk).ok(); Ok(()) } @@ -73,7 +73,7 @@ impl CompleteState { .set_query(query) .set_comment(comment); - agent_info.send_message(&query_.to_a2a_message(), &self.did_doc) + self.did_doc.send_message(&query_.to_a2a_message(), &agent_info.pw_vk) } fn handle_discovery_query(&self, query: Query, agent_info: &AgentInfo) -> VcxResult<()> { @@ -83,6 +83,6 @@ impl CompleteState { .set_protocols(protocols) .set_thread_id(query.id.0.clone()); - agent_info.send_message(&disclose.to_a2a_message(), &self.did_doc) + self.did_doc.send_message(&disclose.to_a2a_message(), &agent_info.pw_vk) } } \ No newline at end of file diff --git a/libvcx/src/aries/handlers/connection/inviter/states/invited.rs b/libvcx/src/aries/handlers/connection/inviter/states/invited.rs index 8b6629d9cf..f0b0c32329 100644 --- a/libvcx/src/aries/handlers/connection/inviter/states/invited.rs +++ b/libvcx/src/aries/handlers/connection/inviter/states/invited.rs @@ -48,7 +48,8 @@ impl InvitedState { .set_thread_id(&request.id.0) .encode(&prev_agent_info.pw_vk)?; - new_agent_info.send_message(&signed_response.to_a2a_message(), &request.connection.did_doc)?; + + request.connection.did_doc.send_message(&signed_response.to_a2a_message(), &new_agent_info.pw_vk)?; Ok((signed_response, new_agent_info)) } diff --git a/libvcx/src/aries/handlers/connection/util.rs b/libvcx/src/aries/handlers/connection/util.rs index 70d50edcbb..e064838f63 100644 --- a/libvcx/src/aries/handlers/connection/util.rs +++ b/libvcx/src/aries/handlers/connection/util.rs @@ -8,7 +8,8 @@ pub fn handle_ping(ping: &Ping, agent_info: &AgentInfo, did_doc: &DidDoc) -> Vcx if ping.response_requested { let ping_response = PingResponse::create().set_thread_id( &ping.thread.as_ref().and_then(|thread| thread.thid.clone()).unwrap_or(ping.id.0.clone())); - agent_info.send_message(&ping_response.to_a2a_message(), did_doc)?; + + did_doc.send_message(&ping_response.to_a2a_message(), &agent_info.pw_vk)?; } Ok(()) } diff --git a/libvcx/src/aries/messages/connection/did_doc.rs b/libvcx/src/aries/messages/connection/did_doc.rs index 3ae4ce5814..f1066b923c 100644 --- a/libvcx/src/aries/messages/connection/did_doc.rs +++ b/libvcx/src/aries/messages/connection/did_doc.rs @@ -3,6 +3,9 @@ use crate::aries::messages::connection::invite::Invitation; use crate::error::prelude::*; use url::Url; use crate::utils::validation::validate_verkey; +use crate::aries::messages::a2a::A2AMessage; +use crate::aries::utils::encryption_envelope::EncryptionEnvelope; +use crate::utils::httpclient; pub const CONTEXT: &str = "https://w3id.org/did/v1"; pub const KEY_TYPE: &str = "Ed25519VerificationKey2018"; @@ -273,6 +276,26 @@ impl DidDoc { let pars: Vec<&str> = DidDoc::_key_parts(key_reference); pars.get(1).or(pars.get(0)).map(|s| s.to_string()).unwrap_or_default() } + + /** + Sends authenticated message to connection counterparty + */ + pub fn send_message(&self, message: &A2AMessage, sender_verkey: &str) -> VcxResult<()> { + trace!("DidDoc::send_message >>> message: {:?}, did_doc: {:?}", message, &self); + let envelope = EncryptionEnvelope::create(&message, Some(sender_verkey), &self)?; + httpclient::post_message(&envelope.0, &self.get_endpoint())?; + Ok(()) + } + + /** + Sends anonymous message to connection counterparty + */ + pub fn send_message_anonymously(&self, message: &A2AMessage) -> VcxResult<()> { + trace!("DidDoc::send_message_anonymously >>> message: {:?}, did_doc: {:?}", message, &self); + let envelope = EncryptionEnvelope::create(&message, None, &self)?; + httpclient::post_message(&envelope.0, &self.get_endpoint())?; + Ok(()) + } } impl Default for Service { diff --git a/libvcx/src/utils/httpclient.rs b/libvcx/src/utils/httpclient.rs new file mode 100644 index 0000000000..ed184f0e65 --- /dev/null +++ b/libvcx/src/utils/httpclient.rs @@ -0,0 +1,56 @@ +use std::env; +use std::io::Read; + +use reqwest; +use reqwest::header::CONTENT_TYPE; +use crate::error::{VcxError, VcxErrorKind, VcxResult}; +use crate::api::VcxStateType::VcxStateExpired; +use crate::utils::timeout::TimeoutUtils; + +pub fn post_message(body_content: &Vec, url: &str) -> VcxResult> { + //Setting SSL Certs location. This is needed on android platform. Or openssl will fail to verify the certs + if cfg!(target_os = "android") { + info!("::Android code"); + set_ssl_cert_location(); + } + let client = reqwest::ClientBuilder::new().timeout(TimeoutUtils::long_timeout()).build() + .or(Err(VcxError::from_msg(VcxErrorKind::PostMessageFailed, "Preparing Post failed")))?; + debug!("Posting encrypted bundle to: \"{}\"", url); + + let mut response = + client.post(url) + .body(body_content.to_owned()) + .header(CONTENT_TYPE, "application/ssi-agent-wire") + .send() + .map_err(|err| { + error!("error: {}", err); + VcxError::from_msg(VcxErrorKind::PostMessageFailed, format!("Could not connect {:?}", err)) + })?; + + trace!("Response Header: {:?}", response); + if !response.status().is_success() { + let mut content = String::new(); + match response.read_to_string(&mut content) { + Ok(_) => info!("Request failed: {}", content), + Err(_) => info!("could not read response"), + }; + return Err(VcxError::from_msg(VcxErrorKind::PostMessageFailed, format!("POST failed with: {}", content))); + } + + let mut content = Vec::new(); + response.read_to_end(&mut content) + .or(Err(VcxError::from_msg(VcxErrorKind::PostMessageFailed, "could not read response")))?; + + Ok(content) +} + +fn set_ssl_cert_location() { + let ssl_cert_file = "SSL_CERT_FILE"; + env::set_var(ssl_cert_file, env::var("EXTERNAL_STORAGE").unwrap() + "/cacert.pem"); //TODO: CHANGE ME, HARDCODING FOR TESTING ONLY + match env::var(ssl_cert_file) { + Ok(val) => info!("{}:: {:?}", ssl_cert_file, val), + Err(e) => error!("couldn't find var in env {}:: {}. This needs to be set on Android to make https calls.\n See https://github.com/seanmonstar/reqwest/issues/70 for more info", + ssl_cert_file, e), + } + info!("::SSL_CERT_FILE has been set"); +} \ No newline at end of file diff --git a/libvcx/src/utils/mod.rs b/libvcx/src/utils/mod.rs index d5dc251cb5..40e84f038b 100644 --- a/libvcx/src/utils/mod.rs +++ b/libvcx/src/utils/mod.rs @@ -60,6 +60,7 @@ pub mod plugins; pub mod logger; pub mod object_cache; pub mod validation; +pub mod httpclient; pub fn get_temp_dir_path(filename: &str) -> PathBuf { let mut path = env::temp_dir();