IT COMPILES! GOD EXISTS! IT COMPILES!
This commit is contained in:
parent
21f7a9f971
commit
b21a9e0a10
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -680,6 +680,7 @@ name = "hacker-challenge"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"async-stream",
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
"futures",
|
"futures",
|
||||||
"hex",
|
"hex",
|
||||||
@ -690,6 +691,7 @@ dependencies = [
|
|||||||
"salvo",
|
"salvo",
|
||||||
"tabled",
|
"tabled",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-stream",
|
||||||
"tonic",
|
"tonic",
|
||||||
"tonic-build",
|
"tonic-build",
|
||||||
]
|
]
|
||||||
|
@ -5,6 +5,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.86"
|
anyhow = "1.0.86"
|
||||||
|
async-stream = "0.3.5"
|
||||||
ed25519-dalek = { version = "2.1.1", features = ["rand_core", "serde"] }
|
ed25519-dalek = { version = "2.1.1", features = ["rand_core", "serde"] }
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
@ -15,6 +16,7 @@ rand = "0.8.5"
|
|||||||
salvo = { version = "0.70.0", features = ["affix"] }
|
salvo = { version = "0.70.0", features = ["affix"] }
|
||||||
tabled = "0.16.0"
|
tabled = "0.16.0"
|
||||||
tokio = { version = "1.39.2", features = ["macros"] }
|
tokio = { version = "1.39.2", features = ["macros"] }
|
||||||
|
tokio-stream = { version = "0.1.15" }
|
||||||
tonic = "0.12.1"
|
tonic = "0.12.1"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
@ -10,6 +10,6 @@ message NodeUpdate {
|
|||||||
bool online = 4;
|
bool online = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
service KeyDistribution {
|
service Update {
|
||||||
rpc UpdateStreaming (stream NodeUpdate) returns (stream NodeUpdate);
|
rpc GetUpdates (stream NodeUpdate) returns (stream NodeUpdate);
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ impl Store {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn add_mock_node(&self, ip: String) {
|
pub async fn add_mock_node(&self, ip: IP) {
|
||||||
let mut csprng = OsRng;
|
let mut csprng = OsRng;
|
||||||
let privkey = ed25519_dalek::SigningKey::generate(&mut csprng);
|
let privkey = ed25519_dalek::SigningKey::generate(&mut csprng);
|
||||||
self.update_node(
|
self.update_node(
|
||||||
|
145
src/grpc.rs
145
src/grpc.rs
@ -1,90 +1,83 @@
|
|||||||
use crate::database;
|
#![allow(dead_code)]
|
||||||
use crate::database::NodeInfo;
|
|
||||||
use challenge::key_distribution_server::{KeyDistribution, KeyDistributionServer};
|
use crate::datastore::Store;
|
||||||
use challenge::{RemoveNodeReq, UpdateKeyReq, UpdateNodeReq};
|
use challenge::NodeUpdate;
|
||||||
use ed25519_dalek::SigningKey;
|
use std::pin::Pin;
|
||||||
use prost_types::Timestamp;
|
use std::sync::Arc;
|
||||||
use rand::rngs::OsRng;
|
use std::thread::JoinHandle;
|
||||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
use tokio::sync::broadcast::Sender;
|
||||||
use tonic::{transport::Server, Request, Response, Status};
|
use tokio_stream::{Stream, StreamExt};
|
||||||
|
use tonic::{transport::Server, Request, Response, Status, Streaming};
|
||||||
|
|
||||||
pub mod challenge {
|
pub mod challenge {
|
||||||
tonic::include_proto!("challenge");
|
tonic::include_proto!("challenge");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
pub struct MyServer {
|
||||||
pub struct MyKeyDistribution {}
|
ds: Arc<Store>,
|
||||||
|
tx: Sender<NodeUpdate>,
|
||||||
|
}
|
||||||
|
|
||||||
fn update_db(ip: String, privkey: String, updated_at: Option<Timestamp>) {
|
impl MyServer {
|
||||||
let key_bytes = hex::decode(privkey).unwrap();
|
fn init(ds: Arc<Store>, tx: Sender<NodeUpdate>) -> Self {
|
||||||
let privkey = SigningKey::from_bytes(&key_bytes.as_slice().try_into().unwrap());
|
Self { ds, tx }
|
||||||
let pubkey = privkey.verifying_key();
|
}
|
||||||
let updated_at: std::time::SystemTime = match updated_at {
|
|
||||||
Some(ts) => {
|
|
||||||
let duration = Duration::new(ts.seconds as u64, ts.nanos as u32);
|
|
||||||
UNIX_EPOCH
|
|
||||||
.checked_add(duration)
|
|
||||||
.unwrap_or(SystemTime::now())
|
|
||||||
}
|
|
||||||
None => SystemTime::now(),
|
|
||||||
};
|
|
||||||
database::add_node(ip.to_string(), NodeInfo { pubkey, updated_at });
|
|
||||||
|
|
||||||
database::add_key(pubkey, privkey);
|
fn start(self) -> JoinHandle<()> {
|
||||||
|
std::thread::spawn(|| {
|
||||||
|
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
||||||
|
let addr = "0.0.0.0:31373".parse().unwrap();
|
||||||
|
if let Err(e) = Server::builder()
|
||||||
|
.add_service(challenge::update_server::UpdateServer::new(self))
|
||||||
|
.serve(addr)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
println!("gRPC server failed: {e:?}");
|
||||||
|
};
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tonic::async_trait]
|
#[tonic::async_trait]
|
||||||
impl KeyDistribution for MyKeyDistribution {
|
impl challenge::update_server::Update for MyServer {
|
||||||
async fn update_key(&self, request: Request<UpdateKeyReq>) -> Result<Response<()>, Status> {
|
type GetUpdatesStream = Pin<Box<dyn Stream<Item = Result<NodeUpdate, Status>> + Send>>;
|
||||||
let ip = request.remote_addr().unwrap().ip();
|
|
||||||
let req = request.into_inner();
|
|
||||||
update_db(ip.to_string(), req.keypair, req.updated_at);
|
|
||||||
Ok(Response::new(()))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn update_node(&self, request: Request<UpdateNodeReq>) -> Result<Response<()>, Status> {
|
async fn get_updates(
|
||||||
let req = request.into_inner();
|
&self,
|
||||||
update_db(req.ip, req.keypair, req.updated_at);
|
req: Request<Streaming<NodeUpdate>>,
|
||||||
Ok(Response::new(()))
|
) -> Result<Response<Self::GetUpdatesStream>, Status> {
|
||||||
}
|
let remote_ip = req.remote_addr().unwrap().ip().to_string();
|
||||||
|
let tx = self.tx.clone();
|
||||||
|
let mut rx = self.tx.subscribe();
|
||||||
|
let mut inbound = req.into_inner();
|
||||||
|
|
||||||
async fn remove_node(&self, _request: Request<RemoveNodeReq>) -> Result<Response<()>, Status> {
|
let stream = async_stream::stream! {
|
||||||
// Handle RemoveNode request
|
loop {
|
||||||
Ok(Response::new(()))
|
tokio::select! {
|
||||||
|
Some(msg) = inbound.next() => {
|
||||||
|
match msg {
|
||||||
|
Ok(update) => {
|
||||||
|
if let Err(_) = tx.send(update.clone()) {
|
||||||
|
yield Err(Status::internal("Failed to broadcast update"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
yield Err(Status::internal(format!("Error receiving client stream: {}", e)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(update) = rx.recv() => {
|
||||||
|
if update.ip != remote_ip {
|
||||||
|
yield Ok(update);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Response::new(Box::pin(stream) as Self::GetUpdatesStream))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn start_client() {
|
|
||||||
loop {
|
|
||||||
tokio::time::sleep(Duration::from_secs(10)).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn start_server() {
|
|
||||||
let addr = "0.0.0.0:31373".parse().unwrap();
|
|
||||||
let key_distribution = MyKeyDistribution::default();
|
|
||||||
Server::builder()
|
|
||||||
.add_service(KeyDistributionServer::new(key_distribution))
|
|
||||||
.serve(addr)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn start() {
|
|
||||||
let start_client = tokio::task::spawn(start_server());
|
|
||||||
let start_server = tokio::task::spawn(start_server());
|
|
||||||
futures::future::select(start_client, start_server).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_node(ip: String) {
|
|
||||||
let mut csprng = OsRng;
|
|
||||||
let privkey = ed25519_dalek::SigningKey::generate(&mut csprng);
|
|
||||||
database::add_node(
|
|
||||||
ip,
|
|
||||||
NodeInfo {
|
|
||||||
pubkey: privkey.verifying_key(),
|
|
||||||
updated_at: std::time::SystemTime::now(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
database::add_key(privkey.verifying_key(), privkey);
|
|
||||||
}
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
mod grpc;
|
||||||
mod datastore;
|
mod datastore;
|
||||||
mod http_server;
|
mod http_server;
|
||||||
use crate::datastore::Store;
|
use crate::datastore::Store;
|
||||||
|
Loading…
Reference in New Issue
Block a user