mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-13 17:35:37 +00:00
feat/web (Patchset 2) (#444)
This patch implement a restful server without any auth.
usage:
```bash
# run easytier-web, which acts as an gateway and registry for all easytier-core
$> easytier-web
# run easytier-core and connect to easytier-web with a token
$> easytier-core --config-server udp://127.0.0.1:22020/fdsafdsa
# use restful api to list session
$> curl -H "Content-Type: application/json" -X GET 127.0.0.1:11211/api/v1/sessions
[{"token":"fdsafdsa","client_url":"udp://127.0.0.1:48915","machine_id":"de3f5b8f-0f2f-d9d0-fb30-a2ac8951d92f"}]%
# use restful api to run a network instance
$> curl -H "Content-Type: application/json" -X POST 127.0.0.1:11211/api/v1/network/de3f5b8f-0f2f-d9d0-fb30-a2ac8951d92f -d '{"config": "listeners = [\"udp://0.0.0.0:12344\"]"}'
# use restful api to get network instance info
$> curl -H "Content-Type: application/json" -X GET 127.0.0.1:11211/api/v1/network/de3f5b8f-0f2f-d9d0-fb30-a2ac8951d92f/65437e50-b286-4098-a624-74429f2cb839
```
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use tokio::{
|
||||
sync::{broadcast, Mutex},
|
||||
task::JoinSet,
|
||||
time::interval,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
common::get_machine_id,
|
||||
proto::{
|
||||
rpc_impl::bidirect::BidirectRpcManager,
|
||||
rpc_types::controller::BaseController,
|
||||
web::{
|
||||
HeartbeatRequest, HeartbeatResponse, WebClientServiceServer,
|
||||
WebServerServiceClientFactory,
|
||||
},
|
||||
},
|
||||
tunnel::Tunnel,
|
||||
};
|
||||
|
||||
use super::controller::Controller;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct HeartbeatCtx {
|
||||
notifier: Arc<broadcast::Sender<HeartbeatResponse>>,
|
||||
resp: Arc<Mutex<Option<HeartbeatResponse>>>,
|
||||
}
|
||||
|
||||
pub struct Session {
|
||||
rpc_mgr: BidirectRpcManager,
|
||||
controller: Arc<Controller>,
|
||||
|
||||
heartbeat_ctx: HeartbeatCtx,
|
||||
|
||||
tasks: Mutex<JoinSet<()>>,
|
||||
}
|
||||
|
||||
impl Session {
|
||||
pub fn new(tunnel: Box<dyn Tunnel>, controller: Arc<Controller>) -> Self {
|
||||
let rpc_mgr = BidirectRpcManager::new();
|
||||
rpc_mgr.run_with_tunnel(tunnel);
|
||||
|
||||
rpc_mgr
|
||||
.rpc_server()
|
||||
.registry()
|
||||
.register(WebClientServiceServer::new(controller.clone()), "");
|
||||
|
||||
let mut tasks: JoinSet<()> = JoinSet::new();
|
||||
let heartbeat_ctx = Self::heartbeat_routine(&rpc_mgr, controller.token(), &mut tasks);
|
||||
|
||||
Session {
|
||||
rpc_mgr,
|
||||
controller,
|
||||
heartbeat_ctx,
|
||||
tasks: Mutex::new(tasks),
|
||||
}
|
||||
}
|
||||
|
||||
fn heartbeat_routine(
|
||||
rpc_mgr: &BidirectRpcManager,
|
||||
token: String,
|
||||
tasks: &mut JoinSet<()>,
|
||||
) -> HeartbeatCtx {
|
||||
let (tx, _rx1) = broadcast::channel(2);
|
||||
|
||||
let ctx = HeartbeatCtx {
|
||||
notifier: Arc::new(tx),
|
||||
resp: Arc::new(Mutex::new(None)),
|
||||
};
|
||||
|
||||
let mid = get_machine_id();
|
||||
let inst_id = uuid::Uuid::new_v4();
|
||||
let token = token;
|
||||
|
||||
let ctx_clone = ctx.clone();
|
||||
let mut tick = interval(std::time::Duration::from_secs(1));
|
||||
let client = rpc_mgr
|
||||
.rpc_client()
|
||||
.scoped_client::<WebServerServiceClientFactory<BaseController>>(1, 1, "".to_string());
|
||||
tasks.spawn(async move {
|
||||
let req = HeartbeatRequest {
|
||||
machine_id: Some(mid.into()),
|
||||
inst_id: Some(inst_id.into()),
|
||||
user_token: token.to_string(),
|
||||
};
|
||||
loop {
|
||||
tick.tick().await;
|
||||
match client
|
||||
.heartbeat(BaseController::default(), req.clone())
|
||||
.await
|
||||
{
|
||||
Err(e) => {
|
||||
tracing::error!("heartbeat failed: {:?}", e);
|
||||
break;
|
||||
}
|
||||
Ok(resp) => {
|
||||
tracing::debug!("heartbeat response: {:?}", resp);
|
||||
let _ = ctx_clone.notifier.send(resp.clone());
|
||||
ctx_clone.resp.lock().await.replace(resp);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ctx
|
||||
}
|
||||
|
||||
async fn wait_routines(&self) {
|
||||
self.tasks.lock().await.join_next().await;
|
||||
// if any task failed, we should abort all tasks
|
||||
self.tasks.lock().await.abort_all();
|
||||
}
|
||||
|
||||
pub async fn wait(&mut self) {
|
||||
tokio::select! {
|
||||
_ = self.rpc_mgr.wait() => {}
|
||||
_ = self.wait_routines() => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn wait_next_heartbeat(&self) -> Option<HeartbeatResponse> {
|
||||
let mut rx = self.heartbeat_ctx.notifier.subscribe();
|
||||
rx.recv().await.ok()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user