From 4cfa253ae23f1d1bc7d9f87bf37c2d671f0d536d Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Thu, 13 Jun 2024 17:45:22 +0530 Subject: [PATCH 01/65] GH-800: Write the most basic TODOs for this card --- node/src/proxy_client/stream_handler_pool.rs | 26 +++++++++++++++----- node/src/proxy_client/stream_reader.rs | 3 +++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 0c7f1f011..c6501eda8 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -40,6 +40,15 @@ pub struct StreamHandlerPoolReal { } struct StreamHandlerPoolRealInner { + // TODO: Hashmap with two senders in it + // stream_channels: HashMap + // The two senders: + // 1. writer: Box> + // 2. signal: Box> + // KillStreamSignal + // Steps to follow: + // An Actor A sends a message containing the StreamKey signaling that it wants to Kill the stream + // accountant_sub: Recipient, proxy_client_subs: ProxyClientSubs, stream_writer_channels: HashMap>>, @@ -173,6 +182,7 @@ impl StreamHandlerPoolReal { ); } + // After sending the last_data = true, wait for few seconds (maybe 5) before we delete the StreamKey fn write_and_tend( sender_wrapper: Box>, payload: ClientRequestPayload_0v1, @@ -185,14 +195,18 @@ impl StreamHandlerPoolReal { Self::perform_write(payload.sequenced_packet, sender_wrapper.clone()).and_then(move |_| { let mut inner = inner_arc.lock().expect("Stream handler pool is poisoned"); + // TODO: We want to process the payload before we perform what we're supposed to do if last_data is true. if last_data { match inner.stream_writer_channels.remove(&stream_key) { - Some(channel) => debug!( - inner.logger, - "Removing StreamWriter {:?} to {}", - stream_key, - channel.peer_addr() - ), + Some(channel) => { + debug!( + inner.logger, + "Removing StreamWriter {:?} to {}", + stream_key, + channel.peer_addr() + ) + // TODO: We want the StreamReader to shutdown here + } None => debug!( inner.logger, "Trying to remove StreamWriter {:?}, but it's already gone", stream_key diff --git a/node/src/proxy_client/stream_reader.rs b/node/src/proxy_client/stream_reader.rs index 3f3d82477..41326de2c 100644 --- a/node/src/proxy_client/stream_reader.rs +++ b/node/src/proxy_client/stream_reader.rs @@ -29,6 +29,9 @@ impl Future for StreamReader { fn poll(&mut self) -> Result::Item>, ::Error> { let mut buf: [u8; 16384] = [0; 16384]; loop { + // TODO: We should check for a message, try_receive() + // If the check is successful we want to close the Stream and complete the future. + // Async::Ready(()) can be used match self.stream.poll_read(&mut buf) { Ok(Async::NotReady) => return Ok(Async::NotReady), Ok(Async::Ready(0)) => { From 07cfef9023440af2561487d9bc62d67ee9261baf Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Tue, 25 Jun 2024 12:58:53 +0530 Subject: [PATCH 02/65] GH-800: Add todos for renaming purposes --- node/src/proxy_client/stream_handler_pool.rs | 10 ++++++---- node/src/stream_handler_pool.rs | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index c6501eda8..f8a3786d2 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -29,6 +29,8 @@ use tokio::prelude::future::{err, ok}; use trust_dns_resolver::error::ResolveError; use trust_dns_resolver::lookup_ip::LookupIp; +// TODO: GH-800 - This should be renamed to ProxyClientStreamHandlerPoolReal (or something more concise) +// to differentiate it from the other StreamHandlerPool, which, unlike this, is an actor. pub trait StreamHandlerPool { fn process_package(&self, payload: ClientRequestPayload_0v1, paying_wallet_opt: Option); } @@ -40,7 +42,7 @@ pub struct StreamHandlerPoolReal { } struct StreamHandlerPoolRealInner { - // TODO: Hashmap with two senders in it + // TODO: GH-800 - Hashmap with two senders in it // stream_channels: HashMap // The two senders: // 1. writer: Box> @@ -182,7 +184,7 @@ impl StreamHandlerPoolReal { ); } - // After sending the last_data = true, wait for few seconds (maybe 5) before we delete the StreamKey + // TODO: GH-800 - ProxyServer - after sending the last_data = true, wait for few seconds (maybe 5) before we delete the StreamKey fn write_and_tend( sender_wrapper: Box>, payload: ClientRequestPayload_0v1, @@ -195,7 +197,7 @@ impl StreamHandlerPoolReal { Self::perform_write(payload.sequenced_packet, sender_wrapper.clone()).and_then(move |_| { let mut inner = inner_arc.lock().expect("Stream handler pool is poisoned"); - // TODO: We want to process the payload before we perform what we're supposed to do if last_data is true. + // TODO: GH-800 - We want to process the payload before we perform what we're supposed to do if last_data is true. if last_data { match inner.stream_writer_channels.remove(&stream_key) { Some(channel) => { @@ -205,7 +207,7 @@ impl StreamHandlerPoolReal { stream_key, channel.peer_addr() ) - // TODO: We want the StreamReader to shutdown here + // TODO: GH-800 - We want the StreamReader to shutdown here } None => debug!( inner.logger, diff --git a/node/src/stream_handler_pool.rs b/node/src/stream_handler_pool.rs index 3d5512892..8aab602a5 100644 --- a/node/src/stream_handler_pool.rs +++ b/node/src/stream_handler_pool.rs @@ -105,6 +105,7 @@ impl Display for StreamWriterKey { } } +// TODO: GH-800 - To avoid confusion with ProxyClient's StreamHandlerPool, rename this one or the other for easy identification. // It is used to store streams for both neighbors and browser. pub struct StreamHandlerPool { stream_writers: HashMap>>>, From 62db40fd879a8ea56f88a08d950d8fa37e03470d Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Thu, 27 Jun 2024 13:07:20 +0530 Subject: [PATCH 03/65] GH-800: Add a message scheduler for purging the stream key --- node/src/proxy_server/mod.rs | 69 +++++++++++++++++++++++++++++--- node/src/sub_lib/proxy_server.rs | 8 ++++ node/src/sub_lib/utils.rs | 2 +- node/src/test_utils/recorder.rs | 5 ++- 4 files changed, 77 insertions(+), 7 deletions(-) diff --git a/node/src/proxy_server/mod.rs b/node/src/proxy_server/mod.rs index 058c7c12f..08724b2dd 100644 --- a/node/src/proxy_server/mod.rs +++ b/node/src/proxy_server/mod.rs @@ -13,6 +13,7 @@ use crate::proxy_server::client_request_payload_factory::{ use crate::proxy_server::http_protocol_pack::HttpProtocolPack; use crate::proxy_server::protocol_pack::{from_ibcd, from_protocol, ProtocolPack}; use crate::proxy_server::ExitServiceSearch::{Definite, ZeroHop}; +use crate::stream_handler_pool::StreamHandlerPool; use crate::stream_messages::NonClandestineAttributes; use crate::stream_messages::RemovedStreamType; use crate::sub_lib::accountant::RoutingServiceConsumed; @@ -29,22 +30,22 @@ use crate::sub_lib::neighborhood::{ExpectedServices, RatePack}; use crate::sub_lib::neighborhood::{NRMetadataChange, RouteQueryMessage}; use crate::sub_lib::peer_actors::BindMessage; use crate::sub_lib::proxy_client::{ClientResponsePayload_0v1, DnsResolveFailure_0v1}; -use crate::sub_lib::proxy_server::AddReturnRouteMessage; use crate::sub_lib::proxy_server::ProxyServerSubs; +use crate::sub_lib::proxy_server::{AddReturnRouteMessage, StreamKeyPurge}; use crate::sub_lib::proxy_server::{ AddRouteResultMessage, ClientRequestPayload_0v1, ProxyProtocol, }; use crate::sub_lib::route::Route; -use crate::sub_lib::stream_handler_pool::TransmitDataMsg; +use crate::sub_lib::stream_handler_pool::{DispatcherNodeQueryResponse, TransmitDataMsg}; use crate::sub_lib::stream_key::StreamKey; use crate::sub_lib::ttl_hashmap::TtlHashMap; -use crate::sub_lib::utils::{handle_ui_crash_request, NODE_MAILBOX_CAPACITY}; +use crate::sub_lib::utils::{handle_ui_crash_request, MessageScheduler, NODE_MAILBOX_CAPACITY}; use crate::sub_lib::wallet::Wallet; -use actix::Addr; use actix::Context; use actix::Handler; use actix::Recipient; use actix::{Actor, MailboxError}; +use actix::{Addr, AsyncContext}; use masq_lib::logger::Logger; use masq_lib::ui_gateway::NodeFromUiMessage; use masq_lib::utils::MutabilityConflictHelper; @@ -67,6 +68,7 @@ struct ProxyServerOutSubs { add_return_route: Recipient, stream_shutdown_sub: Recipient, route_result_sub: Recipient, + schedule_stream_key_purge: Recipient>, } pub struct ProxyServer { @@ -106,6 +108,7 @@ impl Handler for ProxyServer { add_return_route: msg.peer_actors.proxy_server.add_return_route, stream_shutdown_sub: msg.peer_actors.proxy_server.stream_shutdown_sub, route_result_sub: msg.peer_actors.proxy_server.route_result_sub, + schedule_stream_key_purge: msg.peer_actors.proxy_server.schedule_stream_key_purge, }; self.subs = Some(subs); } @@ -220,6 +223,25 @@ impl Handler for ProxyServer { } } +impl Handler for ProxyServer { + type Result = (); + + fn handle(&mut self, msg: StreamKeyPurge, ctx: &mut Self::Context) -> Self::Result { + todo!() + } +} + +impl Handler> for ProxyServer +where + ProxyServer: Handler, +{ + type Result = (); + + fn handle(&mut self, msg: MessageScheduler, ctx: &mut Self::Context) -> Self::Result { + ctx.notify_later(msg.scheduled_msg, msg.delay); + } +} + impl ProxyServer { pub fn new( main_cryptde: &'static dyn CryptDE, @@ -258,6 +280,7 @@ impl ProxyServer { stream_shutdown_sub: recipient!(addr, StreamShutdownMsg), node_from_ui: recipient!(addr, NodeFromUiMessage), route_result_sub: recipient!(addr, AddRouteResultMessage), + schedule_stream_key_purge: recipient!(addr, MessageScheduler), } } @@ -468,7 +491,18 @@ impl ProxyServer { data: response.sequenced_packet.data, }) .expect("Dispatcher is dead"); + // TODO: GH-800 - Instead send a message to retire it after 5 seconds if last_data { + // todo!("stop"); + self.subs + .as_ref() + .expect("ProxyServer Subs Unbound") + .schedule_stream_key_purge + .try_send(MessageScheduler { + scheduled_msg: StreamKeyPurge { stream_key }, + delay: Duration::from_secs(5), + }) + .expect("ProxyServer is dead"); debug!( self.logger, "Retiring stream key {}: no more data", &stream_key @@ -1379,6 +1413,7 @@ mod tests { add_return_route: recipient!(addr, AddReturnRouteMessage), stream_shutdown_sub: recipient!(addr, StreamShutdownMsg), route_result_sub: recipient!(addr, AddRouteResultMessage), + schedule_stream_key_purge: recipient!(addr, MessageScheduler), } } @@ -3633,8 +3668,14 @@ mod tests { sequenced_packet: SequencedPacket::new(vec![], 1, true), }; let (dispatcher_mock, _, _) = make_recorder(); - let peer_actors = peer_actors_builder().dispatcher(dispatcher_mock).build(); + let (proxy_server, _, proxy_server_recording_arc) = make_recorder(); + let peer_actors = peer_actors_builder() + .dispatcher(dispatcher_mock) + .proxy_server(proxy_server) + .build(); subject.subs.as_mut().unwrap().dispatcher = peer_actors.dispatcher.from_dispatcher_client; + subject.subs.as_mut().unwrap().schedule_stream_key_purge = + peer_actors.proxy_server.schedule_stream_key_purge; let expired_cores_package: ExpiredCoresPackage = ExpiredCoresPackage::new( SocketAddr::from_str("1.2.3.4:1234").unwrap(), @@ -3643,9 +3684,27 @@ mod tests { client_response_payload.into(), 0, ); + let system = + System::new("handle_client_response_payload_purges_stream_keys_for_terminal_response"); subject.handle_client_response_payload(expired_cores_package); + System::current().stop(); + system.run(); + let proxy_server_recording = proxy_server_recording_arc.lock().unwrap(); + eprintln!( + "ProxyServer Recording Length: {:?}", + proxy_server_recording.len() + ); + let schedule_stream_key_purge_msg = + proxy_server_recording.get_record::>(0); + assert_eq!( + schedule_stream_key_purge_msg, + &MessageScheduler { + scheduled_msg: StreamKeyPurge { stream_key }, + delay: Duration::from_secs(5), + } + ); assert!(subject.keys_and_addrs.is_empty()); assert!(subject.stream_key_routes.is_empty()); assert!(subject.tunneled_hosts.is_empty()); diff --git a/node/src/sub_lib/proxy_server.rs b/node/src/sub_lib/proxy_server.rs index 78c61ee72..c3042859f 100644 --- a/node/src/sub_lib/proxy_server.rs +++ b/node/src/sub_lib/proxy_server.rs @@ -9,6 +9,7 @@ use crate::sub_lib::peer_actors::BindMessage; use crate::sub_lib::proxy_client::{ClientResponsePayload_0v1, DnsResolveFailure_0v1}; use crate::sub_lib::sequence_buffer::SequencedPacket; use crate::sub_lib::stream_key::StreamKey; +use crate::sub_lib::utils::MessageScheduler; use crate::sub_lib::versioned_data::VersionedData; use actix::Message; use actix::Recipient; @@ -68,6 +69,11 @@ pub struct AddRouteResultMessage { pub result: Result, } +#[derive(Message, Debug, PartialEq, Eq)] +pub struct StreamKeyPurge { + pub stream_key: StreamKey, +} + #[derive(Clone, PartialEq, Eq)] pub struct ProxyServerSubs { // ProxyServer will handle these messages: @@ -79,6 +85,7 @@ pub struct ProxyServerSubs { pub stream_shutdown_sub: Recipient, pub node_from_ui: Recipient, pub route_result_sub: Recipient, + pub schedule_stream_key_purge: Recipient>, } impl Debug for ProxyServerSubs { @@ -110,6 +117,7 @@ mod tests { stream_shutdown_sub: recipient!(recorder, StreamShutdownMsg), node_from_ui: recipient!(recorder, NodeFromUiMessage), route_result_sub: recipient!(recorder, AddRouteResultMessage), + schedule_stream_key_purge: recipient!(recorder, MessageScheduler), }; assert_eq!(format!("{:?}", subject), "ProxyServerSubs"); diff --git a/node/src/sub_lib/utils.rs b/node/src/sub_lib/utils.rs index f6de206d7..d68d721bb 100644 --- a/node/src/sub_lib/utils.rs +++ b/node/src/sub_lib/utils.rs @@ -245,7 +245,7 @@ pub fn db_connection_launch_panic(err: InitializationError, data_directory: &Pat ) } -#[derive(Message, Clone, PartialEq, Eq)] +#[derive(Message, Debug, Clone, PartialEq, Eq)] pub struct MessageScheduler { pub scheduled_msg: M, pub delay: Duration, diff --git a/node/src/test_utils/recorder.rs b/node/src/test_utils/recorder.rs index 4219b2d08..da1aed944 100644 --- a/node/src/test_utils/recorder.rs +++ b/node/src/test_utils/recorder.rs @@ -39,7 +39,9 @@ use crate::sub_lib::peer_actors::PeerActors; use crate::sub_lib::peer_actors::{BindMessage, NewPublicIp, StartMessage}; use crate::sub_lib::proxy_client::{ClientResponsePayload_0v1, InboundServerData}; use crate::sub_lib::proxy_client::{DnsResolveFailure_0v1, ProxyClientSubs}; -use crate::sub_lib::proxy_server::{AddReturnRouteMessage, ClientRequestPayload_0v1}; +use crate::sub_lib::proxy_server::{ + AddReturnRouteMessage, ClientRequestPayload_0v1, StreamKeyPurge, +}; use crate::sub_lib::proxy_server::{AddRouteResultMessage, ProxyServerSubs}; use crate::sub_lib::stream_handler_pool::DispatcherNodeQueryResponse; use crate::sub_lib::stream_handler_pool::TransmitDataMsg; @@ -398,6 +400,7 @@ pub fn make_proxy_server_subs_from_recorder(addr: &Addr) -> ProxyServe stream_shutdown_sub: recipient!(addr, StreamShutdownMsg), node_from_ui: recipient!(addr, NodeFromUiMessage), route_result_sub: recipient!(addr, AddRouteResultMessage), + schedule_stream_key_purge: recipient!(addr, MessageScheduler), } } From e4199ae16349439f78106ea95b1fa74dbcf3e144 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Fri, 28 Jun 2024 14:04:39 +0530 Subject: [PATCH 04/65] GH-800: Improve the test handle_client_response_payload_purges_stream_keys_for_terminal_response --- node/src/proxy_server/mod.rs | 77 ++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/node/src/proxy_server/mod.rs b/node/src/proxy_server/mod.rs index 08724b2dd..88904d119 100644 --- a/node/src/proxy_server/mod.rs +++ b/node/src/proxy_server/mod.rs @@ -13,7 +13,6 @@ use crate::proxy_server::client_request_payload_factory::{ use crate::proxy_server::http_protocol_pack::HttpProtocolPack; use crate::proxy_server::protocol_pack::{from_ibcd, from_protocol, ProtocolPack}; use crate::proxy_server::ExitServiceSearch::{Definite, ZeroHop}; -use crate::stream_handler_pool::StreamHandlerPool; use crate::stream_messages::NonClandestineAttributes; use crate::stream_messages::RemovedStreamType; use crate::sub_lib::accountant::RoutingServiceConsumed; @@ -36,7 +35,7 @@ use crate::sub_lib::proxy_server::{ AddRouteResultMessage, ClientRequestPayload_0v1, ProxyProtocol, }; use crate::sub_lib::route::Route; -use crate::sub_lib::stream_handler_pool::{DispatcherNodeQueryResponse, TransmitDataMsg}; +use crate::sub_lib::stream_handler_pool::TransmitDataMsg; use crate::sub_lib::stream_key::StreamKey; use crate::sub_lib::ttl_hashmap::TtlHashMap; use crate::sub_lib::utils::{handle_ui_crash_request, MessageScheduler, NODE_MAILBOX_CAPACITY}; @@ -226,8 +225,8 @@ impl Handler for ProxyServer { impl Handler for ProxyServer { type Result = (); - fn handle(&mut self, msg: StreamKeyPurge, ctx: &mut Self::Context) -> Self::Result { - todo!() + fn handle(&mut self, msg: StreamKeyPurge, _ctx: &mut Self::Context) -> Self::Result { + self.purge_stream_key(&msg.stream_key); } } @@ -503,11 +502,6 @@ impl ProxyServer { delay: Duration::from_secs(5), }) .expect("ProxyServer is dead"); - debug!( - self.logger, - "Retiring stream key {}: no more data", &stream_key - ); - self.purge_stream_key(&stream_key); } } None => { @@ -637,6 +631,10 @@ impl ProxyServer { } fn purge_stream_key(&mut self, stream_key: &StreamKey) { + debug!( + self.logger, + "Retiring stream key {}: no more data", &stream_key + ); let _ = self.keys_and_addrs.remove_a(stream_key); let _ = self.stream_key_routes.remove(stream_key); let _ = self.tunneled_hosts.remove(stream_key); @@ -3629,7 +3627,10 @@ mod tests { #[test] fn handle_client_response_payload_purges_stream_keys_for_terminal_response() { + init_test_logging(); + let test_name = "handle_client_response_payload_purges_stream_keys_for_terminal_response"; let cryptde = main_cryptde(); + let waiting_duration_in_secs = 5; let mut subject = ProxyServer::new( cryptde, alias_cryptde(), @@ -3637,6 +3638,7 @@ mod tests { Some(STANDARD_CONSUMING_WALLET_BALANCE), false, ); + subject.logger = Logger::new(test_name); subject.subs = Some(make_proxy_server_out_subs()); let stream_key = StreamKey::make_meaningless_stream_key(); @@ -3667,15 +3669,10 @@ mod tests { stream_key: stream_key.clone(), sequenced_packet: SequencedPacket::new(vec![], 1, true), }; - let (dispatcher_mock, _, _) = make_recorder(); - let (proxy_server, _, proxy_server_recording_arc) = make_recorder(); - let peer_actors = peer_actors_builder() - .dispatcher(dispatcher_mock) - .proxy_server(proxy_server) - .build(); - subject.subs.as_mut().unwrap().dispatcher = peer_actors.dispatcher.from_dispatcher_client; - subject.subs.as_mut().unwrap().schedule_stream_key_purge = - peer_actors.proxy_server.schedule_stream_key_purge; + let proxy_server_addr = subject.start(); + let schedule_stream_key_sub = proxy_server_addr.clone().recipient(); + let mut peer_actors = peer_actors_builder().build(); + peer_actors.proxy_server.schedule_stream_key_purge = schedule_stream_key_sub; let expired_cores_package: ExpiredCoresPackage = ExpiredCoresPackage::new( SocketAddr::from_str("1.2.3.4:1234").unwrap(), @@ -3686,28 +3683,30 @@ mod tests { ); let system = System::new("handle_client_response_payload_purges_stream_keys_for_terminal_response"); - - subject.handle_client_response_payload(expired_cores_package); - - System::current().stop(); + let bind_msg = BindMessage { peer_actors }; + proxy_server_addr.try_send(bind_msg).unwrap(); + + proxy_server_addr.try_send(expired_cores_package).unwrap(); + + let assertions_msg = AssertionsMessage { + assertions: Box::new(move |proxy_server: &mut ProxyServer| { + TestLogHandler::new() + .exists_log_containing(&format!( + "DEBUG: {test_name}: Retiring stream key AAAAAAAAAAAAAAAAAAAAAAAAAAA: no more data" + )); + assert!(proxy_server.keys_and_addrs.is_empty()); + assert!(proxy_server.stream_key_routes.is_empty()); + assert!(proxy_server.tunneled_hosts.is_empty()); + System::current().stop(); + }), + }; + proxy_server_addr + .try_send(MessageScheduler { + scheduled_msg: assertions_msg, + delay: Duration::from_secs(waiting_duration_in_secs + 1), + }) + .unwrap(); system.run(); - let proxy_server_recording = proxy_server_recording_arc.lock().unwrap(); - eprintln!( - "ProxyServer Recording Length: {:?}", - proxy_server_recording.len() - ); - let schedule_stream_key_purge_msg = - proxy_server_recording.get_record::>(0); - assert_eq!( - schedule_stream_key_purge_msg, - &MessageScheduler { - scheduled_msg: StreamKeyPurge { stream_key }, - delay: Duration::from_secs(5), - } - ); - assert!(subject.keys_and_addrs.is_empty()); - assert!(subject.stream_key_routes.is_empty()); - assert!(subject.tunneled_hosts.is_empty()); } #[test] From ee8f8970c5284549ded419279136ee8ed9b01a68 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Fri, 28 Jun 2024 14:28:12 +0530 Subject: [PATCH 05/65] GH-800: Make delay configurable via constant --- node/src/proxy_server/mod.rs | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/node/src/proxy_server/mod.rs b/node/src/proxy_server/mod.rs index 88904d119..4c65289e9 100644 --- a/node/src/proxy_server/mod.rs +++ b/node/src/proxy_server/mod.rs @@ -58,6 +58,8 @@ use tokio::prelude::Future; pub const CRASH_KEY: &str = "PROXYSERVER"; pub const RETURN_ROUTE_TTL: Duration = Duration::from_secs(120); +pub const STREAM_KEY_PURGE_DELAY: Duration = Duration::from_secs(5); + struct ProxyServerOutSubs { dispatcher: Recipient, hopper: Recipient, @@ -87,6 +89,7 @@ pub struct ProxyServer { route_ids_to_return_routes: TtlHashMap, browser_proxy_sequence_offset: bool, inbound_client_data_helper_opt: Option>, + stream_key_purge_delay: Duration, } impl Actor for ProxyServer { @@ -266,6 +269,7 @@ impl ProxyServer { route_ids_to_return_routes: TtlHashMap::new(RETURN_ROUTE_TTL), browser_proxy_sequence_offset: false, inbound_client_data_helper_opt: Some(Box::new(IBCDHelperReal::new())), + stream_key_purge_delay: STREAM_KEY_PURGE_DELAY, } } @@ -490,16 +494,14 @@ impl ProxyServer { data: response.sequenced_packet.data, }) .expect("Dispatcher is dead"); - // TODO: GH-800 - Instead send a message to retire it after 5 seconds if last_data { - // todo!("stop"); self.subs .as_ref() .expect("ProxyServer Subs Unbound") .schedule_stream_key_purge .try_send(MessageScheduler { scheduled_msg: StreamKeyPurge { stream_key }, - delay: Duration::from_secs(5), + delay: self.stream_key_purge_delay, }) .expect("ProxyServer is dead"); } @@ -3630,7 +3632,8 @@ mod tests { init_test_logging(); let test_name = "handle_client_response_payload_purges_stream_keys_for_terminal_response"; let cryptde = main_cryptde(); - let waiting_duration_in_secs = 5; + let stream_key_purge_delay_in_millis = 500; + let offset_in_millis = 100; let mut subject = ProxyServer::new( cryptde, alias_cryptde(), @@ -3638,6 +3641,7 @@ mod tests { Some(STANDARD_CONSUMING_WALLET_BALANCE), false, ); + subject.stream_key_purge_delay = Duration::from_millis(stream_key_purge_delay_in_millis); subject.logger = Logger::new(test_name); subject.subs = Some(make_proxy_server_out_subs()); @@ -3688,7 +3692,20 @@ mod tests { proxy_server_addr.try_send(expired_cores_package).unwrap(); - let assertions_msg = AssertionsMessage { + let pre_assertions_msg = AssertionsMessage { + assertions: Box::new(move |proxy_server: &mut ProxyServer| { + assert!(!proxy_server.keys_and_addrs.is_empty()); + assert!(!proxy_server.stream_key_routes.is_empty()); + assert!(!proxy_server.tunneled_hosts.is_empty()); + }), + }; + proxy_server_addr + .try_send(MessageScheduler { + scheduled_msg: pre_assertions_msg, + delay: Duration::from_millis(stream_key_purge_delay_in_millis - offset_in_millis), + }) + .unwrap(); + let post_assertions_msg = AssertionsMessage { assertions: Box::new(move |proxy_server: &mut ProxyServer| { TestLogHandler::new() .exists_log_containing(&format!( @@ -3702,8 +3719,8 @@ mod tests { }; proxy_server_addr .try_send(MessageScheduler { - scheduled_msg: assertions_msg, - delay: Duration::from_secs(waiting_duration_in_secs + 1), + scheduled_msg: post_assertions_msg, + delay: Duration::from_millis(stream_key_purge_delay_in_millis + offset_in_millis), }) .unwrap(); system.run(); From 91323d47865c0877111910178cc83360c7e18981 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Tue, 2 Jul 2024 16:42:51 +0530 Subject: [PATCH 06/65] GH-800: introduce StreamSenders --- node/src/proxy_client/mod.rs | 7 +- node/src/proxy_client/stream_handler_pool.rs | 108 +++++++++++-------- 2 files changed, 68 insertions(+), 47 deletions(-) diff --git a/node/src/proxy_client/mod.rs b/node/src/proxy_client/mod.rs index d05cb505b..a4329b24f 100644 --- a/node/src/proxy_client/mod.rs +++ b/node/src/proxy_client/mod.rs @@ -30,11 +30,11 @@ use crate::sub_lib::stream_key::StreamKey; use crate::sub_lib::utils::{handle_ui_crash_request, NODE_MAILBOX_CAPACITY}; use crate::sub_lib::versioned_data::VersionedData; use crate::sub_lib::wallet::Wallet; -use actix::Actor; use actix::Addr; use actix::Context; use actix::Handler; use actix::Recipient; +use actix::{Actor, Message}; use masq_lib::logger::Logger; use masq_lib::ui_gateway::NodeFromUiMessage; use pretty_hex::PrettyHex; @@ -48,6 +48,11 @@ use trust_dns_resolver::config::ResolverOpts; pub const CRASH_KEY: &str = "PROXYCLIENT"; +#[derive(Message)] +struct StopListeningForThisStream { + stream_key: StreamKey, +} + pub struct ProxyClient { dns_servers: Vec, resolver_wrapper_factory: Box, diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index f8a3786d2..f9c9d317d 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -13,7 +13,7 @@ use crate::sub_lib::proxy_server::ClientRequestPayload_0v1; use crate::sub_lib::sequence_buffer::SequencedPacket; use crate::sub_lib::stream_key::StreamKey; use crate::sub_lib::wallet::Wallet; -use actix::Recipient; +use actix::{Message, Recipient}; use crossbeam_channel::{unbounded, Receiver}; use futures::future; use futures::future::Future; @@ -41,6 +41,11 @@ pub struct StreamHandlerPoolReal { stream_killer_rx: Receiver<(StreamKey, u64)>, } +pub struct StreamSenders { + pub writer_data: Box>, + pub reader_shutdown: Box>, +} + struct StreamHandlerPoolRealInner { // TODO: GH-800 - Hashmap with two senders in it // stream_channels: HashMap @@ -53,7 +58,7 @@ struct StreamHandlerPoolRealInner { // accountant_sub: Recipient, proxy_client_subs: ProxyClientSubs, - stream_writer_channels: HashMap>>, + stream_writer_channels: HashMap, resolver: Box, logger: Logger, establisher_factory: Box, @@ -174,7 +179,7 @@ impl StreamHandlerPoolReal { debug!( inner.logger, "Removing stream writer for {}", - sender_wrapper.peer_addr() + sender_wrapper.writer_data.peer_addr() ); } Self::send_terminating_package( @@ -184,7 +189,6 @@ impl StreamHandlerPoolReal { ); } - // TODO: GH-800 - ProxyServer - after sending the last_data = true, wait for few seconds (maybe 5) before we delete the StreamKey fn write_and_tend( sender_wrapper: Box>, payload: ClientRequestPayload_0v1, @@ -205,8 +209,9 @@ impl StreamHandlerPoolReal { inner.logger, "Removing StreamWriter {:?} to {}", stream_key, - channel.peer_addr() - ) + channel.writer_data.peer_addr() + ); + todo!("") // TODO: GH-800 - We want the StreamReader to shutdown here } None => debug!( @@ -401,7 +406,8 @@ impl StreamHandlerPoolReal { ) -> Option>> { let inner = inner_arc.lock().expect("Stream handler pool is poisoned"); let sender_wrapper_opt = inner.stream_writer_channels.get(stream_key); - sender_wrapper_opt.map(|sender_wrapper_box_ref| sender_wrapper_box_ref.as_ref().clone()) + sender_wrapper_opt + .map(|sender_wrapper_box_ref| sender_wrapper_box_ref.writer_data.as_ref().clone()) } fn make_logger_copy(inner_arc: &Arc>) -> Logger { @@ -454,14 +460,14 @@ impl StreamHandlerPoolReal { stream_key, last_data: true, sequence_number, - source: writer_channel.peer_addr(), + source: writer_channel.writer_data.peer_addr(), data: vec![], }) .expect("ProxyClient is dead"); debug!( inner.logger, "Killed StreamWriter to {} and sent server-drop report", - writer_channel.peer_addr() + writer_channel.writer_data.peer_addr() ) } None => debug!( @@ -478,15 +484,16 @@ impl StreamHandlerPoolReal { match self.stream_adder_rx.try_recv() { Err(_) => break, Ok((stream_key, stream_writer_channel)) => { - debug!( - inner.logger, - "Persisting StreamWriter to {} under key {:?}", - stream_writer_channel.peer_addr(), - stream_key - ); - inner - .stream_writer_channels - .insert(stream_key, stream_writer_channel) + todo!("GH-800: Fix it such that the stream_adder_rx holds StreamSenders"); + // debug!( + // inner.logger, + // "Persisting StreamWriter to {} under key {:?}", + // stream_writer_channel.peer_addr(), + // stream_key + // ); + // inner + // .stream_writer_channels + // .insert(stream_key, stream_writer_channel) } }; } @@ -535,7 +542,7 @@ mod tests { use crate::proxy_client::local_test_utils::make_send_error; use crate::proxy_client::local_test_utils::ResolverWrapperMock; use crate::proxy_client::stream_establisher::StreamEstablisher; - use crate::sub_lib::channel_wrappers::FuturesChannelFactoryReal; + use crate::sub_lib::channel_wrappers::{FuturesChannelFactoryReal, SenderWrapperReal}; use crate::sub_lib::cryptde::PublicKey; use crate::sub_lib::hopper::ExpiredCoresPackage; use crate::sub_lib::hopper::MessageType; @@ -674,8 +681,9 @@ mod tests { originator_public_key: PublicKey::new(&b"men's souls"[..]), }; let write_parameters = Arc::new(Mutex::new(vec![])); + let peer_addr = SocketAddr::from_str("1.2.3.4:5678").unwrap(); let tx_to_write = Box::new( - SenderWrapperMock::new(SocketAddr::from_str("1.2.3.4:5678").unwrap()) + SenderWrapperMock::new(peer_addr) .unbounded_send_result(Ok(())) .unbounded_send_params(&write_parameters), ); @@ -698,12 +706,13 @@ mod tests { 100, 200, ); - subject - .inner - .lock() - .unwrap() - .stream_writer_channels - .insert(stream_key, tx_to_write); + subject.inner.lock().unwrap().stream_writer_channels.insert( + stream_key, + StreamSenders { + writer_data: tx_to_write, + reader_shutdown: Box::new(SenderWrapperMock::new(peer_addr)), + }, + ); run_process_package_in_actix(subject, package); }); @@ -745,11 +754,10 @@ mod tests { let peer_actors = peer_actors_builder().proxy_client(proxy_client).build(); let resolver = ResolverWrapperMock::new() .lookup_ip_success(vec![IpAddr::from_str("2.3.4.5").unwrap()]); - - let tx_to_write = SenderWrapperMock::new(SocketAddr::from_str("2.3.4.5:80").unwrap()) - .unbounded_send_result(make_send_error( - client_request_payload.sequenced_packet.clone(), - )); + let peer_addr = SocketAddr::from_str("2.3.4.5:80").unwrap(); + let tx_to_write = SenderWrapperMock::new(peer_addr).unbounded_send_result( + make_send_error(client_request_payload.sequenced_packet.clone()), + ); let subject = StreamHandlerPoolReal::new( Box::new(resolver), @@ -759,12 +767,13 @@ mod tests { 100, 200, ); - subject - .inner - .lock() - .unwrap() - .stream_writer_channels - .insert(client_request_payload.stream_key, Box::new(tx_to_write)); + subject.inner.lock().unwrap().stream_writer_channels.insert( + client_request_payload.stream_key, + StreamSenders { + writer_data: Box::new(tx_to_write), + reader_shutdown: Box::new(SenderWrapperMock::new(peer_addr)), + }, + ); run_process_package_in_actix(subject, package); }); @@ -1626,12 +1635,15 @@ mod tests { 100, 200, ); - subject - .inner - .lock() - .unwrap() - .stream_writer_channels - .insert(stream_key, Box::new(sender_wrapper)); + subject.inner.lock().unwrap().stream_writer_channels.insert( + stream_key, + StreamSenders { + writer_data: Box::new(sender_wrapper), + reader_shutdown: Box::new(SenderWrapperMock::new( + SocketAddr::from_str("2.3.4.5:6789").unwrap(), + )), // irrelevant + }, + ); run_process_package_in_actix(subject, package); }); @@ -1727,9 +1739,13 @@ mod tests { let peer_addr = SocketAddr::from_str("1.2.3.4:5678").unwrap(); { let mut inner = subject.inner.lock().unwrap(); - inner - .stream_writer_channels - .insert(stream_key, Box::new(SenderWrapperMock::new(peer_addr))); + inner.stream_writer_channels.insert( + stream_key, + StreamSenders { + writer_data: Box::new(SenderWrapperMock::new(peer_addr)), + reader_shutdown: Box::new(SenderWrapperMock::new(peer_addr)), // irrelevant + }, + ); } stream_killer_tx.send((stream_key, 47)).unwrap(); From 7cc2fbb676f380b124c7cbe440d72efaf8600260 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Thu, 4 Jul 2024 16:26:16 +0530 Subject: [PATCH 07/65] GH-800: introduce channel for shutdown signal --- node/src/proxy_client/stream_establisher.rs | 28 ++++++++++--- node/src/proxy_client/stream_handler_pool.rs | 43 +++++++++++--------- node/src/proxy_client/stream_reader.rs | 12 +++++- 3 files changed, 56 insertions(+), 27 deletions(-) diff --git a/node/src/proxy_client/stream_establisher.rs b/node/src/proxy_client/stream_establisher.rs index f25d7a9fe..a262746b7 100644 --- a/node/src/proxy_client/stream_establisher.rs +++ b/node/src/proxy_client/stream_establisher.rs @@ -1,10 +1,11 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. +use crate::proxy_client::stream_handler_pool::StreamSenders; use crate::proxy_client::stream_reader::StreamReader; use crate::proxy_client::stream_writer::StreamWriter; -use crate::sub_lib::channel_wrappers::FuturesChannelFactory; use crate::sub_lib::channel_wrappers::FuturesChannelFactoryReal; use crate::sub_lib::channel_wrappers::SenderWrapper; +use crate::sub_lib::channel_wrappers::{FuturesChannelFactory, SenderWrapperReal}; use crate::sub_lib::cryptde::CryptDE; use crate::sub_lib::proxy_client::{InboundServerData, ProxyClientSubs}; use crate::sub_lib::proxy_server::ClientRequestPayload_0v1; @@ -14,7 +15,7 @@ use crate::sub_lib::stream_connector::StreamConnectorReal; use crate::sub_lib::stream_key::StreamKey; use crate::sub_lib::tokio_wrappers::ReadHalfWrapper; use actix::Recipient; -use crossbeam_channel::Sender; +use crossbeam_channel::{unbounded, Receiver, Sender}; use masq_lib::logger::Logger; use std::io; use std::net::IpAddr; @@ -22,8 +23,9 @@ use std::net::SocketAddr; pub struct StreamEstablisher { pub cryptde: &'static dyn CryptDE, - pub stream_adder_tx: Sender<(StreamKey, Box>)>, + pub stream_adder_tx: Sender<(StreamKey, StreamSenders)>, pub stream_killer_tx: Sender<(StreamKey, u64)>, + pub shutdown_signal_rx: Receiver<()>, pub stream_connector: Box, pub proxy_client_sub: Recipient, pub logger: Logger, @@ -36,6 +38,7 @@ impl Clone for StreamEstablisher { cryptde: self.cryptde, stream_adder_tx: self.stream_adder_tx.clone(), stream_killer_tx: self.stream_killer_tx.clone(), + shutdown_signal_rx: unbounded().1, stream_connector: Box::new(StreamConnectorReal {}), proxy_client_sub: self.proxy_client_sub.clone(), logger: self.logger.clone(), @@ -58,10 +61,14 @@ impl StreamEstablisher { &self.logger, )?; + // TODO: GH-800: Test Drive Me + let (shutdown_signal_tx, shutdown_signal_rx) = unbounded(); + self.spawn_stream_reader( &payload.clone(), connection_info.reader, connection_info.peer_addr, + shutdown_signal_rx, ); let (tx_to_write, rx_to_write) = self.channel_factory.make(connection_info.peer_addr); @@ -73,8 +80,14 @@ impl StreamEstablisher { ); tokio::spawn(stream_writer); + // TODO: GH-800: Test Drive Me + let stream_senders = StreamSenders { + writer_data: tx_to_write.clone(), + reader_shutdown: shutdown_signal_tx, + }; + self.stream_adder_tx - .send((payload.stream_key, tx_to_write.clone())) + .send((payload.stream_key, stream_senders)) .expect("StreamHandlerPool died"); Ok(tx_to_write) } @@ -84,12 +97,14 @@ impl StreamEstablisher { payload: &ClientRequestPayload_0v1, read_stream: Box, peer_addr: SocketAddr, + shutdown_signal: Receiver<()>, ) { let stream_reader = StreamReader::new( payload.stream_key, self.proxy_client_sub.clone(), read_stream, self.stream_killer_tx.clone(), + shutdown_signal, peer_addr, ); debug!(self.logger, "Spawning StreamReader for {}", peer_addr); @@ -103,7 +118,7 @@ pub trait StreamEstablisherFactory: Send { pub struct StreamEstablisherFactoryReal { pub cryptde: &'static dyn CryptDE, - pub stream_adder_tx: Sender<(StreamKey, Box>)>, + pub stream_adder_tx: Sender<(StreamKey, StreamSenders)>, pub stream_killer_tx: Sender<(StreamKey, u64)>, pub proxy_client_subs: ProxyClientSubs, pub logger: Logger, @@ -115,6 +130,7 @@ impl StreamEstablisherFactory for StreamEstablisherFactoryReal { cryptde: self.cryptde, stream_adder_tx: self.stream_adder_tx.clone(), stream_killer_tx: self.stream_killer_tx.clone(), + shutdown_signal_rx: unbounded().1, stream_connector: Box::new(StreamConnectorReal {}), proxy_client_sub: self.proxy_client_subs.inbound_server_data.clone(), logger: self.logger.clone(), @@ -171,6 +187,7 @@ mod tests { cryptde: main_cryptde(), stream_adder_tx, stream_killer_tx, + shutdown_signal_rx: unbounded().1, stream_connector: Box::new(StreamConnectorMock::new()), // only used in "establish_stream" proxy_client_sub, logger: Logger::new("ProxyClient"), @@ -191,6 +208,7 @@ mod tests { }, read_stream, SocketAddr::from_str("1.2.3.4:5678").unwrap(), + unbounded().1, ); proxy_client_awaiter.await_message_count(1); diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index f9c9d317d..b0119da14 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -14,7 +14,7 @@ use crate::sub_lib::sequence_buffer::SequencedPacket; use crate::sub_lib::stream_key::StreamKey; use crate::sub_lib::wallet::Wallet; use actix::{Message, Recipient}; -use crossbeam_channel::{unbounded, Receiver}; +use crossbeam_channel::{unbounded, Receiver, Sender}; use futures::future; use futures::future::Future; use masq_lib::logger::Logger; @@ -37,21 +37,17 @@ pub trait StreamHandlerPool { pub struct StreamHandlerPoolReal { inner: Arc>, - stream_adder_rx: Receiver<(StreamKey, Box>)>, + stream_adder_rx: Receiver<(StreamKey, StreamSenders)>, stream_killer_rx: Receiver<(StreamKey, u64)>, } pub struct StreamSenders { pub writer_data: Box>, - pub reader_shutdown: Box>, + pub reader_shutdown: Sender<()>, } struct StreamHandlerPoolRealInner { // TODO: GH-800 - Hashmap with two senders in it - // stream_channels: HashMap - // The two senders: - // 1. writer: Box> - // 2. signal: Box> // KillStreamSignal // Steps to follow: // An Actor A sends a message containing the StreamKey signaling that it wants to Kill the stream @@ -204,14 +200,16 @@ impl StreamHandlerPoolReal { // TODO: GH-800 - We want to process the payload before we perform what we're supposed to do if last_data is true. if last_data { match inner.stream_writer_channels.remove(&stream_key) { - Some(channel) => { + Some(stream_senders) => { debug!( inner.logger, "Removing StreamWriter {:?} to {}", stream_key, - channel.writer_data.peer_addr() + stream_senders.writer_data.peer_addr() ); - todo!("") + // You need not to use expect(), _ is sufficient, you may use match in case you want to log it because it might be already gone + todo!("Try stream_senders.reader_shutdown.unbounded_send(()) ") + // TODO: GH-800 - We want the StreamReader to shutdown here } None => debug!( @@ -483,17 +481,17 @@ impl StreamHandlerPoolReal { loop { match self.stream_adder_rx.try_recv() { Err(_) => break, - Ok((stream_key, stream_writer_channel)) => { - todo!("GH-800: Fix it such that the stream_adder_rx holds StreamSenders"); + Ok((stream_key, stream_senders)) => { + // todo!("GH-800: Fix it such that the stream_adder_rx holds StreamSenders"); // debug!( // inner.logger, // "Persisting StreamWriter to {} under key {:?}", - // stream_writer_channel.peer_addr(), + // stream_senders.writer_data.peer_addr(), // stream_key // ); // inner // .stream_writer_channels - // .insert(stream_key, stream_writer_channel) + // .insert(stream_key, stream_senders) } }; } @@ -618,6 +616,7 @@ mod tests { cryptde, stream_adder_tx: unbounded().0, stream_killer_tx: unbounded().0, + shutdown_signal_rx: unbounded().1, stream_connector: Box::new(StreamConnectorMock::new()), proxy_client_sub: peer_actors .proxy_client_opt @@ -710,7 +709,7 @@ mod tests { stream_key, StreamSenders { writer_data: tx_to_write, - reader_shutdown: Box::new(SenderWrapperMock::new(peer_addr)), + reader_shutdown: unbounded().0, }, ); @@ -771,7 +770,7 @@ mod tests { client_request_payload.stream_key, StreamSenders { writer_data: Box::new(tx_to_write), - reader_shutdown: Box::new(SenderWrapperMock::new(peer_addr)), + reader_shutdown: unbounded().0, }, ); @@ -859,6 +858,7 @@ mod tests { cryptde, stream_adder_tx, stream_killer_tx, + shutdown_signal_rx: unbounded().1, stream_connector: Box::new(StreamConnectorMock::new().with_connection( peer_addr.clone(), peer_addr.clone(), @@ -968,6 +968,7 @@ mod tests { cryptde, stream_adder_tx, stream_killer_tx, + shutdown_signal_rx: unbounded().1, stream_connector: Box::new(StreamConnectorMock::new().with_connection( peer_addr.clone(), peer_addr.clone(), @@ -1147,6 +1148,7 @@ mod tests { cryptde, stream_adder_tx, stream_killer_tx, + shutdown_signal_rx: unbounded().1, stream_connector: Box::new(StreamConnectorMock::new().with_connection( peer_addr.clone(), peer_addr.clone(), @@ -1247,6 +1249,7 @@ mod tests { cryptde, stream_adder_tx, stream_killer_tx, + shutdown_signal_rx: unbounded().1, stream_connector: Box::new( StreamConnectorMock::new() .connect_pair_result(Err(Error::from(ErrorKind::Other))), @@ -1369,6 +1372,7 @@ mod tests { cryptde, stream_adder_tx, stream_killer_tx, + shutdown_signal_rx: unbounded().1, stream_connector: Box::new( StreamConnectorMock::new() .connect_pair_result(Err(Error::from(ErrorKind::Other))), @@ -1485,6 +1489,7 @@ mod tests { cryptde, stream_adder_tx, stream_killer_tx, + shutdown_signal_rx: unbounded().1, stream_connector: Box::new( StreamConnectorMock::new() .with_connection(peer_addr, peer_addr, reader, writer), @@ -1639,9 +1644,7 @@ mod tests { stream_key, StreamSenders { writer_data: Box::new(sender_wrapper), - reader_shutdown: Box::new(SenderWrapperMock::new( - SocketAddr::from_str("2.3.4.5:6789").unwrap(), - )), // irrelevant + reader_shutdown: unbounded().0, }, ); @@ -1743,7 +1746,7 @@ mod tests { stream_key, StreamSenders { writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown: Box::new(SenderWrapperMock::new(peer_addr)), // irrelevant + reader_shutdown: unbounded().0, }, ); } diff --git a/node/src/proxy_client/stream_reader.rs b/node/src/proxy_client/stream_reader.rs index 41326de2c..394764e98 100644 --- a/node/src/proxy_client/stream_reader.rs +++ b/node/src/proxy_client/stream_reader.rs @@ -6,7 +6,7 @@ use crate::sub_lib::tokio_wrappers::ReadHalfWrapper; use crate::sub_lib::utils; use crate::sub_lib::utils::indicates_dead_stream; use actix::Recipient; -use crossbeam_channel::Sender; +use crossbeam_channel::{Receiver, Sender}; use masq_lib::logger::Logger; use std::net::SocketAddr; use tokio::prelude::Async; @@ -17,6 +17,7 @@ pub struct StreamReader { proxy_client_sub: Recipient, stream: Box, stream_killer: Sender<(StreamKey, u64)>, + shutdown_signal: Receiver<()>, peer_addr: SocketAddr, logger: Logger, sequencer: Sequencer, @@ -29,7 +30,8 @@ impl Future for StreamReader { fn poll(&mut self) -> Result::Item>, ::Error> { let mut buf: [u8; 16384] = [0; 16384]; loop { - // TODO: We should check for a message, try_receive() + // TODO: GH-800: If there is a message waiting log the message with the info!() and break out of the loop + // TODO: We should check for self.shutdown_signal.try_recv() // If the check is successful we want to close the Stream and complete the future. // Async::Ready(()) can be used match self.stream.poll_read(&mut buf) { @@ -85,6 +87,7 @@ impl StreamReader { proxy_client_sub: Recipient, stream: Box, stream_killer: Sender<(StreamKey, u64)>, + shutdown_signal: Receiver<()>, peer_addr: SocketAddr, ) -> StreamReader { StreamReader { @@ -92,6 +95,7 @@ impl StreamReader { proxy_client_sub, stream, stream_killer, + shutdown_signal, peer_addr, logger: Logger::new(&format!("StreamReader for {:?}/{}", stream_key, peer_addr)[..]), sequencer: Sequencer::new(), @@ -178,6 +182,7 @@ mod tests { proxy_client_sub, stream, stream_killer, + shutdown_signal: unbounded().1, peer_addr: SocketAddr::from_str("8.7.4.3:50").unwrap(), logger: Logger::new("test"), sequencer: Sequencer::new(), @@ -261,6 +266,7 @@ mod tests { proxy_client_sub, stream: Box::new(stream), stream_killer, + shutdown_signal: unbounded().1, peer_addr: SocketAddr::from_str("5.7.9.0:95").unwrap(), logger: Logger::new("test"), sequencer: Sequencer::new(), @@ -331,6 +337,7 @@ mod tests { proxy_client_sub: peer_actors.proxy_client_opt.unwrap().inbound_server_data, stream: Box::new(stream), stream_killer, + shutdown_signal: unbounded().1, peer_addr: SocketAddr::from_str("5.3.4.3:654").unwrap(), logger: Logger::new("test"), sequencer, @@ -379,6 +386,7 @@ mod tests { proxy_client_sub, stream: Box::new(stream), stream_killer, + shutdown_signal: unbounded().1, peer_addr: SocketAddr::from_str("6.5.4.1:8325").unwrap(), logger: Logger::new("test"), sequencer: Sequencer::new(), From d7841570dd280e045729017f11aadb20bcbd9973 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Sat, 6 Jul 2024 20:08:43 +0530 Subject: [PATCH 08/65] GH-800: add test connection_shutdown_test.rs --- node/src/proxy_client/stream_establisher.rs | 6 +- node/src/proxy_client/stream_handler_pool.rs | 3 + node/src/proxy_client/stream_reader.rs | 2 + node/tests/connection_shutdown_test.rs | 70 ++++++++++++++++++++ 4 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 node/tests/connection_shutdown_test.rs diff --git a/node/src/proxy_client/stream_establisher.rs b/node/src/proxy_client/stream_establisher.rs index a262746b7..3d02477e9 100644 --- a/node/src/proxy_client/stream_establisher.rs +++ b/node/src/proxy_client/stream_establisher.rs @@ -62,7 +62,10 @@ impl StreamEstablisher { )?; // TODO: GH-800: Test Drive Me - let (shutdown_signal_tx, shutdown_signal_rx) = unbounded(); + // let (shutdown_signal_tx, shutdown_signal_rx) = unbounded(); + + let shutdown_signal_tx = unbounded().0; + let shutdown_signal_rx = unbounded().1; self.spawn_stream_reader( &payload.clone(), @@ -80,7 +83,6 @@ impl StreamEstablisher { ); tokio::spawn(stream_writer); - // TODO: GH-800: Test Drive Me let stream_senders = StreamSenders { writer_data: tx_to_write.clone(), reader_shutdown: shutdown_signal_tx, diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index b0119da14..3f0d6b96c 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -462,6 +462,8 @@ impl StreamHandlerPoolReal { data: vec![], }) .expect("ProxyClient is dead"); + // TODO: GH-800: Send a signal to the reader_shutdown + // Test should have a fake server, and the (read and write should be different) server debug!( inner.logger, "Killed StreamWriter to {} and sent server-drop report", @@ -819,6 +821,7 @@ mod tests { client_request_payload.into(), 0, ); + // TODO: GH-800: Apparently, we can remove both lookup_ip mock functions let resolver = ResolverWrapperMock::new() .lookup_ip_parameters(&lookup_ip_parameters) .lookup_ip_success(vec![ diff --git a/node/src/proxy_client/stream_reader.rs b/node/src/proxy_client/stream_reader.rs index 394764e98..f7241a6ff 100644 --- a/node/src/proxy_client/stream_reader.rs +++ b/node/src/proxy_client/stream_reader.rs @@ -27,6 +27,8 @@ impl Future for StreamReader { type Item = (); type Error = (); + // Unit test: Create StreamReader and call poll(), it should check return value - return Ok(Async::Ready(())); + // stream.poll_read_results = vec![] fn poll(&mut self) -> Result::Item>, ::Error> { let mut buf: [u8; 16384] = [0; 16384]; loop { diff --git a/node/tests/connection_shutdown_test.rs b/node/tests/connection_shutdown_test.rs new file mode 100644 index 000000000..41b47f701 --- /dev/null +++ b/node/tests/connection_shutdown_test.rs @@ -0,0 +1,70 @@ +// Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. + +pub mod utils; + +use crossbeam_channel::{unbounded, Sender}; +use masq_lib::utils::find_free_port; +use node_lib::test_utils::read_until_timeout; +use std::io::{Read, Write}; +use std::net::{IpAddr, TcpListener, TcpStream}; +use std::net::{Shutdown, SocketAddr}; +use std::str::FromStr; +use std::time::{Duration, Instant}; +use std::{io, thread}; + +// 'node' below must not be named '_' alone or disappear, or the MASQNode will be immediately reclaimed. +#[test] +fn proxy_client_stream_reader_dies_when_client_stream_is_killed_integration() { + let _node = utils::MASQNode::start_standard( + "proxy_client_stream_reader_dies_when_client_stream_is_killed_integration", + None, + true, + true, + false, + true, + ); + let (write_error_tx, write_error_rx) = unbounded(); + let server_port = find_free_port(); + thread::spawn(move || { + endless_write_server(server_port, write_error_tx); + }); + let mut stream = TcpStream::connect(SocketAddr::from_str("127.0.0.1:80").unwrap()).unwrap(); + stream + .set_read_timeout(Some(Duration::from_millis(1000))) + .unwrap(); + let request = format!("GET / HTTP/1.1\r\nHost: 127.0.0.1:{server_port}\r\n\r\n"); + + stream.write(request.as_bytes()).unwrap(); + let mut buf = [0u8; 16384]; + // We want to make sure the Server is sending before we shutdown the stream + stream.read(&mut buf).unwrap(); + stream.shutdown(Shutdown::Write).unwrap(); + let write_error = write_error_rx.recv_timeout(Duration::from_secs(5)).unwrap(); + + assert_eq!(write_error.kind(), io::ErrorKind::ConnectionAborted); +} + +fn endless_write_server(port: u16, write_error_tx: Sender) { + let listener = TcpListener::bind(SocketAddr::new( + IpAddr::from_str("127.0.0.1").unwrap(), + port, + )) + .unwrap(); + let mut buf = [0u8; 16_384]; + let (mut stream, _) = listener.accept().unwrap(); + let _ = stream.read(&mut buf).unwrap(); + stream + .write("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n".as_bytes()) + .unwrap(); + let msg = "Chancellor on brink of second bailout for banks"; + let msg_len = msg.len(); + let chunk_body = format!("{msg_len}\r\n{msg}\r\n"); + loop { + if let Err(e) = stream.write(chunk_body.as_bytes()) { + write_error_tx.send(e).unwrap(); + break; + } + + thread::sleep(Duration::from_millis(250)); + } +} From 14a5de3e10c3e6e3dbae76ae91fee264e11e81ae Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 10 Jul 2024 16:03:28 +0530 Subject: [PATCH 09/65] GH-800: test drive the shutdown signal in StreamReader --- node/src/proxy_client/stream_handler_pool.rs | 2 + node/src/proxy_client/stream_reader.rs | 39 ++++++++++++++++---- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 3f0d6b96c..db9b97f09 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -35,6 +35,8 @@ pub trait StreamHandlerPool { fn process_package(&self, payload: ClientRequestPayload_0v1, paying_wallet_opt: Option); } +// TODO: GH-800: We don't need to keep StreamSenders at two places here, one in stream_adder_rx, +// and the other in inner -> stream_writer_channels pub struct StreamHandlerPoolReal { inner: Arc>, stream_adder_rx: Receiver<(StreamKey, StreamSenders)>, diff --git a/node/src/proxy_client/stream_reader.rs b/node/src/proxy_client/stream_reader.rs index f7241a6ff..7e6c4400b 100644 --- a/node/src/proxy_client/stream_reader.rs +++ b/node/src/proxy_client/stream_reader.rs @@ -6,7 +6,7 @@ use crate::sub_lib::tokio_wrappers::ReadHalfWrapper; use crate::sub_lib::utils; use crate::sub_lib::utils::indicates_dead_stream; use actix::Recipient; -use crossbeam_channel::{Receiver, Sender}; +use crossbeam_channel::{Receiver, Sender, TryRecvError}; use masq_lib::logger::Logger; use std::net::SocketAddr; use tokio::prelude::Async; @@ -27,15 +27,13 @@ impl Future for StreamReader { type Item = (); type Error = (); - // Unit test: Create StreamReader and call poll(), it should check return value - return Ok(Async::Ready(())); - // stream.poll_read_results = vec![] fn poll(&mut self) -> Result::Item>, ::Error> { let mut buf: [u8; 16384] = [0; 16384]; loop { - // TODO: GH-800: If there is a message waiting log the message with the info!() and break out of the loop - // TODO: We should check for self.shutdown_signal.try_recv() - // If the check is successful we want to close the Stream and complete the future. - // Async::Ready(()) can be used + if self.shutdown_signal.try_recv().is_ok() { + info!(self.logger, "Received shutdown signal"); + return Ok(Async::Ready(())); + } match self.stream.poll_read(&mut buf) { Ok(Async::NotReady) => return Ok(Async::NotReady), Ok(Async::Ready(0)) => { @@ -413,4 +411,31 @@ mod tests { } ); } + + #[test] + fn stream_reader_shuts_down_when_it_receives_the_shutdown_signal() { + init_test_logging(); + let proxy_client_sub = peer_actors_builder() + .build() + .proxy_client_opt + .unwrap() + .inbound_server_data; + let (shutdown_tx, shutdown_rx) = unbounded(); + let mut subject = StreamReader { + stream_key: StreamKey::make_meaningless_stream_key(), + proxy_client_sub, + stream: Box::new(ReadHalfWrapperMock::new()), + stream_killer: unbounded().0, + shutdown_signal: shutdown_rx, + peer_addr: SocketAddr::from_str("6.5.4.1:8325").unwrap(), + logger: Logger::new("test"), + sequencer: Sequencer::new(), + }; + + shutdown_tx.send(()).unwrap(); + + let result = subject.poll(); + assert_eq!(result, Ok(Async::Ready(()))); + TestLogHandler::new().exists_log_containing("Received shutdown signal"); + } } From d8d1f102db6fe2b7189303e9a2bc778f45954957 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 10 Jul 2024 16:46:37 +0530 Subject: [PATCH 10/65] GH-800: refactor test stream_reader_shuts_down_when_it_receives_the_shutdown_signal --- node/src/proxy_client/stream_reader.rs | 43 ++++++++++++++++---------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/node/src/proxy_client/stream_reader.rs b/node/src/proxy_client/stream_reader.rs index 7e6c4400b..f2a04d868 100644 --- a/node/src/proxy_client/stream_reader.rs +++ b/node/src/proxy_client/stream_reader.rs @@ -327,14 +327,13 @@ mod tests { stream.poll_read_results = vec![(vec![], Ok(Async::Ready(0)))]; let system = System::new("receiving_0_bytes_sends_empty_cores_response_and_kills_stream"); - let peer_actors = peer_actors_builder().build(); let mut sequencer = Sequencer::new(); sequencer.next_sequence_number(); sequencer.next_sequence_number(); let mut subject = StreamReader { stream_key, - proxy_client_sub: peer_actors.proxy_client_opt.unwrap().inbound_server_data, + proxy_client_sub: make_proxy_client_sub(), stream: Box::new(stream), stream_killer, shutdown_signal: unbounded().1, @@ -415,27 +414,37 @@ mod tests { #[test] fn stream_reader_shuts_down_when_it_receives_the_shutdown_signal() { init_test_logging(); - let proxy_client_sub = peer_actors_builder() - .build() - .proxy_client_opt - .unwrap() - .inbound_server_data; + let test_name = "stream_reader_shuts_down_when_it_receives_the_shutdown_signal"; let (shutdown_tx, shutdown_rx) = unbounded(); - let mut subject = StreamReader { + let mut subject = make_subject(); + subject.shutdown_signal = shutdown_rx; + subject.logger = Logger::new(test_name); + + shutdown_tx.send(()).unwrap(); + + assert_eq!(subject.poll(), Ok(Async::Ready(()))); + TestLogHandler::new() + .exists_log_containing(&format!("INFO: {test_name}: Received shutdown signal")); + } + + pub fn make_subject() -> StreamReader { + StreamReader { stream_key: StreamKey::make_meaningless_stream_key(), - proxy_client_sub, + proxy_client_sub: make_proxy_client_sub(), stream: Box::new(ReadHalfWrapperMock::new()), stream_killer: unbounded().0, - shutdown_signal: shutdown_rx, - peer_addr: SocketAddr::from_str("6.5.4.1:8325").unwrap(), + shutdown_signal: unbounded().1, + peer_addr: SocketAddr::from_str("9.8.7.6:5432").unwrap(), logger: Logger::new("test"), sequencer: Sequencer::new(), - }; - - shutdown_tx.send(()).unwrap(); + } + } - let result = subject.poll(); - assert_eq!(result, Ok(Async::Ready(()))); - TestLogHandler::new().exists_log_containing("Received shutdown signal"); + pub fn make_proxy_client_sub() -> Recipient { + peer_actors_builder() + .build() + .proxy_client_opt + .unwrap() + .inbound_server_data } } From ddf7d9c27b191989fa7636179e17c0accae62ff5 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 10 Jul 2024 17:41:38 +0530 Subject: [PATCH 11/65] GH-800: some refactor inside the file stream_reader --- node/src/proxy_client/stream_reader.rs | 57 +++++++++++++------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/node/src/proxy_client/stream_reader.rs b/node/src/proxy_client/stream_reader.rs index f2a04d868..9e326a4f8 100644 --- a/node/src/proxy_client/stream_reader.rs +++ b/node/src/proxy_client/stream_reader.rs @@ -261,16 +261,12 @@ mod tests { }); let proxy_client_sub = rx.recv().unwrap(); let (stream_killer, stream_killer_params) = unbounded(); - let mut subject = StreamReader { - stream_key: StreamKey::make_meaningless_stream_key(), - proxy_client_sub, - stream: Box::new(stream), - stream_killer, - shutdown_signal: unbounded().1, - peer_addr: SocketAddr::from_str("5.7.9.0:95").unwrap(), - logger: Logger::new("test"), - sequencer: Sequencer::new(), - }; + let peer_addr = SocketAddr::from_str("5.7.9.0:95").unwrap(); + let mut subject = make_subject(); + subject.proxy_client_sub = proxy_client_sub; + subject.stream = Box::new(stream); + subject.stream_killer = stream_killer; + subject.peer_addr = peer_addr; let result = subject.poll(); @@ -283,7 +279,7 @@ mod tests { stream_key: StreamKey::make_meaningless_stream_key(), last_data: false, sequence_number: 0, - source: SocketAddr::from_str("5.7.9.0:95").unwrap(), + source: peer_addr, data: b"HTTP/1.1 200".to_vec() } ); @@ -293,7 +289,7 @@ mod tests { stream_key: StreamKey::make_meaningless_stream_key(), last_data: false, sequence_number: 1, - source: SocketAddr::from_str("5.7.9.0:95").unwrap(), + source: peer_addr, data: b" OK\r\n\r\nHTTP/1.1 40".to_vec() } ); @@ -303,7 +299,7 @@ mod tests { stream_key: StreamKey::make_meaningless_stream_key(), last_data: false, sequence_number: 2, - source: SocketAddr::from_str("5.7.9.0:95").unwrap(), + source: peer_addr, data: b"4 File not found\r\n\r\nHTTP/1.1 503 Server error\r\n\r\n".to_vec() } ); @@ -321,12 +317,13 @@ mod tests { #[test] fn receiving_0_bytes_kills_stream() { init_test_logging(); + let test_name = "receiving_0_bytes_kills_stream"; let stream_key = StreamKey::make_meaningless_stream_key(); let (stream_killer, kill_stream_params) = unbounded(); let mut stream = ReadHalfWrapperMock::new(); stream.poll_read_results = vec![(vec![], Ok(Async::Ready(0)))]; - - let system = System::new("receiving_0_bytes_sends_empty_cores_response_and_kills_stream"); + let peer_addr = SocketAddr::from_str("5.3.4.3:654").unwrap(); + let system = System::new(test_name); let mut sequencer = Sequencer::new(); sequencer.next_sequence_number(); sequencer.next_sequence_number(); @@ -337,33 +334,36 @@ mod tests { stream: Box::new(stream), stream_killer, shutdown_signal: unbounded().1, - peer_addr: SocketAddr::from_str("5.3.4.3:654").unwrap(), - logger: Logger::new("test"), + peer_addr, + logger: Logger::new(test_name), sequencer, }; - System::current().stop_with_code(0); + System::current().stop(); system.run(); let result = subject.poll(); assert_eq!(result, Ok(Async::Ready(()))); assert_eq!(kill_stream_params.try_recv().unwrap(), (stream_key, 2)); - TestLogHandler::new() - .exists_log_containing("Stream from 5.3.4.3:654 was closed: (0-byte read)"); + TestLogHandler::new().exists_log_containing(&format!( + "DEBUG: {test_name}: Stream from 5.3.4.3:654 was closed: (0-byte read)" + )); } #[test] fn non_dead_stream_read_errors_log_but_do_not_shut_down() { init_test_logging(); + let test_name = "non_dead_stream_read_errors_log_but_do_not_shut_down"; let (proxy_client, proxy_client_awaiter, proxy_client_recording_arc) = make_recorder(); let stream_key = StreamKey::make_meaningless_stream_key(); let (stream_killer, _) = unbounded(); let mut stream = ReadHalfWrapperMock::new(); + let http_response = b"HTTP/1.1 200 OK\r\n\r\n"; stream.poll_read_results = vec![ (vec![], Err(Error::from(ErrorKind::Other))), ( - Vec::from(&b"HTTP/1.1 200 OK\r\n\r\n"[..]), - Ok(Async::Ready(b"HTTP/1.1 200 OK\r\n\r\n".len())), + http_response.to_vec(), + Ok(Async::Ready(http_response.len())), ), (vec![], Err(Error::from(ErrorKind::BrokenPipe))), ]; @@ -380,14 +380,15 @@ mod tests { }); let proxy_client_sub = rx.recv().unwrap(); + let peer_addr = SocketAddr::from_str("6.5.4.1:8325").unwrap(); let mut subject = StreamReader { stream_key, proxy_client_sub, stream: Box::new(stream), stream_killer, shutdown_signal: unbounded().1, - peer_addr: SocketAddr::from_str("6.5.4.1:8325").unwrap(), - logger: Logger::new("test"), + peer_addr, + logger: Logger::new(test_name), sequencer: Sequencer::new(), }; @@ -396,17 +397,17 @@ mod tests { assert_eq!(result, Err(())); proxy_client_awaiter.await_message_count(1); TestLogHandler::new().exists_log_containing( - "WARN: test: Continuing after read error on stream from 6.5.4.1:8325: other error", + &format!("WARN: {test_name}: Continuing after read error on stream from {peer_addr}: other error"), ); let proxy_client_recording = proxy_client_recording_arc.lock().unwrap(); assert_eq!( proxy_client_recording.get_record::(0), &InboundServerData { - stream_key: StreamKey::make_meaningless_stream_key(), + stream_key, last_data: false, sequence_number: 0, - source: SocketAddr::from_str("6.5.4.1:8325").unwrap(), - data: b"HTTP/1.1 200 OK\r\n\r\n".to_vec() + source: peer_addr, + data: http_response.to_vec() } ); } From a6f25386ab4cb23356e519717e09a1aa90f47539 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 10 Jul 2024 18:05:59 +0530 Subject: [PATCH 12/65] GH-800: some more refactoring --- node/src/proxy_client/stream_reader.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/node/src/proxy_client/stream_reader.rs b/node/src/proxy_client/stream_reader.rs index 9e326a4f8..ff7f22f06 100644 --- a/node/src/proxy_client/stream_reader.rs +++ b/node/src/proxy_client/stream_reader.rs @@ -127,7 +127,7 @@ mod tests { use crate::test_utils::recorder::make_recorder; use crate::test_utils::recorder::peer_actors_builder; use crate::test_utils::tokio_wrapper_mocks::ReadHalfWrapperMock; - use actix::System; + use actix::{Actor, System}; use crossbeam_channel::unbounded; use masq_lib::test_utils::logging::init_test_logging; use masq_lib::test_utils::logging::TestLogHandler; @@ -330,7 +330,7 @@ mod tests { let mut subject = StreamReader { stream_key, - proxy_client_sub: make_proxy_client_sub(), + proxy_client_sub: make_recorder().0.start().recipient(), stream: Box::new(stream), stream_killer, shutdown_signal: unbounded().1, @@ -346,7 +346,7 @@ mod tests { assert_eq!(result, Ok(Async::Ready(()))); assert_eq!(kill_stream_params.try_recv().unwrap(), (stream_key, 2)); TestLogHandler::new().exists_log_containing(&format!( - "DEBUG: {test_name}: Stream from 5.3.4.3:654 was closed: (0-byte read)" + "DEBUG: {test_name}: Stream from {peer_addr} was closed: (0-byte read)" )); } @@ -431,7 +431,7 @@ mod tests { pub fn make_subject() -> StreamReader { StreamReader { stream_key: StreamKey::make_meaningless_stream_key(), - proxy_client_sub: make_proxy_client_sub(), + proxy_client_sub: make_recorder().0.start().recipient(), stream: Box::new(ReadHalfWrapperMock::new()), stream_killer: unbounded().0, shutdown_signal: unbounded().1, @@ -440,12 +440,4 @@ mod tests { sequencer: Sequencer::new(), } } - - pub fn make_proxy_client_sub() -> Recipient { - peer_actors_builder() - .build() - .proxy_client_opt - .unwrap() - .inbound_server_data - } } From 130a37c92b70f41c7ccab9b2e1ebd95f34e712c8 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Thu, 11 Jul 2024 16:59:46 +0530 Subject: [PATCH 13/65] GH-800: trying_to_write_a_test_for_stream_senders was a success --- node/src/proxy_client/stream_handler_pool.rs | 128 ++++++++++++++++++- node/src/proxy_client/stream_reader.rs | 11 +- node/tests/connection_shutdown_test.rs | 2 +- 3 files changed, 132 insertions(+), 9 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index db9b97f09..9db102b99 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -49,11 +49,6 @@ pub struct StreamSenders { } struct StreamHandlerPoolRealInner { - // TODO: GH-800 - Hashmap with two senders in it - // KillStreamSignal - // Steps to follow: - // An Actor A sends a message containing the StreamKey signaling that it wants to Kill the stream - // accountant_sub: Recipient, proxy_client_subs: ProxyClientSubs, stream_writer_channels: HashMap, @@ -198,9 +193,11 @@ impl StreamHandlerPoolReal { let payload_size = payload.sequenced_packet.data.len(); Self::perform_write(payload.sequenced_packet, sender_wrapper.clone()).and_then(move |_| { + eprintln!("executing perform_write"); let mut inner = inner_arc.lock().expect("Stream handler pool is poisoned"); // TODO: GH-800 - We want to process the payload before we perform what we're supposed to do if last_data is true. if last_data { + eprintln!("last_data = true detected"); match inner.stream_writer_channels.remove(&stream_key) { Some(stream_senders) => { debug!( @@ -905,6 +902,127 @@ mod tests { ); } + #[test] + fn trying_to_write_a_test_for_stream_senders() { + let cryptde = main_cryptde(); + let lookup_ip_parameters = Arc::new(Mutex::new(vec![])); + let expected_lookup_ip_parameters = lookup_ip_parameters.clone(); + let write_parameters = Arc::new(Mutex::new(vec![])); + let expected_write_parameters = write_parameters.clone(); + let (proxy_client, proxy_client_awaiter, proxy_client_recording_arc) = make_recorder(); + thread::spawn(move || { + let peer_actors = peer_actors_builder().proxy_client(proxy_client).build(); + let stream_key = StreamKey::make_meaningful_stream_key("i should die"); + let client_request_payload = ClientRequestPayload_0v1 { + stream_key, + sequenced_packet: SequencedPacket { + data: b"These are the times".to_vec(), + sequence_number: 0, + last_data: true, + }, + target_hostname: Some(String::from("3.4.5.6:80")), + target_port: HTTP_PORT, + protocol: ProxyProtocol::HTTP, + originator_public_key: PublicKey::new(&b"men's souls"[..]), + }; + let package = ExpiredCoresPackage::new( + SocketAddr::from_str("1.2.3.4:1234").unwrap(), + Some(make_wallet("consuming")), + make_meaningless_route(), + client_request_payload.into(), + 0, + ); + // TODO: GH-800: Apparently, we can remove both lookup_ip mock functions + let resolver = ResolverWrapperMock::new() + .lookup_ip_parameters(&lookup_ip_parameters) + .lookup_ip_success(vec![ + IpAddr::from_str("2.3.4.5").unwrap(), + IpAddr::from_str("3.4.5.6").unwrap(), + ]); + let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); + let first_read_result = b"HTTP/1.1 200 OK\r\n\r\n"; + let reader = ReadHalfWrapperMock { + poll_read_results: vec![ + ( + first_read_result.to_vec(), + Ok(Async::Ready(first_read_result.len())), + ), + (vec![], Err(Error::from(ErrorKind::ConnectionAborted))), + ], + }; + let writer = WriteHalfWrapperMock { + poll_write_params: write_parameters, + poll_write_results: vec![Ok(Async::Ready(first_read_result.len()))], + // Vec, io::Error>>; + shutdown_results: Arc::new(Mutex::new(vec![Ok(Async::Ready(()))])), + }; + let mut subject = StreamHandlerPoolReal::new( + Box::new(resolver), + cryptde, + peer_actors.accountant.report_exit_service_provided.clone(), + peer_actors.proxy_client_opt.unwrap().clone(), + 100, + 200, + ); + let (stream_killer_tx, stream_killer_rx) = unbounded(); + subject.stream_killer_rx = stream_killer_rx; + let (stream_adder_tx, _stream_adder_rx) = unbounded(); + let (shutdown_tx, shutdown_rx) = unbounded(); + { + let mut inner = subject.inner.lock().unwrap(); + inner.stream_writer_channels.insert( + stream_key, + StreamSenders { + writer_data: Box::new(SenderWrapperMock::new(peer_addr)), + reader_shutdown: shutdown_tx, + }, + ); + let establisher = StreamEstablisher { + cryptde, + stream_adder_tx, + stream_killer_tx, + shutdown_signal_rx: shutdown_rx, + stream_connector: Box::new(StreamConnectorMock::new().with_connection( + peer_addr.clone(), + peer_addr.clone(), + reader, + writer, + )), + proxy_client_sub: inner.proxy_client_subs.inbound_server_data.clone(), + logger: inner.logger.clone(), + channel_factory: Box::new(FuturesChannelFactoryReal {}), + }; + + inner.establisher_factory = Box::new(StreamEstablisherFactoryMock { + make_results: RefCell::new(vec![establisher]), + }); + } + + run_process_package_in_actix(subject, package); + }); + + proxy_client_awaiter.await_message_count(1); + assert_eq!( + expected_lookup_ip_parameters.lock().unwrap().deref(), + &(vec![] as Vec) + ); + assert_eq!( + expected_write_parameters.lock().unwrap().remove(0), + b"These are the times".to_vec() + ); + let proxy_client_recording = proxy_client_recording_arc.lock().unwrap(); + assert_eq!( + proxy_client_recording.get_record::(0), + &InboundServerData { + stream_key: StreamKey::make_meaningless_stream_key(), + last_data: false, + sequence_number: 0, + source: SocketAddr::from_str("3.4.5.6:80").unwrap(), + data: b"HTTP/1.1 200 OK\r\n\r\n".to_vec(), + } + ); + } + #[test] fn ip_is_parsed_even_without_port() { let cryptde = main_cryptde(); diff --git a/node/src/proxy_client/stream_reader.rs b/node/src/proxy_client/stream_reader.rs index ff7f22f06..b8f49deaf 100644 --- a/node/src/proxy_client/stream_reader.rs +++ b/node/src/proxy_client/stream_reader.rs @@ -31,7 +31,10 @@ impl Future for StreamReader { let mut buf: [u8; 16384] = [0; 16384]; loop { if self.shutdown_signal.try_recv().is_ok() { - info!(self.logger, "Received shutdown signal"); + info!( + self.logger, + "Shutting down for stream: {:?}", self.stream_key + ); return Ok(Async::Ready(())); } match self.stream.poll_read(&mut buf) { @@ -424,8 +427,10 @@ mod tests { shutdown_tx.send(()).unwrap(); assert_eq!(subject.poll(), Ok(Async::Ready(()))); - TestLogHandler::new() - .exists_log_containing(&format!("INFO: {test_name}: Received shutdown signal")); + TestLogHandler::new().exists_log_containing(&format!( + "INFO: {test_name}: Shutting down for stream: {:?}", + subject.stream_key + )); } pub fn make_subject() -> StreamReader { diff --git a/node/tests/connection_shutdown_test.rs b/node/tests/connection_shutdown_test.rs index 41b47f701..205224fe5 100644 --- a/node/tests/connection_shutdown_test.rs +++ b/node/tests/connection_shutdown_test.rs @@ -39,7 +39,7 @@ fn proxy_client_stream_reader_dies_when_client_stream_is_killed_integration() { // We want to make sure the Server is sending before we shutdown the stream stream.read(&mut buf).unwrap(); stream.shutdown(Shutdown::Write).unwrap(); - let write_error = write_error_rx.recv_timeout(Duration::from_secs(5)).unwrap(); + let write_error = write_error_rx.recv_timeout(Duration::from_secs(5)).unwrap(); // TODO: GH-800 We are failing on this timeout assert_eq!(write_error.kind(), io::ErrorKind::ConnectionAborted); } From 6db4c0c0ef199b06dcb128ba6d10af7482b23362 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Fri, 12 Jul 2024 13:27:38 +0530 Subject: [PATCH 14/65] GH-800: did some refactoring for trying_to_write_a_test_for_stream_senders --- node/src/proxy_client/stream_handler_pool.rs | 35 ++++++-------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 9db102b99..73e7f0cbd 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -537,6 +537,7 @@ impl StreamHandlerPoolFactory for StreamHandlerPoolFactoryReal { #[cfg(test)] mod tests { use super::*; + use crate::match_every_type_id; use crate::node_test_utils::check_timestamp; use crate::proxy_client::local_test_utils::make_send_error; use crate::proxy_client::local_test_utils::ResolverWrapperMock; @@ -555,10 +556,13 @@ mod tests { use crate::test_utils::make_wallet; use crate::test_utils::recorder::make_recorder; use crate::test_utils::recorder::peer_actors_builder; + use crate::test_utils::recorder_stop_conditions::StopCondition; + use crate::test_utils::recorder_stop_conditions::StopConditions; use crate::test_utils::stream_connector_mock::StreamConnectorMock; use crate::test_utils::tokio_wrapper_mocks::ReadHalfWrapperMock; use crate::test_utils::tokio_wrapper_mocks::WriteHalfWrapperMock; use actix::System; + use core::any::TypeId; use masq_lib::constants::HTTP_PORT; use masq_lib::test_utils::logging::init_test_logging; use masq_lib::test_utils::logging::TestLogHandler; @@ -905,11 +909,11 @@ mod tests { #[test] fn trying_to_write_a_test_for_stream_senders() { let cryptde = main_cryptde(); - let lookup_ip_parameters = Arc::new(Mutex::new(vec![])); - let expected_lookup_ip_parameters = lookup_ip_parameters.clone(); let write_parameters = Arc::new(Mutex::new(vec![])); let expected_write_parameters = write_parameters.clone(); - let (proxy_client, proxy_client_awaiter, proxy_client_recording_arc) = make_recorder(); + let (proxy_client, _, proxy_client_recording_arc) = make_recorder(); + let proxy_client = + proxy_client.system_stop_conditions(match_every_type_id!(InboundServerData)); thread::spawn(move || { let peer_actors = peer_actors_builder().proxy_client(proxy_client).build(); let stream_key = StreamKey::make_meaningful_stream_key("i should die"); @@ -933,12 +937,6 @@ mod tests { 0, ); // TODO: GH-800: Apparently, we can remove both lookup_ip mock functions - let resolver = ResolverWrapperMock::new() - .lookup_ip_parameters(&lookup_ip_parameters) - .lookup_ip_success(vec![ - IpAddr::from_str("2.3.4.5").unwrap(), - IpAddr::from_str("3.4.5.6").unwrap(), - ]); let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); let first_read_result = b"HTTP/1.1 200 OK\r\n\r\n"; let reader = ReadHalfWrapperMock { @@ -957,16 +955,13 @@ mod tests { shutdown_results: Arc::new(Mutex::new(vec![Ok(Async::Ready(()))])), }; let mut subject = StreamHandlerPoolReal::new( - Box::new(resolver), + Box::new(ResolverWrapperMock::new()), cryptde, peer_actors.accountant.report_exit_service_provided.clone(), peer_actors.proxy_client_opt.unwrap().clone(), 100, 200, ); - let (stream_killer_tx, stream_killer_rx) = unbounded(); - subject.stream_killer_rx = stream_killer_rx; - let (stream_adder_tx, _stream_adder_rx) = unbounded(); let (shutdown_tx, shutdown_rx) = unbounded(); { let mut inner = subject.inner.lock().unwrap(); @@ -979,8 +974,8 @@ mod tests { ); let establisher = StreamEstablisher { cryptde, - stream_adder_tx, - stream_killer_tx, + stream_adder_tx: unbounded().0, + stream_killer_tx: unbounded().0, shutdown_signal_rx: shutdown_rx, stream_connector: Box::new(StreamConnectorMock::new().with_connection( peer_addr.clone(), @@ -1000,16 +995,6 @@ mod tests { run_process_package_in_actix(subject, package); }); - - proxy_client_awaiter.await_message_count(1); - assert_eq!( - expected_lookup_ip_parameters.lock().unwrap().deref(), - &(vec![] as Vec) - ); - assert_eq!( - expected_write_parameters.lock().unwrap().remove(0), - b"These are the times".to_vec() - ); let proxy_client_recording = proxy_client_recording_arc.lock().unwrap(); assert_eq!( proxy_client_recording.get_record::(0), From c3cc6a89780651f3d0869d075548c83ff0201b66 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Thu, 18 Jul 2024 12:30:23 +0530 Subject: [PATCH 15/65] GH-800: stream_handler_pool_sends_shutdown_signal_when_last_data_is_true passes for the first time --- node/src/proxy_client/stream_handler_pool.rs | 47 ++++++++++++-------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 73e7f0cbd..6a43402b8 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -43,6 +43,7 @@ pub struct StreamHandlerPoolReal { stream_killer_rx: Receiver<(StreamKey, u64)>, } +#[derive(Debug)] pub struct StreamSenders { pub writer_data: Box>, pub reader_shutdown: Sender<()>, @@ -200,21 +201,28 @@ impl StreamHandlerPoolReal { eprintln!("last_data = true detected"); match inner.stream_writer_channels.remove(&stream_key) { Some(stream_senders) => { + eprintln!("Removed stream key: {:?}", stream_key); + stream_senders.reader_shutdown.send(()).unwrap(); + todo!("stop please"); debug!( inner.logger, "Removing StreamWriter {:?} to {}", stream_key, stream_senders.writer_data.peer_addr() ); + // You need not to use expect(), _ is sufficient, you may use match in case you want to log it because it might be already gone todo!("Try stream_senders.reader_shutdown.unbounded_send(()) ") // TODO: GH-800 - We want the StreamReader to shutdown here } - None => debug!( - inner.logger, - "Trying to remove StreamWriter {:?}, but it's already gone", stream_key - ), + None => { + eprintln!("Failed to Remove stream key: {:?}", stream_key); + debug!( + inner.logger, + "Trying to remove StreamWriter {:?}, but it's already gone", stream_key + ) + } } } if payload_size > 0 { @@ -907,13 +915,14 @@ mod tests { } #[test] - fn trying_to_write_a_test_for_stream_senders() { + fn stream_handler_pool_sends_shutdown_signal_when_last_data_is_true() { let cryptde = main_cryptde(); let write_parameters = Arc::new(Mutex::new(vec![])); let expected_write_parameters = write_parameters.clone(); let (proxy_client, _, proxy_client_recording_arc) = make_recorder(); let proxy_client = proxy_client.system_stop_conditions(match_every_type_id!(InboundServerData)); + let (shutdown_tx, shutdown_rx) = unbounded(); thread::spawn(move || { let peer_actors = peer_actors_builder().proxy_client(proxy_client).build(); let stream_key = StreamKey::make_meaningful_stream_key("i should die"); @@ -962,7 +971,6 @@ mod tests { 100, 200, ); - let (shutdown_tx, shutdown_rx) = unbounded(); { let mut inner = subject.inner.lock().unwrap(); inner.stream_writer_channels.insert( @@ -976,7 +984,7 @@ mod tests { cryptde, stream_adder_tx: unbounded().0, stream_killer_tx: unbounded().0, - shutdown_signal_rx: shutdown_rx, + shutdown_signal_rx: unbounded().1, stream_connector: Box::new(StreamConnectorMock::new().with_connection( peer_addr.clone(), peer_addr.clone(), @@ -995,17 +1003,20 @@ mod tests { run_process_package_in_actix(subject, package); }); - let proxy_client_recording = proxy_client_recording_arc.lock().unwrap(); - assert_eq!( - proxy_client_recording.get_record::(0), - &InboundServerData { - stream_key: StreamKey::make_meaningless_stream_key(), - last_data: false, - sequence_number: 0, - source: SocketAddr::from_str("3.4.5.6:80").unwrap(), - data: b"HTTP/1.1 200 OK\r\n\r\n".to_vec(), - } - ); + let received = shutdown_rx.recv(); + assert_eq!(received, Ok(())); + + // let proxy_client_recording = proxy_client_recording_arc.lock().unwrap(); + // assert_eq!( + // proxy_client_recording.get_record::(0), + // &InboundServerData { + // stream_key: StreamKey::make_meaningless_stream_key(), + // last_data: false, + // sequence_number: 0, + // source: SocketAddr::from_str("3.4.5.6:80").unwrap(), + // data: b"HTTP/1.1 200 OK\r\n\r\n".to_vec(), + // } + // ); } #[test] From 75edd8f4272de259e44434d564ec8a545547ff10 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Thu, 18 Jul 2024 12:45:53 +0530 Subject: [PATCH 16/65] GH-800: Minor refactor for the test stream_handler_pool_sends_shutdown_signal_when_last_data_is_true --- node/src/proxy_client/stream_handler_pool.rs | 41 ++++++-------------- 1 file changed, 11 insertions(+), 30 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 6a43402b8..74afcb413 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -202,19 +202,17 @@ impl StreamHandlerPoolReal { match inner.stream_writer_channels.remove(&stream_key) { Some(stream_senders) => { eprintln!("Removed stream key: {:?}", stream_key); - stream_senders.reader_shutdown.send(()).unwrap(); - todo!("stop please"); + stream_senders + .reader_shutdown + .send(()) + .expect("StreamReader Shutdown channel is already gone"); + // TODO: GH-800: Should it be a log instead of expect? debug!( inner.logger, - "Removing StreamWriter {:?} to {}", + "Removing StreamWriter and Shutting down StreamReader for {:?} to {}", stream_key, stream_senders.writer_data.peer_addr() ); - - // You need not to use expect(), _ is sufficient, you may use match in case you want to log it because it might be already gone - todo!("Try stream_senders.reader_shutdown.unbounded_send(()) ") - - // TODO: GH-800 - We want the StreamReader to shutdown here } None => { eprintln!("Failed to Remove stream key: {:?}", stream_key); @@ -916,27 +914,22 @@ mod tests { #[test] fn stream_handler_pool_sends_shutdown_signal_when_last_data_is_true() { - let cryptde = main_cryptde(); - let write_parameters = Arc::new(Mutex::new(vec![])); - let expected_write_parameters = write_parameters.clone(); - let (proxy_client, _, proxy_client_recording_arc) = make_recorder(); - let proxy_client = - proxy_client.system_stop_conditions(match_every_type_id!(InboundServerData)); let (shutdown_tx, shutdown_rx) = unbounded(); thread::spawn(move || { - let peer_actors = peer_actors_builder().proxy_client(proxy_client).build(); + let cryptde = main_cryptde(); + let peer_actors = peer_actors_builder().build(); let stream_key = StreamKey::make_meaningful_stream_key("i should die"); let client_request_payload = ClientRequestPayload_0v1 { stream_key, sequenced_packet: SequencedPacket { - data: b"These are the times".to_vec(), + data: b"I'm gonna kill you stream key".to_vec(), sequence_number: 0, last_data: true, }, target_hostname: Some(String::from("3.4.5.6:80")), target_port: HTTP_PORT, protocol: ProxyProtocol::HTTP, - originator_public_key: PublicKey::new(&b"men's souls"[..]), + originator_public_key: PublicKey::new(&b"brutal death"[..]), }; let package = ExpiredCoresPackage::new( SocketAddr::from_str("1.2.3.4:1234").unwrap(), @@ -958,7 +951,7 @@ mod tests { ], }; let writer = WriteHalfWrapperMock { - poll_write_params: write_parameters, + poll_write_params: Arc::new(Mutex::new(vec![])), poll_write_results: vec![Ok(Async::Ready(first_read_result.len()))], // Vec, io::Error>>; shutdown_results: Arc::new(Mutex::new(vec![Ok(Async::Ready(()))])), @@ -1005,18 +998,6 @@ mod tests { }); let received = shutdown_rx.recv(); assert_eq!(received, Ok(())); - - // let proxy_client_recording = proxy_client_recording_arc.lock().unwrap(); - // assert_eq!( - // proxy_client_recording.get_record::(0), - // &InboundServerData { - // stream_key: StreamKey::make_meaningless_stream_key(), - // last_data: false, - // sequence_number: 0, - // source: SocketAddr::from_str("3.4.5.6:80").unwrap(), - // data: b"HTTP/1.1 200 OK\r\n\r\n".to_vec(), - // } - // ); } #[test] From 296f44983a8a3208faac7446fd178fa84de6f11f Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Thu, 18 Jul 2024 16:07:27 +0530 Subject: [PATCH 17/65] GH-800: more refactoring of the test stream_handler_pool_sends_shutdown_signal_when_last_data_is_true --- node/src/proxy_client/stream_handler_pool.rs | 41 +------------------- 1 file changed, 2 insertions(+), 39 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 74afcb413..f9c875cd5 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -916,8 +916,6 @@ mod tests { fn stream_handler_pool_sends_shutdown_signal_when_last_data_is_true() { let (shutdown_tx, shutdown_rx) = unbounded(); thread::spawn(move || { - let cryptde = main_cryptde(); - let peer_actors = peer_actors_builder().build(); let stream_key = StreamKey::make_meaningful_stream_key("i should die"); let client_request_payload = ClientRequestPayload_0v1 { stream_key, @@ -938,27 +936,11 @@ mod tests { client_request_payload.into(), 0, ); - // TODO: GH-800: Apparently, we can remove both lookup_ip mock functions let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); - let first_read_result = b"HTTP/1.1 200 OK\r\n\r\n"; - let reader = ReadHalfWrapperMock { - poll_read_results: vec![ - ( - first_read_result.to_vec(), - Ok(Async::Ready(first_read_result.len())), - ), - (vec![], Err(Error::from(ErrorKind::ConnectionAborted))), - ], - }; - let writer = WriteHalfWrapperMock { - poll_write_params: Arc::new(Mutex::new(vec![])), - poll_write_results: vec![Ok(Async::Ready(first_read_result.len()))], - // Vec, io::Error>>; - shutdown_results: Arc::new(Mutex::new(vec![Ok(Async::Ready(()))])), - }; + let peer_actors = peer_actors_builder().build(); let mut subject = StreamHandlerPoolReal::new( Box::new(ResolverWrapperMock::new()), - cryptde, + main_cryptde(), peer_actors.accountant.report_exit_service_provided.clone(), peer_actors.proxy_client_opt.unwrap().clone(), 100, @@ -973,25 +955,6 @@ mod tests { reader_shutdown: shutdown_tx, }, ); - let establisher = StreamEstablisher { - cryptde, - stream_adder_tx: unbounded().0, - stream_killer_tx: unbounded().0, - shutdown_signal_rx: unbounded().1, - stream_connector: Box::new(StreamConnectorMock::new().with_connection( - peer_addr.clone(), - peer_addr.clone(), - reader, - writer, - )), - proxy_client_sub: inner.proxy_client_subs.inbound_server_data.clone(), - logger: inner.logger.clone(), - channel_factory: Box::new(FuturesChannelFactoryReal {}), - }; - - inner.establisher_factory = Box::new(StreamEstablisherFactoryMock { - make_results: RefCell::new(vec![establisher]), - }); } run_process_package_in_actix(subject, package); From a2c763d9e6e12e1840de64b953d3cf6414145e55 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Thu, 18 Jul 2024 16:17:40 +0530 Subject: [PATCH 18/65] GH-800: stream_handler_pool_sends_shutdown_signal_when_last_data_is_true is working fine --- node/src/proxy_client/stream_handler_pool.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index f9c875cd5..0f69e5f51 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -914,9 +914,10 @@ mod tests { #[test] fn stream_handler_pool_sends_shutdown_signal_when_last_data_is_true() { + init_test_logging(); let (shutdown_tx, shutdown_rx) = unbounded(); thread::spawn(move || { - let stream_key = StreamKey::make_meaningful_stream_key("i should die"); + let stream_key = StreamKey::make_meaningful_stream_key("I should die"); let client_request_payload = ClientRequestPayload_0v1 { stream_key, sequenced_packet: SequencedPacket { @@ -961,6 +962,11 @@ mod tests { }); let received = shutdown_rx.recv(); assert_eq!(received, Ok(())); + TestLogHandler::new().await_log_containing( + "Removing StreamWriter and Shutting down StreamReader \ + for 8vVp1ZyZaZzRXCPNdf1OSE1bCVs to 3.4.5.6:80", + 100, + ); } #[test] From 3c223ea022177e2cb9b81cc021073b7b8a41812d Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Thu, 18 Jul 2024 16:47:22 +0530 Subject: [PATCH 19/65] GH-800: some more todos removed --- node/src/proxy_client/stream_handler_pool.rs | 60 ++++++++++---------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 0f69e5f51..a15ec4967 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -194,19 +194,34 @@ impl StreamHandlerPoolReal { let payload_size = payload.sequenced_packet.data.len(); Self::perform_write(payload.sequenced_packet, sender_wrapper.clone()).and_then(move |_| { - eprintln!("executing perform_write"); let mut inner = inner_arc.lock().expect("Stream handler pool is poisoned"); - // TODO: GH-800 - We want to process the payload before we perform what we're supposed to do if last_data is true. + if payload_size > 0 { + match paying_wallet_opt { + Some(wallet) => inner + .accountant_sub + .try_send(ReportExitServiceProvidedMessage { + timestamp: SystemTime::now(), + paying_wallet: wallet, + payload_size, + service_rate: inner.exit_service_rate, + byte_rate: inner.exit_byte_rate, + }) + .expect("Accountant is dead"), + // This log is here mostly for testing, to prove that no Accountant message is sent in the no-wallet case + None => debug!( + inner.logger, + "Sent {}-byte request without consuming wallet for free", payload_size + ), + } + } if last_data { - eprintln!("last_data = true detected"); match inner.stream_writer_channels.remove(&stream_key) { Some(stream_senders) => { - eprintln!("Removed stream key: {:?}", stream_key); stream_senders .reader_shutdown .send(()) .expect("StreamReader Shutdown channel is already gone"); - // TODO: GH-800: Should it be a log instead of expect? + // TODO: GH-800: Should it be a log instead debug!( inner.logger, "Removing StreamWriter and Shutting down StreamReader for {:?} to {}", @@ -223,25 +238,7 @@ impl StreamHandlerPoolReal { } } } - if payload_size > 0 { - match paying_wallet_opt { - Some(wallet) => inner - .accountant_sub - .try_send(ReportExitServiceProvidedMessage { - timestamp: SystemTime::now(), - paying_wallet: wallet, - payload_size, - service_rate: inner.exit_service_rate, - byte_rate: inner.exit_byte_rate, - }) - .expect("Accountant is dead"), - // This log is here mostly for testing, to prove that no Accountant message is sent in the no-wallet case - None => debug!( - inner.logger, - "Sent {}-byte request without consuming wallet for free", payload_size - ), - } - } + Ok(()) }) } @@ -455,7 +452,7 @@ impl StreamHandlerPoolReal { let mut inner = self.inner.lock().expect("Stream handler pool is poisoned"); while let Ok((stream_key, sequence_number)) = self.stream_killer_rx.try_recv() { match inner.stream_writer_channels.remove(&stream_key) { - Some(writer_channel) => { + Some(stream_senders) => { inner .proxy_client_subs .inbound_server_data @@ -463,16 +460,18 @@ impl StreamHandlerPoolReal { stream_key, last_data: true, sequence_number, - source: writer_channel.writer_data.peer_addr(), + source: stream_senders.writer_data.peer_addr(), data: vec![], }) .expect("ProxyClient is dead"); - // TODO: GH-800: Send a signal to the reader_shutdown + if let Err(e) = stream_senders.reader_shutdown.send(()) { + todo!("test drive me"); + }; // Test should have a fake server, and the (read and write should be different) server debug!( inner.logger, "Killed StreamWriter to {} and sent server-drop report", - writer_channel.writer_data.peer_addr() + stream_senders.writer_data.peer_addr() ) } None => debug!( @@ -1809,13 +1808,14 @@ mod tests { subject.stream_killer_rx = stream_killer_rx; let stream_key = StreamKey::make_meaningless_stream_key(); let peer_addr = SocketAddr::from_str("1.2.3.4:5678").unwrap(); + let (shutdown_tx, shutdown_rx) = unbounded(); { let mut inner = subject.inner.lock().unwrap(); inner.stream_writer_channels.insert( stream_key, StreamSenders { writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown: unbounded().0, + reader_shutdown: shutdown_tx, }, ); } @@ -1827,6 +1827,8 @@ mod tests { system.run(); let proxy_client_recording = proxy_client_recording_arc.lock().unwrap(); let report = proxy_client_recording.get_record::(0); + let shutdown_signal_received = shutdown_rx.recv(); + assert_eq!(shutdown_signal_received, Ok(())); assert_eq!( report, &InboundServerData { From 4605d833f3493944d027477abb55f52da0853d8a Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Fri, 19 Jul 2024 11:32:04 +0530 Subject: [PATCH 20/65] GH-800: clean_up_dead_streams_logs_when_the_shutdown_channel_is_down is passing --- node/src/proxy_client/stream_handler_pool.rs | 46 +++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index a15ec4967..902062aa4 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -465,7 +465,7 @@ impl StreamHandlerPoolReal { }) .expect("ProxyClient is dead"); if let Err(e) = stream_senders.reader_shutdown.send(()) { - todo!("test drive me"); + debug!(inner.logger, "Unable to send a shutdown signal to the StreamReader for stream key {:?}. The channel is already gone.", stream_key) }; // Test should have a fake server, and the (read and write should be different) server debug!( @@ -1841,6 +1841,50 @@ mod tests { ); } + #[test] + fn clean_up_dead_streams_logs_when_the_shutdown_channel_is_down() { + init_test_logging(); + let test_name = "clean_up_dead_streams_logs_when_the_shutdown_channel_is_down"; + let system = System::new(test_name); + let (proxy_client, _, proxy_client_recording_arc) = make_recorder(); + let peer_actors = peer_actors_builder().proxy_client(proxy_client).build(); + let mut subject = StreamHandlerPoolReal::new( + Box::new(ResolverWrapperMock::new()), + main_cryptde(), + peer_actors.accountant.report_exit_service_provided, + peer_actors.proxy_client_opt.unwrap(), + 0, + 0, + ); + let (stream_killer_tx, stream_killer_rx) = unbounded(); + subject.stream_killer_rx = stream_killer_rx; + let stream_key = StreamKey::make_meaningful_stream_key("I'll be gone well before then."); + let peer_addr = SocketAddr::from_str("1.2.3.4:5678").unwrap(); + let broken_shutdown_channel_tx = unbounded().0; + { + let mut inner = subject.inner.lock().unwrap(); + inner.logger = Logger::new(test_name); + inner.stream_writer_channels.insert( + stream_key, + StreamSenders { + writer_data: Box::new(SenderWrapperMock::new(peer_addr)), + reader_shutdown: broken_shutdown_channel_tx, + }, + ); + } + stream_killer_tx.send((stream_key, 47)).unwrap(); + + subject.clean_up_dead_streams(); + + System::current().stop_with_code(0); + system.run(); + TestLogHandler::new().exists_log_containing(&format!( + "DEBUG: {test_name}: Unable to send a shutdown signal \ + to the StreamReader for stream key cv9IZ5fizc4kZmR+0d+OQGXr3bw. \ + The channel is already gone." + )); + } + #[test] fn clean_up_dead_streams_does_not_send_server_drop_report_if_dead_stream_is_gone_already() { let system = System::new("test"); From e1417c884f51578012dc362aedf198e57003e58e Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Fri, 19 Jul 2024 11:40:27 +0530 Subject: [PATCH 21/65] GH-800: tests are passing in StreamHandlerPool --- node/src/proxy_client/stream_handler_pool.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 902062aa4..b1f779902 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -470,7 +470,8 @@ impl StreamHandlerPoolReal { // Test should have a fake server, and the (read and write should be different) server debug!( inner.logger, - "Killed StreamWriter to {} and sent server-drop report", + "Killed StreamWriter and StreamReader for the stream key {:?} to {} and sent server-drop report", + stream_key, stream_senders.writer_data.peer_addr() ) } @@ -960,12 +961,12 @@ mod tests { run_process_package_in_actix(subject, package); }); let received = shutdown_rx.recv(); - assert_eq!(received, Ok(())); TestLogHandler::new().await_log_containing( "Removing StreamWriter and Shutting down StreamReader \ - for 8vVp1ZyZaZzRXCPNdf1OSE1bCVs to 3.4.5.6:80", - 100, + for oUHoHuDKHjeWq+BJzBIqHpPFBQw to 3.4.5.6:80", + 500, ); + assert_eq!(received, Ok(())); } #[test] @@ -1846,8 +1847,7 @@ mod tests { init_test_logging(); let test_name = "clean_up_dead_streams_logs_when_the_shutdown_channel_is_down"; let system = System::new(test_name); - let (proxy_client, _, proxy_client_recording_arc) = make_recorder(); - let peer_actors = peer_actors_builder().proxy_client(proxy_client).build(); + let peer_actors = peer_actors_builder().build(); let mut subject = StreamHandlerPoolReal::new( Box::new(ResolverWrapperMock::new()), main_cryptde(), From 6e28ff100ab1fe5d14172ae8d04e5e4d3145f7d5 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Fri, 19 Jul 2024 13:45:25 +0530 Subject: [PATCH 22/65] GH-800: Wrote a test for the case when the shutdown signal channel is gone --- node/src/proxy_client/stream_handler_pool.rs | 83 ++++++++++++++++++-- 1 file changed, 75 insertions(+), 8 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index b1f779902..cf69bd09a 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -217,11 +217,15 @@ impl StreamHandlerPoolReal { if last_data { match inner.stream_writer_channels.remove(&stream_key) { Some(stream_senders) => { - stream_senders - .reader_shutdown - .send(()) - .expect("StreamReader Shutdown channel is already gone"); - // TODO: GH-800: Should it be a log instead + if let Err(e) = stream_senders.reader_shutdown.send(()) { + debug!( + inner.logger, + "Unable to send a shutdown signal to the StreamReader for \ + stream key {:?}. The channel is already gone.", + stream_key + ); + } + // .expect("StreamReader Shutdown channel is already gone"); debug!( inner.logger, "Removing StreamWriter and Shutting down StreamReader for {:?} to {}", @@ -915,6 +919,7 @@ mod tests { #[test] fn stream_handler_pool_sends_shutdown_signal_when_last_data_is_true() { init_test_logging(); + let test_name = "stream_handler_pool_sends_shutdown_signal_when_last_data_is_true"; let (shutdown_tx, shutdown_rx) = unbounded(); thread::spawn(move || { let stream_key = StreamKey::make_meaningful_stream_key("I should die"); @@ -949,6 +954,7 @@ mod tests { ); { let mut inner = subject.inner.lock().unwrap(); + inner.logger = Logger::new(test_name); inner.stream_writer_channels.insert( stream_key, StreamSenders { @@ -961,12 +967,73 @@ mod tests { run_process_package_in_actix(subject, package); }); let received = shutdown_rx.recv(); + assert_eq!(received, Ok(())); TestLogHandler::new().await_log_containing( - "Removing StreamWriter and Shutting down StreamReader \ - for oUHoHuDKHjeWq+BJzBIqHpPFBQw to 3.4.5.6:80", + &format!( + "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ + for oUHoHuDKHjeWq+BJzBIqHpPFBQw to 3.4.5.6:80" + ), + 500, + ); + } + + #[test] + fn stream_handler_pool_logs_when_shutdown_channel_is_broken() { + init_test_logging(); + let test_name = "stream_handler_pool_logs_when_shutdown_channel_is_broken"; + let broken_shutdown_channel_tx = unbounded().0; + thread::spawn(move || { + let stream_key = StreamKey::make_meaningful_stream_key("I should die"); + let client_request_payload = ClientRequestPayload_0v1 { + stream_key, + sequenced_packet: SequencedPacket { + data: b"I'm gonna kill you stream key".to_vec(), + sequence_number: 0, + last_data: true, + }, + target_hostname: Some(String::from("3.4.5.6:80")), + target_port: HTTP_PORT, + protocol: ProxyProtocol::HTTP, + originator_public_key: PublicKey::new(&b"brutal death"[..]), + }; + let package = ExpiredCoresPackage::new( + SocketAddr::from_str("1.2.3.4:1234").unwrap(), + Some(make_wallet("consuming")), + make_meaningless_route(), + client_request_payload.into(), + 0, + ); + let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); + let peer_actors = peer_actors_builder().build(); + let mut subject = StreamHandlerPoolReal::new( + Box::new(ResolverWrapperMock::new()), + main_cryptde(), + peer_actors.accountant.report_exit_service_provided.clone(), + peer_actors.proxy_client_opt.unwrap().clone(), + 100, + 200, + ); + { + let mut inner = subject.inner.lock().unwrap(); + inner.logger = Logger::new(test_name); + inner.stream_writer_channels.insert( + stream_key, + StreamSenders { + writer_data: Box::new(SenderWrapperMock::new(peer_addr)), + reader_shutdown: broken_shutdown_channel_tx, + }, + ); + } + + run_process_package_in_actix(subject, package); + }); + TestLogHandler::new().await_log_containing( + &format!( + "DEBUG: {test_name}: Unable to send a shutdown signal to the StreamReader \ + for stream key oUHoHuDKHjeWq+BJzBIqHpPFBQw. The channel is already gone." + ), 500, ); - assert_eq!(received, Ok(())); } #[test] From 6849db6a434b75e247519391daff867ddb059bd5 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Mon, 22 Jul 2024 12:01:58 +0530 Subject: [PATCH 23/65] GH-800: make it easier to understand who experiences the write error --- node/tests/connection_shutdown_test.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/node/tests/connection_shutdown_test.rs b/node/tests/connection_shutdown_test.rs index 205224fe5..e76f73a1e 100644 --- a/node/tests/connection_shutdown_test.rs +++ b/node/tests/connection_shutdown_test.rs @@ -23,10 +23,10 @@ fn proxy_client_stream_reader_dies_when_client_stream_is_killed_integration() { false, true, ); - let (write_error_tx, write_error_rx) = unbounded(); + let (server_write_error_tx, server_write_error_rx) = unbounded(); let server_port = find_free_port(); thread::spawn(move || { - endless_write_server(server_port, write_error_tx); + endless_write_server(server_port, server_write_error_tx); }); let mut stream = TcpStream::connect(SocketAddr::from_str("127.0.0.1:80").unwrap()).unwrap(); stream @@ -39,7 +39,9 @@ fn proxy_client_stream_reader_dies_when_client_stream_is_killed_integration() { // We want to make sure the Server is sending before we shutdown the stream stream.read(&mut buf).unwrap(); stream.shutdown(Shutdown::Write).unwrap(); - let write_error = write_error_rx.recv_timeout(Duration::from_secs(5)).unwrap(); // TODO: GH-800 We are failing on this timeout + let write_error = server_write_error_rx + .recv_timeout(Duration::from_secs(5)) + .unwrap(); // TODO: GH-800 We are failing on this timeout assert_eq!(write_error.kind(), io::ErrorKind::ConnectionAborted); } From af09d25af3707a5dda9bce6f43047374fa58351f Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Mon, 22 Jul 2024 13:00:57 +0530 Subject: [PATCH 24/65] GH-800: trying to write test while_housekeeping_the_stream_senders_are_received_by_stream_handler_pool --- node/src/proxy_client/stream_handler_pool.rs | 84 ++++++++++++++++++-- 1 file changed, 78 insertions(+), 6 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index cf69bd09a..6faa3d6d1 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -35,8 +35,6 @@ pub trait StreamHandlerPool { fn process_package(&self, payload: ClientRequestPayload_0v1, paying_wallet_opt: Option); } -// TODO: GH-800: We don't need to keep StreamSenders at two places here, one in stream_adder_rx, -// and the other in inner -> stream_writer_channels pub struct StreamHandlerPoolReal { inner: Arc>, stream_adder_rx: Receiver<(StreamKey, StreamSenders)>, @@ -491,9 +489,9 @@ impl StreamHandlerPoolReal { let mut inner = self.inner.lock().expect("Stream handler pool is poisoned"); loop { match self.stream_adder_rx.try_recv() { - Err(_) => break, + Err(e) => panic!("{:?}", e), Ok((stream_key, stream_senders)) => { - // todo!("GH-800: Fix it such that the stream_adder_rx holds StreamSenders"); + todo!("GH-800: Fix it such that the stream_adder_rx holds StreamSenders"); // debug!( // inner.logger, // "Persisting StreamWriter to {} under key {:?}", @@ -564,14 +562,14 @@ mod tests { use crate::test_utils::main_cryptde; use crate::test_utils::make_meaningless_route; use crate::test_utils::make_wallet; - use crate::test_utils::recorder::make_recorder; use crate::test_utils::recorder::peer_actors_builder; + use crate::test_utils::recorder::{make_proxy_client_subs_from_recorder, make_recorder}; use crate::test_utils::recorder_stop_conditions::StopCondition; use crate::test_utils::recorder_stop_conditions::StopConditions; use crate::test_utils::stream_connector_mock::StreamConnectorMock; use crate::test_utils::tokio_wrapper_mocks::ReadHalfWrapperMock; use crate::test_utils::tokio_wrapper_mocks::WriteHalfWrapperMock; - use actix::System; + use actix::{Actor, System}; use core::any::TypeId; use masq_lib::constants::HTTP_PORT; use masq_lib::test_utils::logging::init_test_logging; @@ -916,6 +914,80 @@ mod tests { ); } + #[test] + fn while_housekeeping_the_stream_senders_are_received_by_stream_handler_pool() { + init_test_logging(); + let test_name = "stream_handler_pool_sends_shutdown_signal_when_last_data_is_true"; + let (shutdown_tx, shutdown_rx) = unbounded(); + let (stream_adder_tx, stream_adder_rx) = unbounded(); + thread::spawn(move || { + let stream_key = StreamKey::make_meaningful_stream_key("I should die"); + let client_request_payload = ClientRequestPayload_0v1 { + stream_key, + sequenced_packet: SequencedPacket { + data: b"I'm gonna kill you stream key".to_vec(), + sequence_number: 0, + last_data: true, + }, + target_hostname: Some(String::from("3.4.5.6:80")), + target_port: HTTP_PORT, + protocol: ProxyProtocol::HTTP, + originator_public_key: PublicKey::new(&b"brutal death"[..]), + }; + let package = ExpiredCoresPackage::new( + SocketAddr::from_str("1.2.3.4:1234").unwrap(), + Some(make_wallet("consuming")), + make_meaningless_route(), + client_request_payload.into(), + 0, + ); + let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); + let peer_actors = peer_actors_builder().build(); + let mut subject = StreamHandlerPoolReal::new( + Box::new(ResolverWrapperMock::new()), + main_cryptde(), + peer_actors.accountant.report_exit_service_provided.clone(), + peer_actors.proxy_client_opt.unwrap().clone(), + 100, + 200, + ); + subject.stream_adder_rx = stream_adder_rx; + { + let mut inner = subject.inner.lock().unwrap(); + inner.logger = Logger::new(test_name); + inner.stream_writer_channels.insert( + stream_key, + StreamSenders { + writer_data: Box::new(SenderWrapperMock::new(peer_addr)), + reader_shutdown: shutdown_tx, + }, + ); + inner.establisher_factory = Box::new(StreamEstablisherFactoryReal { + cryptde: main_cryptde(), + stream_adder_tx, + stream_killer_tx: unbounded().0, + proxy_client_subs: make_proxy_client_subs_from_recorder( + &make_recorder().0.start(), + ), + logger: Logger::new("test"), + }); + } + + // TODO: GH-800: Make sure that the stream_adder_tx sends something to the receiver + + run_process_package_in_actix(subject, package); + }); + let received = shutdown_rx.recv(); + assert_eq!(received, Ok(())); + TestLogHandler::new().await_log_containing( + &format!( + "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ + for oUHoHuDKHjeWq+BJzBIqHpPFBQw to 3.4.5.6:80" + ), + 500, + ); + } + #[test] fn stream_handler_pool_sends_shutdown_signal_when_last_data_is_true() { init_test_logging(); From b896db6724deee7e919d7c95e7b526876fd3d298 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Fri, 26 Jul 2024 12:16:47 +0530 Subject: [PATCH 25/65] GH-800: add test add_new_streams_works --- node/src/proxy_client/stream_handler_pool.rs | 98 +++++++++++++++++--- 1 file changed, 86 insertions(+), 12 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 6faa3d6d1..a0404aa30 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -64,6 +64,7 @@ impl StreamHandlerPool for StreamHandlerPoolReal { payload: ClientRequestPayload_0v1, paying_wallet_opt: Option, ) { + // TODO: GH-800: We need a test to prove that do_housekeeping() is called self.do_housekeeping(); Self::process_package(payload, paying_wallet_opt, self.inner.clone()) } @@ -489,18 +490,17 @@ impl StreamHandlerPoolReal { let mut inner = self.inner.lock().expect("Stream handler pool is poisoned"); loop { match self.stream_adder_rx.try_recv() { - Err(e) => panic!("{:?}", e), + Err(_) => break, Ok((stream_key, stream_senders)) => { - todo!("GH-800: Fix it such that the stream_adder_rx holds StreamSenders"); - // debug!( - // inner.logger, - // "Persisting StreamWriter to {} under key {:?}", - // stream_senders.writer_data.peer_addr(), - // stream_key - // ); - // inner - // .stream_writer_channels - // .insert(stream_key, stream_senders) + debug!( + inner.logger, + "Persisting StreamWriter to {} under key {:?}", + stream_senders.writer_data.peer_addr(), + stream_key + ); + inner + .stream_writer_channels + .insert(stream_key, stream_senders) } }; } @@ -580,9 +580,10 @@ mod tests { use std::net::IpAddr; use std::net::SocketAddr; use std::ops::Deref; + use std::ptr::addr_of; use std::str::FromStr; use std::sync::{Arc, Mutex}; - use std::thread; + use std::{sync, thread}; use tokio; use tokio::prelude::Async; use trust_dns_resolver::error::ResolveErrorKind; @@ -2049,4 +2050,77 @@ mod tests { let proxy_client_recording = proxy_client_recording_arc.lock().unwrap(); assert_eq!(proxy_client_recording.len(), 0); } + + #[test] + fn add_new_streams_works() { + init_test_logging(); + let test_name = "add_new_streams_works"; + let (stream_adder_tx, stream_adder_rx) = unbounded(); + let peer_actors = peer_actors_builder().build(); + let mut subject = StreamHandlerPoolReal::new( + Box::new(ResolverWrapperMock::new()), + main_cryptde(), + peer_actors.accountant.report_exit_service_provided, + peer_actors.proxy_client_opt.unwrap(), + 0, + 0, + ); + subject.stream_adder_rx = stream_adder_rx; + { + subject.inner.lock().unwrap().logger = Logger::new(test_name); + } + let first_stream_key = StreamKey::make_meaningful_stream_key("first_stream_key"); + let (first_writer_data_tx, first_writer_data_rx) = futures::sync::mpsc::unbounded(); + let (first_shutdown_tx, first_shutdown_rx) = unbounded(); + let first_stream_senders = StreamSenders { + writer_data: Box::new(SenderWrapperReal::new( + SocketAddr::from_str("1.2.3.4:5678").unwrap(), + first_writer_data_tx, + )), + reader_shutdown: first_shutdown_tx, + }; + let (second_writer_data_tx, second_writer_data_rx) = futures::sync::mpsc::unbounded(); + let (second_shutdown_tx, second_shutdown_rx) = unbounded(); + let second_stream_key = StreamKey::make_meaningful_stream_key("second_stream_key"); + let second_stream_senders = StreamSenders { + writer_data: Box::new(SenderWrapperReal::new( + SocketAddr::from_str("2.3.4.5:6789").unwrap(), + second_writer_data_tx, + )), + reader_shutdown: second_shutdown_tx, + }; + stream_adder_tx + .send((first_stream_key.clone(), first_stream_senders)) + .unwrap(); + stream_adder_tx + .send((second_stream_key.clone(), second_stream_senders)) + .unwrap(); + + subject.add_new_streams(); + + let mut inner = subject.inner.lock().unwrap(); + let actual_first_stream_senders = inner + .stream_writer_channels + .remove(&first_stream_key) + .unwrap(); + let actual_second_stream_senders = inner + .stream_writer_channels + .remove(&second_stream_key) + .unwrap(); + assert_eq!( + actual_first_stream_senders.writer_data.peer_addr(), + SocketAddr::from_str("1.2.3.4:5678").unwrap() + ); + assert_eq!( + actual_second_stream_senders.writer_data.peer_addr(), + SocketAddr::from_str("2.3.4.5:6789").unwrap() + ); + let tlh = TestLogHandler::new(); + tlh.exists_log_containing(&format!( + "DEBUG: {test_name}: Persisting StreamWriter to 1.2.3.4:5678 under key gY2vJ+OwPuItsBcFhbilDI61LGo" + )); + tlh.exists_log_containing(&format!( + "DEBUG: {test_name}: Persisting StreamWriter to 2.3.4.5:6789 under key 1Kbv+3/MIN4/1hLQXLeNPgdDM58" + )); + } } From acf2c897c99ed973ae941c9489390e8372427eb6 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Fri, 26 Jul 2024 15:05:32 +0530 Subject: [PATCH 26/65] GH-800: wip: add the log --- node/src/proxy_client/stream_handler_pool.rs | 24 ++++++++++++-------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index a0404aa30..c107e39db 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -14,7 +14,7 @@ use crate::sub_lib::sequence_buffer::SequencedPacket; use crate::sub_lib::stream_key::StreamKey; use crate::sub_lib::wallet::Wallet; use actix::{Message, Recipient}; -use crossbeam_channel::{unbounded, Receiver, Sender}; +use crossbeam_channel::{unbounded, Receiver, SendError, Sender}; use futures::future; use futures::future::Future; use masq_lib::logger::Logger; @@ -213,18 +213,24 @@ impl StreamHandlerPoolReal { ), } } + debug!(Logger::new("TEST"), "Stop right before last_data check!"); if last_data { match inner.stream_writer_channels.remove(&stream_key) { Some(stream_senders) => { - if let Err(e) = stream_senders.reader_shutdown.send(()) { - debug!( - inner.logger, - "Unable to send a shutdown signal to the StreamReader for \ - stream key {:?}. The channel is already gone.", - stream_key - ); + // TODO: GH-800: We need a log here + match stream_senders.reader_shutdown.send(()) { + Ok(()) => { + debug!(inner.logger, "A shutdown signal was sent.") + } + Err(e) => { + debug!( + inner.logger, + "Unable to send a shutdown signal to the StreamReader for \ + stream key {:?}. The channel is already gone.", + stream_key + ); + } } - // .expect("StreamReader Shutdown channel is already gone"); debug!( inner.logger, "Removing StreamWriter and Shutting down StreamReader for {:?} to {}", From deb15355bf2dafbc864ff137cfab9430a7c2f0ef Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 31 Jul 2024 16:56:24 +0530 Subject: [PATCH 27/65] GH-800: test proxy_client_stream_reader_dies_when_client_stream_is_killed_integration is passing --- node/src/proxy_client/stream_establisher.rs | 7 +---- node/src/proxy_client/stream_handler_pool.rs | 28 +++++++++++++------- node/src/proxy_client/stream_reader.rs | 13 ++++++++- node/tests/connection_shutdown_test.rs | 15 +++++++---- 4 files changed, 42 insertions(+), 21 deletions(-) diff --git a/node/src/proxy_client/stream_establisher.rs b/node/src/proxy_client/stream_establisher.rs index 3d02477e9..a8e59b423 100644 --- a/node/src/proxy_client/stream_establisher.rs +++ b/node/src/proxy_client/stream_establisher.rs @@ -60,12 +60,7 @@ impl StreamEstablisher { payload.target_port, &self.logger, )?; - - // TODO: GH-800: Test Drive Me - // let (shutdown_signal_tx, shutdown_signal_rx) = unbounded(); - - let shutdown_signal_tx = unbounded().0; - let shutdown_signal_rx = unbounded().1; + let (shutdown_signal_tx, shutdown_signal_rx) = unbounded(); self.spawn_stream_reader( &payload.clone(), diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index c107e39db..4ebc8af66 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -169,11 +169,16 @@ impl StreamHandlerPoolReal { "Couldn't process request from CORES package: {}", error ); if let Some(sender_wrapper) = inner.stream_writer_channels.remove(stream_key) { + debug!( + Logger::new("TEST"), + "clean_up_bad_stream() removed the stream key" + ); debug!( inner.logger, "Removing stream writer for {}", sender_wrapper.writer_data.peer_addr() ); + // TODO: GH-800: Send a shutdown signal to the Reader } Self::send_terminating_package( stream_key, @@ -191,6 +196,7 @@ impl StreamHandlerPoolReal { let stream_key = payload.stream_key; let last_data = payload.sequenced_packet.last_data; let payload_size = payload.sequenced_packet.data.len(); + let test_logger = Logger::new("TEST"); Self::perform_write(payload.sequenced_packet, sender_wrapper.clone()).and_then(move |_| { let mut inner = inner_arc.lock().expect("Stream handler pool is poisoned"); @@ -213,14 +219,20 @@ impl StreamHandlerPoolReal { ), } } - debug!(Logger::new("TEST"), "Stop right before last_data check!"); + debug!(test_logger, "Stop right before last_data check!"); if last_data { + debug!(test_logger, "last_data = true"); match inner.stream_writer_channels.remove(&stream_key) { Some(stream_senders) => { - // TODO: GH-800: We need a log here + debug!( + inner.logger, + "Removing StreamWriter and Shutting down StreamReader for {:?} to {}", + stream_key, + stream_senders.writer_data.peer_addr() + ); match stream_senders.reader_shutdown.send(()) { Ok(()) => { - debug!(inner.logger, "A shutdown signal was sent.") + debug!(test_logger, "A shutdown signal was sent.") } Err(e) => { debug!( @@ -231,12 +243,6 @@ impl StreamHandlerPoolReal { ); } } - debug!( - inner.logger, - "Removing StreamWriter and Shutting down StreamReader for {:?} to {}", - stream_key, - stream_senders.writer_data.peer_addr() - ); } None => { eprintln!("Failed to Remove stream key: {:?}", stream_key); @@ -462,6 +468,10 @@ impl StreamHandlerPoolReal { while let Ok((stream_key, sequence_number)) = self.stream_killer_rx.try_recv() { match inner.stream_writer_channels.remove(&stream_key) { Some(stream_senders) => { + debug!( + Logger::new("TEST"), + "clean_up_dead_streams() removed the stream key" + ); inner .proxy_client_subs .inbound_server_data diff --git a/node/src/proxy_client/stream_reader.rs b/node/src/proxy_client/stream_reader.rs index b8f49deaf..4ec7d825d 100644 --- a/node/src/proxy_client/stream_reader.rs +++ b/node/src/proxy_client/stream_reader.rs @@ -84,6 +84,15 @@ impl Future for StreamReader { } } +impl Drop for StreamReader { + fn drop(&mut self) { + debug!( + Logger::new("TEST"), + "StreamReader for stream key {:?} is being dropped.", self.stream_key + ) + } +} + impl StreamReader { pub fn new( stream_key: StreamKey, @@ -93,6 +102,8 @@ impl StreamReader { shutdown_signal: Receiver<()>, peer_addr: SocketAddr, ) -> StreamReader { + let logger = Logger::new(&format!("StreamReader for {:?}/{}", stream_key, peer_addr)[..]); + debug!(logger, "Initialised StreamReader"); StreamReader { stream_key, proxy_client_sub, @@ -100,7 +111,7 @@ impl StreamReader { stream_killer, shutdown_signal, peer_addr, - logger: Logger::new(&format!("StreamReader for {:?}/{}", stream_key, peer_addr)[..]), + logger, sequencer: Sequencer::new(), } } diff --git a/node/tests/connection_shutdown_test.rs b/node/tests/connection_shutdown_test.rs index e76f73a1e..1c2a23692 100644 --- a/node/tests/connection_shutdown_test.rs +++ b/node/tests/connection_shutdown_test.rs @@ -2,6 +2,7 @@ pub mod utils; +use crate::utils::CommandConfig; use crossbeam_channel::{unbounded, Sender}; use masq_lib::utils::find_free_port; use node_lib::test_utils::read_until_timeout; @@ -25,7 +26,7 @@ fn proxy_client_stream_reader_dies_when_client_stream_is_killed_integration() { ); let (server_write_error_tx, server_write_error_rx) = unbounded(); let server_port = find_free_port(); - thread::spawn(move || { + let join_handle = thread::spawn(move || { endless_write_server(server_port, server_write_error_tx); }); let mut stream = TcpStream::connect(SocketAddr::from_str("127.0.0.1:80").unwrap()).unwrap(); @@ -33,17 +34,18 @@ fn proxy_client_stream_reader_dies_when_client_stream_is_killed_integration() { .set_read_timeout(Some(Duration::from_millis(1000))) .unwrap(); let request = format!("GET / HTTP/1.1\r\nHost: 127.0.0.1:{server_port}\r\n\r\n"); - stream.write(request.as_bytes()).unwrap(); let mut buf = [0u8; 16384]; // We want to make sure the Server is sending before we shutdown the stream stream.read(&mut buf).unwrap(); + stream.shutdown(Shutdown::Write).unwrap(); + let write_error = server_write_error_rx - .recv_timeout(Duration::from_secs(5)) + .recv_timeout(Duration::from_secs(60)) .unwrap(); // TODO: GH-800 We are failing on this timeout - - assert_eq!(write_error.kind(), io::ErrorKind::ConnectionAborted); + assert_eq!(write_error.kind(), io::ErrorKind::BrokenPipe); + join_handle.join().unwrap(); } fn endless_write_server(port: u16, write_error_tx: Sender) { @@ -54,6 +56,9 @@ fn endless_write_server(port: u16, write_error_tx: Sender) { .unwrap(); let mut buf = [0u8; 16_384]; let (mut stream, _) = listener.accept().unwrap(); + stream + .set_write_timeout(Some(Duration::from_secs(1))) + .unwrap(); let _ = stream.read(&mut buf).unwrap(); stream .write("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n".as_bytes()) From 2ecfebc9d5c711e1281c1658122924aa2a8b3045 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 31 Jul 2024 17:55:50 +0530 Subject: [PATCH 28/65] GH-800: change the channel from crossbeam to tokio --- node/src/proxy_client/stream_establisher.rs | 11 ++-- node/src/proxy_client/stream_handler_pool.rs | 64 +++++++++++--------- node/src/proxy_client/stream_reader.rs | 43 ++++++++----- 3 files changed, 70 insertions(+), 48 deletions(-) diff --git a/node/src/proxy_client/stream_establisher.rs b/node/src/proxy_client/stream_establisher.rs index a8e59b423..c485e71c9 100644 --- a/node/src/proxy_client/stream_establisher.rs +++ b/node/src/proxy_client/stream_establisher.rs @@ -20,6 +20,7 @@ use masq_lib::logger::Logger; use std::io; use std::net::IpAddr; use std::net::SocketAddr; +use tokio::sync::mpsc::UnboundedReceiver; pub struct StreamEstablisher { pub cryptde: &'static dyn CryptDE, @@ -60,7 +61,8 @@ impl StreamEstablisher { payload.target_port, &self.logger, )?; - let (shutdown_signal_tx, shutdown_signal_rx) = unbounded(); + // TODO: GH-800: Change it to a tokio channel instead of a crossbeam channel + let (shutdown_signal_tx, shutdown_signal_rx) = tokio::sync::mpsc::unbounded_channel(); self.spawn_stream_reader( &payload.clone(), @@ -80,7 +82,7 @@ impl StreamEstablisher { let stream_senders = StreamSenders { writer_data: tx_to_write.clone(), - reader_shutdown: shutdown_signal_tx, + reader_shutdown_tx: shutdown_signal_tx, }; self.stream_adder_tx @@ -94,7 +96,7 @@ impl StreamEstablisher { payload: &ClientRequestPayload_0v1, read_stream: Box, peer_addr: SocketAddr, - shutdown_signal: Receiver<()>, + shutdown_signal: UnboundedReceiver<()>, ) { let stream_reader = StreamReader::new( payload.stream_key, @@ -153,6 +155,7 @@ mod tests { use std::str::FromStr; use std::thread; use tokio::prelude::Async; + use tokio::sync::mpsc::unbounded_channel; #[test] fn spawn_stream_reader_handles_data() { @@ -205,7 +208,7 @@ mod tests { }, read_stream, SocketAddr::from_str("1.2.3.4:5678").unwrap(), - unbounded().1, + unbounded_channel().1, ); proxy_client_awaiter.await_message_count(1); diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 4ebc8af66..de32893fb 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -14,9 +14,9 @@ use crate::sub_lib::sequence_buffer::SequencedPacket; use crate::sub_lib::stream_key::StreamKey; use crate::sub_lib::wallet::Wallet; use actix::{Message, Recipient}; -use crossbeam_channel::{unbounded, Receiver, SendError, Sender}; -use futures::future; +use crossbeam_channel::{unbounded, Receiver}; use futures::future::Future; +use futures::{future, Sink}; use masq_lib::logger::Logger; use std::collections::HashMap; use std::io; @@ -26,6 +26,8 @@ use std::sync::{Arc, Mutex}; use std::time::SystemTime; use tokio::prelude::future::FutureResult; use tokio::prelude::future::{err, ok}; +use tokio::sync::mpsc::error::TrySendError; +use tokio::sync::mpsc::{Sender, UnboundedSender}; use trust_dns_resolver::error::ResolveError; use trust_dns_resolver::lookup_ip::LookupIp; @@ -44,7 +46,7 @@ pub struct StreamHandlerPoolReal { #[derive(Debug)] pub struct StreamSenders { pub writer_data: Box>, - pub reader_shutdown: Sender<()>, + pub reader_shutdown_tx: UnboundedSender<()>, } struct StreamHandlerPoolRealInner { @@ -223,14 +225,14 @@ impl StreamHandlerPoolReal { if last_data { debug!(test_logger, "last_data = true"); match inner.stream_writer_channels.remove(&stream_key) { - Some(stream_senders) => { + Some(mut stream_senders) => { debug!( inner.logger, "Removing StreamWriter and Shutting down StreamReader for {:?} to {}", stream_key, stream_senders.writer_data.peer_addr() ); - match stream_senders.reader_shutdown.send(()) { + match stream_senders.reader_shutdown_tx.try_send(()) { Ok(()) => { debug!(test_logger, "A shutdown signal was sent.") } @@ -467,7 +469,7 @@ impl StreamHandlerPoolReal { let mut inner = self.inner.lock().expect("Stream handler pool is poisoned"); while let Ok((stream_key, sequence_number)) = self.stream_killer_rx.try_recv() { match inner.stream_writer_channels.remove(&stream_key) { - Some(stream_senders) => { + Some(mut stream_senders) => { debug!( Logger::new("TEST"), "clean_up_dead_streams() removed the stream key" @@ -483,7 +485,7 @@ impl StreamHandlerPoolReal { data: vec![], }) .expect("ProxyClient is dead"); - if let Err(e) = stream_senders.reader_shutdown.send(()) { + if let Err(e) = stream_senders.reader_shutdown_tx.try_send(()) { debug!(inner.logger, "Unable to send a shutdown signal to the StreamReader for stream key {:?}. The channel is already gone.", stream_key) }; // Test should have a fake server, and the (read and write should be different) server @@ -587,6 +589,7 @@ mod tests { use crate::test_utils::tokio_wrapper_mocks::WriteHalfWrapperMock; use actix::{Actor, System}; use core::any::TypeId; + use futures::Stream; use masq_lib::constants::HTTP_PORT; use masq_lib::test_utils::logging::init_test_logging; use masq_lib::test_utils::logging::TestLogHandler; @@ -602,6 +605,7 @@ mod tests { use std::{sync, thread}; use tokio; use tokio::prelude::Async; + use tokio::sync::mpsc::unbounded_channel; use trust_dns_resolver::error::ResolveErrorKind; struct StreamEstablisherFactoryMock { @@ -739,7 +743,7 @@ mod tests { stream_key, StreamSenders { writer_data: tx_to_write, - reader_shutdown: unbounded().0, + reader_shutdown_tx: unbounded_channel().0, }, ); @@ -800,7 +804,7 @@ mod tests { client_request_payload.stream_key, StreamSenders { writer_data: Box::new(tx_to_write), - reader_shutdown: unbounded().0, + reader_shutdown_tx: unbounded_channel().0, }, ); @@ -935,7 +939,7 @@ mod tests { fn while_housekeeping_the_stream_senders_are_received_by_stream_handler_pool() { init_test_logging(); let test_name = "stream_handler_pool_sends_shutdown_signal_when_last_data_is_true"; - let (shutdown_tx, shutdown_rx) = unbounded(); + let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); let (stream_adder_tx, stream_adder_rx) = unbounded(); thread::spawn(move || { let stream_key = StreamKey::make_meaningful_stream_key("I should die"); @@ -976,7 +980,7 @@ mod tests { stream_key, StreamSenders { writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown: shutdown_tx, + reader_shutdown_tx: shutdown_tx, }, ); inner.establisher_factory = Box::new(StreamEstablisherFactoryReal { @@ -994,8 +998,8 @@ mod tests { run_process_package_in_actix(subject, package); }); - let received = shutdown_rx.recv(); - assert_eq!(received, Ok(())); + let received = shutdown_rx.poll().unwrap(); + assert_eq!(received, Async::Ready(Some(()))); TestLogHandler::new().await_log_containing( &format!( "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ @@ -1009,7 +1013,7 @@ mod tests { fn stream_handler_pool_sends_shutdown_signal_when_last_data_is_true() { init_test_logging(); let test_name = "stream_handler_pool_sends_shutdown_signal_when_last_data_is_true"; - let (shutdown_tx, shutdown_rx) = unbounded(); + let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); thread::spawn(move || { let stream_key = StreamKey::make_meaningful_stream_key("I should die"); let client_request_payload = ClientRequestPayload_0v1 { @@ -1048,15 +1052,15 @@ mod tests { stream_key, StreamSenders { writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown: shutdown_tx, + reader_shutdown_tx: shutdown_tx, }, ); } run_process_package_in_actix(subject, package); }); - let received = shutdown_rx.recv(); - assert_eq!(received, Ok(())); + let received = shutdown_rx.poll().unwrap(); + assert_eq!(received, Async::Ready(Some(()))); TestLogHandler::new().await_log_containing( &format!( "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ @@ -1070,7 +1074,7 @@ mod tests { fn stream_handler_pool_logs_when_shutdown_channel_is_broken() { init_test_logging(); let test_name = "stream_handler_pool_logs_when_shutdown_channel_is_broken"; - let broken_shutdown_channel_tx = unbounded().0; + let broken_shutdown_channel_tx = unbounded_channel().0; thread::spawn(move || { let stream_key = StreamKey::make_meaningful_stream_key("I should die"); let client_request_payload = ClientRequestPayload_0v1 { @@ -1109,7 +1113,7 @@ mod tests { stream_key, StreamSenders { writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown: broken_shutdown_channel_tx, + reader_shutdown_tx: broken_shutdown_channel_tx, }, ); } @@ -1869,7 +1873,7 @@ mod tests { stream_key, StreamSenders { writer_data: Box::new(sender_wrapper), - reader_shutdown: unbounded().0, + reader_shutdown_tx: unbounded_channel().0, }, ); @@ -1965,14 +1969,14 @@ mod tests { subject.stream_killer_rx = stream_killer_rx; let stream_key = StreamKey::make_meaningless_stream_key(); let peer_addr = SocketAddr::from_str("1.2.3.4:5678").unwrap(); - let (shutdown_tx, shutdown_rx) = unbounded(); + let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); { let mut inner = subject.inner.lock().unwrap(); inner.stream_writer_channels.insert( stream_key, StreamSenders { writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown: shutdown_tx, + reader_shutdown_tx: shutdown_tx, }, ); } @@ -1984,8 +1988,8 @@ mod tests { system.run(); let proxy_client_recording = proxy_client_recording_arc.lock().unwrap(); let report = proxy_client_recording.get_record::(0); - let shutdown_signal_received = shutdown_rx.recv(); - assert_eq!(shutdown_signal_received, Ok(())); + let shutdown_signal_received = shutdown_rx.poll().unwrap(); + assert_eq!(shutdown_signal_received, Async::Ready(Some(()))); assert_eq!( report, &InboundServerData { @@ -2016,7 +2020,7 @@ mod tests { subject.stream_killer_rx = stream_killer_rx; let stream_key = StreamKey::make_meaningful_stream_key("I'll be gone well before then."); let peer_addr = SocketAddr::from_str("1.2.3.4:5678").unwrap(); - let broken_shutdown_channel_tx = unbounded().0; + let broken_shutdown_channel_tx = unbounded_channel().0; { let mut inner = subject.inner.lock().unwrap(); inner.logger = Logger::new(test_name); @@ -2024,7 +2028,7 @@ mod tests { stream_key, StreamSenders { writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown: broken_shutdown_channel_tx, + reader_shutdown_tx: broken_shutdown_channel_tx, }, ); } @@ -2087,23 +2091,23 @@ mod tests { } let first_stream_key = StreamKey::make_meaningful_stream_key("first_stream_key"); let (first_writer_data_tx, first_writer_data_rx) = futures::sync::mpsc::unbounded(); - let (first_shutdown_tx, first_shutdown_rx) = unbounded(); + let (first_shutdown_tx, first_shutdown_rx) = unbounded_channel(); let first_stream_senders = StreamSenders { writer_data: Box::new(SenderWrapperReal::new( SocketAddr::from_str("1.2.3.4:5678").unwrap(), first_writer_data_tx, )), - reader_shutdown: first_shutdown_tx, + reader_shutdown_tx: first_shutdown_tx, }; let (second_writer_data_tx, second_writer_data_rx) = futures::sync::mpsc::unbounded(); - let (second_shutdown_tx, second_shutdown_rx) = unbounded(); + let (second_shutdown_tx, second_shutdown_rx) = unbounded_channel(); let second_stream_key = StreamKey::make_meaningful_stream_key("second_stream_key"); let second_stream_senders = StreamSenders { writer_data: Box::new(SenderWrapperReal::new( SocketAddr::from_str("2.3.4.5:6789").unwrap(), second_writer_data_tx, )), - reader_shutdown: second_shutdown_tx, + reader_shutdown_tx: second_shutdown_tx, }; stream_adder_tx .send((first_stream_key.clone(), first_stream_senders)) diff --git a/node/src/proxy_client/stream_reader.rs b/node/src/proxy_client/stream_reader.rs index 4ec7d825d..d9e24bd4d 100644 --- a/node/src/proxy_client/stream_reader.rs +++ b/node/src/proxy_client/stream_reader.rs @@ -7,17 +7,19 @@ use crate::sub_lib::utils; use crate::sub_lib::utils::indicates_dead_stream; use actix::Recipient; use crossbeam_channel::{Receiver, Sender, TryRecvError}; +use futures::{Poll, Stream}; use masq_lib::logger::Logger; use std::net::SocketAddr; use tokio::prelude::Async; use tokio::prelude::Future; +use tokio::sync::mpsc::UnboundedReceiver; pub struct StreamReader { stream_key: StreamKey, proxy_client_sub: Recipient, stream: Box, stream_killer: Sender<(StreamKey, u64)>, - shutdown_signal: Receiver<()>, + shutdown_signal: UnboundedReceiver<()>, peer_addr: SocketAddr, logger: Logger, sequencer: Sequencer, @@ -30,12 +32,24 @@ impl Future for StreamReader { fn poll(&mut self) -> Result::Item>, ::Error> { let mut buf: [u8; 16384] = [0; 16384]; loop { - if self.shutdown_signal.try_recv().is_ok() { - info!( - self.logger, - "Shutting down for stream: {:?}", self.stream_key - ); - return Ok(Async::Ready(())); + match self.shutdown_signal.poll() { + // TODO: GH-800: Test Drive Me + Ok(Async::Ready(_something)) => { + info!( + self.logger, + "Shutting down for stream: {:?}", self.stream_key + ); + return Ok(Async::Ready(())); + } + Ok(Async::NotReady) => (), + Err(_e) => { + warning!( + self.logger, + "Failed to receive a signal for shutting down StreamReader for stream key: {:?}", + self.stream_key, + ); + return Err(()); + } } match self.stream.poll_read(&mut buf) { Ok(Async::NotReady) => return Ok(Async::NotReady), @@ -99,7 +113,7 @@ impl StreamReader { proxy_client_sub: Recipient, stream: Box, stream_killer: Sender<(StreamKey, u64)>, - shutdown_signal: Receiver<()>, + shutdown_signal: UnboundedReceiver<()>, peer_addr: SocketAddr, ) -> StreamReader { let logger = Logger::new(&format!("StreamReader for {:?}/{}", stream_key, peer_addr)[..]); @@ -150,6 +164,7 @@ mod tests { use std::net::SocketAddr; use std::str::FromStr; use std::thread; + use tokio::sync::mpsc::unbounded_channel; #[test] fn stream_reader_assigns_a_sequence_to_client_response_payloads() { @@ -196,7 +211,7 @@ mod tests { proxy_client_sub, stream, stream_killer, - shutdown_signal: unbounded().1, + shutdown_signal: unbounded_channel().1, peer_addr: SocketAddr::from_str("8.7.4.3:50").unwrap(), logger: Logger::new("test"), sequencer: Sequencer::new(), @@ -347,7 +362,7 @@ mod tests { proxy_client_sub: make_recorder().0.start().recipient(), stream: Box::new(stream), stream_killer, - shutdown_signal: unbounded().1, + shutdown_signal: unbounded_channel().1, peer_addr, logger: Logger::new(test_name), sequencer, @@ -400,7 +415,7 @@ mod tests { proxy_client_sub, stream: Box::new(stream), stream_killer, - shutdown_signal: unbounded().1, + shutdown_signal: unbounded_channel().1, peer_addr, logger: Logger::new(test_name), sequencer: Sequencer::new(), @@ -430,12 +445,12 @@ mod tests { fn stream_reader_shuts_down_when_it_receives_the_shutdown_signal() { init_test_logging(); let test_name = "stream_reader_shuts_down_when_it_receives_the_shutdown_signal"; - let (shutdown_tx, shutdown_rx) = unbounded(); + let (mut shutdown_tx, shutdown_rx) = unbounded_channel(); let mut subject = make_subject(); subject.shutdown_signal = shutdown_rx; subject.logger = Logger::new(test_name); - shutdown_tx.send(()).unwrap(); + shutdown_tx.try_send(()).unwrap(); assert_eq!(subject.poll(), Ok(Async::Ready(()))); TestLogHandler::new().exists_log_containing(&format!( @@ -450,7 +465,7 @@ mod tests { proxy_client_sub: make_recorder().0.start().recipient(), stream: Box::new(ReadHalfWrapperMock::new()), stream_killer: unbounded().0, - shutdown_signal: unbounded().1, + shutdown_signal: unbounded_channel().1, peer_addr: SocketAddr::from_str("9.8.7.6:5432").unwrap(), logger: Logger::new("test"), sequencer: Sequencer::new(), From 3b387a7e4092e85a83b19ed4d2537fde8c3309bc Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Tue, 6 Aug 2024 12:20:59 +0530 Subject: [PATCH 29/65] GH-800: Add fn send_shutdown_signal_to_stream_reader --- node/src/proxy_client/stream_handler_pool.rs | 59 ++++++++++++-------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index de32893fb..0872ddae4 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -66,7 +66,6 @@ impl StreamHandlerPool for StreamHandlerPoolReal { payload: ClientRequestPayload_0v1, paying_wallet_opt: Option, ) { - // TODO: GH-800: We need a test to prove that do_housekeeping() is called self.do_housekeeping(); Self::process_package(payload, paying_wallet_opt, self.inner.clone()) } @@ -159,6 +158,27 @@ impl StreamHandlerPoolReal { }; } + fn send_shutdown_signal_to_stream_reader( + mut reader_shutdown_tx: UnboundedSender<()>, + stream_key: &StreamKey, + logger: &Logger, + ) { + // TODO: GH-800: Test Drive Me especially the logs + match reader_shutdown_tx.try_send(()) { + Ok(()) => { + debug!(logger, "A shutdown signal was sent.") + } + Err(_e) => { + debug!( + logger, + "Unable to send a shutdown signal to the StreamReader for \ + stream key {:?}. The channel is already gone.", + stream_key + ); + } + } + } + fn clean_up_bad_stream( inner_arc: Arc>, stream_key: &StreamKey, @@ -170,17 +190,17 @@ impl StreamHandlerPoolReal { inner.logger, "Couldn't process request from CORES package: {}", error ); - if let Some(sender_wrapper) = inner.stream_writer_channels.remove(stream_key) { - debug!( - Logger::new("TEST"), - "clean_up_bad_stream() removed the stream key" - ); + if let Some(mut stream_senders) = inner.stream_writer_channels.remove(stream_key) { debug!( inner.logger, "Removing stream writer for {}", - sender_wrapper.writer_data.peer_addr() + stream_senders.writer_data.peer_addr() ); - // TODO: GH-800: Send a shutdown signal to the Reader + Self::send_shutdown_signal_to_stream_reader( + stream_senders.reader_shutdown_tx, + stream_key, + &inner.logger, + ) } Self::send_terminating_package( stream_key, @@ -232,19 +252,11 @@ impl StreamHandlerPoolReal { stream_key, stream_senders.writer_data.peer_addr() ); - match stream_senders.reader_shutdown_tx.try_send(()) { - Ok(()) => { - debug!(test_logger, "A shutdown signal was sent.") - } - Err(e) => { - debug!( - inner.logger, - "Unable to send a shutdown signal to the StreamReader for \ - stream key {:?}. The channel is already gone.", - stream_key - ); - } - } + Self::send_shutdown_signal_to_stream_reader( + stream_senders.reader_shutdown_tx, + &stream_key, + &inner.logger, + ); } None => { eprintln!("Failed to Remove stream key: {:?}", stream_key); @@ -764,6 +776,7 @@ mod tests { let cryptde = main_cryptde(); let (proxy_client, proxy_client_awaiter, proxy_client_recording_arc) = make_recorder(); let originator_key = PublicKey::new(&b"men's souls"[..]); + let (reader_shutdown_tx, mut reader_shutdown_rx) = unbounded_channel(); thread::spawn(move || { let client_request_payload = ClientRequestPayload_0v1 { stream_key: StreamKey::make_meaningless_stream_key(), @@ -804,7 +817,7 @@ mod tests { client_request_payload.stream_key, StreamSenders { writer_data: Box::new(tx_to_write), - reader_shutdown_tx: unbounded_channel().0, + reader_shutdown_tx, }, ); @@ -812,6 +825,8 @@ mod tests { }); proxy_client_awaiter.await_message_count(1); let proxy_client_recording = proxy_client_recording_arc.lock().unwrap(); + let received = reader_shutdown_rx.poll().unwrap(); + assert_eq!(received, Async::Ready(Some(()))); assert_eq!( proxy_client_recording.get_record::(0), &InboundServerData { From f94c8d355822176dbb60bee9796c4bdae062deb6 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 7 Aug 2024 14:05:49 +0530 Subject: [PATCH 30/65] GH-800: wip: fixing 2 tests --- node/src/proxy_client/stream_handler_pool.rs | 128 +++++++++++-------- 1 file changed, 75 insertions(+), 53 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 0872ddae4..ba55fe0c1 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -1026,63 +1026,85 @@ mod tests { #[test] fn stream_handler_pool_sends_shutdown_signal_when_last_data_is_true() { + // TODO: GH-800: Identify why am I receiving this error - no Task is currently running init_test_logging(); let test_name = "stream_handler_pool_sends_shutdown_signal_when_last_data_is_true"; - let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); - thread::spawn(move || { - let stream_key = StreamKey::make_meaningful_stream_key("I should die"); - let client_request_payload = ClientRequestPayload_0v1 { - stream_key, - sequenced_packet: SequencedPacket { - data: b"I'm gonna kill you stream key".to_vec(), - sequence_number: 0, - last_data: true, - }, - target_hostname: Some(String::from("3.4.5.6:80")), - target_port: HTTP_PORT, - protocol: ProxyProtocol::HTTP, - originator_public_key: PublicKey::new(&b"brutal death"[..]), - }; - let package = ExpiredCoresPackage::new( - SocketAddr::from_str("1.2.3.4:1234").unwrap(), - Some(make_wallet("consuming")), - make_meaningless_route(), - client_request_payload.into(), - 0, - ); - let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); - let peer_actors = peer_actors_builder().build(); - let mut subject = StreamHandlerPoolReal::new( - Box::new(ResolverWrapperMock::new()), - main_cryptde(), - peer_actors.accountant.report_exit_service_provided.clone(), - peer_actors.proxy_client_opt.unwrap().clone(), - 100, - 200, - ); - { - let mut inner = subject.inner.lock().unwrap(); - inner.logger = Logger::new(test_name); - inner.stream_writer_channels.insert( - stream_key, - StreamSenders { - writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown_tx: shutdown_tx, - }, - ); - } + let mut system = System::new(test_name); + let future = future::lazy(move || { + let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); + actix::spawn(move || { + future::lazy({ + let stream_key = StreamKey::make_meaningful_stream_key("I should die"); + let client_request_payload = ClientRequestPayload_0v1 { + stream_key, + sequenced_packet: SequencedPacket { + data: b"I'm gonna kill you stream key".to_vec(), + sequence_number: 0, + last_data: true, + }, + target_hostname: Some(String::from("3.4.5.6:80")), + target_port: HTTP_PORT, + protocol: ProxyProtocol::HTTP, + originator_public_key: PublicKey::new(&b"brutal death"[..]), + }; + let package = ExpiredCoresPackage::new( + SocketAddr::from_str("1.2.3.4:1234").unwrap(), + Some(make_wallet("consuming")), + make_meaningless_route(), + client_request_payload.into(), + 0, + ); + let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); + let peer_actors = peer_actors_builder().build(); + let mut subject = StreamHandlerPoolReal::new( + Box::new(ResolverWrapperMock::new()), + main_cryptde(), + peer_actors.accountant.report_exit_service_provided.clone(), + peer_actors.proxy_client_opt.unwrap().clone(), + 100, + 200, + ); + { + let mut inner = subject.inner.lock().unwrap(); + inner.logger = Logger::new(test_name); + inner.stream_writer_channels.insert( + stream_key, + StreamSenders { + writer_data: Box::new(SenderWrapperMock::new(peer_addr)), + reader_shutdown_tx: shutdown_tx, + }, + ); + } - run_process_package_in_actix(subject, package); - }); - let received = shutdown_rx.poll().unwrap(); - assert_eq!(received, Async::Ready(Some(()))); - TestLogHandler::new().await_log_containing( - &format!( - "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ + let paying_wallet = package.paying_wallet.clone(); + let payload = match package.payload { + MessageType::ClientRequest(vd) => vd + .extract( + &crate::sub_lib::migrations::client_request_payload::MIGRATIONS, + ) + .unwrap(), + _ => panic!("Expected MessageType::ClientRequest, got something else"), + }; + // actix::run(move || { + subject.process_package(payload, paying_wallet); + // ok(()) + // }) + + // run_process_package_in_actix(subject, package); + }) + }); + let received = shutdown_rx.poll().unwrap(); + assert_eq!(received, Async::Ready(Some(()))); + TestLogHandler::new().await_log_containing( + &format!( + "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ for oUHoHuDKHjeWq+BJzBIqHpPFBQw to 3.4.5.6:80" - ), - 500, - ); + ), + 500, + ); + ok(()) + }); + system.block_on(future).unwrap(); } #[test] From 54040ae355352370feab82300067e9d5fc7c65ee Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 7 Aug 2024 17:55:16 +0530 Subject: [PATCH 31/65] GH-800: stream_handler_pool_sends_shutdown_signal_when_last_data_is_true is passing --- node/src/proxy_client/stream_handler_pool.rs | 135 +++++++++---------- 1 file changed, 60 insertions(+), 75 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index ba55fe0c1..9df8f863c 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -601,7 +601,7 @@ mod tests { use crate::test_utils::tokio_wrapper_mocks::WriteHalfWrapperMock; use actix::{Actor, System}; use core::any::TypeId; - use futures::Stream; + use futures::{Poll, Stream}; use masq_lib::constants::HTTP_PORT; use masq_lib::test_utils::logging::init_test_logging; use masq_lib::test_utils::logging::TestLogHandler; @@ -610,10 +610,11 @@ mod tests { use std::io::ErrorKind; use std::net::IpAddr; use std::net::SocketAddr; - use std::ops::Deref; + use std::ops::{Add, Deref}; use std::ptr::addr_of; use std::str::FromStr; use std::sync::{Arc, Mutex}; + use std::time::{Duration, Instant}; use std::{sync, thread}; use tokio; use tokio::prelude::Async; @@ -1026,85 +1027,69 @@ mod tests { #[test] fn stream_handler_pool_sends_shutdown_signal_when_last_data_is_true() { - // TODO: GH-800: Identify why am I receiving this error - no Task is currently running init_test_logging(); let test_name = "stream_handler_pool_sends_shutdown_signal_when_last_data_is_true"; let mut system = System::new(test_name); - let future = future::lazy(move || { - let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); - actix::spawn(move || { - future::lazy({ - let stream_key = StreamKey::make_meaningful_stream_key("I should die"); - let client_request_payload = ClientRequestPayload_0v1 { - stream_key, - sequenced_packet: SequencedPacket { - data: b"I'm gonna kill you stream key".to_vec(), - sequence_number: 0, - last_data: true, - }, - target_hostname: Some(String::from("3.4.5.6:80")), - target_port: HTTP_PORT, - protocol: ProxyProtocol::HTTP, - originator_public_key: PublicKey::new(&b"brutal death"[..]), - }; - let package = ExpiredCoresPackage::new( - SocketAddr::from_str("1.2.3.4:1234").unwrap(), - Some(make_wallet("consuming")), - make_meaningless_route(), - client_request_payload.into(), - 0, - ); - let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); - let peer_actors = peer_actors_builder().build(); - let mut subject = StreamHandlerPoolReal::new( - Box::new(ResolverWrapperMock::new()), - main_cryptde(), - peer_actors.accountant.report_exit_service_provided.clone(), - peer_actors.proxy_client_opt.unwrap().clone(), - 100, - 200, - ); - { - let mut inner = subject.inner.lock().unwrap(); - inner.logger = Logger::new(test_name); - inner.stream_writer_channels.insert( - stream_key, - StreamSenders { - writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown_tx: shutdown_tx, - }, - ); - } + let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); + let stream_key = StreamKey::make_meaningful_stream_key("I should die"); + let client_request_payload = ClientRequestPayload_0v1 { + stream_key, + sequenced_packet: SequencedPacket { + data: b"I'm gonna kill you stream key".to_vec(), + sequence_number: 0, + last_data: true, + }, + target_hostname: Some(String::from("3.4.5.6:80")), + target_port: HTTP_PORT, + protocol: ProxyProtocol::HTTP, + originator_public_key: PublicKey::new(&b"brutal death"[..]), + }; + let package = ExpiredCoresPackage::new( + SocketAddr::from_str("1.2.3.4:1234").unwrap(), + Some(make_wallet("consuming")), + make_meaningless_route(), + client_request_payload.into(), + 0, + ); + let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); + let peer_actors = peer_actors_builder().build(); + let mut subject = StreamHandlerPoolReal::new( + Box::new(ResolverWrapperMock::new()), + main_cryptde(), + peer_actors.accountant.report_exit_service_provided.clone(), + peer_actors.proxy_client_opt.unwrap().clone(), + 100, + 200, + ); + { + let mut inner = subject.inner.lock().unwrap(); + inner.logger = Logger::new(test_name); + inner.stream_writer_channels.insert( + stream_key, + StreamSenders { + writer_data: Box::new(SenderWrapperMock::new(peer_addr)), + reader_shutdown_tx: shutdown_tx, + }, + ); + } + let paying_wallet = package.paying_wallet.clone(); + let payload = match package.payload { + MessageType::ClientRequest(vd) => vd + .extract(&crate::sub_lib::migrations::client_request_payload::MIGRATIONS) + .unwrap(), + _ => panic!("Expected MessageType::ClientRequest, got something else"), + }; - let paying_wallet = package.paying_wallet.clone(); - let payload = match package.payload { - MessageType::ClientRequest(vd) => vd - .extract( - &crate::sub_lib::migrations::client_request_payload::MIGRATIONS, - ) - .unwrap(), - _ => panic!("Expected MessageType::ClientRequest, got something else"), - }; - // actix::run(move || { - subject.process_package(payload, paying_wallet); - // ok(()) - // }) + subject.process_package(payload, paying_wallet); - // run_process_package_in_actix(subject, package); - }) - }); - let received = shutdown_rx.poll().unwrap(); - assert_eq!(received, Async::Ready(Some(()))); - TestLogHandler::new().await_log_containing( - &format!( - "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ + let future_result = shutdown_rx.and_then(|_| Ok(())); + let future_with_timeout = + tokio::timer::Timeout::new(future_result, Duration::from_secs(10)).into_future(); + assert!(system.block_on(future_with_timeout).is_ok()); + TestLogHandler::new().exists_log_containing(&format!( + "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ for oUHoHuDKHjeWq+BJzBIqHpPFBQw to 3.4.5.6:80" - ), - 500, - ); - ok(()) - }); - system.block_on(future).unwrap(); + )); } #[test] From 31db7c4c0281a9a83099038b4d456f8c2e29b06c Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Fri, 16 Aug 2024 13:02:15 +0530 Subject: [PATCH 32/65] GH-800: all tests in stream_handler_pool.rs are passing --- node/src/proxy_client/stream_handler_pool.rs | 123 ++++++++++--------- 1 file changed, 62 insertions(+), 61 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 9df8f863c..135fa0b28 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -952,77 +952,78 @@ mod tests { } #[test] - fn while_housekeeping_the_stream_senders_are_received_by_stream_handler_pool() { + fn while_housekeeping_the_shutdown_signal_is_sent() { init_test_logging(); let test_name = "stream_handler_pool_sends_shutdown_signal_when_last_data_is_true"; let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); let (stream_adder_tx, stream_adder_rx) = unbounded(); - thread::spawn(move || { - let stream_key = StreamKey::make_meaningful_stream_key("I should die"); - let client_request_payload = ClientRequestPayload_0v1 { + let mut system = System::new(test_name); + let stream_key = StreamKey::make_meaningful_stream_key("I should die"); + let client_request_payload = ClientRequestPayload_0v1 { + stream_key, + sequenced_packet: SequencedPacket { + data: b"I'm gonna kill you stream key".to_vec(), + sequence_number: 0, + last_data: true, + }, + target_hostname: Some(String::from("3.4.5.6:80")), + target_port: HTTP_PORT, + protocol: ProxyProtocol::HTTP, + originator_public_key: PublicKey::new(&b"brutal death"[..]), + }; + let package = ExpiredCoresPackage::new( + SocketAddr::from_str("1.2.3.4:1234").unwrap(), + Some(make_wallet("consuming")), + make_meaningless_route(), + client_request_payload.into(), + 0, + ); + let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); + let peer_actors = peer_actors_builder().build(); + let mut subject = StreamHandlerPoolReal::new( + Box::new(ResolverWrapperMock::new()), + main_cryptde(), + peer_actors.accountant.report_exit_service_provided.clone(), + peer_actors.proxy_client_opt.unwrap().clone(), + 100, + 200, + ); + { + let mut inner = subject.inner.lock().unwrap(); + inner.logger = Logger::new(test_name); + inner.stream_writer_channels.insert( stream_key, - sequenced_packet: SequencedPacket { - data: b"I'm gonna kill you stream key".to_vec(), - sequence_number: 0, - last_data: true, + StreamSenders { + writer_data: Box::new(SenderWrapperMock::new(peer_addr)), + reader_shutdown_tx: shutdown_tx, }, - target_hostname: Some(String::from("3.4.5.6:80")), - target_port: HTTP_PORT, - protocol: ProxyProtocol::HTTP, - originator_public_key: PublicKey::new(&b"brutal death"[..]), - }; - let package = ExpiredCoresPackage::new( - SocketAddr::from_str("1.2.3.4:1234").unwrap(), - Some(make_wallet("consuming")), - make_meaningless_route(), - client_request_payload.into(), - 0, - ); - let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); - let peer_actors = peer_actors_builder().build(); - let mut subject = StreamHandlerPoolReal::new( - Box::new(ResolverWrapperMock::new()), - main_cryptde(), - peer_actors.accountant.report_exit_service_provided.clone(), - peer_actors.proxy_client_opt.unwrap().clone(), - 100, - 200, ); - subject.stream_adder_rx = stream_adder_rx; - { - let mut inner = subject.inner.lock().unwrap(); - inner.logger = Logger::new(test_name); - inner.stream_writer_channels.insert( - stream_key, - StreamSenders { - writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown_tx: shutdown_tx, - }, - ); - inner.establisher_factory = Box::new(StreamEstablisherFactoryReal { - cryptde: main_cryptde(), - stream_adder_tx, - stream_killer_tx: unbounded().0, - proxy_client_subs: make_proxy_client_subs_from_recorder( - &make_recorder().0.start(), - ), - logger: Logger::new("test"), - }); - } + inner.establisher_factory = Box::new(StreamEstablisherFactoryReal { + cryptde: main_cryptde(), + stream_adder_tx, + stream_killer_tx: unbounded().0, + proxy_client_subs: make_proxy_client_subs_from_recorder(&make_recorder().0.start()), + logger: Logger::new("test"), + }); + } + let paying_wallet = package.paying_wallet.clone(); + let payload = match package.payload { + MessageType::ClientRequest(vd) => vd + .extract(&crate::sub_lib::migrations::client_request_payload::MIGRATIONS) + .unwrap(), + _ => panic!("Expected MessageType::ClientRequest, got something else"), + }; - // TODO: GH-800: Make sure that the stream_adder_tx sends something to the receiver + subject.process_package(payload, paying_wallet); - run_process_package_in_actix(subject, package); - }); - let received = shutdown_rx.poll().unwrap(); - assert_eq!(received, Async::Ready(Some(()))); - TestLogHandler::new().await_log_containing( - &format!( - "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ + let future_result = shutdown_rx.and_then(|_| Ok(())); + let future_with_timeout = + tokio::timer::Timeout::new(future_result, Duration::from_secs(10)).into_future(); + assert!(system.block_on(future_with_timeout).is_ok()); + TestLogHandler::new().exists_log_containing(&format!( + "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ for oUHoHuDKHjeWq+BJzBIqHpPFBQw to 3.4.5.6:80" - ), - 500, - ); + )); } #[test] From 4f8c141c4adbef9ab5ffd8d28840c4b9f7979da1 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Tue, 27 Aug 2024 12:44:02 +0530 Subject: [PATCH 33/65] GH-800: add test for the logs; all tests passing --- node/src/proxy_client/stream_establisher.rs | 1 - node/src/proxy_client/stream_handler_pool.rs | 14 +++++++++++--- node/tests/connection_shutdown_test.rs | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/node/src/proxy_client/stream_establisher.rs b/node/src/proxy_client/stream_establisher.rs index c485e71c9..ccbaae2f3 100644 --- a/node/src/proxy_client/stream_establisher.rs +++ b/node/src/proxy_client/stream_establisher.rs @@ -61,7 +61,6 @@ impl StreamEstablisher { payload.target_port, &self.logger, )?; - // TODO: GH-800: Change it to a tokio channel instead of a crossbeam channel let (shutdown_signal_tx, shutdown_signal_rx) = tokio::sync::mpsc::unbounded_channel(); self.spawn_stream_reader( diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 135fa0b28..f73aca19d 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -163,10 +163,13 @@ impl StreamHandlerPoolReal { stream_key: &StreamKey, logger: &Logger, ) { - // TODO: GH-800: Test Drive Me especially the logs match reader_shutdown_tx.try_send(()) { Ok(()) => { - debug!(logger, "A shutdown signal was sent.") + debug!( + logger, + "A shutdown signal was sent to the StreamReader for stream key {:?}.", + stream_key + ); } Err(_e) => { debug!( @@ -1087,7 +1090,12 @@ mod tests { let future_with_timeout = tokio::timer::Timeout::new(future_result, Duration::from_secs(10)).into_future(); assert!(system.block_on(future_with_timeout).is_ok()); - TestLogHandler::new().exists_log_containing(&format!( + let tlh = TestLogHandler::new(); + tlh.exists_log_containing(&format!( + "DEBUG: {test_name}: A shutdown signal was sent to the StreamReader \ + for stream key oUHoHuDKHjeWq+BJzBIqHpPFBQw." + )); + tlh.exists_log_containing(&format!( "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ for oUHoHuDKHjeWq+BJzBIqHpPFBQw to 3.4.5.6:80" )); diff --git a/node/tests/connection_shutdown_test.rs b/node/tests/connection_shutdown_test.rs index 1c2a23692..38dbf2cb5 100644 --- a/node/tests/connection_shutdown_test.rs +++ b/node/tests/connection_shutdown_test.rs @@ -43,7 +43,7 @@ fn proxy_client_stream_reader_dies_when_client_stream_is_killed_integration() { let write_error = server_write_error_rx .recv_timeout(Duration::from_secs(60)) - .unwrap(); // TODO: GH-800 We are failing on this timeout + .unwrap(); assert_eq!(write_error.kind(), io::ErrorKind::BrokenPipe); join_handle.join().unwrap(); } From 1880006f8143499a0852f44d5eecc9acec38b9a7 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Tue, 27 Aug 2024 12:46:24 +0530 Subject: [PATCH 34/65] GH-800: remove lookup_ip() mock fns from a test --- node/src/proxy_client/stream_handler_pool.rs | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index f73aca19d..1f9801d31 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -846,8 +846,6 @@ mod tests { #[test] fn when_hostname_is_ip_establish_stream_without_dns_lookup() { let cryptde = main_cryptde(); - let lookup_ip_parameters = Arc::new(Mutex::new(vec![])); - let expected_lookup_ip_parameters = lookup_ip_parameters.clone(); let write_parameters = Arc::new(Mutex::new(vec![])); let expected_write_parameters = write_parameters.clone(); let (proxy_client, proxy_client_awaiter, proxy_client_recording_arc) = make_recorder(); @@ -872,13 +870,6 @@ mod tests { client_request_payload.into(), 0, ); - // TODO: GH-800: Apparently, we can remove both lookup_ip mock functions - let resolver = ResolverWrapperMock::new() - .lookup_ip_parameters(&lookup_ip_parameters) - .lookup_ip_success(vec![ - IpAddr::from_str("2.3.4.5").unwrap(), - IpAddr::from_str("3.4.5.6").unwrap(), - ]); let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); let first_read_result = b"HTTP/1.1 200 OK\r\n\r\n"; let reader = ReadHalfWrapperMock { @@ -896,7 +887,7 @@ mod tests { shutdown_results: Arc::new(Mutex::new(vec![])), }; let mut subject = StreamHandlerPoolReal::new( - Box::new(resolver), + Box::new(ResolverWrapperMock::new()), cryptde, peer_actors.accountant.report_exit_service_provided.clone(), peer_actors.proxy_client_opt.unwrap().clone(), @@ -933,10 +924,6 @@ mod tests { }); proxy_client_awaiter.await_message_count(1); - assert_eq!( - expected_lookup_ip_parameters.lock().unwrap().deref(), - &(vec![] as Vec) - ); assert_eq!( expected_write_parameters.lock().unwrap().remove(0), b"These are the times".to_vec() From d81c2f017b477702c1cad48d82ad02c141c2a6c0 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Tue, 27 Aug 2024 12:54:40 +0530 Subject: [PATCH 35/65] GH-800: remove warnings --- node/src/proxy_client/mod.rs | 7 +-- node/src/proxy_client/stream_establisher.rs | 2 +- node/src/proxy_client/stream_handler_pool.rs | 47 +++++++++----------- node/src/proxy_client/stream_reader.rs | 4 +- 4 files changed, 25 insertions(+), 35 deletions(-) diff --git a/node/src/proxy_client/mod.rs b/node/src/proxy_client/mod.rs index a4329b24f..d05cb505b 100644 --- a/node/src/proxy_client/mod.rs +++ b/node/src/proxy_client/mod.rs @@ -30,11 +30,11 @@ use crate::sub_lib::stream_key::StreamKey; use crate::sub_lib::utils::{handle_ui_crash_request, NODE_MAILBOX_CAPACITY}; use crate::sub_lib::versioned_data::VersionedData; use crate::sub_lib::wallet::Wallet; +use actix::Actor; use actix::Addr; use actix::Context; use actix::Handler; use actix::Recipient; -use actix::{Actor, Message}; use masq_lib::logger::Logger; use masq_lib::ui_gateway::NodeFromUiMessage; use pretty_hex::PrettyHex; @@ -48,11 +48,6 @@ use trust_dns_resolver::config::ResolverOpts; pub const CRASH_KEY: &str = "PROXYCLIENT"; -#[derive(Message)] -struct StopListeningForThisStream { - stream_key: StreamKey, -} - pub struct ProxyClient { dns_servers: Vec, resolver_wrapper_factory: Box, diff --git a/node/src/proxy_client/stream_establisher.rs b/node/src/proxy_client/stream_establisher.rs index ccbaae2f3..e80021cb9 100644 --- a/node/src/proxy_client/stream_establisher.rs +++ b/node/src/proxy_client/stream_establisher.rs @@ -3,9 +3,9 @@ use crate::proxy_client::stream_handler_pool::StreamSenders; use crate::proxy_client::stream_reader::StreamReader; use crate::proxy_client::stream_writer::StreamWriter; +use crate::sub_lib::channel_wrappers::FuturesChannelFactory; use crate::sub_lib::channel_wrappers::FuturesChannelFactoryReal; use crate::sub_lib::channel_wrappers::SenderWrapper; -use crate::sub_lib::channel_wrappers::{FuturesChannelFactory, SenderWrapperReal}; use crate::sub_lib::cryptde::CryptDE; use crate::sub_lib::proxy_client::{InboundServerData, ProxyClientSubs}; use crate::sub_lib::proxy_server::ClientRequestPayload_0v1; diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 1f9801d31..76c2ab259 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -13,10 +13,10 @@ use crate::sub_lib::proxy_server::ClientRequestPayload_0v1; use crate::sub_lib::sequence_buffer::SequencedPacket; use crate::sub_lib::stream_key::StreamKey; use crate::sub_lib::wallet::Wallet; -use actix::{Message, Recipient}; +use actix::Recipient; use crossbeam_channel::{unbounded, Receiver}; +use futures::future; use futures::future::Future; -use futures::{future, Sink}; use masq_lib::logger::Logger; use std::collections::HashMap; use std::io; @@ -26,8 +26,7 @@ use std::sync::{Arc, Mutex}; use std::time::SystemTime; use tokio::prelude::future::FutureResult; use tokio::prelude::future::{err, ok}; -use tokio::sync::mpsc::error::TrySendError; -use tokio::sync::mpsc::{Sender, UnboundedSender}; +use tokio::sync::mpsc::UnboundedSender; use trust_dns_resolver::error::ResolveError; use trust_dns_resolver::lookup_ip::LookupIp; @@ -193,7 +192,7 @@ impl StreamHandlerPoolReal { inner.logger, "Couldn't process request from CORES package: {}", error ); - if let Some(mut stream_senders) = inner.stream_writer_channels.remove(stream_key) { + if let Some(stream_senders) = inner.stream_writer_channels.remove(stream_key) { debug!( inner.logger, "Removing stream writer for {}", @@ -248,7 +247,7 @@ impl StreamHandlerPoolReal { if last_data { debug!(test_logger, "last_data = true"); match inner.stream_writer_channels.remove(&stream_key) { - Some(mut stream_senders) => { + Some(stream_senders) => { debug!( inner.logger, "Removing StreamWriter and Shutting down StreamReader for {:?} to {}", @@ -500,7 +499,8 @@ impl StreamHandlerPoolReal { data: vec![], }) .expect("ProxyClient is dead"); - if let Err(e) = stream_senders.reader_shutdown_tx.try_send(()) { + // TODO: GH-800: Perhaps you want the function that you created over here + if let Err(_e) = stream_senders.reader_shutdown_tx.try_send(()) { debug!(inner.logger, "Unable to send a shutdown signal to the StreamReader for stream key {:?}. The channel is already gone.", stream_key) }; // Test should have a fake server, and the (read and write should be different) server @@ -578,7 +578,6 @@ impl StreamHandlerPoolFactory for StreamHandlerPoolFactoryReal { #[cfg(test)] mod tests { use super::*; - use crate::match_every_type_id; use crate::node_test_utils::check_timestamp; use crate::proxy_client::local_test_utils::make_send_error; use crate::proxy_client::local_test_utils::ResolverWrapperMock; @@ -597,14 +596,11 @@ mod tests { use crate::test_utils::make_wallet; use crate::test_utils::recorder::peer_actors_builder; use crate::test_utils::recorder::{make_proxy_client_subs_from_recorder, make_recorder}; - use crate::test_utils::recorder_stop_conditions::StopCondition; - use crate::test_utils::recorder_stop_conditions::StopConditions; use crate::test_utils::stream_connector_mock::StreamConnectorMock; use crate::test_utils::tokio_wrapper_mocks::ReadHalfWrapperMock; use crate::test_utils::tokio_wrapper_mocks::WriteHalfWrapperMock; use actix::{Actor, System}; - use core::any::TypeId; - use futures::{Poll, Stream}; + use futures::Stream; use masq_lib::constants::HTTP_PORT; use masq_lib::test_utils::logging::init_test_logging; use masq_lib::test_utils::logging::TestLogHandler; @@ -613,12 +609,11 @@ mod tests { use std::io::ErrorKind; use std::net::IpAddr; use std::net::SocketAddr; - use std::ops::{Add, Deref}; - use std::ptr::addr_of; + use std::ops::Deref; use std::str::FromStr; use std::sync::{Arc, Mutex}; - use std::time::{Duration, Instant}; - use std::{sync, thread}; + use std::thread; + use std::time::Duration; use tokio; use tokio::prelude::Async; use tokio::sync::mpsc::unbounded_channel; @@ -945,8 +940,8 @@ mod tests { fn while_housekeeping_the_shutdown_signal_is_sent() { init_test_logging(); let test_name = "stream_handler_pool_sends_shutdown_signal_when_last_data_is_true"; - let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); - let (stream_adder_tx, stream_adder_rx) = unbounded(); + let (shutdown_tx, shutdown_rx) = unbounded_channel(); + let (stream_adder_tx, _stream_adder_rx) = unbounded(); let mut system = System::new(test_name); let stream_key = StreamKey::make_meaningful_stream_key("I should die"); let client_request_payload = ClientRequestPayload_0v1 { @@ -970,7 +965,7 @@ mod tests { ); let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); let peer_actors = peer_actors_builder().build(); - let mut subject = StreamHandlerPoolReal::new( + let subject = StreamHandlerPoolReal::new( Box::new(ResolverWrapperMock::new()), main_cryptde(), peer_actors.accountant.report_exit_service_provided.clone(), @@ -1021,7 +1016,7 @@ mod tests { init_test_logging(); let test_name = "stream_handler_pool_sends_shutdown_signal_when_last_data_is_true"; let mut system = System::new(test_name); - let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); + let (shutdown_tx, shutdown_rx) = unbounded_channel(); let stream_key = StreamKey::make_meaningful_stream_key("I should die"); let client_request_payload = ClientRequestPayload_0v1 { stream_key, @@ -1044,7 +1039,7 @@ mod tests { ); let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); let peer_actors = peer_actors_builder().build(); - let mut subject = StreamHandlerPoolReal::new( + let subject = StreamHandlerPoolReal::new( Box::new(ResolverWrapperMock::new()), main_cryptde(), peer_actors.accountant.report_exit_service_provided.clone(), @@ -1116,7 +1111,7 @@ mod tests { ); let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); let peer_actors = peer_actors_builder().build(); - let mut subject = StreamHandlerPoolReal::new( + let subject = StreamHandlerPoolReal::new( Box::new(ResolverWrapperMock::new()), main_cryptde(), peer_actors.accountant.report_exit_service_provided.clone(), @@ -2108,8 +2103,8 @@ mod tests { subject.inner.lock().unwrap().logger = Logger::new(test_name); } let first_stream_key = StreamKey::make_meaningful_stream_key("first_stream_key"); - let (first_writer_data_tx, first_writer_data_rx) = futures::sync::mpsc::unbounded(); - let (first_shutdown_tx, first_shutdown_rx) = unbounded_channel(); + let (first_writer_data_tx, _first_writer_data_rx) = futures::sync::mpsc::unbounded(); + let (first_shutdown_tx, _first_shutdown_rx) = unbounded_channel(); let first_stream_senders = StreamSenders { writer_data: Box::new(SenderWrapperReal::new( SocketAddr::from_str("1.2.3.4:5678").unwrap(), @@ -2117,8 +2112,8 @@ mod tests { )), reader_shutdown_tx: first_shutdown_tx, }; - let (second_writer_data_tx, second_writer_data_rx) = futures::sync::mpsc::unbounded(); - let (second_shutdown_tx, second_shutdown_rx) = unbounded_channel(); + let (second_writer_data_tx, _second_writer_data_rx) = futures::sync::mpsc::unbounded(); + let (second_shutdown_tx, _second_shutdown_rx) = unbounded_channel(); let second_stream_key = StreamKey::make_meaningful_stream_key("second_stream_key"); let second_stream_senders = StreamSenders { writer_data: Box::new(SenderWrapperReal::new( diff --git a/node/src/proxy_client/stream_reader.rs b/node/src/proxy_client/stream_reader.rs index d9e24bd4d..59686c1cf 100644 --- a/node/src/proxy_client/stream_reader.rs +++ b/node/src/proxy_client/stream_reader.rs @@ -6,8 +6,8 @@ use crate::sub_lib::tokio_wrappers::ReadHalfWrapper; use crate::sub_lib::utils; use crate::sub_lib::utils::indicates_dead_stream; use actix::Recipient; -use crossbeam_channel::{Receiver, Sender, TryRecvError}; -use futures::{Poll, Stream}; +use crossbeam_channel::Sender; +use futures::Stream; use masq_lib::logger::Logger; use std::net::SocketAddr; use tokio::prelude::Async; From ae0893040def1384e40cd5914def79157fc131a3 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Tue, 27 Aug 2024 12:59:22 +0530 Subject: [PATCH 36/65] GH-800: use fn send_shutdown_signal_to_stream_reader in clean_up_dead_streams() --- node/src/proxy_client/stream_handler_pool.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 76c2ab259..e872041ea 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -483,7 +483,7 @@ impl StreamHandlerPoolReal { let mut inner = self.inner.lock().expect("Stream handler pool is poisoned"); while let Ok((stream_key, sequence_number)) = self.stream_killer_rx.try_recv() { match inner.stream_writer_channels.remove(&stream_key) { - Some(mut stream_senders) => { + Some(stream_senders) => { debug!( Logger::new("TEST"), "clean_up_dead_streams() removed the stream key" @@ -499,11 +499,11 @@ impl StreamHandlerPoolReal { data: vec![], }) .expect("ProxyClient is dead"); - // TODO: GH-800: Perhaps you want the function that you created over here - if let Err(_e) = stream_senders.reader_shutdown_tx.try_send(()) { - debug!(inner.logger, "Unable to send a shutdown signal to the StreamReader for stream key {:?}. The channel is already gone.", stream_key) - }; - // Test should have a fake server, and the (read and write should be different) server + Self::send_shutdown_signal_to_stream_reader( + stream_senders.reader_shutdown_tx, + &stream_key, + &inner.logger, + ); debug!( inner.logger, "Killed StreamWriter and StreamReader for the stream key {:?} to {} and sent server-drop report", From 23fc9ab8a97f29cbe5d7699a880434023fe20ffb Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 4 Sep 2024 11:39:38 +0530 Subject: [PATCH 37/65] Revert "GH-800: use fn send_shutdown_signal_to_stream_reader in clean_up_dead_streams()" This reverts commit ae0893040def1384e40cd5914def79157fc131a3. --- node/src/proxy_client/stream_handler_pool.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index e872041ea..76c2ab259 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -483,7 +483,7 @@ impl StreamHandlerPoolReal { let mut inner = self.inner.lock().expect("Stream handler pool is poisoned"); while let Ok((stream_key, sequence_number)) = self.stream_killer_rx.try_recv() { match inner.stream_writer_channels.remove(&stream_key) { - Some(stream_senders) => { + Some(mut stream_senders) => { debug!( Logger::new("TEST"), "clean_up_dead_streams() removed the stream key" @@ -499,11 +499,11 @@ impl StreamHandlerPoolReal { data: vec![], }) .expect("ProxyClient is dead"); - Self::send_shutdown_signal_to_stream_reader( - stream_senders.reader_shutdown_tx, - &stream_key, - &inner.logger, - ); + // TODO: GH-800: Perhaps you want the function that you created over here + if let Err(_e) = stream_senders.reader_shutdown_tx.try_send(()) { + debug!(inner.logger, "Unable to send a shutdown signal to the StreamReader for stream key {:?}. The channel is already gone.", stream_key) + }; + // Test should have a fake server, and the (read and write should be different) server debug!( inner.logger, "Killed StreamWriter and StreamReader for the stream key {:?} to {} and sent server-drop report", From f9491e76723d36fa5b1ee81bb9b0b140a112aaed Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 4 Sep 2024 11:39:51 +0530 Subject: [PATCH 38/65] Revert "GH-800: remove warnings" This reverts commit d81c2f017b477702c1cad48d82ad02c141c2a6c0. --- node/src/proxy_client/mod.rs | 7 ++- node/src/proxy_client/stream_establisher.rs | 2 +- node/src/proxy_client/stream_handler_pool.rs | 47 +++++++++++--------- node/src/proxy_client/stream_reader.rs | 4 +- 4 files changed, 35 insertions(+), 25 deletions(-) diff --git a/node/src/proxy_client/mod.rs b/node/src/proxy_client/mod.rs index d05cb505b..a4329b24f 100644 --- a/node/src/proxy_client/mod.rs +++ b/node/src/proxy_client/mod.rs @@ -30,11 +30,11 @@ use crate::sub_lib::stream_key::StreamKey; use crate::sub_lib::utils::{handle_ui_crash_request, NODE_MAILBOX_CAPACITY}; use crate::sub_lib::versioned_data::VersionedData; use crate::sub_lib::wallet::Wallet; -use actix::Actor; use actix::Addr; use actix::Context; use actix::Handler; use actix::Recipient; +use actix::{Actor, Message}; use masq_lib::logger::Logger; use masq_lib::ui_gateway::NodeFromUiMessage; use pretty_hex::PrettyHex; @@ -48,6 +48,11 @@ use trust_dns_resolver::config::ResolverOpts; pub const CRASH_KEY: &str = "PROXYCLIENT"; +#[derive(Message)] +struct StopListeningForThisStream { + stream_key: StreamKey, +} + pub struct ProxyClient { dns_servers: Vec, resolver_wrapper_factory: Box, diff --git a/node/src/proxy_client/stream_establisher.rs b/node/src/proxy_client/stream_establisher.rs index e80021cb9..ccbaae2f3 100644 --- a/node/src/proxy_client/stream_establisher.rs +++ b/node/src/proxy_client/stream_establisher.rs @@ -3,9 +3,9 @@ use crate::proxy_client::stream_handler_pool::StreamSenders; use crate::proxy_client::stream_reader::StreamReader; use crate::proxy_client::stream_writer::StreamWriter; -use crate::sub_lib::channel_wrappers::FuturesChannelFactory; use crate::sub_lib::channel_wrappers::FuturesChannelFactoryReal; use crate::sub_lib::channel_wrappers::SenderWrapper; +use crate::sub_lib::channel_wrappers::{FuturesChannelFactory, SenderWrapperReal}; use crate::sub_lib::cryptde::CryptDE; use crate::sub_lib::proxy_client::{InboundServerData, ProxyClientSubs}; use crate::sub_lib::proxy_server::ClientRequestPayload_0v1; diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 76c2ab259..1f9801d31 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -13,10 +13,10 @@ use crate::sub_lib::proxy_server::ClientRequestPayload_0v1; use crate::sub_lib::sequence_buffer::SequencedPacket; use crate::sub_lib::stream_key::StreamKey; use crate::sub_lib::wallet::Wallet; -use actix::Recipient; +use actix::{Message, Recipient}; use crossbeam_channel::{unbounded, Receiver}; -use futures::future; use futures::future::Future; +use futures::{future, Sink}; use masq_lib::logger::Logger; use std::collections::HashMap; use std::io; @@ -26,7 +26,8 @@ use std::sync::{Arc, Mutex}; use std::time::SystemTime; use tokio::prelude::future::FutureResult; use tokio::prelude::future::{err, ok}; -use tokio::sync::mpsc::UnboundedSender; +use tokio::sync::mpsc::error::TrySendError; +use tokio::sync::mpsc::{Sender, UnboundedSender}; use trust_dns_resolver::error::ResolveError; use trust_dns_resolver::lookup_ip::LookupIp; @@ -192,7 +193,7 @@ impl StreamHandlerPoolReal { inner.logger, "Couldn't process request from CORES package: {}", error ); - if let Some(stream_senders) = inner.stream_writer_channels.remove(stream_key) { + if let Some(mut stream_senders) = inner.stream_writer_channels.remove(stream_key) { debug!( inner.logger, "Removing stream writer for {}", @@ -247,7 +248,7 @@ impl StreamHandlerPoolReal { if last_data { debug!(test_logger, "last_data = true"); match inner.stream_writer_channels.remove(&stream_key) { - Some(stream_senders) => { + Some(mut stream_senders) => { debug!( inner.logger, "Removing StreamWriter and Shutting down StreamReader for {:?} to {}", @@ -499,8 +500,7 @@ impl StreamHandlerPoolReal { data: vec![], }) .expect("ProxyClient is dead"); - // TODO: GH-800: Perhaps you want the function that you created over here - if let Err(_e) = stream_senders.reader_shutdown_tx.try_send(()) { + if let Err(e) = stream_senders.reader_shutdown_tx.try_send(()) { debug!(inner.logger, "Unable to send a shutdown signal to the StreamReader for stream key {:?}. The channel is already gone.", stream_key) }; // Test should have a fake server, and the (read and write should be different) server @@ -578,6 +578,7 @@ impl StreamHandlerPoolFactory for StreamHandlerPoolFactoryReal { #[cfg(test)] mod tests { use super::*; + use crate::match_every_type_id; use crate::node_test_utils::check_timestamp; use crate::proxy_client::local_test_utils::make_send_error; use crate::proxy_client::local_test_utils::ResolverWrapperMock; @@ -596,11 +597,14 @@ mod tests { use crate::test_utils::make_wallet; use crate::test_utils::recorder::peer_actors_builder; use crate::test_utils::recorder::{make_proxy_client_subs_from_recorder, make_recorder}; + use crate::test_utils::recorder_stop_conditions::StopCondition; + use crate::test_utils::recorder_stop_conditions::StopConditions; use crate::test_utils::stream_connector_mock::StreamConnectorMock; use crate::test_utils::tokio_wrapper_mocks::ReadHalfWrapperMock; use crate::test_utils::tokio_wrapper_mocks::WriteHalfWrapperMock; use actix::{Actor, System}; - use futures::Stream; + use core::any::TypeId; + use futures::{Poll, Stream}; use masq_lib::constants::HTTP_PORT; use masq_lib::test_utils::logging::init_test_logging; use masq_lib::test_utils::logging::TestLogHandler; @@ -609,11 +613,12 @@ mod tests { use std::io::ErrorKind; use std::net::IpAddr; use std::net::SocketAddr; - use std::ops::Deref; + use std::ops::{Add, Deref}; + use std::ptr::addr_of; use std::str::FromStr; use std::sync::{Arc, Mutex}; - use std::thread; - use std::time::Duration; + use std::time::{Duration, Instant}; + use std::{sync, thread}; use tokio; use tokio::prelude::Async; use tokio::sync::mpsc::unbounded_channel; @@ -940,8 +945,8 @@ mod tests { fn while_housekeeping_the_shutdown_signal_is_sent() { init_test_logging(); let test_name = "stream_handler_pool_sends_shutdown_signal_when_last_data_is_true"; - let (shutdown_tx, shutdown_rx) = unbounded_channel(); - let (stream_adder_tx, _stream_adder_rx) = unbounded(); + let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); + let (stream_adder_tx, stream_adder_rx) = unbounded(); let mut system = System::new(test_name); let stream_key = StreamKey::make_meaningful_stream_key("I should die"); let client_request_payload = ClientRequestPayload_0v1 { @@ -965,7 +970,7 @@ mod tests { ); let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); let peer_actors = peer_actors_builder().build(); - let subject = StreamHandlerPoolReal::new( + let mut subject = StreamHandlerPoolReal::new( Box::new(ResolverWrapperMock::new()), main_cryptde(), peer_actors.accountant.report_exit_service_provided.clone(), @@ -1016,7 +1021,7 @@ mod tests { init_test_logging(); let test_name = "stream_handler_pool_sends_shutdown_signal_when_last_data_is_true"; let mut system = System::new(test_name); - let (shutdown_tx, shutdown_rx) = unbounded_channel(); + let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); let stream_key = StreamKey::make_meaningful_stream_key("I should die"); let client_request_payload = ClientRequestPayload_0v1 { stream_key, @@ -1039,7 +1044,7 @@ mod tests { ); let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); let peer_actors = peer_actors_builder().build(); - let subject = StreamHandlerPoolReal::new( + let mut subject = StreamHandlerPoolReal::new( Box::new(ResolverWrapperMock::new()), main_cryptde(), peer_actors.accountant.report_exit_service_provided.clone(), @@ -1111,7 +1116,7 @@ mod tests { ); let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); let peer_actors = peer_actors_builder().build(); - let subject = StreamHandlerPoolReal::new( + let mut subject = StreamHandlerPoolReal::new( Box::new(ResolverWrapperMock::new()), main_cryptde(), peer_actors.accountant.report_exit_service_provided.clone(), @@ -2103,8 +2108,8 @@ mod tests { subject.inner.lock().unwrap().logger = Logger::new(test_name); } let first_stream_key = StreamKey::make_meaningful_stream_key("first_stream_key"); - let (first_writer_data_tx, _first_writer_data_rx) = futures::sync::mpsc::unbounded(); - let (first_shutdown_tx, _first_shutdown_rx) = unbounded_channel(); + let (first_writer_data_tx, first_writer_data_rx) = futures::sync::mpsc::unbounded(); + let (first_shutdown_tx, first_shutdown_rx) = unbounded_channel(); let first_stream_senders = StreamSenders { writer_data: Box::new(SenderWrapperReal::new( SocketAddr::from_str("1.2.3.4:5678").unwrap(), @@ -2112,8 +2117,8 @@ mod tests { )), reader_shutdown_tx: first_shutdown_tx, }; - let (second_writer_data_tx, _second_writer_data_rx) = futures::sync::mpsc::unbounded(); - let (second_shutdown_tx, _second_shutdown_rx) = unbounded_channel(); + let (second_writer_data_tx, second_writer_data_rx) = futures::sync::mpsc::unbounded(); + let (second_shutdown_tx, second_shutdown_rx) = unbounded_channel(); let second_stream_key = StreamKey::make_meaningful_stream_key("second_stream_key"); let second_stream_senders = StreamSenders { writer_data: Box::new(SenderWrapperReal::new( diff --git a/node/src/proxy_client/stream_reader.rs b/node/src/proxy_client/stream_reader.rs index 59686c1cf..d9e24bd4d 100644 --- a/node/src/proxy_client/stream_reader.rs +++ b/node/src/proxy_client/stream_reader.rs @@ -6,8 +6,8 @@ use crate::sub_lib::tokio_wrappers::ReadHalfWrapper; use crate::sub_lib::utils; use crate::sub_lib::utils::indicates_dead_stream; use actix::Recipient; -use crossbeam_channel::Sender; -use futures::Stream; +use crossbeam_channel::{Receiver, Sender, TryRecvError}; +use futures::{Poll, Stream}; use masq_lib::logger::Logger; use std::net::SocketAddr; use tokio::prelude::Async; From 3e3fa7198da1d1792fc812b9b40fe1565dbfa014 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 4 Sep 2024 11:39:54 +0530 Subject: [PATCH 39/65] Revert "GH-800: remove lookup_ip() mock fns from a test" This reverts commit 1880006f8143499a0852f44d5eecc9acec38b9a7. --- node/src/proxy_client/stream_handler_pool.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 1f9801d31..f73aca19d 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -846,6 +846,8 @@ mod tests { #[test] fn when_hostname_is_ip_establish_stream_without_dns_lookup() { let cryptde = main_cryptde(); + let lookup_ip_parameters = Arc::new(Mutex::new(vec![])); + let expected_lookup_ip_parameters = lookup_ip_parameters.clone(); let write_parameters = Arc::new(Mutex::new(vec![])); let expected_write_parameters = write_parameters.clone(); let (proxy_client, proxy_client_awaiter, proxy_client_recording_arc) = make_recorder(); @@ -870,6 +872,13 @@ mod tests { client_request_payload.into(), 0, ); + // TODO: GH-800: Apparently, we can remove both lookup_ip mock functions + let resolver = ResolverWrapperMock::new() + .lookup_ip_parameters(&lookup_ip_parameters) + .lookup_ip_success(vec![ + IpAddr::from_str("2.3.4.5").unwrap(), + IpAddr::from_str("3.4.5.6").unwrap(), + ]); let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); let first_read_result = b"HTTP/1.1 200 OK\r\n\r\n"; let reader = ReadHalfWrapperMock { @@ -887,7 +896,7 @@ mod tests { shutdown_results: Arc::new(Mutex::new(vec![])), }; let mut subject = StreamHandlerPoolReal::new( - Box::new(ResolverWrapperMock::new()), + Box::new(resolver), cryptde, peer_actors.accountant.report_exit_service_provided.clone(), peer_actors.proxy_client_opt.unwrap().clone(), @@ -924,6 +933,10 @@ mod tests { }); proxy_client_awaiter.await_message_count(1); + assert_eq!( + expected_lookup_ip_parameters.lock().unwrap().deref(), + &(vec![] as Vec) + ); assert_eq!( expected_write_parameters.lock().unwrap().remove(0), b"These are the times".to_vec() From d4e807505ca0b5ba431bacd40943e1bf78e30e47 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 4 Sep 2024 11:39:56 +0530 Subject: [PATCH 40/65] Revert "GH-800: add test for the logs; all tests passing" This reverts commit 4f8c141c4adbef9ab5ffd8d28840c4b9f7979da1. --- node/src/proxy_client/stream_establisher.rs | 1 + node/src/proxy_client/stream_handler_pool.rs | 14 +++----------- node/tests/connection_shutdown_test.rs | 2 +- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/node/src/proxy_client/stream_establisher.rs b/node/src/proxy_client/stream_establisher.rs index ccbaae2f3..c485e71c9 100644 --- a/node/src/proxy_client/stream_establisher.rs +++ b/node/src/proxy_client/stream_establisher.rs @@ -61,6 +61,7 @@ impl StreamEstablisher { payload.target_port, &self.logger, )?; + // TODO: GH-800: Change it to a tokio channel instead of a crossbeam channel let (shutdown_signal_tx, shutdown_signal_rx) = tokio::sync::mpsc::unbounded_channel(); self.spawn_stream_reader( diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index f73aca19d..135fa0b28 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -163,13 +163,10 @@ impl StreamHandlerPoolReal { stream_key: &StreamKey, logger: &Logger, ) { + // TODO: GH-800: Test Drive Me especially the logs match reader_shutdown_tx.try_send(()) { Ok(()) => { - debug!( - logger, - "A shutdown signal was sent to the StreamReader for stream key {:?}.", - stream_key - ); + debug!(logger, "A shutdown signal was sent.") } Err(_e) => { debug!( @@ -1090,12 +1087,7 @@ mod tests { let future_with_timeout = tokio::timer::Timeout::new(future_result, Duration::from_secs(10)).into_future(); assert!(system.block_on(future_with_timeout).is_ok()); - let tlh = TestLogHandler::new(); - tlh.exists_log_containing(&format!( - "DEBUG: {test_name}: A shutdown signal was sent to the StreamReader \ - for stream key oUHoHuDKHjeWq+BJzBIqHpPFBQw." - )); - tlh.exists_log_containing(&format!( + TestLogHandler::new().exists_log_containing(&format!( "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ for oUHoHuDKHjeWq+BJzBIqHpPFBQw to 3.4.5.6:80" )); diff --git a/node/tests/connection_shutdown_test.rs b/node/tests/connection_shutdown_test.rs index 38dbf2cb5..1c2a23692 100644 --- a/node/tests/connection_shutdown_test.rs +++ b/node/tests/connection_shutdown_test.rs @@ -43,7 +43,7 @@ fn proxy_client_stream_reader_dies_when_client_stream_is_killed_integration() { let write_error = server_write_error_rx .recv_timeout(Duration::from_secs(60)) - .unwrap(); + .unwrap(); // TODO: GH-800 We are failing on this timeout assert_eq!(write_error.kind(), io::ErrorKind::BrokenPipe); join_handle.join().unwrap(); } From 5aa11073d8db112c4a70758e4434cc2fff7a9fc1 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 4 Sep 2024 11:39:57 +0530 Subject: [PATCH 41/65] Revert "GH-800: all tests in stream_handler_pool.rs are passing" This reverts commit 31db7c4c0281a9a83099038b4d456f8c2e29b06c. --- node/src/proxy_client/stream_handler_pool.rs | 123 +++++++++---------- 1 file changed, 61 insertions(+), 62 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 135fa0b28..9df8f863c 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -952,78 +952,77 @@ mod tests { } #[test] - fn while_housekeeping_the_shutdown_signal_is_sent() { + fn while_housekeeping_the_stream_senders_are_received_by_stream_handler_pool() { init_test_logging(); let test_name = "stream_handler_pool_sends_shutdown_signal_when_last_data_is_true"; let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); let (stream_adder_tx, stream_adder_rx) = unbounded(); - let mut system = System::new(test_name); - let stream_key = StreamKey::make_meaningful_stream_key("I should die"); - let client_request_payload = ClientRequestPayload_0v1 { - stream_key, - sequenced_packet: SequencedPacket { - data: b"I'm gonna kill you stream key".to_vec(), - sequence_number: 0, - last_data: true, - }, - target_hostname: Some(String::from("3.4.5.6:80")), - target_port: HTTP_PORT, - protocol: ProxyProtocol::HTTP, - originator_public_key: PublicKey::new(&b"brutal death"[..]), - }; - let package = ExpiredCoresPackage::new( - SocketAddr::from_str("1.2.3.4:1234").unwrap(), - Some(make_wallet("consuming")), - make_meaningless_route(), - client_request_payload.into(), - 0, - ); - let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); - let peer_actors = peer_actors_builder().build(); - let mut subject = StreamHandlerPoolReal::new( - Box::new(ResolverWrapperMock::new()), - main_cryptde(), - peer_actors.accountant.report_exit_service_provided.clone(), - peer_actors.proxy_client_opt.unwrap().clone(), - 100, - 200, - ); - { - let mut inner = subject.inner.lock().unwrap(); - inner.logger = Logger::new(test_name); - inner.stream_writer_channels.insert( + thread::spawn(move || { + let stream_key = StreamKey::make_meaningful_stream_key("I should die"); + let client_request_payload = ClientRequestPayload_0v1 { stream_key, - StreamSenders { - writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown_tx: shutdown_tx, + sequenced_packet: SequencedPacket { + data: b"I'm gonna kill you stream key".to_vec(), + sequence_number: 0, + last_data: true, }, + target_hostname: Some(String::from("3.4.5.6:80")), + target_port: HTTP_PORT, + protocol: ProxyProtocol::HTTP, + originator_public_key: PublicKey::new(&b"brutal death"[..]), + }; + let package = ExpiredCoresPackage::new( + SocketAddr::from_str("1.2.3.4:1234").unwrap(), + Some(make_wallet("consuming")), + make_meaningless_route(), + client_request_payload.into(), + 0, ); - inner.establisher_factory = Box::new(StreamEstablisherFactoryReal { - cryptde: main_cryptde(), - stream_adder_tx, - stream_killer_tx: unbounded().0, - proxy_client_subs: make_proxy_client_subs_from_recorder(&make_recorder().0.start()), - logger: Logger::new("test"), - }); - } - let paying_wallet = package.paying_wallet.clone(); - let payload = match package.payload { - MessageType::ClientRequest(vd) => vd - .extract(&crate::sub_lib::migrations::client_request_payload::MIGRATIONS) - .unwrap(), - _ => panic!("Expected MessageType::ClientRequest, got something else"), - }; + let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); + let peer_actors = peer_actors_builder().build(); + let mut subject = StreamHandlerPoolReal::new( + Box::new(ResolverWrapperMock::new()), + main_cryptde(), + peer_actors.accountant.report_exit_service_provided.clone(), + peer_actors.proxy_client_opt.unwrap().clone(), + 100, + 200, + ); + subject.stream_adder_rx = stream_adder_rx; + { + let mut inner = subject.inner.lock().unwrap(); + inner.logger = Logger::new(test_name); + inner.stream_writer_channels.insert( + stream_key, + StreamSenders { + writer_data: Box::new(SenderWrapperMock::new(peer_addr)), + reader_shutdown_tx: shutdown_tx, + }, + ); + inner.establisher_factory = Box::new(StreamEstablisherFactoryReal { + cryptde: main_cryptde(), + stream_adder_tx, + stream_killer_tx: unbounded().0, + proxy_client_subs: make_proxy_client_subs_from_recorder( + &make_recorder().0.start(), + ), + logger: Logger::new("test"), + }); + } - subject.process_package(payload, paying_wallet); + // TODO: GH-800: Make sure that the stream_adder_tx sends something to the receiver - let future_result = shutdown_rx.and_then(|_| Ok(())); - let future_with_timeout = - tokio::timer::Timeout::new(future_result, Duration::from_secs(10)).into_future(); - assert!(system.block_on(future_with_timeout).is_ok()); - TestLogHandler::new().exists_log_containing(&format!( - "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ + run_process_package_in_actix(subject, package); + }); + let received = shutdown_rx.poll().unwrap(); + assert_eq!(received, Async::Ready(Some(()))); + TestLogHandler::new().await_log_containing( + &format!( + "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ for oUHoHuDKHjeWq+BJzBIqHpPFBQw to 3.4.5.6:80" - )); + ), + 500, + ); } #[test] From f2dbe7bf035f70b5eed762e3396246bc7b93c15d Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 4 Sep 2024 11:39:59 +0530 Subject: [PATCH 42/65] Revert "GH-800: stream_handler_pool_sends_shutdown_signal_when_last_data_is_true is passing" This reverts commit 54040ae355352370feab82300067e9d5fc7c65ee. --- node/src/proxy_client/stream_handler_pool.rs | 135 ++++++++++--------- 1 file changed, 75 insertions(+), 60 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 9df8f863c..ba55fe0c1 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -601,7 +601,7 @@ mod tests { use crate::test_utils::tokio_wrapper_mocks::WriteHalfWrapperMock; use actix::{Actor, System}; use core::any::TypeId; - use futures::{Poll, Stream}; + use futures::Stream; use masq_lib::constants::HTTP_PORT; use masq_lib::test_utils::logging::init_test_logging; use masq_lib::test_utils::logging::TestLogHandler; @@ -610,11 +610,10 @@ mod tests { use std::io::ErrorKind; use std::net::IpAddr; use std::net::SocketAddr; - use std::ops::{Add, Deref}; + use std::ops::Deref; use std::ptr::addr_of; use std::str::FromStr; use std::sync::{Arc, Mutex}; - use std::time::{Duration, Instant}; use std::{sync, thread}; use tokio; use tokio::prelude::Async; @@ -1027,69 +1026,85 @@ mod tests { #[test] fn stream_handler_pool_sends_shutdown_signal_when_last_data_is_true() { + // TODO: GH-800: Identify why am I receiving this error - no Task is currently running init_test_logging(); let test_name = "stream_handler_pool_sends_shutdown_signal_when_last_data_is_true"; let mut system = System::new(test_name); - let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); - let stream_key = StreamKey::make_meaningful_stream_key("I should die"); - let client_request_payload = ClientRequestPayload_0v1 { - stream_key, - sequenced_packet: SequencedPacket { - data: b"I'm gonna kill you stream key".to_vec(), - sequence_number: 0, - last_data: true, - }, - target_hostname: Some(String::from("3.4.5.6:80")), - target_port: HTTP_PORT, - protocol: ProxyProtocol::HTTP, - originator_public_key: PublicKey::new(&b"brutal death"[..]), - }; - let package = ExpiredCoresPackage::new( - SocketAddr::from_str("1.2.3.4:1234").unwrap(), - Some(make_wallet("consuming")), - make_meaningless_route(), - client_request_payload.into(), - 0, - ); - let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); - let peer_actors = peer_actors_builder().build(); - let mut subject = StreamHandlerPoolReal::new( - Box::new(ResolverWrapperMock::new()), - main_cryptde(), - peer_actors.accountant.report_exit_service_provided.clone(), - peer_actors.proxy_client_opt.unwrap().clone(), - 100, - 200, - ); - { - let mut inner = subject.inner.lock().unwrap(); - inner.logger = Logger::new(test_name); - inner.stream_writer_channels.insert( - stream_key, - StreamSenders { - writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown_tx: shutdown_tx, - }, - ); - } - let paying_wallet = package.paying_wallet.clone(); - let payload = match package.payload { - MessageType::ClientRequest(vd) => vd - .extract(&crate::sub_lib::migrations::client_request_payload::MIGRATIONS) - .unwrap(), - _ => panic!("Expected MessageType::ClientRequest, got something else"), - }; + let future = future::lazy(move || { + let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); + actix::spawn(move || { + future::lazy({ + let stream_key = StreamKey::make_meaningful_stream_key("I should die"); + let client_request_payload = ClientRequestPayload_0v1 { + stream_key, + sequenced_packet: SequencedPacket { + data: b"I'm gonna kill you stream key".to_vec(), + sequence_number: 0, + last_data: true, + }, + target_hostname: Some(String::from("3.4.5.6:80")), + target_port: HTTP_PORT, + protocol: ProxyProtocol::HTTP, + originator_public_key: PublicKey::new(&b"brutal death"[..]), + }; + let package = ExpiredCoresPackage::new( + SocketAddr::from_str("1.2.3.4:1234").unwrap(), + Some(make_wallet("consuming")), + make_meaningless_route(), + client_request_payload.into(), + 0, + ); + let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); + let peer_actors = peer_actors_builder().build(); + let mut subject = StreamHandlerPoolReal::new( + Box::new(ResolverWrapperMock::new()), + main_cryptde(), + peer_actors.accountant.report_exit_service_provided.clone(), + peer_actors.proxy_client_opt.unwrap().clone(), + 100, + 200, + ); + { + let mut inner = subject.inner.lock().unwrap(); + inner.logger = Logger::new(test_name); + inner.stream_writer_channels.insert( + stream_key, + StreamSenders { + writer_data: Box::new(SenderWrapperMock::new(peer_addr)), + reader_shutdown_tx: shutdown_tx, + }, + ); + } - subject.process_package(payload, paying_wallet); + let paying_wallet = package.paying_wallet.clone(); + let payload = match package.payload { + MessageType::ClientRequest(vd) => vd + .extract( + &crate::sub_lib::migrations::client_request_payload::MIGRATIONS, + ) + .unwrap(), + _ => panic!("Expected MessageType::ClientRequest, got something else"), + }; + // actix::run(move || { + subject.process_package(payload, paying_wallet); + // ok(()) + // }) - let future_result = shutdown_rx.and_then(|_| Ok(())); - let future_with_timeout = - tokio::timer::Timeout::new(future_result, Duration::from_secs(10)).into_future(); - assert!(system.block_on(future_with_timeout).is_ok()); - TestLogHandler::new().exists_log_containing(&format!( - "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ + // run_process_package_in_actix(subject, package); + }) + }); + let received = shutdown_rx.poll().unwrap(); + assert_eq!(received, Async::Ready(Some(()))); + TestLogHandler::new().await_log_containing( + &format!( + "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ for oUHoHuDKHjeWq+BJzBIqHpPFBQw to 3.4.5.6:80" - )); + ), + 500, + ); + ok(()) + }); + system.block_on(future).unwrap(); } #[test] From a24dcda6b3ed26021e1a3388011d433d503c03f6 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 4 Sep 2024 11:40:00 +0530 Subject: [PATCH 43/65] Revert "GH-800: wip: fixing 2 tests" This reverts commit f94c8d355822176dbb60bee9796c4bdae062deb6. --- node/src/proxy_client/stream_handler_pool.rs | 128 ++++++++----------- 1 file changed, 53 insertions(+), 75 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index ba55fe0c1..0872ddae4 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -1026,85 +1026,63 @@ mod tests { #[test] fn stream_handler_pool_sends_shutdown_signal_when_last_data_is_true() { - // TODO: GH-800: Identify why am I receiving this error - no Task is currently running init_test_logging(); let test_name = "stream_handler_pool_sends_shutdown_signal_when_last_data_is_true"; - let mut system = System::new(test_name); - let future = future::lazy(move || { - let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); - actix::spawn(move || { - future::lazy({ - let stream_key = StreamKey::make_meaningful_stream_key("I should die"); - let client_request_payload = ClientRequestPayload_0v1 { - stream_key, - sequenced_packet: SequencedPacket { - data: b"I'm gonna kill you stream key".to_vec(), - sequence_number: 0, - last_data: true, - }, - target_hostname: Some(String::from("3.4.5.6:80")), - target_port: HTTP_PORT, - protocol: ProxyProtocol::HTTP, - originator_public_key: PublicKey::new(&b"brutal death"[..]), - }; - let package = ExpiredCoresPackage::new( - SocketAddr::from_str("1.2.3.4:1234").unwrap(), - Some(make_wallet("consuming")), - make_meaningless_route(), - client_request_payload.into(), - 0, - ); - let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); - let peer_actors = peer_actors_builder().build(); - let mut subject = StreamHandlerPoolReal::new( - Box::new(ResolverWrapperMock::new()), - main_cryptde(), - peer_actors.accountant.report_exit_service_provided.clone(), - peer_actors.proxy_client_opt.unwrap().clone(), - 100, - 200, - ); - { - let mut inner = subject.inner.lock().unwrap(); - inner.logger = Logger::new(test_name); - inner.stream_writer_channels.insert( - stream_key, - StreamSenders { - writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown_tx: shutdown_tx, - }, - ); - } - - let paying_wallet = package.paying_wallet.clone(); - let payload = match package.payload { - MessageType::ClientRequest(vd) => vd - .extract( - &crate::sub_lib::migrations::client_request_payload::MIGRATIONS, - ) - .unwrap(), - _ => panic!("Expected MessageType::ClientRequest, got something else"), - }; - // actix::run(move || { - subject.process_package(payload, paying_wallet); - // ok(()) - // }) - - // run_process_package_in_actix(subject, package); - }) - }); - let received = shutdown_rx.poll().unwrap(); - assert_eq!(received, Async::Ready(Some(()))); - TestLogHandler::new().await_log_containing( - &format!( - "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ - for oUHoHuDKHjeWq+BJzBIqHpPFBQw to 3.4.5.6:80" - ), - 500, + let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); + thread::spawn(move || { + let stream_key = StreamKey::make_meaningful_stream_key("I should die"); + let client_request_payload = ClientRequestPayload_0v1 { + stream_key, + sequenced_packet: SequencedPacket { + data: b"I'm gonna kill you stream key".to_vec(), + sequence_number: 0, + last_data: true, + }, + target_hostname: Some(String::from("3.4.5.6:80")), + target_port: HTTP_PORT, + protocol: ProxyProtocol::HTTP, + originator_public_key: PublicKey::new(&b"brutal death"[..]), + }; + let package = ExpiredCoresPackage::new( + SocketAddr::from_str("1.2.3.4:1234").unwrap(), + Some(make_wallet("consuming")), + make_meaningless_route(), + client_request_payload.into(), + 0, ); - ok(()) + let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); + let peer_actors = peer_actors_builder().build(); + let mut subject = StreamHandlerPoolReal::new( + Box::new(ResolverWrapperMock::new()), + main_cryptde(), + peer_actors.accountant.report_exit_service_provided.clone(), + peer_actors.proxy_client_opt.unwrap().clone(), + 100, + 200, + ); + { + let mut inner = subject.inner.lock().unwrap(); + inner.logger = Logger::new(test_name); + inner.stream_writer_channels.insert( + stream_key, + StreamSenders { + writer_data: Box::new(SenderWrapperMock::new(peer_addr)), + reader_shutdown_tx: shutdown_tx, + }, + ); + } + + run_process_package_in_actix(subject, package); }); - system.block_on(future).unwrap(); + let received = shutdown_rx.poll().unwrap(); + assert_eq!(received, Async::Ready(Some(()))); + TestLogHandler::new().await_log_containing( + &format!( + "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ + for oUHoHuDKHjeWq+BJzBIqHpPFBQw to 3.4.5.6:80" + ), + 500, + ); } #[test] From c61cc5a968684e6c69cc3cd1a3bb4ee5fcd70f9d Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 4 Sep 2024 11:40:02 +0530 Subject: [PATCH 44/65] Revert "GH-800: Add fn send_shutdown_signal_to_stream_reader" This reverts commit 3b387a7e4092e85a83b19ed4d2537fde8c3309bc. --- node/src/proxy_client/stream_handler_pool.rs | 59 ++++++++------------ 1 file changed, 22 insertions(+), 37 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 0872ddae4..de32893fb 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -66,6 +66,7 @@ impl StreamHandlerPool for StreamHandlerPoolReal { payload: ClientRequestPayload_0v1, paying_wallet_opt: Option, ) { + // TODO: GH-800: We need a test to prove that do_housekeeping() is called self.do_housekeeping(); Self::process_package(payload, paying_wallet_opt, self.inner.clone()) } @@ -158,27 +159,6 @@ impl StreamHandlerPoolReal { }; } - fn send_shutdown_signal_to_stream_reader( - mut reader_shutdown_tx: UnboundedSender<()>, - stream_key: &StreamKey, - logger: &Logger, - ) { - // TODO: GH-800: Test Drive Me especially the logs - match reader_shutdown_tx.try_send(()) { - Ok(()) => { - debug!(logger, "A shutdown signal was sent.") - } - Err(_e) => { - debug!( - logger, - "Unable to send a shutdown signal to the StreamReader for \ - stream key {:?}. The channel is already gone.", - stream_key - ); - } - } - } - fn clean_up_bad_stream( inner_arc: Arc>, stream_key: &StreamKey, @@ -190,17 +170,17 @@ impl StreamHandlerPoolReal { inner.logger, "Couldn't process request from CORES package: {}", error ); - if let Some(mut stream_senders) = inner.stream_writer_channels.remove(stream_key) { + if let Some(sender_wrapper) = inner.stream_writer_channels.remove(stream_key) { + debug!( + Logger::new("TEST"), + "clean_up_bad_stream() removed the stream key" + ); debug!( inner.logger, "Removing stream writer for {}", - stream_senders.writer_data.peer_addr() + sender_wrapper.writer_data.peer_addr() ); - Self::send_shutdown_signal_to_stream_reader( - stream_senders.reader_shutdown_tx, - stream_key, - &inner.logger, - ) + // TODO: GH-800: Send a shutdown signal to the Reader } Self::send_terminating_package( stream_key, @@ -252,11 +232,19 @@ impl StreamHandlerPoolReal { stream_key, stream_senders.writer_data.peer_addr() ); - Self::send_shutdown_signal_to_stream_reader( - stream_senders.reader_shutdown_tx, - &stream_key, - &inner.logger, - ); + match stream_senders.reader_shutdown_tx.try_send(()) { + Ok(()) => { + debug!(test_logger, "A shutdown signal was sent.") + } + Err(e) => { + debug!( + inner.logger, + "Unable to send a shutdown signal to the StreamReader for \ + stream key {:?}. The channel is already gone.", + stream_key + ); + } + } } None => { eprintln!("Failed to Remove stream key: {:?}", stream_key); @@ -776,7 +764,6 @@ mod tests { let cryptde = main_cryptde(); let (proxy_client, proxy_client_awaiter, proxy_client_recording_arc) = make_recorder(); let originator_key = PublicKey::new(&b"men's souls"[..]); - let (reader_shutdown_tx, mut reader_shutdown_rx) = unbounded_channel(); thread::spawn(move || { let client_request_payload = ClientRequestPayload_0v1 { stream_key: StreamKey::make_meaningless_stream_key(), @@ -817,7 +804,7 @@ mod tests { client_request_payload.stream_key, StreamSenders { writer_data: Box::new(tx_to_write), - reader_shutdown_tx, + reader_shutdown_tx: unbounded_channel().0, }, ); @@ -825,8 +812,6 @@ mod tests { }); proxy_client_awaiter.await_message_count(1); let proxy_client_recording = proxy_client_recording_arc.lock().unwrap(); - let received = reader_shutdown_rx.poll().unwrap(); - assert_eq!(received, Async::Ready(Some(()))); assert_eq!( proxy_client_recording.get_record::(0), &InboundServerData { From af9a6732a631c85cdded7f2e41d31138bae4dd89 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 4 Sep 2024 11:40:04 +0530 Subject: [PATCH 45/65] Revert "GH-800: change the channel from crossbeam to tokio" This reverts commit 2ecfebc9d5c711e1281c1658122924aa2a8b3045. --- node/src/proxy_client/stream_establisher.rs | 11 ++-- node/src/proxy_client/stream_handler_pool.rs | 64 +++++++++----------- node/src/proxy_client/stream_reader.rs | 43 +++++-------- 3 files changed, 48 insertions(+), 70 deletions(-) diff --git a/node/src/proxy_client/stream_establisher.rs b/node/src/proxy_client/stream_establisher.rs index c485e71c9..a8e59b423 100644 --- a/node/src/proxy_client/stream_establisher.rs +++ b/node/src/proxy_client/stream_establisher.rs @@ -20,7 +20,6 @@ use masq_lib::logger::Logger; use std::io; use std::net::IpAddr; use std::net::SocketAddr; -use tokio::sync::mpsc::UnboundedReceiver; pub struct StreamEstablisher { pub cryptde: &'static dyn CryptDE, @@ -61,8 +60,7 @@ impl StreamEstablisher { payload.target_port, &self.logger, )?; - // TODO: GH-800: Change it to a tokio channel instead of a crossbeam channel - let (shutdown_signal_tx, shutdown_signal_rx) = tokio::sync::mpsc::unbounded_channel(); + let (shutdown_signal_tx, shutdown_signal_rx) = unbounded(); self.spawn_stream_reader( &payload.clone(), @@ -82,7 +80,7 @@ impl StreamEstablisher { let stream_senders = StreamSenders { writer_data: tx_to_write.clone(), - reader_shutdown_tx: shutdown_signal_tx, + reader_shutdown: shutdown_signal_tx, }; self.stream_adder_tx @@ -96,7 +94,7 @@ impl StreamEstablisher { payload: &ClientRequestPayload_0v1, read_stream: Box, peer_addr: SocketAddr, - shutdown_signal: UnboundedReceiver<()>, + shutdown_signal: Receiver<()>, ) { let stream_reader = StreamReader::new( payload.stream_key, @@ -155,7 +153,6 @@ mod tests { use std::str::FromStr; use std::thread; use tokio::prelude::Async; - use tokio::sync::mpsc::unbounded_channel; #[test] fn spawn_stream_reader_handles_data() { @@ -208,7 +205,7 @@ mod tests { }, read_stream, SocketAddr::from_str("1.2.3.4:5678").unwrap(), - unbounded_channel().1, + unbounded().1, ); proxy_client_awaiter.await_message_count(1); diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index de32893fb..4ebc8af66 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -14,9 +14,9 @@ use crate::sub_lib::sequence_buffer::SequencedPacket; use crate::sub_lib::stream_key::StreamKey; use crate::sub_lib::wallet::Wallet; use actix::{Message, Recipient}; -use crossbeam_channel::{unbounded, Receiver}; +use crossbeam_channel::{unbounded, Receiver, SendError, Sender}; +use futures::future; use futures::future::Future; -use futures::{future, Sink}; use masq_lib::logger::Logger; use std::collections::HashMap; use std::io; @@ -26,8 +26,6 @@ use std::sync::{Arc, Mutex}; use std::time::SystemTime; use tokio::prelude::future::FutureResult; use tokio::prelude::future::{err, ok}; -use tokio::sync::mpsc::error::TrySendError; -use tokio::sync::mpsc::{Sender, UnboundedSender}; use trust_dns_resolver::error::ResolveError; use trust_dns_resolver::lookup_ip::LookupIp; @@ -46,7 +44,7 @@ pub struct StreamHandlerPoolReal { #[derive(Debug)] pub struct StreamSenders { pub writer_data: Box>, - pub reader_shutdown_tx: UnboundedSender<()>, + pub reader_shutdown: Sender<()>, } struct StreamHandlerPoolRealInner { @@ -225,14 +223,14 @@ impl StreamHandlerPoolReal { if last_data { debug!(test_logger, "last_data = true"); match inner.stream_writer_channels.remove(&stream_key) { - Some(mut stream_senders) => { + Some(stream_senders) => { debug!( inner.logger, "Removing StreamWriter and Shutting down StreamReader for {:?} to {}", stream_key, stream_senders.writer_data.peer_addr() ); - match stream_senders.reader_shutdown_tx.try_send(()) { + match stream_senders.reader_shutdown.send(()) { Ok(()) => { debug!(test_logger, "A shutdown signal was sent.") } @@ -469,7 +467,7 @@ impl StreamHandlerPoolReal { let mut inner = self.inner.lock().expect("Stream handler pool is poisoned"); while let Ok((stream_key, sequence_number)) = self.stream_killer_rx.try_recv() { match inner.stream_writer_channels.remove(&stream_key) { - Some(mut stream_senders) => { + Some(stream_senders) => { debug!( Logger::new("TEST"), "clean_up_dead_streams() removed the stream key" @@ -485,7 +483,7 @@ impl StreamHandlerPoolReal { data: vec![], }) .expect("ProxyClient is dead"); - if let Err(e) = stream_senders.reader_shutdown_tx.try_send(()) { + if let Err(e) = stream_senders.reader_shutdown.send(()) { debug!(inner.logger, "Unable to send a shutdown signal to the StreamReader for stream key {:?}. The channel is already gone.", stream_key) }; // Test should have a fake server, and the (read and write should be different) server @@ -589,7 +587,6 @@ mod tests { use crate::test_utils::tokio_wrapper_mocks::WriteHalfWrapperMock; use actix::{Actor, System}; use core::any::TypeId; - use futures::Stream; use masq_lib::constants::HTTP_PORT; use masq_lib::test_utils::logging::init_test_logging; use masq_lib::test_utils::logging::TestLogHandler; @@ -605,7 +602,6 @@ mod tests { use std::{sync, thread}; use tokio; use tokio::prelude::Async; - use tokio::sync::mpsc::unbounded_channel; use trust_dns_resolver::error::ResolveErrorKind; struct StreamEstablisherFactoryMock { @@ -743,7 +739,7 @@ mod tests { stream_key, StreamSenders { writer_data: tx_to_write, - reader_shutdown_tx: unbounded_channel().0, + reader_shutdown: unbounded().0, }, ); @@ -804,7 +800,7 @@ mod tests { client_request_payload.stream_key, StreamSenders { writer_data: Box::new(tx_to_write), - reader_shutdown_tx: unbounded_channel().0, + reader_shutdown: unbounded().0, }, ); @@ -939,7 +935,7 @@ mod tests { fn while_housekeeping_the_stream_senders_are_received_by_stream_handler_pool() { init_test_logging(); let test_name = "stream_handler_pool_sends_shutdown_signal_when_last_data_is_true"; - let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); + let (shutdown_tx, shutdown_rx) = unbounded(); let (stream_adder_tx, stream_adder_rx) = unbounded(); thread::spawn(move || { let stream_key = StreamKey::make_meaningful_stream_key("I should die"); @@ -980,7 +976,7 @@ mod tests { stream_key, StreamSenders { writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown_tx: shutdown_tx, + reader_shutdown: shutdown_tx, }, ); inner.establisher_factory = Box::new(StreamEstablisherFactoryReal { @@ -998,8 +994,8 @@ mod tests { run_process_package_in_actix(subject, package); }); - let received = shutdown_rx.poll().unwrap(); - assert_eq!(received, Async::Ready(Some(()))); + let received = shutdown_rx.recv(); + assert_eq!(received, Ok(())); TestLogHandler::new().await_log_containing( &format!( "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ @@ -1013,7 +1009,7 @@ mod tests { fn stream_handler_pool_sends_shutdown_signal_when_last_data_is_true() { init_test_logging(); let test_name = "stream_handler_pool_sends_shutdown_signal_when_last_data_is_true"; - let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); + let (shutdown_tx, shutdown_rx) = unbounded(); thread::spawn(move || { let stream_key = StreamKey::make_meaningful_stream_key("I should die"); let client_request_payload = ClientRequestPayload_0v1 { @@ -1052,15 +1048,15 @@ mod tests { stream_key, StreamSenders { writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown_tx: shutdown_tx, + reader_shutdown: shutdown_tx, }, ); } run_process_package_in_actix(subject, package); }); - let received = shutdown_rx.poll().unwrap(); - assert_eq!(received, Async::Ready(Some(()))); + let received = shutdown_rx.recv(); + assert_eq!(received, Ok(())); TestLogHandler::new().await_log_containing( &format!( "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ @@ -1074,7 +1070,7 @@ mod tests { fn stream_handler_pool_logs_when_shutdown_channel_is_broken() { init_test_logging(); let test_name = "stream_handler_pool_logs_when_shutdown_channel_is_broken"; - let broken_shutdown_channel_tx = unbounded_channel().0; + let broken_shutdown_channel_tx = unbounded().0; thread::spawn(move || { let stream_key = StreamKey::make_meaningful_stream_key("I should die"); let client_request_payload = ClientRequestPayload_0v1 { @@ -1113,7 +1109,7 @@ mod tests { stream_key, StreamSenders { writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown_tx: broken_shutdown_channel_tx, + reader_shutdown: broken_shutdown_channel_tx, }, ); } @@ -1873,7 +1869,7 @@ mod tests { stream_key, StreamSenders { writer_data: Box::new(sender_wrapper), - reader_shutdown_tx: unbounded_channel().0, + reader_shutdown: unbounded().0, }, ); @@ -1969,14 +1965,14 @@ mod tests { subject.stream_killer_rx = stream_killer_rx; let stream_key = StreamKey::make_meaningless_stream_key(); let peer_addr = SocketAddr::from_str("1.2.3.4:5678").unwrap(); - let (shutdown_tx, mut shutdown_rx) = unbounded_channel(); + let (shutdown_tx, shutdown_rx) = unbounded(); { let mut inner = subject.inner.lock().unwrap(); inner.stream_writer_channels.insert( stream_key, StreamSenders { writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown_tx: shutdown_tx, + reader_shutdown: shutdown_tx, }, ); } @@ -1988,8 +1984,8 @@ mod tests { system.run(); let proxy_client_recording = proxy_client_recording_arc.lock().unwrap(); let report = proxy_client_recording.get_record::(0); - let shutdown_signal_received = shutdown_rx.poll().unwrap(); - assert_eq!(shutdown_signal_received, Async::Ready(Some(()))); + let shutdown_signal_received = shutdown_rx.recv(); + assert_eq!(shutdown_signal_received, Ok(())); assert_eq!( report, &InboundServerData { @@ -2020,7 +2016,7 @@ mod tests { subject.stream_killer_rx = stream_killer_rx; let stream_key = StreamKey::make_meaningful_stream_key("I'll be gone well before then."); let peer_addr = SocketAddr::from_str("1.2.3.4:5678").unwrap(); - let broken_shutdown_channel_tx = unbounded_channel().0; + let broken_shutdown_channel_tx = unbounded().0; { let mut inner = subject.inner.lock().unwrap(); inner.logger = Logger::new(test_name); @@ -2028,7 +2024,7 @@ mod tests { stream_key, StreamSenders { writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown_tx: broken_shutdown_channel_tx, + reader_shutdown: broken_shutdown_channel_tx, }, ); } @@ -2091,23 +2087,23 @@ mod tests { } let first_stream_key = StreamKey::make_meaningful_stream_key("first_stream_key"); let (first_writer_data_tx, first_writer_data_rx) = futures::sync::mpsc::unbounded(); - let (first_shutdown_tx, first_shutdown_rx) = unbounded_channel(); + let (first_shutdown_tx, first_shutdown_rx) = unbounded(); let first_stream_senders = StreamSenders { writer_data: Box::new(SenderWrapperReal::new( SocketAddr::from_str("1.2.3.4:5678").unwrap(), first_writer_data_tx, )), - reader_shutdown_tx: first_shutdown_tx, + reader_shutdown: first_shutdown_tx, }; let (second_writer_data_tx, second_writer_data_rx) = futures::sync::mpsc::unbounded(); - let (second_shutdown_tx, second_shutdown_rx) = unbounded_channel(); + let (second_shutdown_tx, second_shutdown_rx) = unbounded(); let second_stream_key = StreamKey::make_meaningful_stream_key("second_stream_key"); let second_stream_senders = StreamSenders { writer_data: Box::new(SenderWrapperReal::new( SocketAddr::from_str("2.3.4.5:6789").unwrap(), second_writer_data_tx, )), - reader_shutdown_tx: second_shutdown_tx, + reader_shutdown: second_shutdown_tx, }; stream_adder_tx .send((first_stream_key.clone(), first_stream_senders)) diff --git a/node/src/proxy_client/stream_reader.rs b/node/src/proxy_client/stream_reader.rs index d9e24bd4d..4ec7d825d 100644 --- a/node/src/proxy_client/stream_reader.rs +++ b/node/src/proxy_client/stream_reader.rs @@ -7,19 +7,17 @@ use crate::sub_lib::utils; use crate::sub_lib::utils::indicates_dead_stream; use actix::Recipient; use crossbeam_channel::{Receiver, Sender, TryRecvError}; -use futures::{Poll, Stream}; use masq_lib::logger::Logger; use std::net::SocketAddr; use tokio::prelude::Async; use tokio::prelude::Future; -use tokio::sync::mpsc::UnboundedReceiver; pub struct StreamReader { stream_key: StreamKey, proxy_client_sub: Recipient, stream: Box, stream_killer: Sender<(StreamKey, u64)>, - shutdown_signal: UnboundedReceiver<()>, + shutdown_signal: Receiver<()>, peer_addr: SocketAddr, logger: Logger, sequencer: Sequencer, @@ -32,24 +30,12 @@ impl Future for StreamReader { fn poll(&mut self) -> Result::Item>, ::Error> { let mut buf: [u8; 16384] = [0; 16384]; loop { - match self.shutdown_signal.poll() { - // TODO: GH-800: Test Drive Me - Ok(Async::Ready(_something)) => { - info!( - self.logger, - "Shutting down for stream: {:?}", self.stream_key - ); - return Ok(Async::Ready(())); - } - Ok(Async::NotReady) => (), - Err(_e) => { - warning!( - self.logger, - "Failed to receive a signal for shutting down StreamReader for stream key: {:?}", - self.stream_key, - ); - return Err(()); - } + if self.shutdown_signal.try_recv().is_ok() { + info!( + self.logger, + "Shutting down for stream: {:?}", self.stream_key + ); + return Ok(Async::Ready(())); } match self.stream.poll_read(&mut buf) { Ok(Async::NotReady) => return Ok(Async::NotReady), @@ -113,7 +99,7 @@ impl StreamReader { proxy_client_sub: Recipient, stream: Box, stream_killer: Sender<(StreamKey, u64)>, - shutdown_signal: UnboundedReceiver<()>, + shutdown_signal: Receiver<()>, peer_addr: SocketAddr, ) -> StreamReader { let logger = Logger::new(&format!("StreamReader for {:?}/{}", stream_key, peer_addr)[..]); @@ -164,7 +150,6 @@ mod tests { use std::net::SocketAddr; use std::str::FromStr; use std::thread; - use tokio::sync::mpsc::unbounded_channel; #[test] fn stream_reader_assigns_a_sequence_to_client_response_payloads() { @@ -211,7 +196,7 @@ mod tests { proxy_client_sub, stream, stream_killer, - shutdown_signal: unbounded_channel().1, + shutdown_signal: unbounded().1, peer_addr: SocketAddr::from_str("8.7.4.3:50").unwrap(), logger: Logger::new("test"), sequencer: Sequencer::new(), @@ -362,7 +347,7 @@ mod tests { proxy_client_sub: make_recorder().0.start().recipient(), stream: Box::new(stream), stream_killer, - shutdown_signal: unbounded_channel().1, + shutdown_signal: unbounded().1, peer_addr, logger: Logger::new(test_name), sequencer, @@ -415,7 +400,7 @@ mod tests { proxy_client_sub, stream: Box::new(stream), stream_killer, - shutdown_signal: unbounded_channel().1, + shutdown_signal: unbounded().1, peer_addr, logger: Logger::new(test_name), sequencer: Sequencer::new(), @@ -445,12 +430,12 @@ mod tests { fn stream_reader_shuts_down_when_it_receives_the_shutdown_signal() { init_test_logging(); let test_name = "stream_reader_shuts_down_when_it_receives_the_shutdown_signal"; - let (mut shutdown_tx, shutdown_rx) = unbounded_channel(); + let (shutdown_tx, shutdown_rx) = unbounded(); let mut subject = make_subject(); subject.shutdown_signal = shutdown_rx; subject.logger = Logger::new(test_name); - shutdown_tx.try_send(()).unwrap(); + shutdown_tx.send(()).unwrap(); assert_eq!(subject.poll(), Ok(Async::Ready(()))); TestLogHandler::new().exists_log_containing(&format!( @@ -465,7 +450,7 @@ mod tests { proxy_client_sub: make_recorder().0.start().recipient(), stream: Box::new(ReadHalfWrapperMock::new()), stream_killer: unbounded().0, - shutdown_signal: unbounded_channel().1, + shutdown_signal: unbounded().1, peer_addr: SocketAddr::from_str("9.8.7.6:5432").unwrap(), logger: Logger::new("test"), sequencer: Sequencer::new(), From 5ba55df271b1dfa202b180a6a0d07fc80c1e4e80 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 4 Sep 2024 11:48:38 +0530 Subject: [PATCH 46/65] GH-800: reverted the channel to crossbeam; remove warnings --- node/src/proxy_client/mod.rs | 7 +---- node/src/proxy_client/stream_establisher.rs | 2 +- node/src/proxy_client/stream_handler_pool.rs | 29 +++++++++----------- node/src/proxy_client/stream_reader.rs | 2 +- 4 files changed, 16 insertions(+), 24 deletions(-) diff --git a/node/src/proxy_client/mod.rs b/node/src/proxy_client/mod.rs index a4329b24f..d05cb505b 100644 --- a/node/src/proxy_client/mod.rs +++ b/node/src/proxy_client/mod.rs @@ -30,11 +30,11 @@ use crate::sub_lib::stream_key::StreamKey; use crate::sub_lib::utils::{handle_ui_crash_request, NODE_MAILBOX_CAPACITY}; use crate::sub_lib::versioned_data::VersionedData; use crate::sub_lib::wallet::Wallet; +use actix::Actor; use actix::Addr; use actix::Context; use actix::Handler; use actix::Recipient; -use actix::{Actor, Message}; use masq_lib::logger::Logger; use masq_lib::ui_gateway::NodeFromUiMessage; use pretty_hex::PrettyHex; @@ -48,11 +48,6 @@ use trust_dns_resolver::config::ResolverOpts; pub const CRASH_KEY: &str = "PROXYCLIENT"; -#[derive(Message)] -struct StopListeningForThisStream { - stream_key: StreamKey, -} - pub struct ProxyClient { dns_servers: Vec, resolver_wrapper_factory: Box, diff --git a/node/src/proxy_client/stream_establisher.rs b/node/src/proxy_client/stream_establisher.rs index a8e59b423..febd9274e 100644 --- a/node/src/proxy_client/stream_establisher.rs +++ b/node/src/proxy_client/stream_establisher.rs @@ -3,9 +3,9 @@ use crate::proxy_client::stream_handler_pool::StreamSenders; use crate::proxy_client::stream_reader::StreamReader; use crate::proxy_client::stream_writer::StreamWriter; +use crate::sub_lib::channel_wrappers::FuturesChannelFactory; use crate::sub_lib::channel_wrappers::FuturesChannelFactoryReal; use crate::sub_lib::channel_wrappers::SenderWrapper; -use crate::sub_lib::channel_wrappers::{FuturesChannelFactory, SenderWrapperReal}; use crate::sub_lib::cryptde::CryptDE; use crate::sub_lib::proxy_client::{InboundServerData, ProxyClientSubs}; use crate::sub_lib::proxy_server::ClientRequestPayload_0v1; diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 4ebc8af66..e2b2e264f 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -13,8 +13,8 @@ use crate::sub_lib::proxy_server::ClientRequestPayload_0v1; use crate::sub_lib::sequence_buffer::SequencedPacket; use crate::sub_lib::stream_key::StreamKey; use crate::sub_lib::wallet::Wallet; -use actix::{Message, Recipient}; -use crossbeam_channel::{unbounded, Receiver, SendError, Sender}; +use actix::Recipient; +use crossbeam_channel::{unbounded, Receiver, Sender}; use futures::future; use futures::future::Future; use masq_lib::logger::Logger; @@ -230,11 +230,12 @@ impl StreamHandlerPoolReal { stream_key, stream_senders.writer_data.peer_addr() ); + // TODO: GH-800: Maybe you want to use a refactored code here match stream_senders.reader_shutdown.send(()) { Ok(()) => { debug!(test_logger, "A shutdown signal was sent.") } - Err(e) => { + Err(_e) => { debug!( inner.logger, "Unable to send a shutdown signal to the StreamReader for \ @@ -483,7 +484,8 @@ impl StreamHandlerPoolReal { data: vec![], }) .expect("ProxyClient is dead"); - if let Err(e) = stream_senders.reader_shutdown.send(()) { + // TODO: GH-800: Maybe you want the refactored code here too + if let Err(_e) = stream_senders.reader_shutdown.send(()) { debug!(inner.logger, "Unable to send a shutdown signal to the StreamReader for stream key {:?}. The channel is already gone.", stream_key) }; // Test should have a fake server, and the (read and write should be different) server @@ -561,7 +563,6 @@ impl StreamHandlerPoolFactory for StreamHandlerPoolFactoryReal { #[cfg(test)] mod tests { use super::*; - use crate::match_every_type_id; use crate::node_test_utils::check_timestamp; use crate::proxy_client::local_test_utils::make_send_error; use crate::proxy_client::local_test_utils::ResolverWrapperMock; @@ -580,13 +581,10 @@ mod tests { use crate::test_utils::make_wallet; use crate::test_utils::recorder::peer_actors_builder; use crate::test_utils::recorder::{make_proxy_client_subs_from_recorder, make_recorder}; - use crate::test_utils::recorder_stop_conditions::StopCondition; - use crate::test_utils::recorder_stop_conditions::StopConditions; use crate::test_utils::stream_connector_mock::StreamConnectorMock; use crate::test_utils::tokio_wrapper_mocks::ReadHalfWrapperMock; use crate::test_utils::tokio_wrapper_mocks::WriteHalfWrapperMock; use actix::{Actor, System}; - use core::any::TypeId; use masq_lib::constants::HTTP_PORT; use masq_lib::test_utils::logging::init_test_logging; use masq_lib::test_utils::logging::TestLogHandler; @@ -596,10 +594,9 @@ mod tests { use std::net::IpAddr; use std::net::SocketAddr; use std::ops::Deref; - use std::ptr::addr_of; use std::str::FromStr; use std::sync::{Arc, Mutex}; - use std::{sync, thread}; + use std::thread; use tokio; use tokio::prelude::Async; use trust_dns_resolver::error::ResolveErrorKind; @@ -1033,7 +1030,7 @@ mod tests { ); let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); let peer_actors = peer_actors_builder().build(); - let mut subject = StreamHandlerPoolReal::new( + let subject = StreamHandlerPoolReal::new( Box::new(ResolverWrapperMock::new()), main_cryptde(), peer_actors.accountant.report_exit_service_provided.clone(), @@ -1094,7 +1091,7 @@ mod tests { ); let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); let peer_actors = peer_actors_builder().build(); - let mut subject = StreamHandlerPoolReal::new( + let subject = StreamHandlerPoolReal::new( Box::new(ResolverWrapperMock::new()), main_cryptde(), peer_actors.accountant.report_exit_service_provided.clone(), @@ -2086,8 +2083,8 @@ mod tests { subject.inner.lock().unwrap().logger = Logger::new(test_name); } let first_stream_key = StreamKey::make_meaningful_stream_key("first_stream_key"); - let (first_writer_data_tx, first_writer_data_rx) = futures::sync::mpsc::unbounded(); - let (first_shutdown_tx, first_shutdown_rx) = unbounded(); + let (first_writer_data_tx, _first_writer_data_rx) = futures::sync::mpsc::unbounded(); + let (first_shutdown_tx, _first_shutdown_rx) = unbounded(); let first_stream_senders = StreamSenders { writer_data: Box::new(SenderWrapperReal::new( SocketAddr::from_str("1.2.3.4:5678").unwrap(), @@ -2095,8 +2092,8 @@ mod tests { )), reader_shutdown: first_shutdown_tx, }; - let (second_writer_data_tx, second_writer_data_rx) = futures::sync::mpsc::unbounded(); - let (second_shutdown_tx, second_shutdown_rx) = unbounded(); + let (second_writer_data_tx, _second_writer_data_rx) = futures::sync::mpsc::unbounded(); + let (second_shutdown_tx, _second_shutdown_rx) = unbounded(); let second_stream_key = StreamKey::make_meaningful_stream_key("second_stream_key"); let second_stream_senders = StreamSenders { writer_data: Box::new(SenderWrapperReal::new( diff --git a/node/src/proxy_client/stream_reader.rs b/node/src/proxy_client/stream_reader.rs index 4ec7d825d..65bf4253f 100644 --- a/node/src/proxy_client/stream_reader.rs +++ b/node/src/proxy_client/stream_reader.rs @@ -6,7 +6,7 @@ use crate::sub_lib::tokio_wrappers::ReadHalfWrapper; use crate::sub_lib::utils; use crate::sub_lib::utils::indicates_dead_stream; use actix::Recipient; -use crossbeam_channel::{Receiver, Sender, TryRecvError}; +use crossbeam_channel::{Receiver, Sender}; use masq_lib::logger::Logger; use std::net::SocketAddr; use tokio::prelude::Async; From 5579c12bf8a8b6c75922a648aa57ddd23e93f6c7 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 4 Sep 2024 12:14:48 +0530 Subject: [PATCH 47/65] GH-800: solve some TODOs --- node/src/proxy_client/stream_handler_pool.rs | 18 ++---------------- node/src/stream_handler_pool.rs | 2 +- node/tests/connection_shutdown_test.rs | 2 +- 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index e2b2e264f..c60c7f306 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -29,7 +29,7 @@ use tokio::prelude::future::{err, ok}; use trust_dns_resolver::error::ResolveError; use trust_dns_resolver::lookup_ip::LookupIp; -// TODO: GH-800 - This should be renamed to ProxyClientStreamHandlerPoolReal (or something more concise) +// TODO: This should be renamed to ProxyClientStreamHandlerPoolReal (or something more concise) // to differentiate it from the other StreamHandlerPool, which, unlike this, is an actor. pub trait StreamHandlerPool { fn process_package(&self, payload: ClientRequestPayload_0v1, paying_wallet_opt: Option); @@ -64,7 +64,6 @@ impl StreamHandlerPool for StreamHandlerPoolReal { payload: ClientRequestPayload_0v1, paying_wallet_opt: Option, ) { - // TODO: GH-800: We need a test to prove that do_housekeeping() is called self.do_housekeeping(); Self::process_package(payload, paying_wallet_opt, self.inner.clone()) } @@ -820,8 +819,6 @@ mod tests { #[test] fn when_hostname_is_ip_establish_stream_without_dns_lookup() { let cryptde = main_cryptde(); - let lookup_ip_parameters = Arc::new(Mutex::new(vec![])); - let expected_lookup_ip_parameters = lookup_ip_parameters.clone(); let write_parameters = Arc::new(Mutex::new(vec![])); let expected_write_parameters = write_parameters.clone(); let (proxy_client, proxy_client_awaiter, proxy_client_recording_arc) = make_recorder(); @@ -846,13 +843,6 @@ mod tests { client_request_payload.into(), 0, ); - // TODO: GH-800: Apparently, we can remove both lookup_ip mock functions - let resolver = ResolverWrapperMock::new() - .lookup_ip_parameters(&lookup_ip_parameters) - .lookup_ip_success(vec![ - IpAddr::from_str("2.3.4.5").unwrap(), - IpAddr::from_str("3.4.5.6").unwrap(), - ]); let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); let first_read_result = b"HTTP/1.1 200 OK\r\n\r\n"; let reader = ReadHalfWrapperMock { @@ -870,7 +860,7 @@ mod tests { shutdown_results: Arc::new(Mutex::new(vec![])), }; let mut subject = StreamHandlerPoolReal::new( - Box::new(resolver), + Box::new(ResolverWrapperMock::new()), cryptde, peer_actors.accountant.report_exit_service_provided.clone(), peer_actors.proxy_client_opt.unwrap().clone(), @@ -907,10 +897,6 @@ mod tests { }); proxy_client_awaiter.await_message_count(1); - assert_eq!( - expected_lookup_ip_parameters.lock().unwrap().deref(), - &(vec![] as Vec) - ); assert_eq!( expected_write_parameters.lock().unwrap().remove(0), b"These are the times".to_vec() diff --git a/node/src/stream_handler_pool.rs b/node/src/stream_handler_pool.rs index 8aab602a5..b80e01f92 100644 --- a/node/src/stream_handler_pool.rs +++ b/node/src/stream_handler_pool.rs @@ -105,7 +105,7 @@ impl Display for StreamWriterKey { } } -// TODO: GH-800 - To avoid confusion with ProxyClient's StreamHandlerPool, rename this one or the other for easy identification. +// TODO: To avoid confusion with ProxyClient's StreamHandlerPool, rename this one or the other for easy identification. // It is used to store streams for both neighbors and browser. pub struct StreamHandlerPool { stream_writers: HashMap>>>, diff --git a/node/tests/connection_shutdown_test.rs b/node/tests/connection_shutdown_test.rs index 1c2a23692..38dbf2cb5 100644 --- a/node/tests/connection_shutdown_test.rs +++ b/node/tests/connection_shutdown_test.rs @@ -43,7 +43,7 @@ fn proxy_client_stream_reader_dies_when_client_stream_is_killed_integration() { let write_error = server_write_error_rx .recv_timeout(Duration::from_secs(60)) - .unwrap(); // TODO: GH-800 We are failing on this timeout + .unwrap(); assert_eq!(write_error.kind(), io::ErrorKind::BrokenPipe); join_handle.join().unwrap(); } From 3f34e83e9acdfbc7a5186602ddcf4d9426562b54 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 4 Sep 2024 12:41:03 +0530 Subject: [PATCH 48/65] GH-800: add refactored fn send_shutdown_signal_to_stream_reader; crtitical integration test passing --- node/src/proxy_client/stream_establisher.rs | 2 +- node/src/proxy_client/stream_handler_pool.rs | 85 +++++++++++--------- node/tests/connection_shutdown_test.rs | 4 +- 3 files changed, 50 insertions(+), 41 deletions(-) diff --git a/node/src/proxy_client/stream_establisher.rs b/node/src/proxy_client/stream_establisher.rs index febd9274e..63c898dcf 100644 --- a/node/src/proxy_client/stream_establisher.rs +++ b/node/src/proxy_client/stream_establisher.rs @@ -80,7 +80,7 @@ impl StreamEstablisher { let stream_senders = StreamSenders { writer_data: tx_to_write.clone(), - reader_shutdown: shutdown_signal_tx, + reader_shutdown_tx: shutdown_signal_tx, }; self.stream_adder_tx diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index c60c7f306..27e93809b 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -44,7 +44,7 @@ pub struct StreamHandlerPoolReal { #[derive(Debug)] pub struct StreamSenders { pub writer_data: Box>, - pub reader_shutdown: Sender<()>, + pub reader_shutdown_tx: Sender<()>, } struct StreamHandlerPoolRealInner { @@ -156,6 +156,30 @@ impl StreamHandlerPoolReal { }; } + fn send_shutdown_signal_to_stream_reader( + reader_shutdown_tx: Sender<()>, + stream_key: &StreamKey, + logger: &Logger, + ) { + match reader_shutdown_tx.try_send(()) { + Ok(()) => { + debug!( + logger, + "A shutdown signal was sent to the StreamReader for stream key {:?}.", + stream_key + ); + } + Err(_e) => { + debug!( + logger, + "Unable to send a shutdown signal to the StreamReader for \ + stream key {:?}. The channel is already gone.", + stream_key + ); + } + } + } + fn clean_up_bad_stream( inner_arc: Arc>, stream_key: &StreamKey, @@ -167,17 +191,17 @@ impl StreamHandlerPoolReal { inner.logger, "Couldn't process request from CORES package: {}", error ); - if let Some(sender_wrapper) = inner.stream_writer_channels.remove(stream_key) { - debug!( - Logger::new("TEST"), - "clean_up_bad_stream() removed the stream key" - ); + if let Some(stream_senders) = inner.stream_writer_channels.remove(stream_key) { debug!( inner.logger, "Removing stream writer for {}", - sender_wrapper.writer_data.peer_addr() + stream_senders.writer_data.peer_addr() ); - // TODO: GH-800: Send a shutdown signal to the Reader + Self::send_shutdown_signal_to_stream_reader( + stream_senders.reader_shutdown_tx, + stream_key, + &inner.logger, + ) } Self::send_terminating_package( stream_key, @@ -195,7 +219,6 @@ impl StreamHandlerPoolReal { let stream_key = payload.stream_key; let last_data = payload.sequenced_packet.last_data; let payload_size = payload.sequenced_packet.data.len(); - let test_logger = Logger::new("TEST"); Self::perform_write(payload.sequenced_packet, sender_wrapper.clone()).and_then(move |_| { let mut inner = inner_arc.lock().expect("Stream handler pool is poisoned"); @@ -218,9 +241,7 @@ impl StreamHandlerPoolReal { ), } } - debug!(test_logger, "Stop right before last_data check!"); if last_data { - debug!(test_logger, "last_data = true"); match inner.stream_writer_channels.remove(&stream_key) { Some(stream_senders) => { debug!( @@ -229,23 +250,13 @@ impl StreamHandlerPoolReal { stream_key, stream_senders.writer_data.peer_addr() ); - // TODO: GH-800: Maybe you want to use a refactored code here - match stream_senders.reader_shutdown.send(()) { - Ok(()) => { - debug!(test_logger, "A shutdown signal was sent.") - } - Err(_e) => { - debug!( - inner.logger, - "Unable to send a shutdown signal to the StreamReader for \ - stream key {:?}. The channel is already gone.", - stream_key - ); - } - } + Self::send_shutdown_signal_to_stream_reader( + stream_senders.reader_shutdown_tx, + &stream_key, + &inner.logger, + ) } None => { - eprintln!("Failed to Remove stream key: {:?}", stream_key); debug!( inner.logger, "Trying to remove StreamWriter {:?}, but it's already gone", stream_key @@ -484,7 +495,7 @@ impl StreamHandlerPoolReal { }) .expect("ProxyClient is dead"); // TODO: GH-800: Maybe you want the refactored code here too - if let Err(_e) = stream_senders.reader_shutdown.send(()) { + if let Err(_e) = stream_senders.reader_shutdown_tx.send(()) { debug!(inner.logger, "Unable to send a shutdown signal to the StreamReader for stream key {:?}. The channel is already gone.", stream_key) }; // Test should have a fake server, and the (read and write should be different) server @@ -735,7 +746,7 @@ mod tests { stream_key, StreamSenders { writer_data: tx_to_write, - reader_shutdown: unbounded().0, + reader_shutdown_tx: unbounded().0, }, ); @@ -796,7 +807,7 @@ mod tests { client_request_payload.stream_key, StreamSenders { writer_data: Box::new(tx_to_write), - reader_shutdown: unbounded().0, + reader_shutdown_tx: unbounded().0, }, ); @@ -959,7 +970,7 @@ mod tests { stream_key, StreamSenders { writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown: shutdown_tx, + reader_shutdown_tx: shutdown_tx, }, ); inner.establisher_factory = Box::new(StreamEstablisherFactoryReal { @@ -1031,7 +1042,7 @@ mod tests { stream_key, StreamSenders { writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown: shutdown_tx, + reader_shutdown_tx: shutdown_tx, }, ); } @@ -1092,7 +1103,7 @@ mod tests { stream_key, StreamSenders { writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown: broken_shutdown_channel_tx, + reader_shutdown_tx: broken_shutdown_channel_tx, }, ); } @@ -1852,7 +1863,7 @@ mod tests { stream_key, StreamSenders { writer_data: Box::new(sender_wrapper), - reader_shutdown: unbounded().0, + reader_shutdown_tx: unbounded().0, }, ); @@ -1955,7 +1966,7 @@ mod tests { stream_key, StreamSenders { writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown: shutdown_tx, + reader_shutdown_tx: shutdown_tx, }, ); } @@ -2007,7 +2018,7 @@ mod tests { stream_key, StreamSenders { writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown: broken_shutdown_channel_tx, + reader_shutdown_tx: broken_shutdown_channel_tx, }, ); } @@ -2076,7 +2087,7 @@ mod tests { SocketAddr::from_str("1.2.3.4:5678").unwrap(), first_writer_data_tx, )), - reader_shutdown: first_shutdown_tx, + reader_shutdown_tx: first_shutdown_tx, }; let (second_writer_data_tx, _second_writer_data_rx) = futures::sync::mpsc::unbounded(); let (second_shutdown_tx, _second_shutdown_rx) = unbounded(); @@ -2086,7 +2097,7 @@ mod tests { SocketAddr::from_str("2.3.4.5:6789").unwrap(), second_writer_data_tx, )), - reader_shutdown: second_shutdown_tx, + reader_shutdown_tx: second_shutdown_tx, }; stream_adder_tx .send((first_stream_key.clone(), first_stream_senders)) diff --git a/node/tests/connection_shutdown_test.rs b/node/tests/connection_shutdown_test.rs index 38dbf2cb5..b695dd86b 100644 --- a/node/tests/connection_shutdown_test.rs +++ b/node/tests/connection_shutdown_test.rs @@ -2,15 +2,13 @@ pub mod utils; -use crate::utils::CommandConfig; use crossbeam_channel::{unbounded, Sender}; use masq_lib::utils::find_free_port; -use node_lib::test_utils::read_until_timeout; use std::io::{Read, Write}; use std::net::{IpAddr, TcpListener, TcpStream}; use std::net::{Shutdown, SocketAddr}; use std::str::FromStr; -use std::time::{Duration, Instant}; +use std::time::Duration; use std::{io, thread}; // 'node' below must not be named '_' alone or disappear, or the MASQNode will be immediately reclaimed. From 681a79faf439c3ec51ddb878a2faeb9adef6ae46 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 4 Sep 2024 12:55:12 +0530 Subject: [PATCH 49/65] GH-800: write_failure_for_nonexistent_stream_generates_termination_message is improved --- node/src/proxy_client/stream_handler_pool.rs | 28 +++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 27e93809b..1ed156a61 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -163,6 +163,7 @@ impl StreamHandlerPoolReal { ) { match reader_shutdown_tx.try_send(()) { Ok(()) => { + // todo!("Ok"); debug!( logger, "A shutdown signal was sent to the StreamReader for stream key {:?}.", @@ -244,6 +245,7 @@ impl StreamHandlerPoolReal { if last_data { match inner.stream_writer_channels.remove(&stream_key) { Some(stream_senders) => { + // todo!("stop for write_and_tend"); debug!( inner.logger, "Removing StreamWriter and Shutting down StreamReader for {:?} to {}", @@ -764,9 +766,11 @@ mod tests { #[test] fn write_failure_for_nonexistent_stream_generates_termination_message() { init_test_logging(); + let test_name = "write_failure_for_nonexistent_stream_generates_termination_message"; let cryptde = main_cryptde(); let (proxy_client, proxy_client_awaiter, proxy_client_recording_arc) = make_recorder(); let originator_key = PublicKey::new(&b"men's souls"[..]); + let (reader_shutdown_tx, reader_shutdown_rx) = unbounded(); thread::spawn(move || { let client_request_payload = ClientRequestPayload_0v1 { stream_key: StreamKey::make_meaningless_stream_key(), @@ -803,18 +807,24 @@ mod tests { 100, 200, ); - subject.inner.lock().unwrap().stream_writer_channels.insert( - client_request_payload.stream_key, - StreamSenders { - writer_data: Box::new(tx_to_write), - reader_shutdown_tx: unbounded().0, - }, - ); + { + let mut inner = subject.inner.lock().unwrap(); + inner.stream_writer_channels.insert( + client_request_payload.stream_key, + StreamSenders { + writer_data: Box::new(tx_to_write), + reader_shutdown_tx, + }, + ); + inner.logger = Logger::new(test_name); + } run_process_package_in_actix(subject, package); }); proxy_client_awaiter.await_message_count(1); let proxy_client_recording = proxy_client_recording_arc.lock().unwrap(); + let received = reader_shutdown_rx.try_recv(); + assert_eq!(received, Ok(())); assert_eq!( proxy_client_recording.get_record::(0), &InboundServerData { @@ -825,6 +835,10 @@ mod tests { data: vec![], } ); + TestLogHandler::new().exists_log_containing(&format!( + "DEBUG: {test_name}: A shutdown signal was sent to the StreamReader \ + for stream key AAAAAAAAAAAAAAAAAAAAAAAAAAA." + )); } #[test] From 0811b5e7326b8cca51cbebaac9d14a93baad8992 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Thu, 5 Sep 2024 12:29:01 +0530 Subject: [PATCH 50/65] GH-800: everything is tested --- node/src/proxy_client/stream_handler_pool.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 1ed156a61..f00c22f65 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -171,6 +171,7 @@ impl StreamHandlerPoolReal { ); } Err(_e) => { + // todo!("ERR"); debug!( logger, "Unable to send a shutdown signal to the StreamReader for \ @@ -245,7 +246,6 @@ impl StreamHandlerPoolReal { if last_data { match inner.stream_writer_channels.remove(&stream_key) { Some(stream_senders) => { - // todo!("stop for write_and_tend"); debug!( inner.logger, "Removing StreamWriter and Shutting down StreamReader for {:?} to {}", @@ -481,10 +481,6 @@ impl StreamHandlerPoolReal { while let Ok((stream_key, sequence_number)) = self.stream_killer_rx.try_recv() { match inner.stream_writer_channels.remove(&stream_key) { Some(stream_senders) => { - debug!( - Logger::new("TEST"), - "clean_up_dead_streams() removed the stream key" - ); inner .proxy_client_subs .inbound_server_data @@ -496,11 +492,11 @@ impl StreamHandlerPoolReal { data: vec![], }) .expect("ProxyClient is dead"); - // TODO: GH-800: Maybe you want the refactored code here too - if let Err(_e) = stream_senders.reader_shutdown_tx.send(()) { - debug!(inner.logger, "Unable to send a shutdown signal to the StreamReader for stream key {:?}. The channel is already gone.", stream_key) - }; - // Test should have a fake server, and the (read and write should be different) server + Self::send_shutdown_signal_to_stream_reader( + stream_senders.reader_shutdown_tx, + &stream_key, + &inner.logger, + ); debug!( inner.logger, "Killed StreamWriter and StreamReader for the stream key {:?} to {} and sent server-drop report", From d86918e08cd73fcc22351db09acb0be841defbea Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Fri, 6 Sep 2024 16:33:58 +0530 Subject: [PATCH 51/65] GH-800: fix proxy_server_receives_terminal_response_from_hopper --- node/src/proxy_server/mod.rs | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/node/src/proxy_server/mod.rs b/node/src/proxy_server/mod.rs index 4c65289e9..20633d00e 100644 --- a/node/src/proxy_server/mod.rs +++ b/node/src/proxy_server/mod.rs @@ -3571,6 +3571,7 @@ mod tests { init_test_logging(); let system = System::new("proxy_server_receives_response_from_hopper"); let (dispatcher, _, dispatcher_recording_arc) = make_recorder(); + let (proxy_server, _, proxy_server_recording_arc) = make_recorder(); let cryptde = main_cryptde(); let mut subject = ProxyServer::new( cryptde, @@ -3611,20 +3612,32 @@ mod tests { 0, ); let second_expired_cores_package = first_expired_cores_package.clone(); - let peer_actors = peer_actors_builder().dispatcher(dispatcher).build(); + let peer_actors = peer_actors_builder() + .dispatcher(dispatcher) + .proxy_server(proxy_server) + .build(); subject_addr.try_send(BindMessage { peer_actors }).unwrap(); subject_addr.try_send(first_expired_cores_package).unwrap(); - subject_addr.try_send(second_expired_cores_package).unwrap(); // should generate log because stream key is now unknown + subject_addr.try_send(second_expired_cores_package).unwrap(); // should shedule a new message System::current().stop(); system.run(); let dispatcher_recording = dispatcher_recording_arc.lock().unwrap(); - let record = dispatcher_recording.get_record::(0); - assert_eq!(record.endpoint, Endpoint::Socket(socket_addr)); - assert_eq!(record.last_data, true); - assert_eq!(record.data, b"16 bytes of data".to_vec()); - TestLogHandler::new().exists_log_containing(&format!("WARN: ProxyServer: Discarding 16-byte packet 12345678 from an unrecognized stream key: {:?}", stream_key)); + let transmit_data_msg = dispatcher_recording.get_record::(0); + let proxy_server_recording = proxy_server_recording_arc.lock().unwrap(); + let scheduled_msg = + proxy_server_recording.get_record::>(0); + assert_eq!(transmit_data_msg.endpoint, Endpoint::Socket(socket_addr)); + assert_eq!(transmit_data_msg.last_data, true); + assert_eq!(transmit_data_msg.data, b"16 bytes of data".to_vec()); + assert_eq!( + scheduled_msg, + &MessageScheduler { + scheduled_msg: StreamKeyPurge { stream_key }, + delay: Duration::from_secs(5) + } + ) } #[test] From 53eadfaaba9926417e8869de056a2fcb179e331f Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Tue, 10 Sep 2024 13:24:10 +0530 Subject: [PATCH 52/65] GH-800: trigger actions From 74eb8570610df5af17a21fda7797086d1b0dfbe2 Mon Sep 17 00:00:00 2001 From: Utkarsh Gupta Date: Tue, 10 Sep 2024 13:52:49 +0530 Subject: [PATCH 53/65] GH-800: assert on a different error on non-mac os --- node/tests/connection_shutdown_test.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/node/tests/connection_shutdown_test.rs b/node/tests/connection_shutdown_test.rs index b695dd86b..4dd8495be 100644 --- a/node/tests/connection_shutdown_test.rs +++ b/node/tests/connection_shutdown_test.rs @@ -42,7 +42,12 @@ fn proxy_client_stream_reader_dies_when_client_stream_is_killed_integration() { let write_error = server_write_error_rx .recv_timeout(Duration::from_secs(60)) .unwrap(); - assert_eq!(write_error.kind(), io::ErrorKind::BrokenPipe); + if cfg!(target_os = "macos") { + assert_eq!(write_error.kind(), io::ErrorKind::BrokenPipe); + } else { + assert_eq!(write_error.kind(), io::ErrorKind::ConnectionReset); + } + join_handle.join().unwrap(); } From ce0d3c5bef9c75647194fef200a807edc51d42bd Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 11 Sep 2024 14:40:20 +0530 Subject: [PATCH 54/65] GH-80: add changes of self-review --- node/src/proxy_client/stream_establisher.rs | 4 - node/src/proxy_client/stream_handler_pool.rs | 85 +------------------- 2 files changed, 2 insertions(+), 87 deletions(-) diff --git a/node/src/proxy_client/stream_establisher.rs b/node/src/proxy_client/stream_establisher.rs index 63c898dcf..4d6fdad24 100644 --- a/node/src/proxy_client/stream_establisher.rs +++ b/node/src/proxy_client/stream_establisher.rs @@ -25,7 +25,6 @@ pub struct StreamEstablisher { pub cryptde: &'static dyn CryptDE, pub stream_adder_tx: Sender<(StreamKey, StreamSenders)>, pub stream_killer_tx: Sender<(StreamKey, u64)>, - pub shutdown_signal_rx: Receiver<()>, pub stream_connector: Box, pub proxy_client_sub: Recipient, pub logger: Logger, @@ -38,7 +37,6 @@ impl Clone for StreamEstablisher { cryptde: self.cryptde, stream_adder_tx: self.stream_adder_tx.clone(), stream_killer_tx: self.stream_killer_tx.clone(), - shutdown_signal_rx: unbounded().1, stream_connector: Box::new(StreamConnectorReal {}), proxy_client_sub: self.proxy_client_sub.clone(), logger: self.logger.clone(), @@ -127,7 +125,6 @@ impl StreamEstablisherFactory for StreamEstablisherFactoryReal { cryptde: self.cryptde, stream_adder_tx: self.stream_adder_tx.clone(), stream_killer_tx: self.stream_killer_tx.clone(), - shutdown_signal_rx: unbounded().1, stream_connector: Box::new(StreamConnectorReal {}), proxy_client_sub: self.proxy_client_subs.inbound_server_data.clone(), logger: self.logger.clone(), @@ -184,7 +181,6 @@ mod tests { cryptde: main_cryptde(), stream_adder_tx, stream_killer_tx, - shutdown_signal_rx: unbounded().1, stream_connector: Box::new(StreamConnectorMock::new()), // only used in "establish_stream" proxy_client_sub, logger: Logger::new("ProxyClient"), diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index f00c22f65..56dccf91a 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -587,12 +587,12 @@ mod tests { use crate::test_utils::main_cryptde; use crate::test_utils::make_meaningless_route; use crate::test_utils::make_wallet; + use crate::test_utils::recorder::make_recorder; use crate::test_utils::recorder::peer_actors_builder; - use crate::test_utils::recorder::{make_proxy_client_subs_from_recorder, make_recorder}; use crate::test_utils::stream_connector_mock::StreamConnectorMock; use crate::test_utils::tokio_wrapper_mocks::ReadHalfWrapperMock; use crate::test_utils::tokio_wrapper_mocks::WriteHalfWrapperMock; - use actix::{Actor, System}; + use actix::System; use masq_lib::constants::HTTP_PORT; use masq_lib::test_utils::logging::init_test_logging; use masq_lib::test_utils::logging::TestLogHandler; @@ -651,7 +651,6 @@ mod tests { cryptde, stream_adder_tx: unbounded().0, stream_killer_tx: unbounded().0, - shutdown_signal_rx: unbounded().1, stream_connector: Box::new(StreamConnectorMock::new()), proxy_client_sub: peer_actors .proxy_client_opt @@ -897,7 +896,6 @@ mod tests { cryptde, stream_adder_tx, stream_killer_tx, - shutdown_signal_rx: unbounded().1, stream_connector: Box::new(StreamConnectorMock::new().with_connection( peer_addr.clone(), peer_addr.clone(), @@ -935,80 +933,6 @@ mod tests { ); } - #[test] - fn while_housekeeping_the_stream_senders_are_received_by_stream_handler_pool() { - init_test_logging(); - let test_name = "stream_handler_pool_sends_shutdown_signal_when_last_data_is_true"; - let (shutdown_tx, shutdown_rx) = unbounded(); - let (stream_adder_tx, stream_adder_rx) = unbounded(); - thread::spawn(move || { - let stream_key = StreamKey::make_meaningful_stream_key("I should die"); - let client_request_payload = ClientRequestPayload_0v1 { - stream_key, - sequenced_packet: SequencedPacket { - data: b"I'm gonna kill you stream key".to_vec(), - sequence_number: 0, - last_data: true, - }, - target_hostname: Some(String::from("3.4.5.6:80")), - target_port: HTTP_PORT, - protocol: ProxyProtocol::HTTP, - originator_public_key: PublicKey::new(&b"brutal death"[..]), - }; - let package = ExpiredCoresPackage::new( - SocketAddr::from_str("1.2.3.4:1234").unwrap(), - Some(make_wallet("consuming")), - make_meaningless_route(), - client_request_payload.into(), - 0, - ); - let peer_addr = SocketAddr::from_str("3.4.5.6:80").unwrap(); - let peer_actors = peer_actors_builder().build(); - let mut subject = StreamHandlerPoolReal::new( - Box::new(ResolverWrapperMock::new()), - main_cryptde(), - peer_actors.accountant.report_exit_service_provided.clone(), - peer_actors.proxy_client_opt.unwrap().clone(), - 100, - 200, - ); - subject.stream_adder_rx = stream_adder_rx; - { - let mut inner = subject.inner.lock().unwrap(); - inner.logger = Logger::new(test_name); - inner.stream_writer_channels.insert( - stream_key, - StreamSenders { - writer_data: Box::new(SenderWrapperMock::new(peer_addr)), - reader_shutdown_tx: shutdown_tx, - }, - ); - inner.establisher_factory = Box::new(StreamEstablisherFactoryReal { - cryptde: main_cryptde(), - stream_adder_tx, - stream_killer_tx: unbounded().0, - proxy_client_subs: make_proxy_client_subs_from_recorder( - &make_recorder().0.start(), - ), - logger: Logger::new("test"), - }); - } - - // TODO: GH-800: Make sure that the stream_adder_tx sends something to the receiver - - run_process_package_in_actix(subject, package); - }); - let received = shutdown_rx.recv(); - assert_eq!(received, Ok(())); - TestLogHandler::new().await_log_containing( - &format!( - "DEBUG: {test_name}: Removing StreamWriter and Shutting down StreamReader \ - for oUHoHuDKHjeWq+BJzBIqHpPFBQw to 3.4.5.6:80" - ), - 500, - ); - } - #[test] fn stream_handler_pool_sends_shutdown_signal_when_last_data_is_true() { init_test_logging(); @@ -1197,7 +1121,6 @@ mod tests { cryptde, stream_adder_tx, stream_killer_tx, - shutdown_signal_rx: unbounded().1, stream_connector: Box::new(StreamConnectorMock::new().with_connection( peer_addr.clone(), peer_addr.clone(), @@ -1377,7 +1300,6 @@ mod tests { cryptde, stream_adder_tx, stream_killer_tx, - shutdown_signal_rx: unbounded().1, stream_connector: Box::new(StreamConnectorMock::new().with_connection( peer_addr.clone(), peer_addr.clone(), @@ -1478,7 +1400,6 @@ mod tests { cryptde, stream_adder_tx, stream_killer_tx, - shutdown_signal_rx: unbounded().1, stream_connector: Box::new( StreamConnectorMock::new() .connect_pair_result(Err(Error::from(ErrorKind::Other))), @@ -1601,7 +1522,6 @@ mod tests { cryptde, stream_adder_tx, stream_killer_tx, - shutdown_signal_rx: unbounded().1, stream_connector: Box::new( StreamConnectorMock::new() .connect_pair_result(Err(Error::from(ErrorKind::Other))), @@ -1718,7 +1638,6 @@ mod tests { cryptde, stream_adder_tx, stream_killer_tx, - shutdown_signal_rx: unbounded().1, stream_connector: Box::new( StreamConnectorMock::new() .with_connection(peer_addr, peer_addr, reader, writer), From 7afe4c7bc584a14b7d1b3c167d54b7a0fd953b52 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Wed, 11 Sep 2024 15:12:53 +0530 Subject: [PATCH 55/65] GH-800: some other missed changes --- node/src/proxy_client/stream_handler_pool.rs | 16 +++++++--------- node/src/proxy_client/stream_reader.rs | 9 --------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 56dccf91a..4ab27e09d 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -35,18 +35,18 @@ pub trait StreamHandlerPool { fn process_package(&self, payload: ClientRequestPayload_0v1, paying_wallet_opt: Option); } -pub struct StreamHandlerPoolReal { - inner: Arc>, - stream_adder_rx: Receiver<(StreamKey, StreamSenders)>, - stream_killer_rx: Receiver<(StreamKey, u64)>, -} - #[derive(Debug)] pub struct StreamSenders { pub writer_data: Box>, pub reader_shutdown_tx: Sender<()>, } +pub struct StreamHandlerPoolReal { + inner: Arc>, + stream_adder_rx: Receiver<(StreamKey, StreamSenders)>, + stream_killer_rx: Receiver<(StreamKey, u64)>, +} + struct StreamHandlerPoolRealInner { accountant_sub: Recipient, proxy_client_subs: ProxyClientSubs, @@ -163,7 +163,6 @@ impl StreamHandlerPoolReal { ) { match reader_shutdown_tx.try_send(()) { Ok(()) => { - // todo!("Ok"); debug!( logger, "A shutdown signal was sent to the StreamReader for stream key {:?}.", @@ -171,7 +170,6 @@ impl StreamHandlerPoolReal { ); } Err(_e) => { - // todo!("ERR"); debug!( logger, "Unable to send a shutdown signal to the StreamReader for \ @@ -261,7 +259,7 @@ impl StreamHandlerPoolReal { None => { debug!( inner.logger, - "Trying to remove StreamWriter {:?}, but it's already gone", stream_key + "Trying to remove StreamWriter and StreamReader for stream key {:?}, but it's already gone", stream_key ) } } diff --git a/node/src/proxy_client/stream_reader.rs b/node/src/proxy_client/stream_reader.rs index 65bf4253f..496608900 100644 --- a/node/src/proxy_client/stream_reader.rs +++ b/node/src/proxy_client/stream_reader.rs @@ -84,15 +84,6 @@ impl Future for StreamReader { } } -impl Drop for StreamReader { - fn drop(&mut self) { - debug!( - Logger::new("TEST"), - "StreamReader for stream key {:?} is being dropped.", self.stream_key - ) - } -} - impl StreamReader { pub fn new( stream_key: StreamKey, From 87a9e20752251e9e1f7dbd419026c6ab82f93708 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Thu, 12 Sep 2024 15:02:24 +0530 Subject: [PATCH 56/65] GH-800: add review 1 changes --- node/src/proxy_client/stream_handler_pool.rs | 9 +- node/src/proxy_client/stream_reader.rs | 5 +- node/src/proxy_server/mod.rs | 140 +++++++++++++++---- node/tests/connection_shutdown_test.rs | 11 +- 4 files changed, 126 insertions(+), 39 deletions(-) diff --git a/node/src/proxy_client/stream_handler_pool.rs b/node/src/proxy_client/stream_handler_pool.rs index 4ab27e09d..5ecbe9794 100644 --- a/node/src/proxy_client/stream_handler_pool.rs +++ b/node/src/proxy_client/stream_handler_pool.rs @@ -29,8 +29,8 @@ use tokio::prelude::future::{err, ok}; use trust_dns_resolver::error::ResolveError; use trust_dns_resolver::lookup_ip::LookupIp; -// TODO: This should be renamed to ProxyClientStreamHandlerPoolReal (or something more concise) -// to differentiate it from the other StreamHandlerPool, which, unlike this, is an actor. +// TODO: This should be renamed to differentiate it from the other StreamHandlerPool, +// which, unlike this, is an actor. pub trait StreamHandlerPool { fn process_package(&self, payload: ClientRequestPayload_0v1, paying_wallet_opt: Option); } @@ -785,9 +785,8 @@ mod tests { 0, ); let peer_actors = peer_actors_builder().proxy_client(proxy_client).build(); - let resolver = ResolverWrapperMock::new() - .lookup_ip_success(vec![IpAddr::from_str("2.3.4.5").unwrap()]); let peer_addr = SocketAddr::from_str("2.3.4.5:80").unwrap(); + let resolver = ResolverWrapperMock::new().lookup_ip_success(vec![peer_addr.ip()]); let tx_to_write = SenderWrapperMock::new(peer_addr).unbounded_send_result( make_send_error(client_request_payload.sequenced_packet.clone()), ); @@ -1920,7 +1919,7 @@ mod tests { } #[test] - fn clean_up_dead_streams_logs_when_the_shutdown_channel_is_down() { + fn clean_up_dead_streams_logs_when_the_stream_reader_is_down() { init_test_logging(); let test_name = "clean_up_dead_streams_logs_when_the_shutdown_channel_is_down"; let system = System::new(test_name); diff --git a/node/src/proxy_client/stream_reader.rs b/node/src/proxy_client/stream_reader.rs index 496608900..63188fd86 100644 --- a/node/src/proxy_client/stream_reader.rs +++ b/node/src/proxy_client/stream_reader.rs @@ -425,10 +425,11 @@ mod tests { let mut subject = make_subject(); subject.shutdown_signal = shutdown_rx; subject.logger = Logger::new(test_name); - shutdown_tx.send(()).unwrap(); - assert_eq!(subject.poll(), Ok(Async::Ready(()))); + let result = subject.poll(); + + assert_eq!(result, Ok(Async::Ready(()))); TestLogHandler::new().exists_log_containing(&format!( "INFO: {test_name}: Shutting down for stream: {:?}", subject.stream_key diff --git a/node/src/proxy_server/mod.rs b/node/src/proxy_server/mod.rs index 20633d00e..98146074d 100644 --- a/node/src/proxy_server/mod.rs +++ b/node/src/proxy_server/mod.rs @@ -80,6 +80,7 @@ pub struct ProxyServer { tunneled_hosts: HashMap, dns_failure_retries: HashMap, stream_key_routes: HashMap, + stream_key_ttl: HashMap, is_decentralized: bool, consuming_wallet_balance: Option, main_cryptde: &'static dyn CryptDE, @@ -260,6 +261,7 @@ impl ProxyServer { tunneled_hosts: HashMap::new(), dns_failure_retries: HashMap::new(), stream_key_routes: HashMap::new(), + stream_key_ttl: HashMap::new(), is_decentralized, consuming_wallet_balance, main_cryptde, @@ -436,6 +438,39 @@ impl ProxyServer { } } + fn schedule_stream_key_purge(&mut self, stream_key: StreamKey) { + debug!( + self.logger, + "Last data received for stream key {:?}, which was tunneling through host {:?}. \ + It will be purged after {:?}.", + &stream_key, + self.tunneled_hosts.get(&stream_key), + self.stream_key_purge_delay + ); + self.stream_key_ttl.insert(stream_key, SystemTime::now()); + self.subs + .as_ref() + .expect("ProxyServer Subs Unbound") + .schedule_stream_key_purge + .try_send(MessageScheduler { + scheduled_msg: StreamKeyPurge { stream_key }, + delay: self.stream_key_purge_delay, + }) + .expect("ProxyServer is dead"); + } + + fn log_straggling_packet(&self, stream_key: &StreamKey, old_timestamp: &SystemTime) { + let duration_since = SystemTime::now() + .duration_since(*old_timestamp) + .expect("time calculation error"); + debug!( + self.logger, + "Straggling packet received for a stream key {:?} with a delay of {:?}", + stream_key, + duration_since + ); + } + fn handle_client_response_payload( &mut self, msg: ExpiredCoresPackage, @@ -495,15 +530,12 @@ impl ProxyServer { }) .expect("Dispatcher is dead"); if last_data { - self.subs - .as_ref() - .expect("ProxyServer Subs Unbound") - .schedule_stream_key_purge - .try_send(MessageScheduler { - scheduled_msg: StreamKeyPurge { stream_key }, - delay: self.stream_key_purge_delay, - }) - .expect("ProxyServer is dead"); + match self.stream_key_ttl.get(&stream_key) { + None => self.schedule_stream_key_purge(stream_key), + Some(old_timestamp) => { + self.log_straggling_packet(&stream_key, old_timestamp) + } + } } } None => { @@ -633,13 +665,11 @@ impl ProxyServer { } fn purge_stream_key(&mut self, stream_key: &StreamKey) { - debug!( - self.logger, - "Retiring stream key {}: no more data", &stream_key - ); + debug!(self.logger, "Retiring stream key {}", &stream_key); let _ = self.keys_and_addrs.remove_a(stream_key); let _ = self.stream_key_routes.remove(stream_key); let _ = self.tunneled_hosts.remove(stream_key); + let _ = self.stream_key_ttl.remove(stream_key); } fn make_payload( @@ -3569,7 +3599,8 @@ mod tests { #[test] fn proxy_server_receives_terminal_response_from_hopper() { init_test_logging(); - let system = System::new("proxy_server_receives_response_from_hopper"); + let test_name = "proxy_server_receives_terminal_response_from_hopper"; + let system = System::new(test_name); let (dispatcher, _, dispatcher_recording_arc) = make_recorder(); let (proxy_server, _, proxy_server_recording_arc) = make_recorder(); let cryptde = main_cryptde(); @@ -3580,8 +3611,9 @@ mod tests { Some(STANDARD_CONSUMING_WALLET_BALANCE), false, ); + subject.logger = Logger::new(test_name); let socket_addr = SocketAddr::from_str("1.2.3.4:5678").unwrap(); - let stream_key = StreamKey::make_meaningless_stream_key(); + let stream_key = StreamKey::make_meaningful_stream_key(test_name); subject .keys_and_addrs .insert(stream_key.clone(), socket_addr.clone()); @@ -3618,8 +3650,8 @@ mod tests { .build(); subject_addr.try_send(BindMessage { peer_actors }).unwrap(); - subject_addr.try_send(first_expired_cores_package).unwrap(); - subject_addr.try_send(second_expired_cores_package).unwrap(); // should shedule a new message + subject_addr.try_send(first_expired_cores_package).unwrap(); // should schedule a new message + subject_addr.try_send(second_expired_cores_package).unwrap(); // should cause the straggling message log System::current().stop(); system.run(); @@ -3635,13 +3667,52 @@ mod tests { scheduled_msg, &MessageScheduler { scheduled_msg: StreamKeyPurge { stream_key }, - delay: Duration::from_secs(5) + delay: STREAM_KEY_PURGE_DELAY } - ) + ); + TestLogHandler::new() + .exists_log_containing(&format!( + "DEBUG: {test_name}: Straggling packet received for a stream key {stream_key} with a delay of" + )); + } + + #[test] + #[should_panic(expected = "time calculation error")] + fn log_straggling_packet_panics_if_timestamp_is_wrong() { + let subject = ProxyServer::new( + main_cryptde(), + alias_cryptde(), + true, + Some(STANDARD_CONSUMING_WALLET_BALANCE), + false, + ); + let stream_key = StreamKey::make_meaningless_stream_key(); + let timestamp = SystemTime::now() + .checked_add(Duration::from_secs(10)) + .unwrap(); + let _ = subject.log_straggling_packet(&stream_key, ×tamp); } #[test] fn handle_client_response_payload_purges_stream_keys_for_terminal_response() { + /* + +---------------------------------------------------------------------------+ + | if current_time < stream_key_purge_delay_in_millis - offset_in_millis | + | -> Records Exist | + +---------------------------------------------------------------------------+ + | + v + +---------------------------------------------------------------------------+ + | Purge happens when current_time reaches stream_key_purge_delay_in_millis | + +---------------------------------------------------------------------------+ + | + v + +---------------------------------------------------------------------------+ + | if current_time > stream_key_purge_delay_in_millis + offset_in_millis | + | -> Records were purged | + +---------------------------------------------------------------------------+ + */ + init_test_logging(); let test_name = "handle_client_response_payload_purges_stream_keys_for_terminal_response"; let cryptde = main_cryptde(); @@ -3657,8 +3728,7 @@ mod tests { subject.stream_key_purge_delay = Duration::from_millis(stream_key_purge_delay_in_millis); subject.logger = Logger::new(test_name); subject.subs = Some(make_proxy_server_out_subs()); - - let stream_key = StreamKey::make_meaningless_stream_key(); + let stream_key = StreamKey::make_meaningful_stream_key(test_name); let socket_addr = SocketAddr::from_str("1.2.3.4:5678").unwrap(); subject .keys_and_addrs @@ -3698,18 +3768,34 @@ mod tests { client_response_payload.into(), 0, ); - let system = - System::new("handle_client_response_payload_purges_stream_keys_for_terminal_response"); + let system = System::new(test_name); let bind_msg = BindMessage { peer_actors }; proxy_server_addr.try_send(bind_msg).unwrap(); + let time_before_sending_package = SystemTime::now(); proxy_server_addr.try_send(expired_cores_package).unwrap(); + let time_after_sending_package = time_before_sending_package + .checked_add(Duration::from_secs(1)) + .unwrap(); let pre_assertions_msg = AssertionsMessage { assertions: Box::new(move |proxy_server: &mut ProxyServer| { + let purge_timestamp = proxy_server + .stream_key_ttl + .get(&stream_key) + .unwrap() + .clone(); + assert!( + time_before_sending_package <= purge_timestamp + && purge_timestamp <= time_after_sending_package + ); assert!(!proxy_server.keys_and_addrs.is_empty()); assert!(!proxy_server.stream_key_routes.is_empty()); assert!(!proxy_server.tunneled_hosts.is_empty()); + TestLogHandler::new().exists_log_containing(&format!( + "DEBUG: {test_name}: Last data received for stream key vYMR621EYFzvxTJqpzrGKr3KMbc, \ + which was tunneling through host Some(\"hostname\"). It will be purged after 500ms." + )); }), }; proxy_server_addr @@ -3720,13 +3806,13 @@ mod tests { .unwrap(); let post_assertions_msg = AssertionsMessage { assertions: Box::new(move |proxy_server: &mut ProxyServer| { - TestLogHandler::new() - .exists_log_containing(&format!( - "DEBUG: {test_name}: Retiring stream key AAAAAAAAAAAAAAAAAAAAAAAAAAA: no more data" - )); assert!(proxy_server.keys_and_addrs.is_empty()); assert!(proxy_server.stream_key_routes.is_empty()); assert!(proxy_server.tunneled_hosts.is_empty()); + assert!(proxy_server.stream_key_ttl.is_empty()); + TestLogHandler::new().exists_log_containing(&format!( + "DEBUG: {test_name}: Retiring stream key vYMR621EYFzvxTJqpzrGKr3KMbc" + )); System::current().stop(); }), }; diff --git a/node/tests/connection_shutdown_test.rs b/node/tests/connection_shutdown_test.rs index 4dd8495be..24cd9d25c 100644 --- a/node/tests/connection_shutdown_test.rs +++ b/node/tests/connection_shutdown_test.rs @@ -27,17 +27,18 @@ fn proxy_client_stream_reader_dies_when_client_stream_is_killed_integration() { let join_handle = thread::spawn(move || { endless_write_server(server_port, server_write_error_tx); }); - let mut stream = TcpStream::connect(SocketAddr::from_str("127.0.0.1:80").unwrap()).unwrap(); - stream + let mut browser_stream = + TcpStream::connect(SocketAddr::from_str("127.0.0.1:80").unwrap()).unwrap(); + browser_stream .set_read_timeout(Some(Duration::from_millis(1000))) .unwrap(); let request = format!("GET / HTTP/1.1\r\nHost: 127.0.0.1:{server_port}\r\n\r\n"); - stream.write(request.as_bytes()).unwrap(); + browser_stream.write(request.as_bytes()).unwrap(); let mut buf = [0u8; 16384]; // We want to make sure the Server is sending before we shutdown the stream - stream.read(&mut buf).unwrap(); + browser_stream.read(&mut buf).unwrap(); - stream.shutdown(Shutdown::Write).unwrap(); + browser_stream.shutdown(Shutdown::Write).unwrap(); let write_error = server_write_error_rx .recv_timeout(Duration::from_secs(60)) From 34a42dc31ea59ae5fbd5d0694f772357ddc541b3 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Thu, 19 Sep 2024 14:36:45 +0530 Subject: [PATCH 57/65] GH-800: add review 2 changes --- node/src/proxy_server/mod.rs | 241 +++++++++++++++++++++++++++-------- 1 file changed, 189 insertions(+), 52 deletions(-) diff --git a/node/src/proxy_server/mod.rs b/node/src/proxy_server/mod.rs index 98146074d..78329f90e 100644 --- a/node/src/proxy_server/mod.rs +++ b/node/src/proxy_server/mod.rs @@ -459,13 +459,19 @@ impl ProxyServer { .expect("ProxyServer is dead"); } - fn log_straggling_packet(&self, stream_key: &StreamKey, old_timestamp: &SystemTime) { + fn log_straggling_packet( + &self, + stream_key: &StreamKey, + packet_len: usize, + old_timestamp: &SystemTime, + ) { let duration_since = SystemTime::now() .duration_since(*old_timestamp) .expect("time calculation error"); - debug!( + warning!( self.logger, - "Straggling packet received for a stream key {:?} with a delay of {:?}", + "Straggling packet of length {} received for a stream key {:?} after a delay of {:?}", + packet_len, stream_key, duration_since ); @@ -498,7 +504,8 @@ impl ProxyServer { response.sequenced_packet.data.len(), payload_data_len, ); - match self.remove_dns_failure_retry(&response.stream_key) { + let stream_key = response.stream_key; + match self.remove_dns_failure_retry(&stream_key) { Ok(_) => { debug!(self.logger, "Successful attempt of DNS resolution, removing DNS retry entry for stream key: {}", &response.stream_key) } @@ -510,10 +517,12 @@ impl ProxyServer { ) } } - match self.keys_and_addrs.a_to_b(&response.stream_key) { + if let Some(old_timestamp) = self.stream_key_ttl.get(&stream_key) { + self.log_straggling_packet(&stream_key, payload_data_len, old_timestamp) + } + match self.keys_and_addrs.a_to_b(&stream_key) { Some(socket_addr) => { let last_data = response.sequenced_packet.last_data; - let stream_key = response.stream_key; let sequence_number = Some( response.sequenced_packet.sequence_number + self.browser_proxy_sequence_offset as u64, @@ -530,12 +539,11 @@ impl ProxyServer { }) .expect("Dispatcher is dead"); if last_data { - match self.stream_key_ttl.get(&stream_key) { - None => self.schedule_stream_key_purge(stream_key), - Some(old_timestamp) => { - self.log_straggling_packet(&stream_key, old_timestamp) - } - } + debug!( + self.logger, + "Received last data for the stream key {stream_key}." + ); + self.purge_stream_key(&stream_key); } } None => { @@ -618,6 +626,7 @@ impl ProxyServer { self.logger, "Reporting shutdown of {} to counterpart", &stream_key ); + self.schedule_stream_key_purge(stream_key); let ibcd = InboundClientData { timestamp: SystemTime::now(), peer_addr: msg.peer_addr, @@ -3602,7 +3611,6 @@ mod tests { let test_name = "proxy_server_receives_terminal_response_from_hopper"; let system = System::new(test_name); let (dispatcher, _, dispatcher_recording_arc) = make_recorder(); - let (proxy_server, _, proxy_server_recording_arc) = make_recorder(); let cryptde = main_cryptde(); let mut subject = ProxyServer::new( cryptde, @@ -3644,36 +3652,28 @@ mod tests { 0, ); let second_expired_cores_package = first_expired_cores_package.clone(); - let peer_actors = peer_actors_builder() - .dispatcher(dispatcher) - .proxy_server(proxy_server) - .build(); + let peer_actors = peer_actors_builder().dispatcher(dispatcher).build(); subject_addr.try_send(BindMessage { peer_actors }).unwrap(); - subject_addr.try_send(first_expired_cores_package).unwrap(); // should schedule a new message - subject_addr.try_send(second_expired_cores_package).unwrap(); // should cause the straggling message log + subject_addr.try_send(first_expired_cores_package).unwrap(); // This will purge the stream key records + subject_addr.try_send(second_expired_cores_package).unwrap(); // This will be discarded System::current().stop(); system.run(); let dispatcher_recording = dispatcher_recording_arc.lock().unwrap(); let transmit_data_msg = dispatcher_recording.get_record::(0); - let proxy_server_recording = proxy_server_recording_arc.lock().unwrap(); - let scheduled_msg = - proxy_server_recording.get_record::>(0); assert_eq!(transmit_data_msg.endpoint, Endpoint::Socket(socket_addr)); assert_eq!(transmit_data_msg.last_data, true); assert_eq!(transmit_data_msg.data, b"16 bytes of data".to_vec()); - assert_eq!( - scheduled_msg, - &MessageScheduler { - scheduled_msg: StreamKeyPurge { stream_key }, - delay: STREAM_KEY_PURGE_DELAY - } - ); - TestLogHandler::new() - .exists_log_containing(&format!( - "DEBUG: {test_name}: Straggling packet received for a stream key {stream_key} with a delay of" - )); + let tlh = TestLogHandler::new(); + tlh.exists_log_containing(&format!( + "DEBUG: {test_name}: Received last data for the stream key {:?}.", + stream_key + )); + tlh.exists_log_containing(&format!( + "WARN: {test_name}: Discarding 16-byte packet 12345678 from an unrecognized stream key: {:?}", + stream_key + )); } #[test] @@ -3690,11 +3690,70 @@ mod tests { let timestamp = SystemTime::now() .checked_add(Duration::from_secs(10)) .unwrap(); - let _ = subject.log_straggling_packet(&stream_key, ×tamp); + let _ = subject.log_straggling_packet(&stream_key, 10, ×tamp); } #[test] fn handle_client_response_payload_purges_stream_keys_for_terminal_response() { + let cryptde = main_cryptde(); + let mut subject = ProxyServer::new( + cryptde, + alias_cryptde(), + true, + Some(STANDARD_CONSUMING_WALLET_BALANCE), + false, + ); + subject.subs = Some(make_proxy_server_out_subs()); + + let stream_key = StreamKey::make_meaningless_stream_key(); + let socket_addr = SocketAddr::from_str("1.2.3.4:5678").unwrap(); + subject + .keys_and_addrs + .insert(stream_key.clone(), socket_addr.clone()); + subject.stream_key_routes.insert( + stream_key.clone(), + RouteQueryResponse { + route: Route { hops: vec![] }, + expected_services: ExpectedServices::RoundTrip(vec![], vec![], 1234), + }, + ); + subject + .tunneled_hosts + .insert(stream_key.clone(), "hostname".to_string()); + subject.route_ids_to_return_routes.insert( + 1234, + AddReturnRouteMessage { + return_route_id: 1234, + expected_services: vec![], + protocol: ProxyProtocol::HTTP, + hostname_opt: None, + }, + ); + let client_response_payload = ClientResponsePayload_0v1 { + stream_key: stream_key.clone(), + sequenced_packet: SequencedPacket::new(vec![], 1, true), + }; + let (dispatcher_mock, _, _) = make_recorder(); + let peer_actors = peer_actors_builder().dispatcher(dispatcher_mock).build(); + subject.subs.as_mut().unwrap().dispatcher = peer_actors.dispatcher.from_dispatcher_client; + let expired_cores_package: ExpiredCoresPackage = + ExpiredCoresPackage::new( + SocketAddr::from_str("1.2.3.4:1234").unwrap(), + Some(make_wallet("irrelevant")), + return_route_with_id(cryptde, 1234), + client_response_payload.into(), + 0, + ); + + subject.handle_client_response_payload(expired_cores_package); + + assert!(subject.keys_and_addrs.is_empty()); + assert!(subject.stream_key_routes.is_empty()); + assert!(subject.tunneled_hosts.is_empty()); + } + + #[test] + fn proxy_server_schedules_stream_key_purge_once_shutdown_order_is_received_for_stream() { /* +---------------------------------------------------------------------------+ | if current_time < stream_key_purge_delay_in_millis - offset_in_millis | @@ -3714,7 +3773,8 @@ mod tests { */ init_test_logging(); - let test_name = "handle_client_response_payload_purges_stream_keys_for_terminal_response"; + let test_name = + "proxy_server_schedules_stream_key_purge_once_shutdown_order_is_received_for_stream"; let cryptde = main_cryptde(); let stream_key_purge_delay_in_millis = 500; let offset_in_millis = 100; @@ -3752,28 +3812,24 @@ mod tests { hostname_opt: None, }, ); - let client_response_payload = ClientResponsePayload_0v1 { - stream_key: stream_key.clone(), - sequenced_packet: SequencedPacket::new(vec![], 1, true), - }; let proxy_server_addr = subject.start(); - let schedule_stream_key_sub = proxy_server_addr.clone().recipient(); + let schedule_stream_key_purge_sub = proxy_server_addr.clone().recipient(); let mut peer_actors = peer_actors_builder().build(); - peer_actors.proxy_server.schedule_stream_key_purge = schedule_stream_key_sub; - let expired_cores_package: ExpiredCoresPackage = - ExpiredCoresPackage::new( - SocketAddr::from_str("1.2.3.4:1234").unwrap(), - Some(make_wallet("irrelevant")), - return_route_with_id(cryptde, 1234), - client_response_payload.into(), - 0, - ); + peer_actors.proxy_server.schedule_stream_key_purge = schedule_stream_key_purge_sub; let system = System::new(test_name); let bind_msg = BindMessage { peer_actors }; proxy_server_addr.try_send(bind_msg).unwrap(); let time_before_sending_package = SystemTime::now(); + let stream_shutdown_msg = StreamShutdownMsg { + peer_addr: socket_addr, + stream_type: RemovedStreamType::NonClandestine(NonClandestineAttributes { + reception_port: 0, + sequence_number: 0, + }), + report_to_counterpart: true, + }; - proxy_server_addr.try_send(expired_cores_package).unwrap(); + proxy_server_addr.try_send(stream_shutdown_msg).unwrap(); let time_after_sending_package = time_before_sending_package .checked_add(Duration::from_secs(1)) @@ -3793,7 +3849,7 @@ mod tests { assert!(!proxy_server.stream_key_routes.is_empty()); assert!(!proxy_server.tunneled_hosts.is_empty()); TestLogHandler::new().exists_log_containing(&format!( - "DEBUG: {test_name}: Last data received for stream key vYMR621EYFzvxTJqpzrGKr3KMbc, \ + "DEBUG: {test_name}: Last data received for stream key zpi6SfvohvBgqq9y8zLgzIhxPS4, \ which was tunneling through host Some(\"hostname\"). It will be purged after 500ms." )); }), @@ -3811,7 +3867,7 @@ mod tests { assert!(proxy_server.tunneled_hosts.is_empty()); assert!(proxy_server.stream_key_ttl.is_empty()); TestLogHandler::new().exists_log_containing(&format!( - "DEBUG: {test_name}: Retiring stream key vYMR621EYFzvxTJqpzrGKr3KMbc" + "DEBUG: {test_name}: Retiring stream key zpi6SfvohvBgqq9y8zLgzIhxPS4" )); System::current().stop(); }), @@ -3825,6 +3881,85 @@ mod tests { system.run(); } + #[test] + fn straggling_packets_are_logged() { + init_test_logging(); + let test_name = "straggling_packets_are_logged"; + let cryptde = main_cryptde(); + let mut subject = ProxyServer::new( + cryptde, + alias_cryptde(), + true, + Some(STANDARD_CONSUMING_WALLET_BALANCE), + false, + ); + subject.logger = Logger::new(test_name); + subject.subs = Some(make_proxy_server_out_subs()); + let stream_key = StreamKey::make_meaningful_stream_key(test_name); + let socket_addr = SocketAddr::from_str("1.2.3.4:5678").unwrap(); + subject + .keys_and_addrs + .insert(stream_key.clone(), socket_addr.clone()); + subject.stream_key_routes.insert( + stream_key.clone(), + RouteQueryResponse { + route: Route { hops: vec![] }, + expected_services: ExpectedServices::RoundTrip(vec![], vec![], 1234), + }, + ); + subject + .tunneled_hosts + .insert(stream_key.clone(), "hostname".to_string()); + subject.route_ids_to_return_routes.insert( + 1234, + AddReturnRouteMessage { + return_route_id: 1234, + expected_services: vec![], + protocol: ProxyProtocol::HTTP, + hostname_opt: None, + }, + ); + let proxy_server_addr = subject.start(); + let schedule_stream_key_purge_sub = proxy_server_addr.clone().recipient(); + let mut peer_actors = peer_actors_builder().build(); + peer_actors.proxy_server.schedule_stream_key_purge = schedule_stream_key_purge_sub; + + let system = System::new(test_name); + let bind_msg = BindMessage { peer_actors }; + proxy_server_addr.try_send(bind_msg).unwrap(); + let stream_shutdown_msg = StreamShutdownMsg { + peer_addr: socket_addr, + stream_type: RemovedStreamType::NonClandestine(NonClandestineAttributes { + reception_port: 0, + sequence_number: 0, + }), + report_to_counterpart: true, + }; + let client_response_payload = ClientResponsePayload_0v1 { + stream_key: stream_key.clone(), + sequenced_packet: SequencedPacket::new(vec![], 1, true), + }; + let expired_cores_package: ExpiredCoresPackage = + ExpiredCoresPackage::new( + SocketAddr::from_str("1.2.3.4:1234").unwrap(), + Some(make_wallet("irrelevant")), + return_route_with_id(cryptde, 1234), + client_response_payload.into(), + 0, + ); + proxy_server_addr.try_send(stream_shutdown_msg).unwrap(); + + proxy_server_addr.try_send(expired_cores_package).unwrap(); + + System::current().stop(); + system.run(); + TestLogHandler::new().exists_log_containing(&format!( + "WARN: {test_name}: Straggling packet of length 0 received for a \ + stream key {:?} after a delay of", + stream_key + )); + } + #[test] fn proxy_server_receives_nonterminal_response_from_hopper() { let system = System::new("proxy_server_receives_nonterminal_response_from_hopper"); @@ -5745,6 +5880,7 @@ mod tests { fn handle_stream_shutdown_msg_logs_errors_from_handling_normal_client_data() { init_test_logging(); let mut subject = ProxyServer::new(main_cryptde(), alias_cryptde(), true, Some(0), false); + subject.subs = Some(make_proxy_server_out_subs()); let helper = IBCDHelperMock::default() .handle_normal_client_data_result(Err("Our help is not welcome".to_string())); subject.inbound_client_data_helper_opt = Some(Box::new(helper)); @@ -5769,6 +5905,7 @@ mod tests { fn stream_shutdown_msg_populates_correct_inbound_client_data_msg() { let help_to_handle_normal_client_data_params_arc = Arc::new(Mutex::new(vec![])); let mut subject = ProxyServer::new(main_cryptde(), alias_cryptde(), true, Some(0), false); + subject.subs = Some(make_proxy_server_out_subs()); let icd_helper = IBCDHelperMock::default() .handle_normal_client_data_params(&help_to_handle_normal_client_data_params_arc) .handle_normal_client_data_result(Ok(())); From 434fb5b216d90673b34a5ca41c8dd0bb0dd4ecc1 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Fri, 20 Sep 2024 17:54:14 +0530 Subject: [PATCH 58/65] GH-800: add review 3 changes --- node/src/proxy_server/mod.rs | 60 +++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/node/src/proxy_server/mod.rs b/node/src/proxy_server/mod.rs index 78329f90e..991061f88 100644 --- a/node/src/proxy_server/mod.rs +++ b/node/src/proxy_server/mod.rs @@ -441,7 +441,7 @@ impl ProxyServer { fn schedule_stream_key_purge(&mut self, stream_key: StreamKey) { debug!( self.logger, - "Last data received for stream key {:?}, which was tunneling through host {:?}. \ + "Client closed stream referenced by stream key {:?}, which was tunneling to the host {:?}. \ It will be purged after {:?}.", &stream_key, self.tunneled_hosts.get(&stream_key), @@ -3755,21 +3755,28 @@ mod tests { #[test] fn proxy_server_schedules_stream_key_purge_once_shutdown_order_is_received_for_stream() { /* - +---------------------------------------------------------------------------+ - | if current_time < stream_key_purge_delay_in_millis - offset_in_millis | - | -> Records Exist | - +---------------------------------------------------------------------------+ - | - v - +---------------------------------------------------------------------------+ - | Purge happens when current_time reaches stream_key_purge_delay_in_millis | - +---------------------------------------------------------------------------+ - | - v - +---------------------------------------------------------------------------+ - | if current_time > stream_key_purge_delay_in_millis + offset_in_millis | - | -> Records were purged | - +---------------------------------------------------------------------------+ + +------------------------------------------------------------------+ + | (0ms) | + | Stream shutdown is ordered | + +------------------------------------------------------------------+ + | + v + +------------------------------------------------------------------+ + | (400ms) (stream_key_purge_delay_in_millis - offset_in_millis) | + | Pre-purge assertion message finds records | + +------------------------------------------------------------------+ + | + v + +------------------------------------------------------------------+ + | (500ms) (stream_key_purge_delay_in_millis) | + | Stream is purged | + +------------------------------------------------------------------+ + | + v + +------------------------------------------------------------------+ + | (600ms) (stream_key_purge_delay_in_millis + offset_in_millis) | + | Post-purge assertion message finds no records | + +------------------------------------------------------------------+ */ init_test_logging(); @@ -3834,7 +3841,7 @@ mod tests { let time_after_sending_package = time_before_sending_package .checked_add(Duration::from_secs(1)) .unwrap(); - let pre_assertions_msg = AssertionsMessage { + let pre_purge_assertions = AssertionsMessage { assertions: Box::new(move |proxy_server: &mut ProxyServer| { let purge_timestamp = proxy_server .stream_key_ttl @@ -3849,33 +3856,36 @@ mod tests { assert!(!proxy_server.stream_key_routes.is_empty()); assert!(!proxy_server.tunneled_hosts.is_empty()); TestLogHandler::new().exists_log_containing(&format!( - "DEBUG: {test_name}: Last data received for stream key zpi6SfvohvBgqq9y8zLgzIhxPS4, \ - which was tunneling through host Some(\"hostname\"). It will be purged after 500ms." + "DEBUG: {test_name}: Client closed stream referenced by stream key {:?}, \ + which was tunneling to the host Some(\"hostname\"). \ + It will be purged after {stream_key_purge_delay_in_millis}ms.", + stream_key )); }), }; proxy_server_addr .try_send(MessageScheduler { - scheduled_msg: pre_assertions_msg, - delay: Duration::from_millis(stream_key_purge_delay_in_millis - offset_in_millis), + scheduled_msg: pre_purge_assertions, + delay: Duration::from_millis(stream_key_purge_delay_in_millis - offset_in_millis), // 400ms }) .unwrap(); - let post_assertions_msg = AssertionsMessage { + let post_purge_assertions = AssertionsMessage { assertions: Box::new(move |proxy_server: &mut ProxyServer| { assert!(proxy_server.keys_and_addrs.is_empty()); assert!(proxy_server.stream_key_routes.is_empty()); assert!(proxy_server.tunneled_hosts.is_empty()); assert!(proxy_server.stream_key_ttl.is_empty()); TestLogHandler::new().exists_log_containing(&format!( - "DEBUG: {test_name}: Retiring stream key zpi6SfvohvBgqq9y8zLgzIhxPS4" + "DEBUG: {test_name}: Retiring stream key {:?}", + stream_key )); System::current().stop(); }), }; proxy_server_addr .try_send(MessageScheduler { - scheduled_msg: post_assertions_msg, - delay: Duration::from_millis(stream_key_purge_delay_in_millis + offset_in_millis), + scheduled_msg: post_purge_assertions, + delay: Duration::from_millis(stream_key_purge_delay_in_millis + offset_in_millis), // 600ms }) .unwrap(); system.run(); From 1bfcfd8e563cffad1dbea7804c36bfde33325141 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Tue, 24 Sep 2024 14:47:16 +0530 Subject: [PATCH 59/65] GH-800: add review 4 changes --- node/src/proxy_server/mod.rs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/node/src/proxy_server/mod.rs b/node/src/proxy_server/mod.rs index 991061f88..1c4d234c9 100644 --- a/node/src/proxy_server/mod.rs +++ b/node/src/proxy_server/mod.rs @@ -439,12 +439,15 @@ impl ProxyServer { } fn schedule_stream_key_purge(&mut self, stream_key: StreamKey) { + let host_info = match self.tunneled_hosts.get(&stream_key) { + None => String::from(""), + Some(hostname) => format!(", which was tunneling to the host {:?}", hostname), + }; debug!( self.logger, - "Client closed stream referenced by stream key {:?}, which was tunneling to the host {:?}. \ - It will be purged after {:?}.", + "Client closed stream referenced by stream key {:?}{}. It will be purged after {:?}.", &stream_key, - self.tunneled_hosts.get(&stream_key), + host_info, self.stream_key_purge_delay ); self.stream_key_ttl.insert(stream_key, SystemTime::now()); @@ -3857,7 +3860,7 @@ mod tests { assert!(!proxy_server.tunneled_hosts.is_empty()); TestLogHandler::new().exists_log_containing(&format!( "DEBUG: {test_name}: Client closed stream referenced by stream key {:?}, \ - which was tunneling to the host Some(\"hostname\"). \ + which was tunneling to the host \"hostname\". \ It will be purged after {stream_key_purge_delay_in_millis}ms.", stream_key )); @@ -5713,7 +5716,10 @@ mod tests { #[test] fn handle_stream_shutdown_msg_reports_to_counterpart_without_tunnel_when_necessary() { - let system = System::new("test"); + init_test_logging(); + let test_name = + "handle_stream_shutdown_msg_reports_to_counterpart_without_tunnel_when_necessary"; + let system = System::new(test_name); let mut subject = ProxyServer::new( main_cryptde(), alias_cryptde(), @@ -5770,6 +5776,7 @@ mod tests { ), }, ); + subject.logger = Logger::new(test_name); let subject_addr = subject.start(); let (hopper, _, hopper_recording_arc) = make_recorder(); let (proxy_server, _, proxy_server_recording_arc) = make_recorder(); @@ -5824,6 +5831,11 @@ mod tests { report_to_counterpart: false } ); + TestLogHandler::new().exists_log_containing(&format!( + "DEBUG: {test_name}: Client closed stream referenced by stream key {:?}. \ + It will be purged after {:?}.", + &affected_stream_key, STREAM_KEY_PURGE_DELAY + )); } #[test] From 36f08df750f5212ff65bc387f0dcc9efacb5f86e Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Thu, 17 Oct 2024 12:33:23 +0530 Subject: [PATCH 60/65] GH-800: add better logging --- node/src/proxy_client/stream_reader.rs | 6 ++--- node/src/proxy_server/mod.rs | 32 +++++++++----------------- node/src/stream_handler_pool.rs | 28 +++++++++++++++++++--- 3 files changed, 38 insertions(+), 28 deletions(-) diff --git a/node/src/proxy_client/stream_reader.rs b/node/src/proxy_client/stream_reader.rs index 63188fd86..992b58dbf 100644 --- a/node/src/proxy_client/stream_reader.rs +++ b/node/src/proxy_client/stream_reader.rs @@ -3,7 +3,6 @@ use crate::sub_lib::proxy_client::InboundServerData; use crate::sub_lib::sequencer::Sequencer; use crate::sub_lib::stream_key::StreamKey; use crate::sub_lib::tokio_wrappers::ReadHalfWrapper; -use crate::sub_lib::utils; use crate::sub_lib::utils::indicates_dead_stream; use actix::Recipient; use crossbeam_channel::{Receiver, Sender}; @@ -52,10 +51,9 @@ impl Future for StreamReader { if self.logger.trace_enabled() { trace!( self.logger, - "Read {}-byte chunk from {}: {}", + "Read {}-byte chunk from {}", len, - self.peer_addr, - utils::to_string(&Vec::from(&buf[0..len])) + self.peer_addr ); } let stream_key = self.stream_key; diff --git a/node/src/proxy_server/mod.rs b/node/src/proxy_server/mod.rs index 1c4d234c9..112b4d38e 100644 --- a/node/src/proxy_server/mod.rs +++ b/node/src/proxy_server/mod.rs @@ -230,7 +230,7 @@ impl Handler for ProxyServer { type Result = (); fn handle(&mut self, msg: StreamKeyPurge, _ctx: &mut Self::Context) -> Self::Result { - self.purge_stream_key(&msg.stream_key); + self.purge_stream_key(&msg.stream_key, "scheduled message"); } } @@ -326,12 +326,7 @@ impl ProxyServer { } fn retire_stream_key(&mut self, stream_key: &StreamKey) { - warning!( - self.logger, - "Retiring stream key {}: DnsResolveFailure", - stream_key - ); - self.purge_stream_key(stream_key); + self.purge_stream_key(stream_key, "DNS resolution failure"); } fn send_dns_failure_response_to_the_browser( @@ -542,11 +537,7 @@ impl ProxyServer { }) .expect("Dispatcher is dead"); if last_data { - debug!( - self.logger, - "Received last data for the stream key {stream_key}." - ); - self.purge_stream_key(&stream_key); + self.purge_stream_key(&stream_key, "last data received from the exit node"); } } None => { @@ -645,11 +636,7 @@ impl ProxyServer { error!(self.logger, "{}", e) }; } else { - debug!( - self.logger, - "Retiring stream key {}: StreamShutdownMsg for peer {}", &stream_key, msg.peer_addr - ); - self.purge_stream_key(&stream_key); + self.purge_stream_key(&stream_key, "the reason that client closed the stream"); } } @@ -676,8 +663,11 @@ impl ProxyServer { } } - fn purge_stream_key(&mut self, stream_key: &StreamKey) { - debug!(self.logger, "Retiring stream key {}", &stream_key); + fn purge_stream_key(&mut self, stream_key: &StreamKey, reason: &str) { + debug!( + self.logger, + "Retiring stream key {} due to {}", &stream_key, reason + ); let _ = self.keys_and_addrs.remove_a(stream_key); let _ = self.stream_key_routes.remove(stream_key); let _ = self.tunneled_hosts.remove(stream_key); @@ -3670,7 +3660,7 @@ mod tests { assert_eq!(transmit_data_msg.data, b"16 bytes of data".to_vec()); let tlh = TestLogHandler::new(); tlh.exists_log_containing(&format!( - "DEBUG: {test_name}: Received last data for the stream key {:?}.", + "DEBUG: {test_name}: Retiring stream key {:?} due to last data received from the exit node", stream_key )); tlh.exists_log_containing(&format!( @@ -5303,7 +5293,7 @@ mod tests { let make_params = make_params_arc.lock().unwrap(); assert_eq!(make_params.len(), 3); TestLogHandler::new().exists_log_containing(&format!( - "WARN: {test_name}: Retiring stream key {stream_key_clone}: DnsResolveFailure" + "DEBUG: {test_name}: Retiring stream key {stream_key_clone} due to DNS resolution failure" )); } diff --git a/node/src/stream_handler_pool.rs b/node/src/stream_handler_pool.rs index b80e01f92..3e8b511ef 100644 --- a/node/src/stream_handler_pool.rs +++ b/node/src/stream_handler_pool.rs @@ -375,8 +375,30 @@ impl StreamHandlerPool { stream_writer_key ); let report_to_counterpart = match self.stream_writers.remove(&stream_writer_key) { - None | Some(None) => false, - Some(Some(_sender_wrapper)) => true, + None => { + trace!( + self.logger, + "While handling RemoveStreamMsg: Stream Writers did not contain any entry for key {}", + stream_writer_key + ); + false + } + Some(None) => { + trace!( + self.logger, + "While handling RemoveStreamMsg: Stream Writers contain an entry for key {}, but stream writer is missing", + stream_writer_key + ); + true + } + Some(Some(_sender_wrapper)) => { + trace!( + self.logger, + "While handling RemoveStreamMsg: Stream Writers contained an entry for key {}, also found stream writer; removing", + stream_writer_key + ); + true + } }; let stream_shutdown_msg = StreamShutdownMsg { peer_addr: msg.peer_addr, @@ -1297,7 +1319,7 @@ mod tests { &StreamShutdownMsg { peer_addr, stream_type: RemovedStreamType::Clandestine, - report_to_counterpart: false + report_to_counterpart: true } ); } From 540d25925662964ea3e4fd2831b0fd4830b9437b Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Mon, 28 Oct 2024 14:01:51 +0530 Subject: [PATCH 61/65] GH-800: delay purge when the report_to_counterpart is false --- node/src/proxy_server/mod.rs | 48 +++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/node/src/proxy_server/mod.rs b/node/src/proxy_server/mod.rs index 112b4d38e..00f422aaf 100644 --- a/node/src/proxy_server/mod.rs +++ b/node/src/proxy_server/mod.rs @@ -615,12 +615,12 @@ impl ProxyServer { } Some(sk) => sk, }; + self.schedule_stream_key_purge(stream_key); if msg.report_to_counterpart { debug!( self.logger, "Reporting shutdown of {} to counterpart", &stream_key ); - self.schedule_stream_key_purge(stream_key); let ibcd = InboundClientData { timestamp: SystemTime::now(), peer_addr: msg.peer_addr, @@ -635,8 +635,6 @@ impl ProxyServer { { error!(self.logger, "{}", e) }; - } else { - self.purge_stream_key(&stream_key, "the reason that client closed the stream"); } } @@ -3747,6 +3745,25 @@ mod tests { #[test] fn proxy_server_schedules_stream_key_purge_once_shutdown_order_is_received_for_stream() { + let common_msg = StreamShutdownMsg { + peer_addr: SocketAddr::from_str("1.2.3.4:5678").unwrap(), + stream_type: RemovedStreamType::NonClandestine(NonClandestineAttributes { + reception_port: 0, + sequence_number: 0, + }), + report_to_counterpart: true, + }; + stream_is_purged_with_a_delay(StreamShutdownMsg { + report_to_counterpart: true, + ..common_msg.clone() + }); + stream_is_purged_with_a_delay(StreamShutdownMsg { + report_to_counterpart: false, + ..common_msg + }); + } + + fn stream_is_purged_with_a_delay(msg: StreamShutdownMsg) { /* +------------------------------------------------------------------+ | (0ms) | @@ -3773,7 +3790,7 @@ mod tests { */ init_test_logging(); - let test_name = + let unique_identifier = "proxy_server_schedules_stream_key_purge_once_shutdown_order_is_received_for_stream"; let cryptde = main_cryptde(); let stream_key_purge_delay_in_millis = 500; @@ -3786,13 +3803,12 @@ mod tests { false, ); subject.stream_key_purge_delay = Duration::from_millis(stream_key_purge_delay_in_millis); - subject.logger = Logger::new(test_name); + subject.logger = Logger::new(&unique_identifier); subject.subs = Some(make_proxy_server_out_subs()); - let stream_key = StreamKey::make_meaningful_stream_key(test_name); - let socket_addr = SocketAddr::from_str("1.2.3.4:5678").unwrap(); + let stream_key = StreamKey::make_meaningful_stream_key(&unique_identifier); subject .keys_and_addrs - .insert(stream_key.clone(), socket_addr.clone()); + .insert(stream_key.clone(), msg.peer_addr.clone()); subject.stream_key_routes.insert( stream_key.clone(), RouteQueryResponse { @@ -3816,20 +3832,12 @@ mod tests { let schedule_stream_key_purge_sub = proxy_server_addr.clone().recipient(); let mut peer_actors = peer_actors_builder().build(); peer_actors.proxy_server.schedule_stream_key_purge = schedule_stream_key_purge_sub; - let system = System::new(test_name); + let system = System::new(unique_identifier); let bind_msg = BindMessage { peer_actors }; proxy_server_addr.try_send(bind_msg).unwrap(); let time_before_sending_package = SystemTime::now(); - let stream_shutdown_msg = StreamShutdownMsg { - peer_addr: socket_addr, - stream_type: RemovedStreamType::NonClandestine(NonClandestineAttributes { - reception_port: 0, - sequence_number: 0, - }), - report_to_counterpart: true, - }; - proxy_server_addr.try_send(stream_shutdown_msg).unwrap(); + proxy_server_addr.try_send(msg).unwrap(); let time_after_sending_package = time_before_sending_package .checked_add(Duration::from_secs(1)) @@ -3849,7 +3857,7 @@ mod tests { assert!(!proxy_server.stream_key_routes.is_empty()); assert!(!proxy_server.tunneled_hosts.is_empty()); TestLogHandler::new().exists_log_containing(&format!( - "DEBUG: {test_name}: Client closed stream referenced by stream key {:?}, \ + "DEBUG: {unique_identifier}: Client closed stream referenced by stream key {:?}, \ which was tunneling to the host \"hostname\". \ It will be purged after {stream_key_purge_delay_in_millis}ms.", stream_key @@ -3869,7 +3877,7 @@ mod tests { assert!(proxy_server.tunneled_hosts.is_empty()); assert!(proxy_server.stream_key_ttl.is_empty()); TestLogHandler::new().exists_log_containing(&format!( - "DEBUG: {test_name}: Retiring stream key {:?}", + "DEBUG: {unique_identifier}: Retiring stream key {:?}", stream_key )); System::current().stop(); From 9dfd4ea55d5cece7ef6c2acc15a4f54182df2614 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Tue, 29 Oct 2024 12:17:33 +0530 Subject: [PATCH 62/65] GH-800: final changes --- node/src/proxy_server/mod.rs | 75 ++++-------------------------------- 1 file changed, 8 insertions(+), 67 deletions(-) diff --git a/node/src/proxy_server/mod.rs b/node/src/proxy_server/mod.rs index 00f422aaf..0ff6abb60 100644 --- a/node/src/proxy_server/mod.rs +++ b/node/src/proxy_server/mod.rs @@ -58,7 +58,7 @@ use tokio::prelude::Future; pub const CRASH_KEY: &str = "PROXYSERVER"; pub const RETURN_ROUTE_TTL: Duration = Duration::from_secs(120); -pub const STREAM_KEY_PURGE_DELAY: Duration = Duration::from_secs(5); +pub const STREAM_KEY_PURGE_DELAY: Duration = Duration::from_secs(30); struct ProxyServerOutSubs { dispatcher: Recipient, @@ -1427,6 +1427,7 @@ mod tests { fn constants_have_correct_values() { assert_eq!(CRASH_KEY, "PROXYSERVER"); assert_eq!(RETURN_ROUTE_TTL, Duration::from_secs(120)); + assert_eq!(STREAM_KEY_PURGE_DELAY, Duration::from_secs(30)); } const STANDARD_CONSUMING_WALLET_BALANCE: i64 = 0; @@ -3790,7 +3791,7 @@ mod tests { */ init_test_logging(); - let unique_identifier = + let test_name = "proxy_server_schedules_stream_key_purge_once_shutdown_order_is_received_for_stream"; let cryptde = main_cryptde(); let stream_key_purge_delay_in_millis = 500; @@ -3803,9 +3804,9 @@ mod tests { false, ); subject.stream_key_purge_delay = Duration::from_millis(stream_key_purge_delay_in_millis); - subject.logger = Logger::new(&unique_identifier); + subject.logger = Logger::new(&test_name); subject.subs = Some(make_proxy_server_out_subs()); - let stream_key = StreamKey::make_meaningful_stream_key(&unique_identifier); + let stream_key = StreamKey::make_meaningful_stream_key(&test_name); subject .keys_and_addrs .insert(stream_key.clone(), msg.peer_addr.clone()); @@ -3832,7 +3833,7 @@ mod tests { let schedule_stream_key_purge_sub = proxy_server_addr.clone().recipient(); let mut peer_actors = peer_actors_builder().build(); peer_actors.proxy_server.schedule_stream_key_purge = schedule_stream_key_purge_sub; - let system = System::new(unique_identifier); + let system = System::new(test_name); let bind_msg = BindMessage { peer_actors }; proxy_server_addr.try_send(bind_msg).unwrap(); let time_before_sending_package = SystemTime::now(); @@ -3857,7 +3858,7 @@ mod tests { assert!(!proxy_server.stream_key_routes.is_empty()); assert!(!proxy_server.tunneled_hosts.is_empty()); TestLogHandler::new().exists_log_containing(&format!( - "DEBUG: {unique_identifier}: Client closed stream referenced by stream key {:?}, \ + "DEBUG: {test_name}: Client closed stream referenced by stream key {:?}, \ which was tunneling to the host \"hostname\". \ It will be purged after {stream_key_purge_delay_in_millis}ms.", stream_key @@ -3877,7 +3878,7 @@ mod tests { assert!(proxy_server.tunneled_hosts.is_empty()); assert!(proxy_server.stream_key_ttl.is_empty()); TestLogHandler::new().exists_log_containing(&format!( - "DEBUG: {unique_identifier}: Retiring stream key {:?}", + "DEBUG: {test_name}: Retiring stream key {:?}", stream_key )); System::current().stop(); @@ -5836,66 +5837,6 @@ mod tests { )); } - #[test] - fn handle_stream_shutdown_msg_does_not_report_to_counterpart_when_unnecessary() { - let mut subject = ProxyServer::new(main_cryptde(), alias_cryptde(), true, None, false); - let unaffected_socket_addr = SocketAddr::from_str("2.3.4.5:6789").unwrap(); - let unaffected_stream_key = StreamKey::make_meaningful_stream_key("unaffected"); - let affected_socket_addr = SocketAddr::from_str("3.4.5.6:7890").unwrap(); - let affected_stream_key = StreamKey::make_meaningful_stream_key("affected"); - subject - .keys_and_addrs - .insert(unaffected_stream_key, unaffected_socket_addr); - subject - .keys_and_addrs - .insert(affected_stream_key, affected_socket_addr); - subject.stream_key_routes.insert( - unaffected_stream_key, - RouteQueryResponse { - route: Route { hops: vec![] }, - expected_services: ExpectedServices::RoundTrip(vec![], vec![], 1234), - }, - ); - subject.stream_key_routes.insert( - affected_stream_key, - RouteQueryResponse { - route: Route { hops: vec![] }, - expected_services: ExpectedServices::RoundTrip(vec![], vec![], 1234), - }, - ); - subject - .tunneled_hosts - .insert(unaffected_stream_key, "blah".to_string()); - subject - .tunneled_hosts - .insert(affected_stream_key, "blah".to_string()); - - subject.handle_stream_shutdown_msg(StreamShutdownMsg { - peer_addr: affected_socket_addr, - stream_type: RemovedStreamType::NonClandestine(NonClandestineAttributes { - reception_port: HTTP_PORT, - sequence_number: 1234, - }), - report_to_counterpart: false, - }); - - // Subject is unbound but didn't panic; therefore, no attempt to send to Hopper: perfect! - assert!(subject - .keys_and_addrs - .a_to_b(&unaffected_stream_key) - .is_some()); - assert!(subject - .stream_key_routes - .contains_key(&unaffected_stream_key)); - assert!(subject.tunneled_hosts.contains_key(&unaffected_stream_key)); - assert!(subject - .keys_and_addrs - .a_to_b(&affected_stream_key) - .is_none()); - assert!(!subject.stream_key_routes.contains_key(&affected_stream_key)); - assert!(!subject.tunneled_hosts.contains_key(&affected_stream_key)); - } - #[test] fn handle_stream_shutdown_msg_logs_errors_from_handling_normal_client_data() { init_test_logging(); From e7aaa349ac32f0e165fb3713a505ca866655f908 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Mon, 18 Nov 2024 12:19:08 +0530 Subject: [PATCH 63/65] GH-800: review changes --- node/src/proxy_server/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/node/src/proxy_server/mod.rs b/node/src/proxy_server/mod.rs index 0ff6abb60..9a519c90e 100644 --- a/node/src/proxy_server/mod.rs +++ b/node/src/proxy_server/mod.rs @@ -3754,17 +3754,17 @@ mod tests { }), report_to_counterpart: true, }; - stream_is_purged_with_a_delay(StreamShutdownMsg { + assert_stream_is_purged_with_a_delay(StreamShutdownMsg { report_to_counterpart: true, ..common_msg.clone() }); - stream_is_purged_with_a_delay(StreamShutdownMsg { + assert_stream_is_purged_with_a_delay(StreamShutdownMsg { report_to_counterpart: false, ..common_msg }); } - fn stream_is_purged_with_a_delay(msg: StreamShutdownMsg) { + fn assert_stream_is_purged_with_a_delay(msg: StreamShutdownMsg) { /* +------------------------------------------------------------------+ | (0ms) | From 7e616e255f0cd2cf958d8657bb26533eb3016335 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Mon, 25 Nov 2024 17:48:05 +0530 Subject: [PATCH 64/65] GH-800: fix the final comment discussion changes --- node/src/stream_handler_pool.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/node/src/stream_handler_pool.rs b/node/src/stream_handler_pool.rs index 3e8b511ef..db9bdd4e3 100644 --- a/node/src/stream_handler_pool.rs +++ b/node/src/stream_handler_pool.rs @@ -384,12 +384,13 @@ impl StreamHandlerPool { false } Some(None) => { - trace!( + error!( self.logger, - "While handling RemoveStreamMsg: Stream Writers contain an entry for key {}, but stream writer is missing", - stream_writer_key + "An unpopulated entry in stream_writers was found for a {:?} stream ({:?}) from \ + a client. This shouldn't be possible. Investigate!", + msg.stream_type, stream_writer_key ); - true + false } Some(Some(_sender_wrapper)) => { trace!( @@ -1293,10 +1294,13 @@ mod tests { #[test] fn handle_remove_stream_msg_handles_stream_waiting_for_connect_scenario() { + init_test_logging(); + let test_name = "handle_remove_stream_msg_handles_stream_waiting_for_connect_scenario"; let (recorder, _, recording_arc) = make_recorder(); - let system = System::new("test"); + let system = System::new(test_name); let sub = recorder.start().recipient::(); let mut subject = StreamHandlerPool::new(vec![], false); + subject.logger = Logger::new(test_name); let peer_addr = SocketAddr::from_str("1.2.3.4:5678").unwrap(); let local_addr = SocketAddr::from_str("127.0.0.1:0").unwrap(); let sw_key = StreamWriterKey::from(peer_addr); @@ -1319,9 +1323,14 @@ mod tests { &StreamShutdownMsg { peer_addr, stream_type: RemovedStreamType::Clandestine, - report_to_counterpart: true + report_to_counterpart: false } ); + TestLogHandler::new().exists_log_containing(&format!( + "ERROR: {}: An unpopulated entry in stream_writers was found for a \ + Clandestine stream ({:?}) from a client. This shouldn't be possible. Investigate!", + test_name, sw_key + )); } #[test] From 0a7d8b8c3320334fe6404f2628bac1372b67b1d8 Mon Sep 17 00:00:00 2001 From: utkarshg6 Date: Mon, 25 Nov 2024 18:45:57 +0530 Subject: [PATCH 65/65] GH-800: fix multiple_stream_zero_hop_test --- multinode_integration_tests/tests/data_routing_test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/multinode_integration_tests/tests/data_routing_test.rs b/multinode_integration_tests/tests/data_routing_test.rs index 0b3fa9d21..0c4cef279 100644 --- a/multinode_integration_tests/tests/data_routing_test.rs +++ b/multinode_integration_tests/tests/data_routing_test.rs @@ -316,7 +316,7 @@ fn multiple_stream_zero_hop_test() { let mut another_client = zero_hop_node.make_client(8080, STANDARD_CLIENT_TIMEOUT_MILLIS); one_client.send_chunk(b"GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n"); - another_client.send_chunk(b"GET /online/ HTTP/1.1\r\nHost: whatever.neverssl.com\r\n\r\n"); + another_client.send_chunk(b"GET /online/ HTTP/1.1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\r\nAccept-Language: cs-CZ,cs;q=0.9,en;q=0.8,sk;q=0.7\r\nCache-Control: max-age=0\r\nConnection: keep-alive\r\nHost: whatever.neverssl.com\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36\r\n\r\n"); let one_response = one_client.wait_for_chunk(); let another_response = another_client.wait_for_chunk();