added token in common

This commit is contained in:
asxalex 2024-03-17 23:27:27 +08:00
parent 6e66713b43
commit 50c874e542
9 changed files with 217 additions and 18 deletions

39
docs/api.md Normal file
View File

@ -0,0 +1,39 @@
# sdlan web api文档
sdlan为前端提供了若干api。其中所有的api都使用POST方法将数据以json消息体的方式提交给服务端。服务端根据具体处理结果返回json数据。
## 1. 返回消息体
sdlan api的所有返回的消息体都遵循如下格式
```json
{
"code": $int,
"message": $object,
"error": $string,
}
```
其中code为0代表请求成功返回的内容存放在`message`字段,`error`字段为空字符串;反之,如果请求失败,则`code`不为0同时`message`为空字符串,`error`字段为错误描述字符串。
在后面的描述中,如果请求成功,则默认返回的`code`为0`error`为空字符串,而`message`会写明结构;如果返回失败,则`message`为空字符串,`code``error`会根据情况标明。
## 2. 消息请求参数说明
在实际操作过程中用户会需要先注册注册成功之后需要先使用用户名和密码进行登录密码验证成功之后后台会返回一个token该token有效期为一个小时在登录成功之后所有其他的接口即除了register和login接口在发起请求的时候都需要在请求头的header里面带上`token`,否则会权限热症失败,返回`code`为400`error``“unauthorized”`
## 3. 实际接口
实际接口分成几个类别列举。
### 4.1. 用户操作
用户操作包括用户注册,登录,登出,创建/删除/查看register-token(用于节点登录时填写的token);修改密码等一系列关于用于的操作。
### 4.2. 网络操作
网络操作主要包括网络的创建、列举、删除、路由(给网络添加、删除一系列路由信息)等操作。
### 4.3. 节点操作
节点操作包括对节点的授权、取消授权、在网络之间移动等操作。
#### 4.3.1 授权节点
该接口用于对未授权的节点进行授权操作。
```
POST /peer/authorize
```

View File

@ -3,7 +3,7 @@ pub const FLAGS_TYPE_MASK: u16 = 0x001f;
pub const FLAGS_BITS_MASK: u16 = 0xffe0; pub const FLAGS_BITS_MASK: u16 = 0xffe0;
// common头的flags里面的flag可以组合 // common头的flags里面的flag可以组合
// 表示从SN发送过来的REGISTER_SUPER消息主要用于SN注册 // 表示从SN主动发送到其他SN的消息
pub const SDLNA_FLAGS_FEDERATION: u16 = 0x0010; pub const SDLNA_FLAGS_FEDERATION: u16 = 0x0010;
pub const SDLAN_FLAGS_FROM_SN: u16 = 0x0020; pub const SDLAN_FLAGS_FROM_SN: u16 = 0x0020;
pub const SDLAN_FLAGS_SOCKET: u16 = 0x0040; pub const SDLAN_FLAGS_SOCKET: u16 = 0x0040;

View File

