实现Ling Transmit V1.1协议
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/target
|
||||
Cargo.lock
|
||||
.idea
|
||||
16
Cargo.toml
Normal file
16
Cargo.toml
Normal file
@@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "LingTransmit"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
name = "LingTransmit"
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
|
||||
[dependencies]
|
||||
openssl = "0.10.68"
|
||||
tokio = { version = "1.43.0", features = ["full"] }
|
||||
async-trait = "0.1.85"
|
||||
tokio-macros = "2.5.0"
|
||||
log = "0.4.25"
|
||||
7
src/bin/main.rs
Normal file
7
src/bin/main.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
// 版权所有 (c) ling 保留所有权利。
|
||||
// 除非另行说明,否则仅允许在LingTransmit中使用此文件中的代码。
|
||||
//
|
||||
// 由 ling 创建于 2025/1/18.
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
fn main() {}
|
||||
51
src/close_sender.rs
Normal file
51
src/close_sender.rs
Normal file
@@ -0,0 +1,51 @@
|
||||
// 版权所有 (c) ling 保留所有权利。
|
||||
// 除非另行说明,否则仅允许在LingTransmit中使用此文件中的代码。
|
||||
//
|
||||
// 由 ling 创建于 2025/1/18.
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use tokio::sync::broadcast::error::RecvError;
|
||||
use tokio::sync::broadcast::Receiver;
|
||||
use tokio::sync::broadcast::Sender;
|
||||
use tokio::sync::{broadcast, Mutex, MutexGuard};
|
||||
|
||||
/// 用于广播关闭消息的通道
|
||||
pub struct CloseSender {
|
||||
sender: Mutex<Sender<i8>>,
|
||||
receive: Mutex<Receiver<i8>>,
|
||||
}
|
||||
|
||||
impl CloseSender {
|
||||
pub fn new() -> Self {
|
||||
let (close_tx, close_rx) = broadcast::channel::<i8>(1);
|
||||
CloseSender {
|
||||
sender: Mutex::new(close_tx),
|
||||
receive: Mutex::new(close_rx),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn clone(&self) -> Self {
|
||||
let lock = self.sender.lock().await;
|
||||
CloseSender {
|
||||
sender: Mutex::new(lock.clone()),
|
||||
receive: Mutex::new(lock.subscribe()),
|
||||
}
|
||||
}
|
||||
|
||||
/// 广播关闭消息
|
||||
pub async fn send_close(&self) {
|
||||
let lock = self.sender.lock().await;
|
||||
let _ = lock.send(0);
|
||||
}
|
||||
|
||||
pub async fn send_close_value(&self, value: i8) {
|
||||
let lock = self.sender.lock().await;
|
||||
let _ = lock.send(value);
|
||||
}
|
||||
|
||||
/// 等待收到关闭消息
|
||||
pub async fn wait_close(&self) -> i8 {
|
||||
let value = self.receive.lock().await.recv().await;
|
||||
value.unwrap_or_else(|_| -1)
|
||||
}
|
||||
}
|
||||
4
src/lib.rs
Normal file
4
src/lib.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
pub mod server;
|
||||
pub mod close_sender;
|
||||
pub mod packet;
|
||||
pub mod ssl;
|
||||
26
src/packet/code.rs
Normal file
26
src/packet/code.rs
Normal file
@@ -0,0 +1,26 @@
|
||||
// 版权所有 (c) ling 保留所有权利。
|
||||
// 除非另行说明,否则仅允许在LingTransmit中使用此文件中的代码。
|
||||
//
|
||||
// 由 ling 创建于 2025/1/18.
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
/// SYN V1
|
||||
pub const LING_SYN_V1: i32 = 0x20040202;
|
||||
/// 数据包开始魔数
|
||||
pub const LING_START: i32 = 0x20040202;
|
||||
/// 数据包尾部魔数
|
||||
pub const LING_STOP: i32 = 0x20030507;
|
||||
/// Ling - 1.0 数据包最大长度
|
||||
pub const MAX_SIZE_V1_0: i32 = 32 * 1024;
|
||||
/// Ling - 1.1 数据包最大长度
|
||||
pub const MAX_SIZE_V1_1: i32 = 512 * 1024;
|
||||
|
||||
/// 服务器确认
|
||||
pub const SERVER_ACK: i32 = 99999999;
|
||||
/// 服务器错误
|
||||
pub const SERVER_ERROR: i32 = 100000000;
|
||||
|
||||
/// 用户接口
|
||||
pub const API_TYPE_ASK: i32 = 1;
|
||||
/// 交换密钥
|
||||
pub const API_TYPE_PUSH_AES_KEY: i32 = 4;
|
||||
109
src/packet/mod.rs
Normal file
109
src/packet/mod.rs
Normal file
@@ -0,0 +1,109 @@
|
||||
// 版权所有 (c) ling 保留所有权利。
|
||||
// 除非另行说明,否则仅允许在LingTransmit中使用此文件中的代码。
|
||||
//
|
||||
// 由 ling 创建于 2025/1/18.
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
pub mod code;
|
||||
|
||||
use crate::packet::code::*;
|
||||
use crate::server::accept::OwnedReadHalfAbstraction;
|
||||
use crate::server::Client::Client;
|
||||
use std::fmt::format;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::{error, io};
|
||||
use tokio::io::AsyncReadExt;
|
||||
|
||||
/// 数据包
|
||||
pub enum NetworkPackets {
|
||||
/// 客户端请求执行SYN V1握手,发送服务器公钥证书
|
||||
SynV1,
|
||||
/// 用户接口
|
||||
UserAsk(Vec<u8>),
|
||||
/// 设定会话密钥
|
||||
PushAesKey(Vec<u8>),
|
||||
}
|
||||
|
||||
/// 从字节流中读取一个数据包
|
||||
pub async fn read_packet(
|
||||
read: &mut Box<dyn OwnedReadHalfAbstraction>,
|
||||
client: &Client,
|
||||
) -> io::Result<NetworkPackets> {
|
||||
//根据协议,通信伊始收到 SYN V1 信息,则使用V1协议加密通信
|
||||
//在此实现中,彻底摈弃了未加密的不安全数据。
|
||||
//如果客户端没有建立SSL安全连接就开始通信,则直接掐断。
|
||||
if client.syn_version.load(Ordering::Acquire) == 0
|
||||
&& !client.is_key_negotiation.load(Ordering::Acquire)
|
||||
{
|
||||
let syn = read.read_i32().await?;
|
||||
if syn != LING_SYN_V1 {
|
||||
return Err(make_error("客户端尝试使用未加密连接交换数据"));
|
||||
}
|
||||
client.is_key_negotiation.store(true, Ordering::Release);
|
||||
//客户端请求V1握手
|
||||
return Ok(NetworkPackets::SynV1);
|
||||
}
|
||||
//读取数据包长度
|
||||
let mut size = read.read_i32().await?;
|
||||
// 在旧版本的协议中,没有魔数标记数据包开始,数据包通过 int32_t 类型的size作为开始。
|
||||
// 如果传输过程中出错,导致读取位置发生些许偏差,则size不准,可能错误分配堆内存,带来安全隐患。
|
||||
// 自 Ling V1.1开始,数据包头部必须使用 LING_START 开始
|
||||
// 但为了兼容旧的应用,允许 32kb 以下的数据包不附带魔数。
|
||||
if size > MAX_SIZE_V1_0 {
|
||||
if size != LING_START {
|
||||
return Err(make_error(
|
||||
"客户端发送的数据包过大(Ling Transmit V1.0限制32KB)!",
|
||||
));
|
||||
}
|
||||
//由于size实际上读取的是 LING_START 魔数,所以要重新读取四个字节作为数据包实际大小
|
||||
size = read.read_i32().await?;
|
||||
//附带魔数后,将数据包长度限制提高到 512kb
|
||||
if size > MAX_SIZE_V1_1 {
|
||||
return Err(make_error(
|
||||
"客户端发送的数据包过大(Ling Transmit V1.1限制512KB)!",
|
||||
));
|
||||
}
|
||||
}
|
||||
//根据协议,包体大小必须是正整数,不能为0
|
||||
if size <= 0 {
|
||||
return Err(make_error(format!(
|
||||
"客户端发送了错误的数据包大小:{}",
|
||||
size
|
||||
)));
|
||||
}
|
||||
|
||||
// 数据包类型
|
||||
let data_type = match read.read_i32().await? {
|
||||
API_TYPE_ASK => API_TYPE_ASK,
|
||||
API_TYPE_PUSH_AES_KEY => API_TYPE_PUSH_AES_KEY,
|
||||
num => {
|
||||
return Err(make_error(format!("未知的数据包类型:{}", num)));
|
||||
}
|
||||
};
|
||||
// 读取包体
|
||||
let mut buffer = Vec::new();
|
||||
buffer.resize(size as usize, 0);
|
||||
let read_size = read.read_exact(&mut buffer).await?;
|
||||
if read_size != size as usize {
|
||||
return Err(make_error(format!(
|
||||
"残缺数据包:读取到{}字节,共{}字节",
|
||||
read_size, size
|
||||
)));
|
||||
}
|
||||
|
||||
match data_type {
|
||||
API_TYPE_ASK => Ok(NetworkPackets::UserAsk(buffer)),
|
||||
API_TYPE_PUSH_AES_KEY => Ok(NetworkPackets::PushAesKey(buffer)),
|
||||
_ => Err(make_error("未知的数据包类型")),
|
||||
}
|
||||
}
|
||||
|
||||
fn make_error<E>(str: E) -> io::Error
|
||||
where
|
||||
E: Into<Box<dyn error::Error + Send + Sync>> + std::fmt::Display,
|
||||
{
|
||||
io::Error::new(
|
||||
io::ErrorKind::NetworkUnreachable,
|
||||
format!("协议错误:{}", str),
|
||||
)
|
||||
}
|
||||
175
src/server/Client.rs
Normal file
175
src/server/Client.rs
Normal file
@@ -0,0 +1,175 @@
|
||||
// 版权所有 (c) ling 保留所有权利。
|
||||
// 除非另行说明,否则仅允许在LingTransmit中使用此文件中的代码。
|
||||
//
|
||||
// 由 ling 创建于 2025/1/18.
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use crate::close_sender::CloseSender;
|
||||
use crate::packet::code::{SERVER_ACK, SERVER_ERROR};
|
||||
use crate::packet::{read_packet, NetworkPackets};
|
||||
use crate::server::accept::{OwnedReadHalfAbstraction, OwnedWriteHalfAbstraction, SocketAddr};
|
||||
use crate::server::ClientID;
|
||||
use crate::ssl::ServerCert;
|
||||
use log::{error, info};
|
||||
use openssl::rsa::Padding;
|
||||
use std::io;
|
||||
use std::string::FromUtf8Error;
|
||||
use std::sync::atomic::{AtomicBool, AtomicI32};
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use std::time::Duration;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
pub type ReadSoc = Mutex<Option<Box<dyn OwnedReadHalfAbstraction>>>;
|
||||
pub type WriteSoc = Mutex<Box<dyn OwnedWriteHalfAbstraction>>;
|
||||
|
||||
/// 服务器侧的Client抽象
|
||||
pub struct Client {
|
||||
/// 服务器关闭
|
||||
server_close: CloseSender,
|
||||
/// 连接关闭
|
||||
client_close: CloseSender,
|
||||
read_soc: ReadSoc,
|
||||
write_soc: WriteSoc,
|
||||
pub id: ClientID,
|
||||
pub addr: SocketAddr,
|
||||
/// 协议版本
|
||||
pub syn_version: AtomicI32,
|
||||
/// 是否正在进行密钥协商
|
||||
pub is_key_negotiation: AtomicBool,
|
||||
/// 会话密钥
|
||||
pub key: OnceLock<String>,
|
||||
/// 服务器证书
|
||||
cert: Arc<ServerCert>,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub fn new(
|
||||
server_close: CloseSender,
|
||||
client_close: CloseSender,
|
||||
read_soc: Box<dyn OwnedReadHalfAbstraction>,
|
||||
write_soc: Box<dyn OwnedWriteHalfAbstraction>,
|
||||
id: ClientID,
|
||||
addr: SocketAddr,
|
||||
cert: Arc<ServerCert>,
|
||||
) -> Self {
|
||||
Client {
|
||||
server_close,
|
||||
client_close,
|
||||
read_soc: Mutex::new(Some(read_soc)),
|
||||
write_soc: Mutex::new(write_soc),
|
||||
id,
|
||||
addr,
|
||||
syn_version: AtomicI32::new(0),
|
||||
is_key_negotiation: AtomicBool::new(false),
|
||||
key: OnceLock::new(),
|
||||
cert,
|
||||
}
|
||||
}
|
||||
|
||||
/// 挂断连接
|
||||
pub(super) async fn close(&self) {
|
||||
let mut lock = self.read_soc.lock().await;
|
||||
*lock = None;
|
||||
drop(lock);
|
||||
let mut lock = self.write_soc.lock().await;
|
||||
if let Err(err) = lock.shutdown().await {
|
||||
error!("关闭 {} 号客户端的写入端失败:{}", self.id, err.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
/// 开始处理该客户端的请求
|
||||
pub async fn start(&self) {
|
||||
loop {
|
||||
//从字节流中读取一个数据包
|
||||
let packet = tokio::select! {
|
||||
packet = async {
|
||||
let mut lock = self.read_soc.lock().await;
|
||||
match *lock {
|
||||
None => {
|
||||
Err(io::Error::new(io::ErrorKind::NotFound,"读取端已经被挂断"))
|
||||
}
|
||||
Some(ref mut val) => {
|
||||
read_packet(val,self).await
|
||||
}
|
||||
}
|
||||
} => {
|
||||
match packet {
|
||||
Ok(val) => {val}
|
||||
Err(err) => {
|
||||
info!("{} 号连接读取数据包出错:{}",self.id,err.to_string());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = self.server_close.wait_close() => {
|
||||
info!("{} 号连接被挂断",self.id);
|
||||
return;
|
||||
}
|
||||
_ = self.client_close.wait_close() => {
|
||||
info!("{} 号连接被挂断",self.id);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
//处理客户端请求
|
||||
//将数据包的读取和处理放在不同的select!中,确保数据包的处理过程不会被关闭信号打断
|
||||
tokio::select! {
|
||||
result = self.process_packet(packet) => {
|
||||
if let Err(err) = result {
|
||||
error!("{} 号连接请求处理出错:{}", self.id, err.to_string());
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ = tokio::time::sleep(Duration::from_secs(15)) => {
|
||||
error!("{} 号连接的请求处理超时!",self.id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 处理客户端请求
|
||||
async fn process_packet(&self, packet: NetworkPackets) -> io::Result<()> {
|
||||
match packet {
|
||||
NetworkPackets::SynV1 => self.syn_v1().await,
|
||||
NetworkPackets::UserAsk(_) => Ok(()),
|
||||
NetworkPackets::PushAesKey(data) => self.client_push_key(&data).await,
|
||||
}
|
||||
}
|
||||
|
||||
/// 客户端推送会话密钥
|
||||
async fn client_push_key(&self, buff: &Vec<u8>) -> io::Result<()> {
|
||||
let rsa = self.cert.private_key.rsa()?;
|
||||
|
||||
let mut data = Vec::new();
|
||||
data.resize(rsa.size() as usize, 0u8);
|
||||
|
||||
//解密会话密钥
|
||||
rsa.private_decrypt(buff, &mut data, Padding::PKCS1)?;
|
||||
|
||||
let key = match String::from_utf8(data) {
|
||||
Ok(key) => key,
|
||||
Err(_) => {
|
||||
return Err(io::Error::new(io::ErrorKind::NotFound, "解密会话密钥失败"));
|
||||
}
|
||||
};
|
||||
let mut send = self.write_soc.lock().await;
|
||||
if let Err(_) = self.key.set(key.clone()) {
|
||||
//重复推送,拒绝密钥
|
||||
send.write_i32(SERVER_ERROR).await?;
|
||||
return Ok(());
|
||||
}
|
||||
send.write_i32(SERVER_ACK).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 发送服务器证书
|
||||
async fn syn_v1(&self) -> io::Result<()> {
|
||||
let certificate = self.cert.certificate.to_pem()?;
|
||||
let mut send = self.write_soc.lock().await;
|
||||
send.write_i64(certificate.len() as i64).await?;
|
||||
send.write(&certificate).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
116
src/server/accept.rs
Normal file
116
src/server/accept.rs
Normal file
@@ -0,0 +1,116 @@
|
||||
// 版权所有 (c) ling 保留所有权利。
|
||||
// 除非另行说明,否则仅允许在LingTransmit中使用此文件中的代码。
|
||||
//
|
||||
// 由 ling 创建于 2025/1/18.
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use async_trait::async_trait;
|
||||
use tokio::io;
|
||||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
||||
use tokio::net::{tcp, unix, TcpListener, UnixListener};
|
||||
|
||||
/// 读取抽象,使用小端序
|
||||
#[async_trait]
|
||||
pub trait OwnedReadHalfAbstraction: AsyncRead + Unpin + Send + Sync {
|
||||
async fn read_i32(&mut self) -> io::Result<i32> {
|
||||
let mut buffer = [0u8; 4];
|
||||
self.read_exact(&mut buffer).await?;
|
||||
Ok(i32::from_le_bytes(buffer))
|
||||
}
|
||||
|
||||
async fn read_i64(&mut self) -> io::Result<i64> {
|
||||
let mut buffer = [0u8; 8];
|
||||
self.read_exact(&mut buffer).await?;
|
||||
Ok(i64::from_le_bytes(buffer))
|
||||
}
|
||||
|
||||
async fn read_u32(&mut self) -> io::Result<u32> {
|
||||
let mut buffer = [0u8; 4];
|
||||
self.read_exact(&mut buffer).await?;
|
||||
Ok(u32::from_le_bytes(buffer))
|
||||
}
|
||||
|
||||
async fn read_u64(&mut self) -> io::Result<u64> {
|
||||
let mut buffer = [0u8; 8];
|
||||
self.read_exact(&mut buffer).await?;
|
||||
Ok(u64::from_le_bytes(buffer))
|
||||
}
|
||||
}
|
||||
|
||||
/// 写入抽象,使用小端序
|
||||
#[async_trait]
|
||||
pub trait OwnedWriteHalfAbstraction: AsyncWrite + Unpin + Send + Sync {
|
||||
async fn write_i32(&mut self, value: i32) -> io::Result<usize> {
|
||||
self.write(&value.to_le_bytes()).await
|
||||
}
|
||||
|
||||
async fn write_i64(&mut self, value: i64) -> io::Result<usize> {
|
||||
self.write(&value.to_le_bytes()).await
|
||||
}
|
||||
|
||||
async fn write_u32(&mut self, value: u32) -> io::Result<usize> {
|
||||
self.write(&value.to_le_bytes()).await
|
||||
}
|
||||
|
||||
async fn write_u64(&mut self, value: u64) -> io::Result<usize> {
|
||||
self.write(&value.to_le_bytes()).await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl OwnedReadHalfAbstraction for tcp::OwnedReadHalf {}
|
||||
|
||||
#[async_trait]
|
||||
impl OwnedReadHalfAbstraction for unix::OwnedReadHalf {}
|
||||
|
||||
#[async_trait]
|
||||
impl OwnedWriteHalfAbstraction for tcp::OwnedWriteHalf {}
|
||||
|
||||
#[async_trait]
|
||||
impl OwnedWriteHalfAbstraction for unix::OwnedWriteHalf {}
|
||||
|
||||
#[async_trait]
|
||||
pub trait AcceptSocket {
|
||||
async fn accept(
|
||||
&self,
|
||||
) -> io::Result<(
|
||||
Box<dyn OwnedReadHalfAbstraction>,
|
||||
Box<dyn OwnedWriteHalfAbstraction>,
|
||||
SocketAddr,
|
||||
)>;
|
||||
}
|
||||
|
||||
pub enum SocketAddr {
|
||||
TCP(std::net::SocketAddr),
|
||||
Unix(unix::SocketAddr),
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl AcceptSocket for TcpListener {
|
||||
async fn accept(
|
||||
&self,
|
||||
) -> io::Result<(
|
||||
Box<dyn OwnedReadHalfAbstraction>,
|
||||
Box<dyn OwnedWriteHalfAbstraction>,
|
||||
SocketAddr,
|
||||
)> {
|
||||
let (socket, addr) = self.accept().await?;
|
||||
let (read, write) = socket.into_split();
|
||||
Ok((Box::new(read), Box::new(write), SocketAddr::TCP(addr)))
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl AcceptSocket for UnixListener {
|
||||
async fn accept(
|
||||
&self,
|
||||
) -> io::Result<(
|
||||
Box<dyn OwnedReadHalfAbstraction>,
|
||||
Box<dyn OwnedWriteHalfAbstraction>,
|
||||
SocketAddr,
|
||||
)> {
|
||||
let (socket, addr) = self.accept().await?;
|
||||
let (read, write) = socket.into_split();
|
||||
Ok((Box::new(read), Box::new(write), SocketAddr::Unix(addr)))
|
||||
}
|
||||
}
|
||||
126
src/server/mod.rs
Normal file
126
src/server/mod.rs
Normal file
@@ -0,0 +1,126 @@
|
||||
// 版权所有 (c) ling 保留所有权利。
|
||||
// 除非另行说明,否则仅允许在LingTransmit中使用此文件中的代码。
|
||||
//
|
||||
// 由 ling 创建于 2025/1/18.
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
pub mod Client;
|
||||
pub mod accept;
|
||||
|
||||
use crate::close_sender::CloseSender;
|
||||
use crate::server::accept::AcceptSocket;
|
||||
use crate::ssl::ServerCert;
|
||||
use async_trait::async_trait;
|
||||
use log::{debug, error};
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use std::sync::{mpsc, Arc};
|
||||
use tokio::io;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tokio::net::UnixListener;
|
||||
use tokio::net::{TcpListener, ToSocketAddrs};
|
||||
use tokio::sync::{broadcast, Mutex};
|
||||
|
||||
pub type ClientID = u64;
|
||||
pub type ClientList = Arc<Mutex<HashMap<ClientID, Arc<Client::Client>>>>;
|
||||
|
||||
/// 服务器抽象
|
||||
pub struct Server {
|
||||
listener: Box<dyn AcceptSocket>,
|
||||
close_sender: CloseSender,
|
||||
client_list: ClientList,
|
||||
next_id: AtomicU64,
|
||||
cert: Arc<ServerCert>,
|
||||
}
|
||||
|
||||
impl Server {
|
||||
fn new(listener: Box<dyn AcceptSocket>, cert: ServerCert) -> Self {
|
||||
Server {
|
||||
listener,
|
||||
close_sender: CloseSender::new(),
|
||||
client_list: Arc::new(Mutex::new(HashMap::new())),
|
||||
next_id: AtomicU64::new(0),
|
||||
cert: Arc::new(cert),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn new_tcp<A: ToSocketAddrs>(addr: A, cert: ServerCert) -> io::Result<Self> {
|
||||
let listener = TcpListener::bind(addr).await?;
|
||||
Ok(Server::new(Box::new(listener), cert))
|
||||
}
|
||||
|
||||
pub async fn new_unix<P>(path: P, cert: ServerCert) -> io::Result<Self>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let unix = UnixListener::bind(path)?;
|
||||
Ok(Server::new(Box::new(unix), cert))
|
||||
}
|
||||
|
||||
/// 广播关闭消息
|
||||
pub async fn close(&self) {
|
||||
self.close_sender.send_close().await;
|
||||
}
|
||||
|
||||
/// 获取在线客户端列表
|
||||
pub fn get_client_list(&self) -> ClientList {
|
||||
self.client_list.clone()
|
||||
}
|
||||
|
||||
/// 挂断一个客户端
|
||||
pub async fn close_client(&self, id: ClientID) {
|
||||
Self::close_client_form_arc(&self.client_list, id).await;
|
||||
}
|
||||
|
||||
pub async fn close_client_form_arc(list: &ClientList, id: ClientID) {
|
||||
let mut lock = list.lock().await;
|
||||
if let Some(client) = lock.get(&id) {
|
||||
client.close().await;
|
||||
lock.remove(&id);
|
||||
}
|
||||
}
|
||||
|
||||
/// 开始接收客户端连接
|
||||
pub async fn start_accept(&self) {
|
||||
tokio::select! {
|
||||
_ = async {
|
||||
loop {
|
||||
if let Err(err) = self.accept_client().await {
|
||||
error!("接受连接失败:{}",err.to_string());
|
||||
}
|
||||
}
|
||||
} => {}
|
||||
_ = self.close_sender.wait_close() => {
|
||||
debug!("停止接受客户端连接");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn accept_client(&self) -> io::Result<()> {
|
||||
let (read, write, addr) = self.listener.accept().await?;
|
||||
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
|
||||
let close = CloseSender::new();
|
||||
let client = Arc::new(Client::Client::new(
|
||||
self.close_sender.clone().await,
|
||||
close,
|
||||
read,
|
||||
write,
|
||||
id,
|
||||
addr,
|
||||
self.cert.clone(),
|
||||
));
|
||||
|
||||
let mut lock = self.client_list.lock().await;
|
||||
lock.insert(id, client.clone());
|
||||
drop(lock);
|
||||
|
||||
let list = self.get_client_list();
|
||||
tokio::spawn(async move {
|
||||
client.start().await;
|
||||
//当连接的事件轮退出,则自动挂断
|
||||
Self::close_client_form_arc(&list, id).await;
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
102
src/ssl/mod.rs
Normal file
102
src/ssl/mod.rs
Normal file
@@ -0,0 +1,102 @@
|
||||
// 版权所有 (c) ling 保留所有权利。
|
||||
// 除非另行说明,否则仅允许在LingTransmit中使用此文件中的代码。
|
||||
//
|
||||
// 由 ling 创建于 2025/1/18.
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use openssl::hash::MessageDigest;
|
||||
use openssl::pkey::{PKey, Private, Public};
|
||||
use openssl::rsa::Rsa;
|
||||
use openssl::sign::{Signer, Verifier};
|
||||
use openssl::x509::X509;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{fs, io};
|
||||
|
||||
/// 服务器证书
|
||||
pub struct ServerCert {
|
||||
/// 私钥
|
||||
pub private_key: PKey<Private>,
|
||||
/// 公钥
|
||||
pub public_key: PKey<Public>,
|
||||
/// 证书文件
|
||||
pub certificate: X509,
|
||||
}
|
||||
|
||||
impl ServerCert {
|
||||
pub fn init(certificate_path: &PathBuf, private_path: &PathBuf) -> io::Result<Self> {
|
||||
let cert = Self::load_public(&certificate_path)?;
|
||||
let private_key = Self::load_private(private_path)?;
|
||||
Ok(Self::init_key(cert, private_key)?)
|
||||
}
|
||||
|
||||
pub fn init_password(
|
||||
certificate_path: &PathBuf,
|
||||
private_path: &PathBuf,
|
||||
password: &str,
|
||||
) -> io::Result<Self> {
|
||||
let cert = Self::load_public(&certificate_path)?;
|
||||
let private_key = Self::load_private_password(private_path, password)?;
|
||||
Ok(Self::init_key(cert, private_key)?)
|
||||
}
|
||||
|
||||
pub fn init_buffer(cert: &Vec<u8>, private: &Vec<u8>) -> io::Result<Self> {
|
||||
let x509 = X509::from_pem(cert)?;
|
||||
let private_key = PKey::private_key_from_pem(private)?;
|
||||
Self::init_key(x509, private_key)
|
||||
}
|
||||
|
||||
pub fn init_buffer_password(
|
||||
cert: &Vec<u8>,
|
||||
private: &Vec<u8>,
|
||||
password: &str,
|
||||
) -> io::Result<Self> {
|
||||
let x509 = X509::from_pem(cert)?;
|
||||
let private_key = PKey::private_key_from_pem_passphrase(private, password.as_bytes())?;
|
||||
Self::init_key(x509, private_key)
|
||||
}
|
||||
|
||||
fn init_key(certificate: X509, private_key: PKey<Private>) -> io::Result<Self> {
|
||||
//检查证书和私钥是否匹配
|
||||
let message = b"test message";
|
||||
//先使用私钥签名数据
|
||||
let mut signer = Signer::new(MessageDigest::sha256(), &private_key)?;
|
||||
signer.update(message)?;
|
||||
let signature = signer.sign_to_vec()?;
|
||||
|
||||
//然后使用公钥验证签名
|
||||
let public_key = certificate.public_key()?;
|
||||
let mut verifier = Verifier::new(MessageDigest::sha256(), &public_key)?;
|
||||
verifier.update(message)?;
|
||||
if !verifier.verify(&signature)? {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
"提供的证书和私钥不匹配!",
|
||||
));
|
||||
}
|
||||
drop(verifier);
|
||||
|
||||
Ok(ServerCert {
|
||||
private_key,
|
||||
public_key,
|
||||
certificate,
|
||||
})
|
||||
}
|
||||
|
||||
fn load_public(certificate_path: &PathBuf) -> io::Result<X509> {
|
||||
let cert_data = fs::read(certificate_path)?;
|
||||
Ok(X509::from_pem(&cert_data)?)
|
||||
}
|
||||
|
||||
fn load_private(private_path: &PathBuf) -> io::Result<PKey<Private>> {
|
||||
let key_data = fs::read(private_path)?;
|
||||
Ok(PKey::private_key_from_pem(&key_data)?)
|
||||
}
|
||||
|
||||
fn load_private_password(private_path: &PathBuf, password: &str) -> io::Result<PKey<Private>> {
|
||||
let key_data = fs::read(private_path)?;
|
||||
Ok(PKey::private_key_from_pem_passphrase(
|
||||
&key_data,
|
||||
password.as_bytes(),
|
||||
)?)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user