Skip to content

Commit

Permalink
fix a bug where the initial interval in the refreshcell cannot be int…
Browse files Browse the repository at this point in the history
…errupted by a force refresh
  • Loading branch information
nullchinchilla committed Jan 20, 2025
1 parent 554c538 commit 8e63c5b
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 7 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions binaries/geph5-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ async-broadcast = "0.7.1"
crossbeam-queue = "0.3.11"
async-event = "0.2.1"
ctrlc = {version="3.4.5", features=["termination"]}
futures-intrusive = "0.5.0"

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.9", features = ["minwindef", "mmsystem", "timeapi", "std"] }
Expand Down
14 changes: 9 additions & 5 deletions binaries/geph5-client/src/refresh_cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ use std::{
time::{Duration, SystemTime},
};

use futures_intrusive::sync::ManualResetEvent;
use parking_lot::Mutex;
use smol::{channel::Sender, future::FutureExt};
use smolscale::immortal::Immortal;

pub struct RefreshCell<T: Clone> {
inner: Arc<Mutex<T>>,
inner: Arc<Mutex<Option<T>>>,
last_refresh_start: Arc<Mutex<SystemTime>>,
_task: Immortal,
interval: Duration,
Expand All @@ -21,17 +22,18 @@ impl<T: Clone + Send + 'static> RefreshCell<T> {
interval: Duration,
refresh: impl Fn() -> Fut + Send + Sync + 'static,
) -> Self {
let inner = Arc::new(Mutex::new(refresh().await));
let inner = Arc::new(Mutex::new(None));
let last_refresh_start = Arc::new(Mutex::new(SystemTime::now()));
let inner2 = inner.clone();
let refresh = Arc::new(move || refresh().boxed());
let (force_refresh, recv_force_refresh) = smol::channel::unbounded();
let ready_event = Arc::new(ManualResetEvent::new(false));
let task = {
let refresh = refresh.clone();
let recv_force_refresh = recv_force_refresh.clone();
let last_refresh_start = last_refresh_start.clone();
let ready_event = ready_event.clone();
Immortal::spawn(async move {
smol::Timer::after(interval).await;
loop {
*last_refresh_start.lock() = SystemTime::now();
let refresh = refresh.clone();
Expand All @@ -43,7 +45,8 @@ impl<T: Clone + Send + 'static> RefreshCell<T> {
"RefreshCell refreshed properly"
);
let mut inner = inner2.lock();
*inner = new_value;
*inner = Some(new_value);
ready_event.set();
true
};
let timeout = async {
Expand Down Expand Up @@ -73,6 +76,7 @@ impl<T: Clone + Send + 'static> RefreshCell<T> {
}
})
};
ready_event.wait().await;
Self {
inner,
_task: task,
Expand All @@ -95,6 +99,6 @@ impl<T: Clone + Send + 'static> RefreshCell<T> {
*last_refresh_start = SystemTime::now();
}
}
self.inner.lock().clone()
self.inner.lock().clone().unwrap()
}
}
26 changes: 24 additions & 2 deletions binaries/geph5-client/src/route.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use std::{net::SocketAddr, time::Duration};
use std::{
net::SocketAddr,
time::{Duration, SystemTime},
};

use anyctx::AnyCtx;
use anyhow::Context;
Expand All @@ -11,6 +14,7 @@ use geph5_broker_protocol::{
use isocountry::CountryCode;
use moka::sync::Cache;
use once_cell::sync::Lazy;
use parking_lot::Mutex;
use rand::seq::SliceRandom;
use serde::{Deserialize, Serialize};
use sillad::{
Expand All @@ -20,7 +24,10 @@ use sillad::{
use sillad_sosistab3::{dialer::SosistabDialer, Cookie};

use crate::{
auth::get_connect_token, broker::broker_client, client::Config, client_inner::CONCURRENCY,
auth::get_connect_token,
broker::broker_client,
client::{Config, CtxField},
client_inner::CONCURRENCY,
vpn::vpn_whitelist,
};

Expand Down Expand Up @@ -50,6 +57,21 @@ pub enum ExitConstraint {
CountryCity(CountryCode, String),
}

type DialerWithInfo = (VerifyingKey, ExitDescriptor, DynDialer);

pub async fn get_cached_dialer(ctx: &AnyCtx<Config>) -> anyhow::Result<DialerWithInfo> {
static LAST_DIALER: CtxField<Mutex<Option<(DialerWithInfo, SystemTime)>>> =
|_| Mutex::new(None);
if let Some(last_time) = ctx.get(LAST_DIALER).lock().as_ref().map(|s| s.1) {
if let Ok(elapsed) = last_time.elapsed() {
if elapsed < Duration::from_secs(60) {
return Ok(ctx.get(LAST_DIALER).lock().as_ref().unwrap().0.clone());
}
}
}
todo!()
}

/// Gets a sillad Dialer that produces a single, pre-authentication pipe, as well as the public key.
pub async fn get_dialer(
ctx: &AnyCtx<Config>,
Expand Down

0 comments on commit 8e63c5b

Please sign in to comment.