Compare commits

...

6 Commits

Author SHA1 Message Date
mirsal ec43ca01c6 main: Send beacons to the all-nodes link-local multicast group 2021-03-31 21:28:44 +00:00
mirsal c59ea85329 Quick and dirty peer discovery broadcast mock implementation
* Use `async_std::task` for network loops
 * Send the generated public key over ipv4 udp broadcast frames

(peer discovery is not functional yet, although multiple instances
connected to the same link can now talk to each other, so yay.)
2021-03-31 21:28:44 +00:00
Ujjwal Sharma 7ebae99890 src: rename Node and methods 2021-03-31 21:28:44 +00:00
Ujjwal Sharma ba917197fe src: move network types to new file 2021-03-31 21:28:44 +00:00
Ujjwal Sharma 01b7f1e260 src: improve Node handling 2021-03-31 21:28:44 +00:00
Ujjwal Sharma 85efd45a88 src: implement base64 handling for PublicKey 2021-03-31 21:28:44 +00:00
3 changed files with 127 additions and 41 deletions

View File

@ -1,10 +1,25 @@
use async_std::fs;
use async_std::path::PathBuf;
use async_trait::async_trait;
use ed25519_dalek::{Keypair, PublicKey, SecretKey}; use ed25519_dalek::{Keypair, PublicKey, SecretKey};
use json::{object, JsonValue}; use json::{object, JsonValue};
use rand::rngs::OsRng; use rand::rngs::OsRng;
use regex::Regex; use regex::Regex;
use async_std::fs;
use async_std::path::PathBuf; pub trait SSBPublicKey {
use async_trait::async_trait; fn to_base64(&self) -> String;
fn from_base64(string: &str) -> Self;
}
impl SSBPublicKey for PublicKey {
fn to_base64(&self) -> String {
base64::encode(self.to_bytes())
}
fn from_base64(string: &str) -> Self {
Self::from_bytes(&base64::decode(string).unwrap()).unwrap()
}
}
#[async_trait] #[async_trait]
pub trait SSBKeypair { pub trait SSBKeypair {
@ -16,7 +31,7 @@ pub trait SSBKeypair {
#[async_trait] #[async_trait]
impl SSBKeypair for Keypair { impl SSBKeypair for Keypair {
fn to_json(&self) -> JsonValue { fn to_json(&self) -> JsonValue {
let pubstring = base64::encode(self.public.to_bytes()); let pubstring = self.public.to_base64();
let privstring = base64::encode([self.secret.to_bytes(), self.public.to_bytes()].concat()); let privstring = base64::encode([self.secret.to_bytes(), self.public.to_bytes()].concat());
object! { object! {
curve: "ed25519", curve: "ed25519",
@ -36,8 +51,7 @@ impl SSBKeypair for Keypair {
.unwrap() .unwrap()
.strip_suffix(".ed25519") .strip_suffix(".ed25519")
.unwrap(); .unwrap();
let pubkey = base64::decode(pubkey).unwrap(); let pubkey = SSBPublicKey::from_base64(pubkey);
let pubkey = PublicKey::from_bytes(pubkey.as_slice()).unwrap();
let privkey = obj["private"] let privkey = obj["private"]
.as_str() .as_str()
@ -70,7 +84,8 @@ impl SSBKeypair for Keypair {
keys = keypair_json.pretty(2), keys = keypair_json.pretty(2),
id = keypair_json["id"] id = keypair_json["id"]
), ),
).await )
.await
.unwrap(); .unwrap();
keypair keypair
} }

View File

@ -1,34 +1,49 @@
use async_std::{fs, task};
use async_std::net::{UdpSocket, Ipv6Addr};
use async_std::path::PathBuf;
use async_std::sync::Arc;
use clap::{load_yaml, App}; use clap::{load_yaml, App};
use ed25519_dalek::Keypair; use ed25519_dalek::Keypair;
use async_std::fs;
use async_std::net::UdpSocket;
use async_std::path::PathBuf;
mod keypair; mod keypair;
use keypair::{SSBKeypair, SSBPublicKey};
use keypair::SSBKeypair; mod network;
use network::Peer;
type Config = toml::map::Map<String, toml::Value>; type Config = toml::map::Map<String, toml::Value>;
#[derive(Debug)] async fn peer_discovery_recv() {
struct Host { let socket = UdpSocket::bind(":::8008").await.unwrap();
protocol: String, let all_nodes_addr = Ipv6Addr::new(0xFF02, 0, 0, 0, 0, 0, 0, 0x02);
host: String, let mut buf = [0u8; 1024];
port: String,
pubkey: String, socket.join_multicast_v6(&all_nodes_addr, 0).unwrap();
loop {
let (amt, peer) = socket.recv_from(&mut buf).await.unwrap();
let buf = &mut buf[..amt];
let packet = String::from_utf8(buf.to_vec()).unwrap();
println!(
"{} {}",
peer,
Peer::from_discovery_packet(&packet).to_discovery_packet()
);
}
} }
fn parse_packet(packet: String) -> Host { async fn peer_discovery_send(pubkey: Arc<String>) {
let mut packet = packet.splitn(4, ':'); let socket = UdpSocket::bind(":::0").await.unwrap();
let protocol = packet.next().unwrap(); let msg = format!("net:1.2.3.4:8023~shs:{}", &pubkey);
let host = packet.next().unwrap(); let buf = msg.as_bytes();
let port = packet.next().unwrap().splitn(2, '~').next().unwrap();
let pubkey = packet.next().unwrap(); socket.set_broadcast(true).unwrap();
Host {
protocol: protocol.to_string(), loop {
host: host.to_string(), println!("Sending packet: {:?}", &msg);
port: port.to_string(), socket.send_to(&buf, "255.255.255.255:8008").await.unwrap();
pubkey: pubkey.to_string(), socket.send_to(&buf, "[FF02::2]:8008").await.unwrap();
task::sleep(std::time::Duration::from_secs(1)).await;
} }
} }
@ -39,10 +54,12 @@ async fn main() {
let config_file = match options.value_of("config") { let config_file = match options.value_of("config") {
Some(path) => PathBuf::from(path), Some(path) => PathBuf::from(path),
None => PathBuf::from(dirs::config_dir() None => PathBuf::from(
.unwrap() dirs::config_dir()
.join("cosmoline") .unwrap()
.join("config.toml")), .join("cosmoline")
.join("config.toml"),
),
}; };
let config = fs::read_to_string(config_file).await.unwrap(); let config = fs::read_to_string(config_file).await.unwrap();
let config: Config = toml::from_str(config.as_str()).unwrap(); let config: Config = toml::from_str(config.as_str()).unwrap();
@ -57,14 +74,8 @@ async fn main() {
let keypair = Keypair::read_or_generate(path.join("secret")).await; let keypair = Keypair::read_or_generate(path.join("secret")).await;
println!("{}", keypair.to_json().pretty(2)); println!("{}", keypair.to_json().pretty(2));
let socket = UdpSocket::bind(":::8008").await.unwrap(); let pubkey = keypair.public.to_base64();
let mut buf = [0u8; 1024];
loop {
let (amt, peer) = socket.recv_from(&mut buf).await.unwrap();
let buf = &mut buf[..amt];
let packet = String::from_utf8(buf.to_vec()).unwrap();
println!("{:?}", (peer, parse_packet(packet)));
};
task::spawn(peer_discovery_recv());
task::spawn(peer_discovery_send(Arc::new(pubkey))).await;
} }

60
src/network.rs Normal file
View File

@ -0,0 +1,60 @@
use async_std::net::IpAddr;
use ed25519_dalek::PublicKey;
use crate::keypair::SSBPublicKey;
enum Protocol {
Net,
Ws,
Wss,
}
pub struct Peer {
protocol: Protocol,
host: IpAddr,
port: u16,
pubkey: PublicKey,
}
impl Peer {
pub fn to_discovery_packet(&self) -> String {
let proto = match self.protocol {
Protocol::Net => "net",
Protocol::Ws => "ws",
Protocol::Wss => "wss",
};
format!(
"{}:{}:{}~shs:{}",
proto,
self.host,
self.port,
self.pubkey.to_base64()
)
}
pub fn from_discovery_packet(packet: &str) -> Self {
let mut packet = packet.splitn(4, ':');
let protocol = match packet.next().unwrap() {
"net" => Protocol::Net,
"ws" => Protocol::Ws,
"wss" => Protocol::Wss,
_ => panic!("unknown protocol"),
};
let host = IpAddr::V4(packet.next().unwrap().parse().unwrap());
let port = packet
.next()
.unwrap()
.splitn(2, '~')
.next()
.unwrap()
.parse()
.unwrap();
let pubkey = SSBPublicKey::from_base64(packet.next().unwrap());
Peer {
protocol,
host,
port,
pubkey,
}
}
}