@ -5,8 +5,7 @@ use serde_repr::{Deserialize_repr, Serialize_repr};
#[derive(Debug, PartialEq, Serialize_repr, Deserialize_repr, Copy, Clone)] #[derive(Debug, PartialEq, Serialize_repr, Deserialize_repr, Copy, Clone)]
#[repr(u8)] #[repr(u8)]
pub enum CommandType { pub enum CommandType {
AuthorizePeer, MovePeer = 1,
MovePeer,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@ -15,6 +14,16 @@ pub struct Command {
pub message: Value, pub message: Value,
} }
#[derive(Serialize, Deserialize)]
pub struct MovePeerCommandReq {
pub from_id: String,
pub to_id: String,
pub peer_id: String,
pub new_ip: u32,
pub net_bit_len: u8,
pub user_id: u64,
}
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct CommandResp { pub struct CommandResp {
cmd_type: CommandType, cmd_type: CommandType,

View File

@ -11,7 +11,11 @@ use crate::utils::*;
pub struct Common<'a> { pub struct Common<'a> {
pub packet_id: u16, pub packet_id: u16,
pub version: u8, pub version: u8,
// client's uuid
pub id: &'a str, pub id: &'a str,
pub token: u64,
pub ttl: u8, pub ttl: u8,
// packet type // packet type
pub pc: PacketType, pub pc: PacketType,
@ -25,6 +29,8 @@ impl<'a> Common<'a> {
encode_u8(&mut result, self.version); encode_u8(&mut result, self.version);
encode_buf_without_size(&mut result, &self.id.as_bytes(), 32); encode_buf_without_size(&mut result, &self.id.as_bytes(), 32);
// result.extend_from_slice(self.id.as_bytes());
result.extend_from_slice(&self.token.to_be_bytes());
// encode_buf_with_size_1(&mut result, self.id.as_bytes()); // encode_buf_with_size_1(&mut result, self.id.as_bytes());
encode_u8(&mut result, self.ttl); encode_u8(&mut result, self.ttl);
@ -37,10 +43,11 @@ impl<'a> Common<'a> {
result result
} }
pub fn from_slice(value: &'a [u8]) -> Result<(Common<'a>, &'a [u8])> { pub fn from_slice(value: &'a [u8]) -> Result<(Common, &'a [u8])> {
let id_len = 32; const id_len: usize = 32;
const token_len: usize = 8;
if value.len() < 7 + id_len { if value.len() < 7 + id_len + token_len {
return Err("common header length error".into()); return Err("common header length error".into());
} }
let packet_id = u16::from_be_bytes(value[0..2].try_into().unwrap()); let packet_id = u16::from_be_bytes(value[0..2].try_into().unwrap());
@ -51,26 +58,36 @@ impl<'a> Common<'a> {
Ok(s) => s, Ok(s) => s,
Err(e) => return Err(SDLanError::ConvertError(e.to_string())), Err(e) => return Err(SDLanError::ConvertError(e.to_string())),
}; };
// let id = u64::from_be_bytes(v1);
id = id.trim_end_matches('\0'); id = id.trim_end_matches('\0');
let ttl = value[3 + id_len];
let flags = BigEndian::read_u16(&value[4 + id_len..6 + id_len]); let token = u64::from_be_bytes(
let pc = value[6 + id_len]; value[3 + id_len..3 + id_len + token_len]
.try_into()
.unwrap(),
);
let ttl = value[3 + id_len + token_len];
let flags = BigEndian::read_u16(&value[4 + id_len + token_len..6 + id_len + token_len]);
let pc = value[6 + id_len + token_len];
let common = Self { let common = Self {
packet_id, packet_id,
version, version,
id, id,
ttl, ttl,
token,
pc: pc.into(), pc: pc.into(),
flags: flags, flags: flags,
}; };
Ok((common, &value[7 + id_len..])) Ok((common, &value[7 + id_len + token_len..]))
} }
pub fn from_old_common(cmn: &'a Common) -> Self { pub fn from_old_common(cmn: &'a Common) -> Self {
return Common { return Common {
packet_id: cmn.packet_id, packet_id: cmn.packet_id,
id: cmn.id, id: cmn.id,
token: cmn.token,
version: cmn.version, version: cmn.version,
ttl: cmn.ttl, ttl: cmn.ttl,
pc: cmn.pc, pc: cmn.pc,
@ -82,6 +99,7 @@ impl<'a> Common<'a> {
return Common { return Common {
packet_id: 0, packet_id: 0,
id, id,
token: 0,
version: 1, version: 1,
ttl: 2, ttl: 2,
pc: PacketType::PKTInvalid, pc: PacketType::PKTInvalid,
@ -169,11 +187,13 @@ mod test {
packet_id: 0, packet_id: 0,
version: 0, version: 0,
id, id,
token: 0,
ttl: 2, ttl: 2,
pc: 1.into(), pc: 1.into(),
flags: 0, flags: 0,
}; };
let value1 = common.encode(); let value1 = common.encode();
println!("value1.len: {}", value1.len());
let (common2, _) = Common::from_slice(&value1).unwrap(); let (common2, _) = Common::from_slice(&value1).unwrap();
println!("common2 = {:?}", common2); println!("common2 = {:?}", common2);
assert_eq!(common.id, common2.id); assert_eq!(common.id, common2.id);

View File

@ -20,9 +20,8 @@ pub struct RegisterSuper<'a> {
// 自身的公钥 // 自身的公钥
pub pub_key: String, pub pub_key: String,
// user's token, can be used to specify a user // user's token, can be used to specify a user
pub token: &'a str, // pub token: &'a str,
} }
#[cfg(test)] #[cfg(test)]
@ -74,7 +73,7 @@ mod test {
net_bit_len: 24, net_bit_len: 24,
}, },
pub_key: "public key".to_string(), pub_key: "public key".to_string(),
token: "user's token", // token: "user's token",
}; };
let res = serde_json::to_string(&pkt1).unwrap(); let res = serde_json::to_string(&pkt1).unwrap();
println!("unmarshaled as {}", res); println!("unmarshaled as {}", res);
@ -87,6 +86,7 @@ mod test {
packet_id: 0, packet_id: 0,
version: 1, version: 1,
id: "asxalex", id: "asxalex",
token: 0,
ttl: 128, ttl: 128,
pc: PacketType::PKTRegisterSuper, pc: PacketType::PKTRegisterSuper,
flags: config::SDLAN_FLAGS_FROM_SN, flags: config::SDLAN_FLAGS_FROM_SN,
@ -112,7 +112,7 @@ mod test {
net_bit_len: 24, net_bit_len: 24,
}, },
pub_key: "public key".to_string(), pub_key: "public key".to_string(),
token: "user's token", // token: "user's token",
}; };
(cmn1, pkt1) (cmn1, pkt1)
} }
@ -147,7 +147,7 @@ mod test {
assert_eq!(pkt1.dev_addr.net_addr(), pkt2.dev_addr.net_addr(),); assert_eq!(pkt1.dev_addr.net_addr(), pkt2.dev_addr.net_addr(),);
assert_eq!(pkt1.dev_addr.net_bit_len(), pkt2.dev_addr.net_bit_len()); assert_eq!(pkt1.dev_addr.net_bit_len(), pkt2.dev_addr.net_bit_len());
assert_eq!(pkt1.pub_key, pkt2.pub_key); assert_eq!(pkt1.pub_key, pkt2.pub_key);
assert_eq!(pkt1.token, pkt2.token); // assert_eq!(pkt1.token, pkt2.token);
} }
#[test] #[test]

