summaryrefslogtreecommitdiffhomepage
path: root/mullvad-daemon/src/api.rs
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2022-02-28 17:59:49 +0100
committerDavid Lönnhager <david.l@mullvad.net>2022-03-01 15:30:23 +0100
commitd2bdcd5878ae6ea748e10fe8e430b80548ec2fb5 (patch)
tree47690c0d69b5793eaf0348faaa4440fe92abf84e /mullvad-daemon/src/api.rs
parentbcf3278eeb1b63f2ff8fa6ee68ab4cc8bb8b76fd (diff)
downloadmullvadvpn-d2bdcd5878ae6ea748e10fe8e430b80548ec2fb5.tar.xz
mullvadvpn-d2bdcd5878ae6ea748e10fe8e430b80548ec2fb5.zip
Add proxy config generator to daemon
Diffstat (limited to 'mullvad-daemon/src/api.rs')
-rw-r--r--mullvad-daemon/src/api.rs54
1 files changed, 54 insertions, 0 deletions
diff --git a/mullvad-daemon/src/api.rs b/mullvad-daemon/src/api.rs
new file mode 100644
index 0000000000..2ed689b418
--- /dev/null
+++ b/mullvad-daemon/src/api.rs
@@ -0,0 +1,54 @@
+use crate::DaemonEventSender;
+use futures::{channel::oneshot, stream, Stream, StreamExt};
+use mullvad_rpc::proxy::ApiConnectionMode;
+use talpid_core::mpsc::Sender;
+use talpid_types::ErrorExt;
+
+pub(crate) struct ApiConnectionModeRequest {
+ pub response_tx: oneshot::Sender<ApiConnectionMode>,
+ pub retry_attempt: u32,
+}
+
+/// Returns a stream that returns the next API bridge to try.
+/// `initial_config` refers to the first config returned by the stream. The daemon is not notified
+/// of this.
+pub(crate) fn create_api_config_provider(
+ daemon_sender: DaemonEventSender<ApiConnectionModeRequest>,
+ initial_config: ApiConnectionMode,
+) -> impl Stream<Item = ApiConnectionMode> + Unpin {
+ struct Context {
+ attempt: u32,
+ daemon_sender: DaemonEventSender<ApiConnectionModeRequest>,
+ }
+
+ let ctx = Context {
+ attempt: 1,
+ daemon_sender,
+ };
+
+ Box::pin(
+ stream::once(async move { initial_config }).chain(stream::unfold(
+ ctx,
+ |mut ctx| async move {
+ ctx.attempt = ctx.attempt.wrapping_add(1);
+ let (response_tx, response_rx) = oneshot::channel();
+
+ let _ = ctx.daemon_sender.send(ApiConnectionModeRequest {
+ response_tx,
+ retry_attempt: ctx.attempt,
+ });
+
+ let new_config = response_rx.await.unwrap_or_else(|error| {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg("Failed to receive API proxy config")
+ );
+ // Fall back on unbridged connection
+ ApiConnectionMode::Direct
+ });
+
+ Some((new_config, ctx))
+ },
+ )),
+ )
+}