View File

@ -1,11 +1,13 @@
#![allow(unused)] #![allow(unused)]
use super::utils::Result; use super::utils::Result;
use dashmap::DashMap; use dashmap::DashMap;
use dashmap::DashSet;
use futures::future::BoxFuture; use futures::future::BoxFuture;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sqlx::prelude::FromRow; use sqlx::prelude::FromRow;
use std::default::Default; use std::default::Default;
use std::future::Future; use std::future::Future;
use std::hash::Hasher;
use std::sync::atomic::{AtomicU32, AtomicU64, AtomicU8, Ordering}; use std::sync::atomic::{AtomicU32, AtomicU64, AtomicU8, Ordering};
use std::sync::RwLock; use std::sync::RwLock;
@ -197,6 +199,7 @@ use crate::utils::SDLanError;
use std::pin::Pin; use std::pin::Pin;
pub struct PeerMap { pub struct PeerMap {
pub peers: DashMap<String, Arc<Peer>>, pub peers: DashMap<String, Arc<Peer>>,
// from client's uuid, to the
// ip to peer's uuid, the ip is the logical ip // ip to peer's uuid, the ip is the logical ip
// of tun // of tun
// pub peer_ip_map: DashMap<u32, String>, // pub peer_ip_map: DashMap<u32, String>,
@ -264,6 +267,103 @@ impl PeerMap {
} }
} }
#[derive(Debug)]
pub struct EdgeInfo {
pub edges: DashSet<String>,
ip_to_edge_id: DashMap<u32, String>,
}
impl Default for EdgeInfo {
fn default() -> Self {
Self::new()
}
}
impl EdgeInfo {
pub fn new() -> Self {
Self {
edges: DashSet::new(),
ip_to_edge_id: DashMap::new(),
}
}
// purge peer in self and in PeerMap, together
pub fn purge_peer(&self, id: &str, pm: &PeerMap) {
if let Some((_k, v)) = pm.peers.remove(id) {
let ip = v.dev_addr.net_addr();
self.ip_to_edge_id.remove(&ip);
}
self.edges.remove(id);
}
pub fn unbind_peer(&self, id: &str, ip: u32) {
self.edges.remove(id);
if ip != 0 {
self.ip_to_edge_id.remove(&ip);
}
}
pub fn get_peer_with_id<'a>(&self, id: &'a str, pm: &'a PeerMap) -> Option<Arc<Peer>> {
if !self.edges.contains(id) {
return None;
} else {
if let Some(p) = pm.peers.get(id) {
Some(p.clone())
} else {
// edge conatains, but global peermap does not
// remove it in edges
self.edges.remove(id);
None
}
}
}
pub fn iter_peer_with_id<'a, F>(&'a self, pm: &'a PeerMap, f: F) -> Option<(String, Arc<Peer>)>
where
F: Fn(&Arc<Peer>) -> bool,
{
for id in self.edges.iter() {
if let Some(temp) = pm.peers.get(&*id) {
if f(&temp) {
return Some((id.to_owned(), temp.clone()));
}
}
}
None
}
pub fn get_peer_with_ip(&self, ip: u32, pm: &PeerMap) -> Option<Arc<Peer>> {
if let Some(id) = self.ip_to_edge_id.get(&ip) {
if let Some(p) = pm.peers.get(&*id) {
return Some(p.clone());
}
}
None
}
pub fn contains(&self, id: &str) -> bool {
self.edges.contains(id)
}
pub fn insert_peer(&self, ip: u32, id: String) {
if ip != 0 {
self.ip_to_edge_id.insert(ip, id.clone());
}
self.edges.insert(id);
}
// 重新绑定一个id
pub fn rebind_peer_ip(&self, ip: u32, oldid: &str, newid: &str, pm: &PeerMap) {
if let Some((_, v)) = pm.peers.remove(oldid) {
pm.peers.insert(newid.to_owned(), v);
}
self.ip_to_edge_id.remove(&ip);
self.ip_to_edge_id.insert(ip, newid.to_owned());
self.edges.remove(oldid);
self.edges.insert(newid.to_owned());
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::config::AF_INET; use crate::config::AF_INET;

View File

@ -1,10 +1,12 @@
use std::{convert::From, net::AddrParseError, string::ParseError}; use std::{convert::From, net::AddrParseError, string::ParseError};
use aes::cipher::typenum::IsLessOrEqual;
pub type Result<T> = std::result::Result<T, SDLanError>; pub type Result<T> = std::result::Result<T, SDLanError>;
#[derive(Debug)] #[derive(Debug)]
pub enum SDLanError { pub enum SDLanError {
IOError(std::io::Error), IOError(String),
NormalError(&'static str), NormalError(&'static str),
ConvertError(String), ConvertError(String),
SerializeError(String), SerializeError(String),
@ -12,9 +14,22 @@ pub enum SDLanError {
DBError(String), DBError(String),
} }
impl SDLanError {
pub fn as_str(&self) -> &str {
match *self {
Self::IOError(ref e) => e,
Self::NormalError(ref s) => s,
Self::ConvertError(ref e) => e,
Self::SerializeError(ref e) => e,
Self::EncryptError(ref e) => e,
Self::DBError(ref e) => e,
}
}
}
impl From<std::io::Error> for SDLanError { impl From<std::io::Error> for SDLanError {
fn from(value: std::io::Error) -> Self { fn from(value: std::io::Error) -> Self {
Self::IOError(value) Self::IOError(value.to_string())
} }
} }

View File

@ -31,7 +31,15 @@ impl<T> MyDashMap<T> {
} }
} }
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{Duration, SystemTime, UNIX_EPOCH};
pub fn get_timestamp_after_duration(d: Duration) -> u64 {
if let Some(t) = SystemTime::now().checked_add(d) {
t.duration_since(UNIX_EPOCH).unwrap().as_secs()
} else {
0
}
}
pub fn get_current_timestamp() -> u64 { pub fn get_current_timestamp() -> u64 {
SystemTime::now() SystemTime::now()
.duration_since(UNIX_EPOCH) .duration_since(UNIX_EPOCH)

View File

@ -3,3 +3,11 @@ use uuid::Uuid;
pub fn gen_uuid() -> String { pub fn gen_uuid() -> String {
format!("{:032x}", Uuid::new_v4().as_u128()) format!("{:032x}", Uuid::new_v4().as_u128())
} }
pub fn gen_uuid_u64() -> u64 {
(Uuid::new_v4().as_u128() >> 64) as u64
}
pub fn gen_uuid_u128() -> u128 {
Uuid::new_v4().as_u128()
}