mirror of
https://github.com/lbl8603/vnts.git
synced 2025-09-26 20:21:27 +08:00
支持服务端加密
This commit is contained in:
44
.github/workflows/rust.yml
vendored
44
.github/workflows/rust.yml
vendored
@@ -38,36 +38,53 @@ jobs:
|
||||
include:
|
||||
- TARGET: i686-unknown-linux-musl # test in an alpine container on a mac
|
||||
OS: ubuntu-latest
|
||||
FEATURES: normal
|
||||
- TARGET: x86_64-unknown-linux-gnu # tested in a debian container on a mac
|
||||
OS: ubuntu-latest
|
||||
FEATURES: ring-cipher
|
||||
- TARGET: x86_64-unknown-linux-musl # test in an alpine container on a mac
|
||||
OS: ubuntu-latest
|
||||
FEATURES: ring-cipher
|
||||
- TARGET: aarch64-unknown-linux-gnu # tested on aws t4g.nano
|
||||
OS: ubuntu-latest
|
||||
FEATURES: ring-cipher
|
||||
- TARGET: aarch64-unknown-linux-musl # tested on aws t4g.nano in alpine container
|
||||
OS: ubuntu-latest
|
||||
FEATURES: normal
|
||||
- TARGET: armv7-unknown-linux-gnueabihf # raspberry pi 2-3-4, not tested
|
||||
OS: ubuntu-latest
|
||||
FEATURES: ring-cipher
|
||||
- TARGET: armv7-unknown-linux-musleabihf # raspberry pi 2-3-4, not tested
|
||||
OS: ubuntu-latest
|
||||
FEATURES: normal
|
||||
- TARGET: arm-unknown-linux-gnueabihf # raspberry pi 0-1, not tested
|
||||
OS: ubuntu-latest
|
||||
FEATURES: ring-cipher
|
||||
- TARGET: arm-unknown-linux-musleabihf # raspberry pi 0-1, not tested
|
||||
OS: ubuntu-latest
|
||||
FEATURES: normal
|
||||
- TARGET: x86_64-apple-darwin # tested on a mac, is not properly signed so there are security warnings
|
||||
OS: macos-latest
|
||||
FEATURES: ring-cipher
|
||||
- TARGET: aarch64-apple-darwin # tested on a mac, is not properly signed so there are security warnings
|
||||
OS: macos-latest
|
||||
FEATURES: ring-cipher
|
||||
- TARGET: i686-pc-windows-msvc # tested on a windows machine
|
||||
OS: windows-latest
|
||||
FEATURES: ring-cipher
|
||||
- TARGET: x86_64-pc-windows-msvc # tested on a windows machine
|
||||
OS: windows-latest
|
||||
FEATURES: ring-cipher
|
||||
- TARGET: mipsel-unknown-linux-musl # openwrt
|
||||
OS: ubuntu-latest
|
||||
FEATURES: normal
|
||||
# needs: test
|
||||
runs-on: ${{ matrix.OS }}
|
||||
env:
|
||||
NAME: vnts # change with the name of your project
|
||||
TARGET: ${{ matrix.TARGET }}
|
||||
OS: ${{ matrix.OS }}
|
||||
FEATURES: ${{ matrix.FEATURES }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Cargo cache
|
||||
@@ -84,28 +101,51 @@ jobs:
|
||||
# dependencies are only needed on ubuntu as that's the only place where
|
||||
# we make cross-compilation
|
||||
if [[ $OS =~ ^ubuntu.*$ ]]; then
|
||||
sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf
|
||||
sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf musl-tools gcc-mipsel-linux-gnu
|
||||
fi
|
||||
|
||||
# some additional configuration for cross-compilation on linux
|
||||
cat >>~/.cargo/config <<EOF
|
||||
[target.x86_64-unknown-linux-musl]
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
[target.aarch64-unknown-linux-gnu]
|
||||
linker = "aarch64-linux-gnu-gcc"
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
[target.aarch64-unknown-linux-musl]
|
||||
linker = "aarch64-linux-gnu-gcc"
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
[target.armv7-unknown-linux-gnueabihf]
|
||||
linker = "arm-linux-gnueabihf-gcc"
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
[target.armv7-unknown-linux-musleabihf]
|
||||
linker = "arm-linux-gnueabihf-gcc"
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
[target.arm-unknown-linux-gnueabihf]
|
||||
linker = "arm-linux-gnueabihf-gcc"
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
[target.arm-unknown-linux-musleabihf]
|
||||
linker = "arm-linux-gnueabihf-gcc"
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
[target.mipsel-unknown-linux-musl]
|
||||
linker = "mipsel-linux-gnu-gcc"
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
[target.x86_64-pc-windows-msvc]
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
[target.i686-pc-windows-msvc]
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
[target.x86_64-apple-darwin]
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
[target.aarch64-apple-darwin]
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
[target.i686-unknown-linux-musl]
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
[target.x86_64-unknown-linux-gnu]
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
EOF
|
||||
- name: Install rust target
|
||||
run: rustup target add $TARGET
|
||||
- name: Run build
|
||||
run: cargo build --release --verbose --target $TARGET
|
||||
run: cargo build --release --verbose --target $TARGET --features $FEATURES
|
||||
- name: List target
|
||||
run: find ./target
|
||||
- name: Compress
|
||||
|
12
Cargo.toml
12
Cargo.toml
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "vnts"
|
||||
version = "1.1.1"
|
||||
version = "1.1.2"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
@@ -16,7 +16,10 @@ crossbeam = "0.8.2"
|
||||
parking_lot = "0.12.1"
|
||||
crossbeam-skiplist = "0.1"
|
||||
|
||||
rsa = "0.7.2"
|
||||
rsa = {version="0.7.2", features = [] }
|
||||
spki = {version="0.6.0",features=["fingerprint","alloc"]}
|
||||
aes-gcm = {version="0.10.2", optional = true}
|
||||
ring = {version="0.16.20", optional = true}
|
||||
rand = "0.8.5"
|
||||
sha2 ={version="0.10.6",features=["oid"]}
|
||||
colored = "2.0.0"
|
||||
@@ -29,6 +32,11 @@ protobuf = "3.2.0"
|
||||
tokio = { version = "1.28.1", features = ["full"] }
|
||||
async-trait = "0.1.71"
|
||||
tokio-util = { version = "0.7.8", features = ["full"] }
|
||||
|
||||
[features]
|
||||
default=["aes-gcm"]
|
||||
ring-cipher=["ring"]
|
||||
|
||||
[build-dependencies]
|
||||
protobuf-codegen = "3.2.0"
|
||||
protoc-bin-vendored = "3.0.0"
|
@@ -10,4 +10,10 @@ Options:
|
||||
--netmask <NETMASK> 子网掩码,例如 --netmask 255.255.255.0
|
||||
-h, --help Print help
|
||||
```
|
||||
默认情况服务日志输出在 './log/'下,可通过编写'./log/log4rs.yaml'文件自定义日志配置,参考[log4rs](https://github.com/estk/log4rs)
|
||||
|
||||
## 说明
|
||||
1. 修改服务端密钥后,客户端要重启才能正常链接(修改密钥后无法自动重连)
|
||||
2. 服务端密钥用于加密客户端和服务端之间传输的数据(使用rsa+aes256gcm加密),可以防止token被中间人窃取,如果客户端显示的密钥指纹和服务端的不一致,则表示可能有中间人攻击
|
||||
3. 服务端密钥在'./key/'目录下,可以替换成自定义的密钥对
|
||||
4. 客户端的密码用于加密客户端之间传输的数据
|
||||
5. 默认情况服务日志输出在 './log/'下,可通过编写'./log/log4rs.yaml'文件自定义日志配置,参考[log4rs](https://github.com/estk/log4rs)
|
||||
|
@@ -3,12 +3,12 @@ use std::{fmt, io};
|
||||
/// 地址解析协议,由IP地址找到MAC地址
|
||||
/// https://www.ietf.org/rfc/rfc6747.txt
|
||||
/*
|
||||
0 2 4 5 6 8 10 (字节)
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 硬件类型|协议类型|硬件地址长度|协议地址长度|操作类型|
|
||||
| 源MAC地址 | 源ip地址 |
|
||||
| 目的MAC地址 | 目的ip地址 |
|
||||
*/
|
||||
0 2 4 5 6 8 10 (字节)
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 硬件类型|协议类型|硬件地址长度|协议地址长度|操作类型|
|
||||
| 源MAC地址 | 源ip地址 |
|
||||
| 目的MAC地址 | 目的ip地址 |
|
||||
*/
|
||||
|
||||
pub struct ArpPacket<B> {
|
||||
buffer: B,
|
||||
@@ -119,4 +119,4 @@ impl<B: AsRef<[u8]>> fmt::Debug for ArpPacket<B> {
|
||||
.field("target_protocol_addr", &self.target_protocol_addr())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1 +1 @@
|
||||
pub mod arp;
|
||||
pub mod arp;
|
||||
|
@@ -1,2 +1,2 @@
|
||||
pub mod packet;
|
||||
pub mod protocol;
|
||||
pub mod protocol;
|
||||
|
@@ -1,13 +1,13 @@
|
||||
use std::{fmt, io};
|
||||
use crate::ethernet::protocol::Protocol;
|
||||
use std::{fmt, io};
|
||||
|
||||
/// 以太网帧协议
|
||||
/// https://www.ietf.org/rfc/rfc894.txt
|
||||
/*
|
||||
0 6 12 14 (字节)
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 目的地址 | 源地址 | 类型 |
|
||||
*/
|
||||
0 6 12 14 (字节)
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 目的地址 | 源地址 | 类型 |
|
||||
*/
|
||||
pub struct EthernetPacket<B> {
|
||||
pub buffer: B,
|
||||
}
|
||||
@@ -74,4 +74,4 @@ impl<B: AsRef<[u8]>> fmt::Debug for EthernetPacket<B> {
|
||||
.field("payload", &self.payload())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -102,7 +102,7 @@ impl From<u16> for Protocol {
|
||||
0x88f7 => Ptp,
|
||||
0x8902 => Cfm,
|
||||
0x9100 => QinQ,
|
||||
n => Unknown(n),
|
||||
n => Unknown(n),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,30 +112,30 @@ impl Into<u16> for Protocol {
|
||||
use self::Protocol::*;
|
||||
|
||||
match self {
|
||||
Ipv4 => 0x0800,
|
||||
Arp => 0x0806,
|
||||
WakeOnLan => 0x0842,
|
||||
Trill => 0x22f3,
|
||||
DecNet => 0x6003,
|
||||
Rarp => 0x8035,
|
||||
AppleTalk => 0x809b,
|
||||
Aarp => 0x80f3,
|
||||
Ipx => 0x8137,
|
||||
Qnx => 0x8204,
|
||||
Ipv6 => 0x86dd,
|
||||
FlowControl => 0x8808,
|
||||
CobraNet => 0x8819,
|
||||
Mpls => 0x8847,
|
||||
MplsMulticast => 0x8848,
|
||||
Ipv4 => 0x0800,
|
||||
Arp => 0x0806,
|
||||
WakeOnLan => 0x0842,
|
||||
Trill => 0x22f3,
|
||||
DecNet => 0x6003,
|
||||
Rarp => 0x8035,
|
||||
AppleTalk => 0x809b,
|
||||
Aarp => 0x80f3,
|
||||
Ipx => 0x8137,
|
||||
Qnx => 0x8204,
|
||||
Ipv6 => 0x86dd,
|
||||
FlowControl => 0x8808,
|
||||
CobraNet => 0x8819,
|
||||
Mpls => 0x8847,
|
||||
MplsMulticast => 0x8848,
|
||||
PppoeDiscovery => 0x8863,
|
||||
PppoeSession => 0x8864,
|
||||
Vlan => 0x8100,
|
||||
PBridge => 0x88a8,
|
||||
Lldp => 0x88cc,
|
||||
Ptp => 0x88f7,
|
||||
Cfm => 0x8902,
|
||||
QinQ => 0x9100,
|
||||
Unknown(n) => n,
|
||||
PppoeSession => 0x8864,
|
||||
Vlan => 0x8100,
|
||||
PBridge => 0x88a8,
|
||||
Lldp => 0x88cc,
|
||||
Ptp => 0x88f7,
|
||||
Cfm => 0x8902,
|
||||
QinQ => 0x9100,
|
||||
Unknown(n) => n,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
use std::{fmt, io};
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
use crate::cal_checksum;
|
||||
use crate::icmp::{Code, Kind};
|
||||
use crate::ip::ipv4::packet::IpV4Packet;
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
use std::{fmt, io};
|
||||
|
||||
/// icmp 协议
|
||||
/* https://www.rfc-editor.org/rfc/rfc792
|
||||
@@ -67,7 +67,7 @@ impl<B: AsRef<[u8]>> IcmpPacket<B> {
|
||||
| Kind::TimestampReply
|
||||
| Kind::InformationRequest
|
||||
| Kind::InformationReply => {
|
||||
let ide =u16::from_be_bytes(self.buffer.as_ref()[4..6].try_into().unwrap());
|
||||
let ide = u16::from_be_bytes(self.buffer.as_ref()[4..6].try_into().unwrap());
|
||||
let seq = u16::from_be_bytes(self.buffer.as_ref()[6..8].try_into().unwrap());
|
||||
HeaderOther::Identifier(ide, seq)
|
||||
}
|
||||
@@ -121,11 +121,11 @@ impl<B: AsRef<[u8]>> fmt::Debug for IcmpPacket<B> {
|
||||
} else {
|
||||
"icmp::Packet!"
|
||||
})
|
||||
.field("kind", &self.kind())
|
||||
.field("code", &self.code())
|
||||
.field("checksum", &self.checksum())
|
||||
.field("payload", &self.payload())
|
||||
.finish()
|
||||
.field("kind", &self.kind())
|
||||
.field("code", &self.code())
|
||||
.field("checksum", &self.checksum())
|
||||
.field("payload", &self.payload())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,17 +1,17 @@
|
||||
use std::{fmt, io};
|
||||
use std::net::Ipv4Addr;
|
||||
use crate::cal_checksum;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::{fmt, io};
|
||||
|
||||
/// igmp v1
|
||||
/* https://datatracker.ietf.org/doc/html/rfc1112
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|Version| Type | Unused | Checksum |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Group Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|Version| Type | Unused | Checksum |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Group Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
/// v1版本的报文
|
||||
pub struct IgmpV1Packet<B> {
|
||||
pub buffer: B,
|
||||
@@ -43,7 +43,7 @@ impl Into<u8> for IgmpV1Type {
|
||||
match self {
|
||||
IgmpV1Type::Query => 0x11,
|
||||
IgmpV1Type::ReportV1 => 0x12,
|
||||
IgmpV1Type::Unknown(v) => v
|
||||
IgmpV1Type::Unknown(v) => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,4 +114,4 @@ impl<B: AsRef<[u8]>> fmt::Debug for IgmpV1Packet<B> {
|
||||
.field("group_address", &self.group_address())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,18 +1,18 @@
|
||||
use std::{fmt, io};
|
||||
use std::net::Ipv4Addr;
|
||||
use crate::cal_checksum;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::{fmt, io};
|
||||
|
||||
/// igmp v2
|
||||
/* https://www.rfc-editor.org/rfc/rfc2236.html
|
||||
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type | Max Resp Time | Checksum |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Group Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type | Max Resp Time | Checksum |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Group Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
/// v2版本的报文
|
||||
pub struct IgmpV2Packet<B> {
|
||||
@@ -48,7 +48,7 @@ impl Into<u8> for IgmpV2Type {
|
||||
IgmpV2Type::Query => 0x11,
|
||||
IgmpV2Type::ReportV2 => 0x16,
|
||||
IgmpV2Type::LeaveV2 => 0x17,
|
||||
IgmpV2Type::Unknown(v) => v
|
||||
IgmpV2Type::Unknown(v) => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
use std::{fmt, io};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::{fmt, io};
|
||||
|
||||
use crate::cal_checksum;
|
||||
|
||||
@@ -116,7 +116,7 @@ impl Into<u8> for IgmpV3Type {
|
||||
match self {
|
||||
IgmpV3Type::Query => 0x11,
|
||||
IgmpV3Type::ReportV3 => 0x22,
|
||||
IgmpV3Type::Unknown(v) => v
|
||||
IgmpV3Type::Unknown(v) => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,7 +203,7 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> IgmpV3QueryPacket<B> {
|
||||
self.buffer.as_mut()[2..4].copy_from_slice(&checksum.to_be_bytes())
|
||||
}
|
||||
pub fn set_qrv(&mut self, qrv: u8) {
|
||||
self.buffer.as_mut()[8] = (self.buffer.as_ref()[8]&(!0x07)) | (qrv & 0x07)
|
||||
self.buffer.as_mut()[8] = (self.buffer.as_ref()[8] & (!0x07)) | (qrv & 0x07)
|
||||
}
|
||||
pub fn set_qqic(&mut self, qqic: u8) {
|
||||
self.buffer.as_mut()[9] = qqic
|
||||
@@ -349,7 +349,10 @@ impl<B: AsRef<[u8]>> IgmpV3ReportPacket<B> {
|
||||
return None;
|
||||
}
|
||||
if let Ok(record) = IgmpV3RecordPacket::new(&buf[start..]) {
|
||||
let end = start + 8 + record.aux_data_len() as usize * 4 + record.source_number() as usize * 4;
|
||||
let end = start
|
||||
+ 8
|
||||
+ record.aux_data_len() as usize * 4
|
||||
+ record.source_number() as usize * 4;
|
||||
if end > len {
|
||||
return None;
|
||||
}
|
||||
@@ -364,7 +367,6 @@ impl<B: AsRef<[u8]>> IgmpV3ReportPacket<B> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// group record
|
||||
pub struct IgmpV3RecordPacket<B> {
|
||||
pub buffer: B,
|
||||
@@ -488,4 +490,4 @@ impl<B: AsRef<[u8]>> fmt::Debug for IgmpV3RecordPacket<B> {
|
||||
.field("auxiliary_data", &self.auxiliary_data())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@ pub mod igmp_v1;
|
||||
pub mod igmp_v2;
|
||||
pub mod igmp_v3;
|
||||
|
||||
#[derive(Debug,Copy, Clone,Eq, PartialEq)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum IgmpType {
|
||||
/// 0x11 所有组224.0.0.1或者特定组
|
||||
Query,
|
||||
@@ -40,7 +40,7 @@ impl Into<u8> for IgmpType {
|
||||
IgmpType::ReportV2 => 0x16,
|
||||
IgmpType::ReportV3 => 0x22,
|
||||
IgmpType::LeaveV2 => 0x17,
|
||||
IgmpType::Unknown(v) => v
|
||||
IgmpType::Unknown(v) => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,5 @@
|
||||
use std::{fmt, io};
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use std::{fmt, io};
|
||||
|
||||
use crate::cal_checksum;
|
||||
use crate::ip::ipv4::protocol::Protocol;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#[derive(Eq, PartialEq,Ord, PartialOrd, Copy, Clone, Debug)]
|
||||
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug)]
|
||||
pub enum Protocol {
|
||||
///
|
||||
Hopopt,
|
||||
|
@@ -1,5 +1,5 @@
|
||||
use std::io;
|
||||
use ipv4::packet::IpV4Packet;
|
||||
use std::io;
|
||||
|
||||
pub mod ipv4;
|
||||
|
||||
|
@@ -3,13 +3,13 @@ use std::net::Ipv4Addr;
|
||||
use byteorder::BigEndian;
|
||||
use byteorder::ReadBytesExt;
|
||||
|
||||
pub mod arp;
|
||||
pub mod ethernet;
|
||||
pub mod icmp;
|
||||
pub mod igmp;
|
||||
pub mod ip;
|
||||
pub mod tcp;
|
||||
pub mod udp;
|
||||
pub mod ethernet;
|
||||
pub mod arp;
|
||||
// pub enum IpUpperLayer<B> {
|
||||
// UDP(UdpPacket<B>),
|
||||
// Unknown(B),
|
||||
|
@@ -1,5 +1,5 @@
|
||||
use std::{fmt, io};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::{fmt, io};
|
||||
|
||||
use crate::tcp::Flags;
|
||||
|
||||
@@ -58,7 +58,11 @@ impl<B: AsRef<[u8]>> TcpPacket<B> {
|
||||
buffer,
|
||||
}
|
||||
}
|
||||
pub fn new(source_ip: Ipv4Addr, destination_ip: Ipv4Addr, buffer: B) -> io::Result<TcpPacket<B>> {
|
||||
pub fn new(
|
||||
source_ip: Ipv4Addr,
|
||||
destination_ip: Ipv4Addr,
|
||||
buffer: B,
|
||||
) -> io::Result<TcpPacket<B>> {
|
||||
let packet = TcpPacket::unchecked(source_ip, destination_ip, buffer);
|
||||
|
||||
if packet.buffer.as_ref().len() < 20 {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
use std::{fmt, io};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::{fmt, io};
|
||||
|
||||
/// udp协议
|
||||
///
|
||||
@@ -60,7 +60,11 @@ impl<B: AsRef<[u8]>> UdpPacket<B> {
|
||||
buffer,
|
||||
}
|
||||
}
|
||||
pub fn new(source_ip: Ipv4Addr, destination_ip: Ipv4Addr, buffer: B) -> io::Result<UdpPacket<B>> {
|
||||
pub fn new(
|
||||
source_ip: Ipv4Addr,
|
||||
destination_ip: Ipv4Addr,
|
||||
buffer: B,
|
||||
) -> io::Result<UdpPacket<B>> {
|
||||
if buffer.as_ref().len() < 8 {
|
||||
Err(io::Error::from(io::ErrorKind::InvalidData))?;
|
||||
}
|
||||
|
109
src/cipher/aes_gcm_cipher.rs
Normal file
109
src/cipher/aes_gcm_cipher.rs
Normal file
@@ -0,0 +1,109 @@
|
||||
use std::io;
|
||||
|
||||
use aes_gcm::aead::consts::{U12, U16};
|
||||
use aes_gcm::aead::generic_array::GenericArray;
|
||||
use aes_gcm::{AeadInPlace, Aes256Gcm, Key, KeyInit, Nonce, Tag};
|
||||
use rand::RngCore;
|
||||
|
||||
use crate::cipher::finger::Finger;
|
||||
use crate::protocol::{body::SecretBody, body::ENCRYPTION_RESERVED, NetPacket};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Aes256GcmCipher {
|
||||
cipher: Aes256Gcm,
|
||||
finger: Finger,
|
||||
}
|
||||
|
||||
impl Aes256GcmCipher {
|
||||
pub fn new(key: [u8; 32], finger: Finger) -> Self {
|
||||
let key: &Key<Aes256Gcm> = &key.into();
|
||||
Self {
|
||||
cipher: Aes256Gcm::new(key),
|
||||
finger,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||
&self,
|
||||
net_packet: &mut NetPacket<B>,
|
||||
) -> io::Result<()> {
|
||||
if !net_packet.is_encrypt() {
|
||||
//未加密的数据直接丢弃
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
||||
}
|
||||
if net_packet.payload().len() < ENCRYPTION_RESERVED {
|
||||
log::error!("数据异常,长度小于{}", ENCRYPTION_RESERVED);
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||
}
|
||||
let mut nonce_raw = [0; 12];
|
||||
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||
nonce_raw[8] = net_packet.protocol().into();
|
||||
nonce_raw[9] = net_packet.transport_protocol();
|
||||
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||
nonce_raw[11] = net_packet.source_ttl();
|
||||
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce_raw);
|
||||
|
||||
let mut secret_body = SecretBody::new(net_packet.payload_mut())?;
|
||||
let tag = secret_body.tag();
|
||||
if tag.len() != 16 {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "tag err"));
|
||||
}
|
||||
let finger = self.finger.calculate_finger(&nonce_raw, &secret_body);
|
||||
if &finger != secret_body.finger() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
|
||||
}
|
||||
|
||||
let tag: GenericArray<u8, U16> = Tag::clone_from_slice(tag);
|
||||
if let Err(e) =
|
||||
self.cipher
|
||||
.decrypt_in_place_detached(nonce, &[], secret_body.body_mut(), &tag)
|
||||
{
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("解密失败:{}", e),
|
||||
));
|
||||
}
|
||||
net_packet.set_encrypt_flag(false);
|
||||
net_packet.set_data_len(net_packet.data_len() - ENCRYPTION_RESERVED)?;
|
||||
return Ok(());
|
||||
}
|
||||
/// net_packet 必须预留足够长度
|
||||
/// data_len是有效载荷的长度
|
||||
/// 返回加密后载荷的长度
|
||||
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||
&self,
|
||||
net_packet: &mut NetPacket<B>,
|
||||
) -> io::Result<()> {
|
||||
if net_packet.reserve() < ENCRYPTION_RESERVED {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "too short"));
|
||||
}
|
||||
let mut nonce_raw = [0; 12];
|
||||
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||
nonce_raw[8] = net_packet.protocol().into();
|
||||
nonce_raw[9] = net_packet.transport_protocol();
|
||||
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||
nonce_raw[11] = net_packet.source_ttl();
|
||||
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce_raw);
|
||||
net_packet.set_data_len(net_packet.data_len() + ENCRYPTION_RESERVED)?;
|
||||
let mut secret_body = SecretBody::new(net_packet.payload_mut())?;
|
||||
secret_body.set_random(rand::thread_rng().next_u32());
|
||||
return match self
|
||||
.cipher
|
||||
.encrypt_in_place_detached(nonce, &[], secret_body.body_mut())
|
||||
{
|
||||
Ok(tag) => {
|
||||
secret_body.set_tag(tag.as_slice())?;
|
||||
let finger = self.finger.calculate_finger(&nonce_raw, &secret_body);
|
||||
secret_body.set_finger(&finger)?;
|
||||
net_packet.set_encrypt_flag(true);
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("加密失败:{}", e),
|
||||
)),
|
||||
};
|
||||
}
|
||||
}
|
52
src/cipher/finger.rs
Normal file
52
src/cipher/finger.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
use std::io;
|
||||
|
||||
use sha2::Digest;
|
||||
|
||||
use crate::protocol::{body::SecretBody, body::ENCRYPTION_RESERVED, NetPacket};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Finger {
|
||||
token: String,
|
||||
}
|
||||
|
||||
impl Finger {
|
||||
pub fn new(token: String) -> Self {
|
||||
Finger { token }
|
||||
}
|
||||
pub fn check_finger<B: AsRef<[u8]>>(&self, net_packet: &NetPacket<B>) -> io::Result<()> {
|
||||
if !net_packet.is_encrypt() {
|
||||
//未加密的数据直接丢弃
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
||||
}
|
||||
if net_packet.payload().len() < ENCRYPTION_RESERVED {
|
||||
log::error!("数据异常,长度小于{}", ENCRYPTION_RESERVED);
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||
}
|
||||
let mut nonce_raw = [0; 12];
|
||||
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||
nonce_raw[8] = net_packet.protocol().into();
|
||||
nonce_raw[9] = net_packet.transport_protocol();
|
||||
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||
nonce_raw[11] = net_packet.source_ttl();
|
||||
let secret_body = SecretBody::new(net_packet.payload())?;
|
||||
let finger = self.calculate_finger(&nonce_raw, &secret_body);
|
||||
if &finger != secret_body.finger() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn calculate_finger<B: AsRef<[u8]>>(
|
||||
&self,
|
||||
nonce_raw: &[u8; 12],
|
||||
secret_body: &SecretBody<B>,
|
||||
) -> [u8; 12] {
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
hasher.update(secret_body.body());
|
||||
hasher.update(nonce_raw);
|
||||
hasher.update(secret_body.tag());
|
||||
hasher.update(&self.token);
|
||||
let key: [u8; 32] = hasher.finalize().into();
|
||||
return key[20..].try_into().unwrap();
|
||||
}
|
||||
}
|
13
src/cipher/mod.rs
Normal file
13
src/cipher/mod.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
#[cfg(not(feature = "ring-cipher"))]
|
||||
mod aes_gcm_cipher;
|
||||
mod finger;
|
||||
#[cfg(feature = "ring-cipher")]
|
||||
mod ring_cipher;
|
||||
mod rsa_cipher;
|
||||
|
||||
#[cfg(not(feature = "ring-cipher"))]
|
||||
pub use aes_gcm_cipher::Aes256GcmCipher;
|
||||
pub use finger::Finger;
|
||||
#[cfg(feature = "ring-cipher")]
|
||||
pub use ring_cipher::Aes256GcmCipher;
|
||||
pub use rsa_cipher::RsaCipher;
|
143
src/cipher/ring_cipher.rs
Normal file
143
src/cipher/ring_cipher.rs
Normal file
@@ -0,0 +1,143 @@
|
||||
use crate::cipher::Finger;
|
||||
use rand::RngCore;
|
||||
use ring::aead;
|
||||
use ring::aead::{LessSafeKey, UnboundKey};
|
||||
use std::io;
|
||||
|
||||
use crate::protocol::body::{SecretBody, ENCRYPTION_RESERVED};
|
||||
use crate::protocol::NetPacket;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Aes256GcmCipher {
|
||||
pub(crate) cipher: AesGcmEnum,
|
||||
pub(crate) finger: Finger,
|
||||
}
|
||||
|
||||
pub enum AesGcmEnum {
|
||||
AesGCM128(LessSafeKey, [u8; 16]),
|
||||
AesGCM256(LessSafeKey, [u8; 32]),
|
||||
}
|
||||
|
||||
impl Clone for AesGcmEnum {
|
||||
fn clone(&self) -> Self {
|
||||
match &self {
|
||||
AesGcmEnum::AesGCM128(_, key) => {
|
||||
let c =
|
||||
LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, key.as_slice()).unwrap());
|
||||
AesGcmEnum::AesGCM128(c, *key)
|
||||
}
|
||||
AesGcmEnum::AesGCM256(_, key) => {
|
||||
let c =
|
||||
LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, key.as_slice()).unwrap());
|
||||
AesGcmEnum::AesGCM256(c, *key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Aes256GcmCipher {
|
||||
pub fn new(key: [u8; 32], finger: Finger) -> Self {
|
||||
let cipher = LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, &key).unwrap());
|
||||
Self {
|
||||
cipher: AesGcmEnum::AesGCM256(cipher, key),
|
||||
finger,
|
||||
}
|
||||
}
|
||||
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||
&self,
|
||||
net_packet: &mut NetPacket<B>,
|
||||
) -> io::Result<()> {
|
||||
if !net_packet.is_encrypt() {
|
||||
//未加密的数据直接丢弃
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
||||
}
|
||||
if net_packet.payload().len() < ENCRYPTION_RESERVED {
|
||||
log::error!("数据异常,长度小于{}", ENCRYPTION_RESERVED);
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||
}
|
||||
let mut nonce_raw = [0; 12];
|
||||
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||
nonce_raw[8] = net_packet.protocol().into();
|
||||
nonce_raw[9] = net_packet.transport_protocol();
|
||||
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||
nonce_raw[11] = net_packet.source_ttl();
|
||||
let nonce = aead::Nonce::assume_unique_for_key(nonce_raw);
|
||||
let mut secret_body = SecretBody::new(net_packet.payload_mut())?;
|
||||
let tag = secret_body.tag();
|
||||
if tag.len() != 16 {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "tag err"));
|
||||
}
|
||||
let finger = self.finger.calculate_finger(&nonce_raw, &secret_body);
|
||||
if &finger != secret_body.finger() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
|
||||
}
|
||||
|
||||
let rs = match &self.cipher {
|
||||
AesGcmEnum::AesGCM128(cipher, _) => {
|
||||
cipher.open_in_place(nonce, aead::Aad::empty(), secret_body.en_body_mut())
|
||||
}
|
||||
AesGcmEnum::AesGCM256(cipher, _) => {
|
||||
cipher.open_in_place(nonce, aead::Aad::empty(), secret_body.en_body_mut())
|
||||
}
|
||||
};
|
||||
if let Err(e) = rs {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("解密失败:{}", e),
|
||||
));
|
||||
}
|
||||
net_packet.set_encrypt_flag(false);
|
||||
net_packet.set_data_len(net_packet.data_len() - ENCRYPTION_RESERVED)?;
|
||||
return Ok(());
|
||||
}
|
||||
/// net_packet 必须预留足够长度
|
||||
/// data_len是有效载荷的长度
|
||||
/// 返回加密后载荷的长度
|
||||
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||
&self,
|
||||
net_packet: &mut NetPacket<B>,
|
||||
) -> io::Result<()> {
|
||||
let mut nonce_raw = [0; 12];
|
||||
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||
nonce_raw[8] = net_packet.protocol().into();
|
||||
nonce_raw[9] = net_packet.transport_protocol();
|
||||
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||
nonce_raw[11] = net_packet.source_ttl();
|
||||
let nonce = aead::Nonce::assume_unique_for_key(nonce_raw);
|
||||
let data_len = net_packet.data_len() + ENCRYPTION_RESERVED;
|
||||
net_packet.set_data_len(data_len)?;
|
||||
let mut secret_body = SecretBody::new(net_packet.payload_mut())?;
|
||||
secret_body.set_random(rand::thread_rng().next_u32());
|
||||
|
||||
let rs = match &self.cipher {
|
||||
AesGcmEnum::AesGCM128(cipher, _) => {
|
||||
cipher.seal_in_place_separate_tag(nonce, aead::Aad::empty(), secret_body.body_mut())
|
||||
}
|
||||
AesGcmEnum::AesGCM256(cipher, _) => {
|
||||
cipher.seal_in_place_separate_tag(nonce, aead::Aad::empty(), secret_body.body_mut())
|
||||
}
|
||||
};
|
||||
return match rs {
|
||||
Ok(tag) => {
|
||||
let tag = tag.as_ref();
|
||||
if tag.len() != 16 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("加密tag长度错误:{}", tag.len()),
|
||||
));
|
||||
}
|
||||
secret_body.set_tag(tag)?;
|
||||
let finger = self.finger.calculate_finger(&nonce_raw, &secret_body);
|
||||
secret_body.set_finger(&finger)?;
|
||||
net_packet.set_encrypt_flag(true);
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("加密失败:{}", e),
|
||||
)),
|
||||
};
|
||||
}
|
||||
}
|
146
src/cipher/rsa_cipher.rs
Normal file
146
src/cipher/rsa_cipher.rs
Normal file
@@ -0,0 +1,146 @@
|
||||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::protocol::body::RsaSecretBody;
|
||||
use crate::protocol::NetPacket;
|
||||
use rsa::pkcs8::der::Decode;
|
||||
use rsa::pkcs8::{DecodePrivateKey, EncodePrivateKey, EncodePublicKey, LineEnding};
|
||||
use rsa::{RsaPrivateKey, RsaPublicKey};
|
||||
use sha2::Digest;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RsaCipher {
|
||||
inner: Arc<Inner>,
|
||||
}
|
||||
|
||||
struct Inner {
|
||||
private_key: RsaPrivateKey,
|
||||
public_key_der: Vec<u8>,
|
||||
}
|
||||
|
||||
impl RsaCipher {
|
||||
pub fn new() -> io::Result<Self> {
|
||||
let priv_key_path = PathBuf::from("key/private_key.pem");
|
||||
let private_key = if priv_key_path.exists() {
|
||||
let key = std::fs::read_to_string(priv_key_path)?;
|
||||
let private_key = match RsaPrivateKey::from_pkcs8_pem(&key) {
|
||||
Ok(private_key) => private_key,
|
||||
Err(e) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("'key/private_key.pem' content error {}", e),
|
||||
));
|
||||
}
|
||||
};
|
||||
private_key
|
||||
} else {
|
||||
let path = PathBuf::from("key");
|
||||
if !path.exists() {
|
||||
std::fs::create_dir(path)?;
|
||||
}
|
||||
let mut rng = rand::thread_rng();
|
||||
let bits = 2048;
|
||||
let private_key = match RsaPrivateKey::new(&mut rng, bits) {
|
||||
Ok(private_key) => private_key,
|
||||
Err(e) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("failed to generate a key {}", e),
|
||||
));
|
||||
}
|
||||
};
|
||||
match private_key.write_pkcs8_pem_file(priv_key_path, LineEnding::CRLF) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("failed to write to file 'key/private_key.pem' {}", e),
|
||||
));
|
||||
}
|
||||
};
|
||||
private_key
|
||||
};
|
||||
let public_key = RsaPublicKey::from(&private_key);
|
||||
match public_key.write_public_key_pem_file("key/public_key.pem", LineEnding::CRLF) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("failed to write to file 'key/public_key.pem' {}", e),
|
||||
));
|
||||
}
|
||||
};
|
||||
let public_key_der = match public_key.to_public_key_der() {
|
||||
Ok(public_key_der) => public_key_der.to_vec(),
|
||||
Err(e) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("to_public_key_der failed {}", e),
|
||||
));
|
||||
}
|
||||
};
|
||||
let inner = Inner {
|
||||
private_key,
|
||||
public_key_der,
|
||||
};
|
||||
Ok(Self {
|
||||
inner: Arc::new(inner),
|
||||
})
|
||||
}
|
||||
pub fn finger(&self) -> io::Result<String> {
|
||||
match rsa::pkcs8::SubjectPublicKeyInfo::from_der(&self.inner.public_key_der) {
|
||||
Ok(spki) => match spki.fingerprint_base64() {
|
||||
Ok(finger) => Ok(finger),
|
||||
Err(e) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("fingerprint_base64 error {}", e),
|
||||
)),
|
||||
},
|
||||
Err(e) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("from_der error {}", e),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn public_key(&self) -> &[u8] {
|
||||
&self.inner.public_key_der
|
||||
}
|
||||
}
|
||||
|
||||
impl RsaCipher {
|
||||
pub fn decrypt<B: AsRef<[u8]>>(
|
||||
&self,
|
||||
net_packet: &NetPacket<B>,
|
||||
) -> io::Result<RsaSecretBody<Vec<u8>>> {
|
||||
match self
|
||||
.inner
|
||||
.private_key
|
||||
.decrypt(rsa::PaddingScheme::PKCS1v15Encrypt, net_packet.payload())
|
||||
{
|
||||
Ok(rs) => {
|
||||
let mut nonce_raw = [0; 12];
|
||||
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||
nonce_raw[8] = net_packet.protocol().into();
|
||||
nonce_raw[9] = net_packet.transport_protocol();
|
||||
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||
nonce_raw[11] = net_packet.source_ttl();
|
||||
let secret_body = RsaSecretBody::new(rs)?;
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
hasher.update(secret_body.body());
|
||||
hasher.update(nonce_raw);
|
||||
let key: [u8; 32] = hasher.finalize().into();
|
||||
if secret_body.finger() != &key[16..] {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
|
||||
}
|
||||
Ok(secret_body)
|
||||
}
|
||||
Err(e) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("decrypt failed {}", e),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
108
src/main.rs
108
src/main.rs
@@ -4,14 +4,16 @@ use std::net::Ipv4Addr;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::cipher::RsaCipher;
|
||||
use crate::service::{start_tcp, start_udp};
|
||||
use clap::Parser;
|
||||
use tokio::net::{TcpListener, UdpSocket};
|
||||
use crate::service::{start_tcp, start_udp};
|
||||
|
||||
pub mod error;
|
||||
pub mod proto;
|
||||
pub mod protocol;
|
||||
pub mod service;
|
||||
mod cipher;
|
||||
mod error;
|
||||
mod proto;
|
||||
mod protocol;
|
||||
mod service;
|
||||
|
||||
/// 默认网关信息
|
||||
const GATEWAY: Ipv4Addr = Ipv4Addr::new(10, 26, 0, 1);
|
||||
@@ -52,7 +54,8 @@ fn log_init() {
|
||||
let log_config = log_path.join("log4rs.yaml");
|
||||
if !log_config.exists() {
|
||||
if let Ok(mut f) = std::fs::File::create(&log_config) {
|
||||
let _ = f.write_all(b"refresh_rate: 30 seconds
|
||||
let _ = f.write_all(
|
||||
b"refresh_rate: 30 seconds
|
||||
appenders:
|
||||
rolling_file:
|
||||
kind: rolling_file
|
||||
@@ -74,7 +77,8 @@ appenders:
|
||||
root:
|
||||
level: info
|
||||
appenders:
|
||||
- rolling_file");
|
||||
- rolling_file",
|
||||
);
|
||||
}
|
||||
}
|
||||
let _ = log4rs::init_file(log_config, Default::default());
|
||||
@@ -82,49 +86,76 @@ root:
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
log_init();
|
||||
let args = StartArgs::parse();
|
||||
let port = args.port.unwrap_or(29871);
|
||||
println!("端口:{}", port);
|
||||
let port = args.port.unwrap_or(29872);
|
||||
println!("端口: {}", port);
|
||||
let white_token = if let Some(white_token) = args.white_token {
|
||||
Some(HashSet::from_iter(white_token.into_iter()))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
println!("token白名单:{:?}", white_token);
|
||||
println!("token白名单: {:?}", white_token);
|
||||
let gateway = if let Some(gateway) = args.gateway {
|
||||
gateway.parse::<Ipv4Addr>().expect("网关错误,必须为有效的ipv4地址")
|
||||
match gateway.parse::<Ipv4Addr>() {
|
||||
Ok(ip) => ip,
|
||||
Err(e) => {
|
||||
log::error!("网关错误,必须为有效的ipv4地址 gateway={},e={}", gateway, e);
|
||||
panic!("网关错误,必须为有效的ipv4地址")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
GATEWAY
|
||||
};
|
||||
println!("网关:{:?}", gateway);
|
||||
println!("网关: {:?}", gateway);
|
||||
if gateway.is_unspecified() {
|
||||
println!("网关地址无效");
|
||||
log::error!("网关错误,必须为有效的ipv4地址 gateway={}", gateway);
|
||||
return;
|
||||
}
|
||||
if gateway.is_broadcast() {
|
||||
println!("网关错误,不能为广播地址");
|
||||
log::error!("网关错误,不能为广播地址 gateway={}", gateway);
|
||||
return;
|
||||
}
|
||||
if gateway.is_multicast() {
|
||||
println!("网关错误,不能为组播地址");
|
||||
log::error!("网关错误,不能为组播地址 gateway={}", gateway);
|
||||
return;
|
||||
}
|
||||
if !gateway.is_private() {
|
||||
println!("Warning 不是一个私有地址:{:?},将有可能和公网ip冲突", gateway);
|
||||
println!(
|
||||
"Warning 不是一个私有地址:{:?},将有可能和公网ip冲突",
|
||||
gateway
|
||||
);
|
||||
log::warn!("网关错误,不是一个私有地址 gateway={}", gateway);
|
||||
}
|
||||
let netmask = if let Some(netmask) = args.netmask {
|
||||
netmask.parse::<Ipv4Addr>().expect("子网掩码错误,必须为有效的ipv4地址")
|
||||
match netmask.parse::<Ipv4Addr>() {
|
||||
Ok(ip) => ip,
|
||||
Err(e) => {
|
||||
log::error!(
|
||||
"子网掩码错误,必须为有效的ipv4地址 netmask={},e={}",
|
||||
netmask,
|
||||
e
|
||||
);
|
||||
panic!("子网掩码错误,必须为有效的ipv4地址")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
NETMASK
|
||||
};
|
||||
println!("子网掩码:{:?}", netmask);
|
||||
if netmask.is_broadcast() || netmask.is_unspecified() || !(!u32::from_be_bytes(netmask.octets()) + 1).is_power_of_two() {
|
||||
println!("子网掩码: {:?}", netmask);
|
||||
if netmask.is_broadcast()
|
||||
|| netmask.is_unspecified()
|
||||
|| !(!u32::from_be_bytes(netmask.octets()) + 1).is_power_of_two()
|
||||
{
|
||||
println!("子网掩码错误");
|
||||
log::error!("子网掩码错误 netmask={}", netmask);
|
||||
return;
|
||||
}
|
||||
|
||||
let broadcast = (!u32::from_be_bytes(netmask.octets()))
|
||||
| u32::from_be_bytes(gateway.octets());
|
||||
let broadcast = (!u32::from_be_bytes(netmask.octets())) | u32::from_be_bytes(gateway.octets());
|
||||
let broadcast = Ipv4Addr::from(broadcast);
|
||||
let config = ConfigInfo {
|
||||
port,
|
||||
@@ -133,33 +164,38 @@ async fn main() {
|
||||
broadcast,
|
||||
netmask,
|
||||
};
|
||||
log_init();
|
||||
log::info!("config:{:?}",config);
|
||||
let rsa = match RsaCipher::new() {
|
||||
Ok(rsa) => {
|
||||
println!("密钥指纹: {}", rsa.finger().unwrap());
|
||||
Some(rsa)
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("获取密钥错误:{:?}", e);
|
||||
panic!("获取密钥错误:{}", e);
|
||||
}
|
||||
};
|
||||
log::info!("config:{:?}", config);
|
||||
let udp = match UdpSocket::bind(format!("0.0.0.0:{}", port)).await {
|
||||
Ok(udp) => { Arc::new(udp) }
|
||||
Ok(udp) => Arc::new(udp),
|
||||
Err(e) => {
|
||||
log::warn!("udp启动失败:{:?}",e);
|
||||
panic!("{:?}", e);
|
||||
log::warn!("udp启动失败:{:?}", e);
|
||||
panic!("udp启动失败:{}", e);
|
||||
}
|
||||
};
|
||||
log::info!("监听udp端口:{:?}",udp.local_addr().unwrap());
|
||||
println!("监听udp端口:{:?}", udp.local_addr().unwrap());
|
||||
log::info!("监听udp端口: {:?}", udp.local_addr().unwrap());
|
||||
println!("监听udp端口: {:?}", udp.local_addr().unwrap());
|
||||
let tcp = match TcpListener::bind(format!("0.0.0.0:{}", port)).await {
|
||||
Ok(tcp) => { tcp }
|
||||
Ok(tcp) => tcp,
|
||||
Err(e) => {
|
||||
log::warn!("tcp启动失败:{:?}",e);
|
||||
panic!("{:?}", e);
|
||||
log::warn!("tcp启动失败:{:?}", e);
|
||||
panic!("tcp启动失败:{:?}", e);
|
||||
}
|
||||
};
|
||||
log::info!("监听tcp端口:{:?}",tcp.local_addr().unwrap());
|
||||
println!("监听tcp端口:{:?}", tcp.local_addr().unwrap());
|
||||
log::info!("监听tcp端口: {:?}", tcp.local_addr().unwrap());
|
||||
println!("监听tcp端口: {:?}", tcp.local_addr().unwrap());
|
||||
let config = config.clone();
|
||||
let main_udp = udp.clone();
|
||||
let tcp_config = config.clone();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = start_tcp(tcp, main_udp, tcp_config).await {
|
||||
log::warn!("tcp任务结束:{:?}",e);
|
||||
}
|
||||
});
|
||||
start_udp(udp, config).await;
|
||||
tokio::spawn(start_tcp(tcp, main_udp, tcp_config, rsa.clone()));
|
||||
start_udp(udp, config, rsa.clone()).await;
|
||||
}
|
||||
|
@@ -25,6 +25,462 @@
|
||||
/// of protobuf runtime.
|
||||
const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_2_0;
|
||||
|
||||
#[derive(PartialEq,Clone,Default,Debug)]
|
||||
// @@protoc_insertion_point(message:HandshakeRequest)
|
||||
pub struct HandshakeRequest {
|
||||
// message fields
|
||||
// @@protoc_insertion_point(field:HandshakeRequest.version)
|
||||
pub version: ::std::string::String,
|
||||
// @@protoc_insertion_point(field:HandshakeRequest.secret)
|
||||
pub secret: bool,
|
||||
// special fields
|
||||
// @@protoc_insertion_point(special_field:HandshakeRequest.special_fields)
|
||||
pub special_fields: ::protobuf::SpecialFields,
|
||||
}
|
||||
|
||||
impl<'a> ::std::default::Default for &'a HandshakeRequest {
|
||||
fn default() -> &'a HandshakeRequest {
|
||||
<HandshakeRequest as ::protobuf::Message>::default_instance()
|
||||
}
|
||||
}
|
||||
|
||||
impl HandshakeRequest {
|
||||
pub fn new() -> HandshakeRequest {
|
||||
::std::default::Default::default()
|
||||
}
|
||||
|
||||
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
|
||||
let mut fields = ::std::vec::Vec::with_capacity(2);
|
||||
let mut oneofs = ::std::vec::Vec::with_capacity(0);
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"version",
|
||||
|m: &HandshakeRequest| { &m.version },
|
||||
|m: &mut HandshakeRequest| { &mut m.version },
|
||||
));
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"secret",
|
||||
|m: &HandshakeRequest| { &m.secret },
|
||||
|m: &mut HandshakeRequest| { &mut m.secret },
|
||||
));
|
||||
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<HandshakeRequest>(
|
||||
"HandshakeRequest",
|
||||
fields,
|
||||
oneofs,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Message for HandshakeRequest {
|
||||
const NAME: &'static str = "HandshakeRequest";
|
||||
|
||||
fn is_initialized(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
|
||||
while let Some(tag) = is.read_raw_tag_or_eof()? {
|
||||
match tag {
|
||||
10 => {
|
||||
self.version = is.read_string()?;
|
||||
},
|
||||
16 => {
|
||||
self.secret = is.read_bool()?;
|
||||
},
|
||||
tag => {
|
||||
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
|
||||
},
|
||||
};
|
||||
}
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
// Compute sizes of nested messages
|
||||
#[allow(unused_variables)]
|
||||
fn compute_size(&self) -> u64 {
|
||||
let mut my_size = 0;
|
||||
if !self.version.is_empty() {
|
||||
my_size += ::protobuf::rt::string_size(1, &self.version);
|
||||
}
|
||||
if self.secret != false {
|
||||
my_size += 1 + 1;
|
||||
}
|
||||
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
|
||||
self.special_fields.cached_size().set(my_size as u32);
|
||||
my_size
|
||||
}
|
||||
|
||||
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
|
||||
if !self.version.is_empty() {
|
||||
os.write_string(1, &self.version)?;
|
||||
}
|
||||
if self.secret != false {
|
||||
os.write_bool(2, self.secret)?;
|
||||
}
|
||||
os.write_unknown_fields(self.special_fields.unknown_fields())?;
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
fn special_fields(&self) -> &::protobuf::SpecialFields {
|
||||
&self.special_fields
|
||||
}
|
||||
|
||||
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
|
||||
&mut self.special_fields
|
||||
}
|
||||
|
||||
fn new() -> HandshakeRequest {
|
||||
HandshakeRequest::new()
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
self.version.clear();
|
||||
self.secret = false;
|
||||
self.special_fields.clear();
|
||||
}
|
||||
|
||||
fn default_instance() -> &'static HandshakeRequest {
|
||||
static instance: HandshakeRequest = HandshakeRequest {
|
||||
version: ::std::string::String::new(),
|
||||
secret: false,
|
||||
special_fields: ::protobuf::SpecialFields::new(),
|
||||
};
|
||||
&instance
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::MessageFull for HandshakeRequest {
|
||||
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
|
||||
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
|
||||
descriptor.get(|| file_descriptor().message_by_package_relative_name("HandshakeRequest").unwrap()).clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for HandshakeRequest {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||
::protobuf::text_format::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::reflect::ProtobufValue for HandshakeRequest {
|
||||
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
|
||||
}
|
||||
|
||||
#[derive(PartialEq,Clone,Default,Debug)]
|
||||
// @@protoc_insertion_point(message:HandshakeResponse)
|
||||
pub struct HandshakeResponse {
|
||||
// message fields
|
||||
// @@protoc_insertion_point(field:HandshakeResponse.version)
|
||||
pub version: ::std::string::String,
|
||||
// @@protoc_insertion_point(field:HandshakeResponse.secret)
|
||||
pub secret: bool,
|
||||
// @@protoc_insertion_point(field:HandshakeResponse.public_key)
|
||||
pub public_key: ::std::vec::Vec<u8>,
|
||||
// @@protoc_insertion_point(field:HandshakeResponse.key_finger)
|
||||
pub key_finger: ::std::string::String,
|
||||
// special fields
|
||||
// @@protoc_insertion_point(special_field:HandshakeResponse.special_fields)
|
||||
pub special_fields: ::protobuf::SpecialFields,
|
||||
}
|
||||
|
||||
impl<'a> ::std::default::Default for &'a HandshakeResponse {
|
||||
fn default() -> &'a HandshakeResponse {
|
||||
<HandshakeResponse as ::protobuf::Message>::default_instance()
|
||||
}
|
||||
}
|
||||
|
||||
impl HandshakeResponse {
|
||||
pub fn new() -> HandshakeResponse {
|
||||
::std::default::Default::default()
|
||||
}
|
||||
|
||||
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
|
||||
let mut fields = ::std::vec::Vec::with_capacity(4);
|
||||
let mut oneofs = ::std::vec::Vec::with_capacity(0);
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"version",
|
||||
|m: &HandshakeResponse| { &m.version },
|
||||
|m: &mut HandshakeResponse| { &mut m.version },
|
||||
));
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"secret",
|
||||
|m: &HandshakeResponse| { &m.secret },
|
||||
|m: &mut HandshakeResponse| { &mut m.secret },
|
||||
));
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"public_key",
|
||||
|m: &HandshakeResponse| { &m.public_key },
|
||||
|m: &mut HandshakeResponse| { &mut m.public_key },
|
||||
));
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"key_finger",
|
||||
|m: &HandshakeResponse| { &m.key_finger },
|
||||
|m: &mut HandshakeResponse| { &mut m.key_finger },
|
||||
));
|
||||
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<HandshakeResponse>(
|
||||
"HandshakeResponse",
|
||||
fields,
|
||||
oneofs,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Message for HandshakeResponse {
|
||||
const NAME: &'static str = "HandshakeResponse";
|
||||
|
||||
fn is_initialized(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
|
||||
while let Some(tag) = is.read_raw_tag_or_eof()? {
|
||||
match tag {
|
||||
10 => {
|
||||
self.version = is.read_string()?;
|
||||
},
|
||||
16 => {
|
||||
self.secret = is.read_bool()?;
|
||||
},
|
||||
26 => {
|
||||
self.public_key = is.read_bytes()?;
|
||||
},
|
||||
34 => {
|
||||
self.key_finger = is.read_string()?;
|
||||
},
|
||||
tag => {
|
||||
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
|
||||
},
|
||||
};
|
||||
}
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
// Compute sizes of nested messages
|
||||
#[allow(unused_variables)]
|
||||
fn compute_size(&self) -> u64 {
|
||||
let mut my_size = 0;
|
||||
if !self.version.is_empty() {
|
||||
my_size += ::protobuf::rt::string_size(1, &self.version);
|
||||
}
|
||||
if self.secret != false {
|
||||
my_size += 1 + 1;
|
||||
}
|
||||
if !self.public_key.is_empty() {
|
||||
my_size += ::protobuf::rt::bytes_size(3, &self.public_key);
|
||||
}
|
||||
if !self.key_finger.is_empty() {
|
||||
my_size += ::protobuf::rt::string_size(4, &self.key_finger);
|
||||
}
|
||||
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
|
||||
self.special_fields.cached_size().set(my_size as u32);
|
||||
my_size
|
||||
}
|
||||
|
||||
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
|
||||
if !self.version.is_empty() {
|
||||
os.write_string(1, &self.version)?;
|
||||
}
|
||||
if self.secret != false {
|
||||
os.write_bool(2, self.secret)?;
|
||||
}
|
||||
if !self.public_key.is_empty() {
|
||||
os.write_bytes(3, &self.public_key)?;
|
||||
}
|
||||
if !self.key_finger.is_empty() {
|
||||
os.write_string(4, &self.key_finger)?;
|
||||
}
|
||||
os.write_unknown_fields(self.special_fields.unknown_fields())?;
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
fn special_fields(&self) -> &::protobuf::SpecialFields {
|
||||
&self.special_fields
|
||||
}
|
||||
|
||||
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
|
||||
&mut self.special_fields
|
||||
}
|
||||
|
||||
fn new() -> HandshakeResponse {
|
||||
HandshakeResponse::new()
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
self.version.clear();
|
||||
self.secret = false;
|
||||
self.public_key.clear();
|
||||
self.key_finger.clear();
|
||||
self.special_fields.clear();
|
||||
}
|
||||
|
||||
fn default_instance() -> &'static HandshakeResponse {
|
||||
static instance: HandshakeResponse = HandshakeResponse {
|
||||
version: ::std::string::String::new(),
|
||||
secret: false,
|
||||
public_key: ::std::vec::Vec::new(),
|
||||
key_finger: ::std::string::String::new(),
|
||||
special_fields: ::protobuf::SpecialFields::new(),
|
||||
};
|
||||
&instance
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::MessageFull for HandshakeResponse {
|
||||
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
|
||||
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
|
||||
descriptor.get(|| file_descriptor().message_by_package_relative_name("HandshakeResponse").unwrap()).clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for HandshakeResponse {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||
::protobuf::text_format::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::reflect::ProtobufValue for HandshakeResponse {
|
||||
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
|
||||
}
|
||||
|
||||
#[derive(PartialEq,Clone,Default,Debug)]
|
||||
// @@protoc_insertion_point(message:SecretHandshakeRequest)
|
||||
pub struct SecretHandshakeRequest {
|
||||
// message fields
|
||||
// @@protoc_insertion_point(field:SecretHandshakeRequest.token)
|
||||
pub token: ::std::string::String,
|
||||
// @@protoc_insertion_point(field:SecretHandshakeRequest.key)
|
||||
pub key: ::std::vec::Vec<u8>,
|
||||
// special fields
|
||||
// @@protoc_insertion_point(special_field:SecretHandshakeRequest.special_fields)
|
||||
pub special_fields: ::protobuf::SpecialFields,
|
||||
}
|
||||
|
||||
impl<'a> ::std::default::Default for &'a SecretHandshakeRequest {
|
||||
fn default() -> &'a SecretHandshakeRequest {
|
||||
<SecretHandshakeRequest as ::protobuf::Message>::default_instance()
|
||||
}
|
||||
}
|
||||
|
||||
impl SecretHandshakeRequest {
|
||||
pub fn new() -> SecretHandshakeRequest {
|
||||
::std::default::Default::default()
|
||||
}
|
||||
|
||||
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
|
||||
let mut fields = ::std::vec::Vec::with_capacity(2);
|
||||
let mut oneofs = ::std::vec::Vec::with_capacity(0);
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"token",
|
||||
|m: &SecretHandshakeRequest| { &m.token },
|
||||
|m: &mut SecretHandshakeRequest| { &mut m.token },
|
||||
));
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"key",
|
||||
|m: &SecretHandshakeRequest| { &m.key },
|
||||
|m: &mut SecretHandshakeRequest| { &mut m.key },
|
||||
));
|
||||
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<SecretHandshakeRequest>(
|
||||
"SecretHandshakeRequest",
|
||||
fields,
|
||||
oneofs,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Message for SecretHandshakeRequest {
|
||||
const NAME: &'static str = "SecretHandshakeRequest";
|
||||
|
||||
fn is_initialized(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
|
||||
while let Some(tag) = is.read_raw_tag_or_eof()? {
|
||||
match tag {
|
||||
10 => {
|
||||
self.token = is.read_string()?;
|
||||
},
|
||||
18 => {
|
||||
self.key = is.read_bytes()?;
|
||||
},
|
||||
tag => {
|
||||
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
|
||||
},
|
||||
};
|
||||
}
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
// Compute sizes of nested messages
|
||||
#[allow(unused_variables)]
|
||||
fn compute_size(&self) -> u64 {
|
||||
let mut my_size = 0;
|
||||
if !self.token.is_empty() {
|
||||
my_size += ::protobuf::rt::string_size(1, &self.token);
|
||||
}
|
||||
if !self.key.is_empty() {
|
||||
my_size += ::protobuf::rt::bytes_size(2, &self.key);
|
||||
}
|
||||
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
|
||||
self.special_fields.cached_size().set(my_size as u32);
|
||||
my_size
|
||||
}
|
||||
|
||||
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
|
||||
if !self.token.is_empty() {
|
||||
os.write_string(1, &self.token)?;
|
||||
}
|
||||
if !self.key.is_empty() {
|
||||
os.write_bytes(2, &self.key)?;
|
||||
}
|
||||
os.write_unknown_fields(self.special_fields.unknown_fields())?;
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
fn special_fields(&self) -> &::protobuf::SpecialFields {
|
||||
&self.special_fields
|
||||
}
|
||||
|
||||
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
|
||||
&mut self.special_fields
|
||||
}
|
||||
|
||||
fn new() -> SecretHandshakeRequest {
|
||||
SecretHandshakeRequest::new()
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
self.token.clear();
|
||||
self.key.clear();
|
||||
self.special_fields.clear();
|
||||
}
|
||||
|
||||
fn default_instance() -> &'static SecretHandshakeRequest {
|
||||
static instance: SecretHandshakeRequest = SecretHandshakeRequest {
|
||||
token: ::std::string::String::new(),
|
||||
key: ::std::vec::Vec::new(),
|
||||
special_fields: ::protobuf::SpecialFields::new(),
|
||||
};
|
||||
&instance
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::MessageFull for SecretHandshakeRequest {
|
||||
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
|
||||
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
|
||||
descriptor.get(|| file_descriptor().message_by_package_relative_name("SecretHandshakeRequest").unwrap()).clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for SecretHandshakeRequest {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||
::protobuf::text_format::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::reflect::ProtobufValue for SecretHandshakeRequest {
|
||||
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
|
||||
}
|
||||
|
||||
#[derive(PartialEq,Clone,Default,Debug)]
|
||||
// @@protoc_insertion_point(message:RegistrationRequest)
|
||||
pub struct RegistrationRequest {
|
||||
@@ -43,6 +499,8 @@ pub struct RegistrationRequest {
|
||||
pub virtual_ip: u32,
|
||||
// @@protoc_insertion_point(field:RegistrationRequest.allow_ip_change)
|
||||
pub allow_ip_change: bool,
|
||||
// @@protoc_insertion_point(field:RegistrationRequest.client_secret)
|
||||
pub client_secret: bool,
|
||||
// special fields
|
||||
// @@protoc_insertion_point(special_field:RegistrationRequest.special_fields)
|
||||
pub special_fields: ::protobuf::SpecialFields,
|
||||
@@ -60,7 +518,7 @@ impl RegistrationRequest {
|
||||
}
|
||||
|
||||
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
|
||||
let mut fields = ::std::vec::Vec::with_capacity(7);
|
||||
let mut fields = ::std::vec::Vec::with_capacity(8);
|
||||
let mut oneofs = ::std::vec::Vec::with_capacity(0);
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"token",
|
||||
@@ -97,6 +555,11 @@ impl RegistrationRequest {
|
||||
|m: &RegistrationRequest| { &m.allow_ip_change },
|
||||
|m: &mut RegistrationRequest| { &mut m.allow_ip_change },
|
||||
));
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"client_secret",
|
||||
|m: &RegistrationRequest| { &m.client_secret },
|
||||
|m: &mut RegistrationRequest| { &mut m.client_secret },
|
||||
));
|
||||
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<RegistrationRequest>(
|
||||
"RegistrationRequest",
|
||||
fields,
|
||||
@@ -136,6 +599,9 @@ impl ::protobuf::Message for RegistrationRequest {
|
||||
56 => {
|
||||
self.allow_ip_change = is.read_bool()?;
|
||||
},
|
||||
64 => {
|
||||
self.client_secret = is.read_bool()?;
|
||||
},
|
||||
tag => {
|
||||
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
|
||||
},
|
||||
@@ -169,6 +635,9 @@ impl ::protobuf::Message for RegistrationRequest {
|
||||
if self.allow_ip_change != false {
|
||||
my_size += 1 + 1;
|
||||
}
|
||||
if self.client_secret != false {
|
||||
my_size += 1 + 1;
|
||||
}
|
||||
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
|
||||
self.special_fields.cached_size().set(my_size as u32);
|
||||
my_size
|
||||
@@ -196,6 +665,9 @@ impl ::protobuf::Message for RegistrationRequest {
|
||||
if self.allow_ip_change != false {
|
||||
os.write_bool(7, self.allow_ip_change)?;
|
||||
}
|
||||
if self.client_secret != false {
|
||||
os.write_bool(8, self.client_secret)?;
|
||||
}
|
||||
os.write_unknown_fields(self.special_fields.unknown_fields())?;
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
@@ -220,6 +692,7 @@ impl ::protobuf::Message for RegistrationRequest {
|
||||
self.version.clear();
|
||||
self.virtual_ip = 0;
|
||||
self.allow_ip_change = false;
|
||||
self.client_secret = false;
|
||||
self.special_fields.clear();
|
||||
}
|
||||
|
||||
@@ -232,6 +705,7 @@ impl ::protobuf::Message for RegistrationRequest {
|
||||
version: ::std::string::String::new(),
|
||||
virtual_ip: 0,
|
||||
allow_ip_change: false,
|
||||
client_secret: false,
|
||||
special_fields: ::protobuf::SpecialFields::new(),
|
||||
};
|
||||
&instance
|
||||
@@ -514,6 +988,8 @@ pub struct DeviceInfo {
|
||||
pub virtual_ip: u32,
|
||||
// @@protoc_insertion_point(field:DeviceInfo.device_status)
|
||||
pub device_status: u32,
|
||||
// @@protoc_insertion_point(field:DeviceInfo.client_secret)
|
||||
pub client_secret: bool,
|
||||
// special fields
|
||||
// @@protoc_insertion_point(special_field:DeviceInfo.special_fields)
|
||||
pub special_fields: ::protobuf::SpecialFields,
|
||||
@@ -531,7 +1007,7 @@ impl DeviceInfo {
|
||||
}
|
||||
|
||||
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
|
||||
let mut fields = ::std::vec::Vec::with_capacity(3);
|
||||
let mut fields = ::std::vec::Vec::with_capacity(4);
|
||||
let mut oneofs = ::std::vec::Vec::with_capacity(0);
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"name",
|
||||
@@ -548,6 +1024,11 @@ impl DeviceInfo {
|
||||
|m: &DeviceInfo| { &m.device_status },
|
||||
|m: &mut DeviceInfo| { &mut m.device_status },
|
||||
));
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"client_secret",
|
||||
|m: &DeviceInfo| { &m.client_secret },
|
||||
|m: &mut DeviceInfo| { &mut m.client_secret },
|
||||
));
|
||||
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<DeviceInfo>(
|
||||
"DeviceInfo",
|
||||
fields,
|
||||
@@ -575,6 +1056,9 @@ impl ::protobuf::Message for DeviceInfo {
|
||||
24 => {
|
||||
self.device_status = is.read_uint32()?;
|
||||
},
|
||||
32 => {
|
||||
self.client_secret = is.read_bool()?;
|
||||
},
|
||||
tag => {
|
||||
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
|
||||
},
|
||||
@@ -596,6 +1080,9 @@ impl ::protobuf::Message for DeviceInfo {
|
||||
if self.device_status != 0 {
|
||||
my_size += ::protobuf::rt::uint32_size(3, self.device_status);
|
||||
}
|
||||
if self.client_secret != false {
|
||||
my_size += 1 + 1;
|
||||
}
|
||||
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
|
||||
self.special_fields.cached_size().set(my_size as u32);
|
||||
my_size
|
||||
@@ -611,6 +1098,9 @@ impl ::protobuf::Message for DeviceInfo {
|
||||
if self.device_status != 0 {
|
||||
os.write_uint32(3, self.device_status)?;
|
||||
}
|
||||
if self.client_secret != false {
|
||||
os.write_bool(4, self.client_secret)?;
|
||||
}
|
||||
os.write_unknown_fields(self.special_fields.unknown_fields())?;
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
@@ -631,6 +1121,7 @@ impl ::protobuf::Message for DeviceInfo {
|
||||
self.name.clear();
|
||||
self.virtual_ip = 0;
|
||||
self.device_status = 0;
|
||||
self.client_secret = false;
|
||||
self.special_fields.clear();
|
||||
}
|
||||
|
||||
@@ -639,6 +1130,7 @@ impl ::protobuf::Message for DeviceInfo {
|
||||
name: ::std::string::String::new(),
|
||||
virtual_ip: 0,
|
||||
device_status: 0,
|
||||
client_secret: false,
|
||||
special_fields: ::protobuf::SpecialFields::new(),
|
||||
};
|
||||
&instance
|
||||
@@ -1107,33 +1599,41 @@ impl PunchNatType {
|
||||
}
|
||||
|
||||
static file_descriptor_proto_data: &'static [u8] = b"\
|
||||
\n\rmessage.proto\"\xd6\x01\n\x13RegistrationRequest\x12\x14\n\x05token\
|
||||
\x18\x01\x20\x01(\tR\x05token\x12\x1b\n\tdevice_id\x18\x02\x20\x01(\tR\
|
||||
\x08deviceId\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x17\n\x07\
|
||||
is_fast\x18\x04\x20\x01(\x08R\x06isFast\x12\x18\n\x07version\x18\x05\x20\
|
||||
\x01(\tR\x07version\x12\x1d\n\nvirtual_ip\x18\x06\x20\x01(\x07R\tvirtual\
|
||||
Ip\x12&\n\x0fallow_ip_change\x18\x07\x20\x01(\x08R\rallowIpChange\"\xb3\
|
||||
\x02\n\x14RegistrationResponse\x12\x1d\n\nvirtual_ip\x18\x01\x20\x01(\
|
||||
\x07R\tvirtualIp\x12'\n\x0fvirtual_gateway\x18\x02\x20\x01(\x07R\x0evirt\
|
||||
ualGateway\x12'\n\x0fvirtual_netmask\x18\x03\x20\x01(\x07R\x0evirtualNet\
|
||||
mask\x12\x14\n\x05epoch\x18\x04\x20\x01(\rR\x05epoch\x125\n\x10device_in\
|
||||
fo_list\x18\x05\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\x12\x1b\
|
||||
\n\tpublic_ip\x18\x06\x20\x01(\x07R\x08publicIp\x12\x1f\n\x0bpublic_port\
|
||||
\x18\x07\x20\x01(\rR\npublicPort\x12\x1f\n\x0bpublic_ipv6\x18\x08\x20\
|
||||
\x01(\x0cR\npublicIpv6\"d\n\nDeviceInfo\x12\x12\n\x04name\x18\x01\x20\
|
||||
\x01(\tR\x04name\x12\x1d\n\nvirtual_ip\x18\x02\x20\x01(\x07R\tvirtualIp\
|
||||
\x12#\n\rdevice_status\x18\x03\x20\x01(\rR\x0cdeviceStatus\"Y\n\nDeviceL\
|
||||
ist\x12\x14\n\x05epoch\x18\x01\x20\x01(\rR\x05epoch\x125\n\x10device_inf\
|
||||
o_list\x18\x02\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\"\xa2\x02\
|
||||
\n\tPunchInfo\x12$\n\x0epublic_ip_list\x18\x02\x20\x03(\x07R\x0cpublicIp\
|
||||
List\x12\x1f\n\x0bpublic_port\x18\x03\x20\x01(\rR\npublicPort\x12*\n\x11\
|
||||
public_port_range\x18\x04\x20\x01(\rR\x0fpublicPortRange\x12(\n\x08nat_t\
|
||||
ype\x18\x05\x20\x01(\x0e2\r.PunchNatTypeR\x07natType\x12\x14\n\x05reply\
|
||||
\x18\x06\x20\x01(\x08R\x05reply\x12\x19\n\x08local_ip\x18\x07\x20\x01(\
|
||||
\x07R\x07localIp\x12\x1d\n\nlocal_port\x18\x08\x20\x01(\rR\tlocalPort\
|
||||
\x12(\n\x10public_ipv6_list\x18\t\x20\x03(\x0cR\x0epublicIpv6List*'\n\
|
||||
\x0cPunchNatType\x12\r\n\tSymmetric\x10\0\x12\x08\n\x04Cone\x10\x01b\x06\
|
||||
proto3\
|
||||
\n\rmessage.proto\"D\n\x10HandshakeRequest\x12\x18\n\x07version\x18\x01\
|
||||
\x20\x01(\tR\x07version\x12\x16\n\x06secret\x18\x02\x20\x01(\x08R\x06sec\
|
||||
ret\"\x83\x01\n\x11HandshakeResponse\x12\x18\n\x07version\x18\x01\x20\
|
||||
\x01(\tR\x07version\x12\x16\n\x06secret\x18\x02\x20\x01(\x08R\x06secret\
|
||||
\x12\x1d\n\npublic_key\x18\x03\x20\x01(\x0cR\tpublicKey\x12\x1d\n\nkey_f\
|
||||
inger\x18\x04\x20\x01(\tR\tkeyFinger\"@\n\x16SecretHandshakeRequest\x12\
|
||||
\x14\n\x05token\x18\x01\x20\x01(\tR\x05token\x12\x10\n\x03key\x18\x02\
|
||||
\x20\x01(\x0cR\x03key\"\xfb\x01\n\x13RegistrationRequest\x12\x14\n\x05to\
|
||||
ken\x18\x01\x20\x01(\tR\x05token\x12\x1b\n\tdevice_id\x18\x02\x20\x01(\t\
|
||||
R\x08deviceId\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x17\n\
|
||||
\x07is_fast\x18\x04\x20\x01(\x08R\x06isFast\x12\x18\n\x07version\x18\x05\
|
||||
\x20\x01(\tR\x07version\x12\x1d\n\nvirtual_ip\x18\x06\x20\x01(\x07R\tvir\
|
||||
tualIp\x12&\n\x0fallow_ip_change\x18\x07\x20\x01(\x08R\rallowIpChange\
|
||||
\x12#\n\rclient_secret\x18\x08\x20\x01(\x08R\x0cclientSecret\"\xb3\x02\n\
|
||||
\x14RegistrationResponse\x12\x1d\n\nvirtual_ip\x18\x01\x20\x01(\x07R\tvi\
|
||||
rtualIp\x12'\n\x0fvirtual_gateway\x18\x02\x20\x01(\x07R\x0evirtualGatewa\
|
||||
y\x12'\n\x0fvirtual_netmask\x18\x03\x20\x01(\x07R\x0evirtualNetmask\x12\
|
||||
\x14\n\x05epoch\x18\x04\x20\x01(\rR\x05epoch\x125\n\x10device_info_list\
|
||||
\x18\x05\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\x12\x1b\n\tpubl\
|
||||
ic_ip\x18\x06\x20\x01(\x07R\x08publicIp\x12\x1f\n\x0bpublic_port\x18\x07\
|
||||
\x20\x01(\rR\npublicPort\x12\x1f\n\x0bpublic_ipv6\x18\x08\x20\x01(\x0cR\
|
||||
\npublicIpv6\"\x89\x01\n\nDeviceInfo\x12\x12\n\x04name\x18\x01\x20\x01(\
|
||||
\tR\x04name\x12\x1d\n\nvirtual_ip\x18\x02\x20\x01(\x07R\tvirtualIp\x12#\
|
||||
\n\rdevice_status\x18\x03\x20\x01(\rR\x0cdeviceStatus\x12#\n\rclient_sec\
|
||||
ret\x18\x04\x20\x01(\x08R\x0cclientSecret\"Y\n\nDeviceList\x12\x14\n\x05\
|
||||
epoch\x18\x01\x20\x01(\rR\x05epoch\x125\n\x10device_info_list\x18\x02\
|
||||
\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\"\xa2\x02\n\tPunchInfo\
|
||||
\x12$\n\x0epublic_ip_list\x18\x02\x20\x03(\x07R\x0cpublicIpList\x12\x1f\
|
||||
\n\x0bpublic_port\x18\x03\x20\x01(\rR\npublicPort\x12*\n\x11public_port_\
|
||||
range\x18\x04\x20\x01(\rR\x0fpublicPortRange\x12(\n\x08nat_type\x18\x05\
|
||||
\x20\x01(\x0e2\r.PunchNatTypeR\x07natType\x12\x14\n\x05reply\x18\x06\x20\
|
||||
\x01(\x08R\x05reply\x12\x19\n\x08local_ip\x18\x07\x20\x01(\x07R\x07local\
|
||||
Ip\x12\x1d\n\nlocal_port\x18\x08\x20\x01(\rR\tlocalPort\x12(\n\x10public\
|
||||
_ipv6_list\x18\t\x20\x03(\x0cR\x0epublicIpv6List*'\n\x0cPunchNatType\x12\
|
||||
\r\n\tSymmetric\x10\0\x12\x08\n\x04Cone\x10\x01b\x06proto3\
|
||||
";
|
||||
|
||||
/// `FileDescriptorProto` object which was a source for this generated file
|
||||
@@ -1151,7 +1651,10 @@ pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor {
|
||||
file_descriptor.get(|| {
|
||||
let generated_file_descriptor = generated_file_descriptor_lazy.get(|| {
|
||||
let mut deps = ::std::vec::Vec::with_capacity(0);
|
||||
let mut messages = ::std::vec::Vec::with_capacity(5);
|
||||
let mut messages = ::std::vec::Vec::with_capacity(8);
|
||||
messages.push(HandshakeRequest::generated_message_descriptor_data());
|
||||
messages.push(HandshakeResponse::generated_message_descriptor_data());
|
||||
messages.push(SecretHandshakeRequest::generated_message_descriptor_data());
|
||||
messages.push(RegistrationRequest::generated_message_descriptor_data());
|
||||
messages.push(RegistrationResponse::generated_message_descriptor_data());
|
||||
messages.push(DeviceInfo::generated_message_descriptor_data());
|
||||
|
205
src/protocol/body.rs
Normal file
205
src/protocol/body.rs
Normal file
@@ -0,0 +1,205 @@
|
||||
use std::{fmt, io};
|
||||
|
||||
pub const ENCRYPTION_RESERVED: usize = 32;
|
||||
/* aes_gcm加密数据体
|
||||
0 15 31
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 数据体 |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| random(32) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| tag(32) |
|
||||
| tag(32) |
|
||||
| tag(32) |
|
||||
| tag(32) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| finger(32) |
|
||||
| finger(32) |
|
||||
| finger(32) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
注:finger用于快速校验数据是否被修改,上层可使用token、协议头参与计算finger,
|
||||
确保服务端和客户端都能感知修改(服务端不能解密也能校验指纹)
|
||||
*/
|
||||
pub struct SecretBody<B> {
|
||||
buffer: B,
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> SecretBody<B> {
|
||||
pub fn new(buffer: B) -> io::Result<SecretBody<B>> {
|
||||
let len = buffer.as_ref().len();
|
||||
// 不能大于udp最大载荷长度
|
||||
if len < 32 || len > 65535 - 20 - 8 - 12 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"length overflow",
|
||||
));
|
||||
}
|
||||
Ok(SecretBody { buffer })
|
||||
}
|
||||
pub fn data(&self) -> &[u8] {
|
||||
let end = self.buffer.as_ref().len() - 32;
|
||||
&self.buffer.as_ref()[..end]
|
||||
}
|
||||
pub fn random(&self) -> u32 {
|
||||
let end = self.buffer.as_ref().len() - 16 - 12;
|
||||
u32::from_be_bytes(self.buffer.as_ref()[end - 4..end].try_into().unwrap())
|
||||
}
|
||||
pub fn body(&self) -> &[u8] {
|
||||
let end = self.buffer.as_ref().len() - 16 - 12;
|
||||
&self.buffer.as_ref()[..end]
|
||||
}
|
||||
pub fn tag(&self) -> &[u8] {
|
||||
let end = self.buffer.as_ref().len() - 12;
|
||||
&self.buffer.as_ref()[end - 16..end]
|
||||
}
|
||||
pub fn finger(&self) -> &[u8] {
|
||||
let end = self.buffer.as_ref().len();
|
||||
&self.buffer.as_ref()[end - 12..end]
|
||||
}
|
||||
pub fn buffer(&self) -> &[u8] {
|
||||
self.buffer.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]> + AsMut<[u8]>> SecretBody<B> {
|
||||
pub fn set_data(&mut self, data: &[u8]) -> io::Result<()> {
|
||||
let end = self.buffer.as_ref().len() - 32;
|
||||
if end - 4 != data.len() {
|
||||
return Err(io::Error::new(io::ErrorKind::InvalidData, "end-4 != data.len"));
|
||||
}
|
||||
self.buffer.as_mut()[..end].copy_from_slice(data);
|
||||
Ok(())
|
||||
}
|
||||
pub fn set_random(&mut self, random: u32) {
|
||||
let end = self.buffer.as_ref().len() - 16 - 12;
|
||||
self.buffer.as_mut()[end - 4..end].copy_from_slice(&random.to_be_bytes());
|
||||
}
|
||||
|
||||
pub fn set_tag(&mut self, tag: &[u8]) -> io::Result<()> {
|
||||
if tag.len() != 16 {
|
||||
return Err(io::Error::new(io::ErrorKind::InvalidData, "tag.len != 16"));
|
||||
}
|
||||
let end = self.buffer.as_ref().len() - 12;
|
||||
self.buffer.as_mut()[end - 16..end].copy_from_slice(tag);
|
||||
Ok(())
|
||||
}
|
||||
pub fn set_finger(&mut self, finger: &[u8]) -> io::Result<()> {
|
||||
if finger.len() != 12 {
|
||||
return Err(io::Error::new(io::ErrorKind::InvalidData, "finger.len != 12"));
|
||||
}
|
||||
let end = self.buffer.as_ref().len();
|
||||
self.buffer.as_mut()[end - 12..end].copy_from_slice(finger);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn data_mut(&mut self) -> &mut [u8] {
|
||||
let end = self.buffer.as_ref().len() - 32;
|
||||
&mut self.buffer.as_mut()[..end]
|
||||
}
|
||||
/// 数据部分
|
||||
pub fn body_mut(&mut self) -> &mut [u8] {
|
||||
let end = self.buffer.as_ref().len() - 12 - 16;
|
||||
&mut self.buffer.as_mut()[..end]
|
||||
}
|
||||
pub fn tag_mut(&mut self) -> &mut [u8] {
|
||||
let end = self.buffer.as_ref().len() - 12;
|
||||
&mut self.buffer.as_mut()[end - 16..end]
|
||||
}
|
||||
/// 数据部分+tag部分
|
||||
pub fn en_body_mut(&mut self) -> &mut [u8] {
|
||||
let end = self.buffer.as_ref().len() - 12;
|
||||
&mut self.buffer.as_mut()[..end]
|
||||
}
|
||||
pub fn buffer_mut(&mut self) -> &mut [u8] {
|
||||
self.buffer.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> fmt::Debug for SecretBody<B> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("SecretBody")
|
||||
.field("random", &self.random())
|
||||
.field("body", &self.body())
|
||||
.field("tag", &self.tag())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/* rsa加密数据体
|
||||
0 15 31
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 数据体(n) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| random(32) |
|
||||
| random(32) |
|
||||
| random(32) |
|
||||
| random(32) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| finger(32) |
|
||||
| finger(32) |
|
||||
| finger(32) |
|
||||
| finger(32) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
pub struct RsaSecretBody<B> {
|
||||
buffer: B,
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> RsaSecretBody<B> {
|
||||
pub fn new(buffer: B) -> io::Result<RsaSecretBody<B>> {
|
||||
let len = buffer.as_ref().len();
|
||||
// 不能大于udp最大载荷长度
|
||||
if len < 32 || len > 65535 - 20 - 8 - 12 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"length overflow",
|
||||
));
|
||||
}
|
||||
Ok(RsaSecretBody { buffer })
|
||||
}
|
||||
pub fn data(&self) -> &[u8] {
|
||||
let end = self.buffer.as_ref().len() - 32;
|
||||
&self.buffer.as_ref()[..end]
|
||||
}
|
||||
pub fn random(&self) -> &[u8] {
|
||||
let end = self.buffer.as_ref().len() - 16;
|
||||
&self.buffer.as_ref()[end - 16..end]
|
||||
}
|
||||
pub fn body(&self) -> &[u8] {
|
||||
let end = self.buffer.as_ref().len() - 16;
|
||||
&self.buffer.as_ref()[..end]
|
||||
}
|
||||
pub fn finger(&self) -> &[u8] {
|
||||
let end = self.buffer.as_ref().len() - 16;
|
||||
&self.buffer.as_ref()[end..]
|
||||
}
|
||||
pub fn buffer(&self) -> &[u8] {
|
||||
&self.buffer.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]> + AsMut<[u8]>> RsaSecretBody<B> {
|
||||
pub fn set_random(&mut self, random: &[u8]) -> io::Result<()> {
|
||||
if random.len() != 16 {
|
||||
return Err(io::Error::new(io::ErrorKind::InvalidData, "random.len != 16"));
|
||||
}
|
||||
let end = self.buffer.as_ref().len() - 16;
|
||||
self.buffer.as_mut()[end - 16..end].copy_from_slice(random);
|
||||
Ok(())
|
||||
}
|
||||
pub fn random_mut(&mut self) -> &mut [u8] {
|
||||
let end = self.buffer.as_ref().len() - 16;
|
||||
&mut self.buffer.as_mut()[end - 16..end]
|
||||
}
|
||||
pub fn set_finger(&mut self, finger: &[u8]) -> io::Result<()> {
|
||||
if finger.len() != 16 {
|
||||
return Err(io::Error::new(io::ErrorKind::InvalidData, "finger.len != 16"));
|
||||
}
|
||||
let end = self.buffer.as_ref().len();
|
||||
self.buffer.as_mut()[end - 16..end].copy_from_slice(finger);
|
||||
Ok(())
|
||||
}
|
||||
}
|
@@ -7,6 +7,7 @@ pub enum Protocol {
|
||||
AddressExhausted,
|
||||
IpAlreadyExists,
|
||||
InvalidIp,
|
||||
NoKey,
|
||||
Other(u8),
|
||||
}
|
||||
|
||||
@@ -18,6 +19,7 @@ impl From<u8> for Protocol {
|
||||
3 => Self::AddressExhausted,
|
||||
4 => Self::IpAlreadyExists,
|
||||
5 => Self::InvalidIp,
|
||||
6 => Self::NoKey,
|
||||
val => Self::Other(val),
|
||||
}
|
||||
}
|
||||
@@ -31,6 +33,7 @@ impl Into<u8> for Protocol {
|
||||
Protocol::AddressExhausted => 3,
|
||||
Protocol::IpAlreadyExists => 4,
|
||||
Protocol::InvalidIp => 5,
|
||||
Protocol::NoKey => 6,
|
||||
Protocol::Other(val) => val,
|
||||
}
|
||||
}
|
||||
@@ -42,6 +45,7 @@ pub enum InErrorPacket<B> {
|
||||
AddressExhausted,
|
||||
IpAlreadyExists,
|
||||
InvalidIp,
|
||||
NoKey,
|
||||
OtherError(ErrorPacket<B>),
|
||||
}
|
||||
|
||||
@@ -53,6 +57,7 @@ impl<B: AsRef<[u8]>> InErrorPacket<B> {
|
||||
Protocol::AddressExhausted => Ok(InErrorPacket::AddressExhausted),
|
||||
Protocol::IpAlreadyExists => Ok(InErrorPacket::IpAlreadyExists),
|
||||
Protocol::InvalidIp => Ok(InErrorPacket::InvalidIp),
|
||||
Protocol::NoKey => Ok(InErrorPacket::NoKey),
|
||||
Protocol::Other(_) => Ok(InErrorPacket::OtherError(ErrorPacket::new(buffer)?)),
|
||||
}
|
||||
}
|
||||
|
@@ -3,8 +3,6 @@ use std::net::Ipv4Addr;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
pub enum Protocol {
|
||||
Icmp,
|
||||
Igmp,
|
||||
Ipv4,
|
||||
Ipv4Broadcast,
|
||||
Unknown(u8),
|
||||
@@ -13,8 +11,6 @@ pub enum Protocol {
|
||||
impl From<u8> for Protocol {
|
||||
fn from(value: u8) -> Self {
|
||||
match value {
|
||||
1 => Protocol::Icmp,
|
||||
2 => Protocol::Igmp,
|
||||
4 => Protocol::Ipv4,
|
||||
201 => Protocol::Ipv4Broadcast,
|
||||
val => Protocol::Unknown(val),
|
||||
@@ -25,8 +21,6 @@ impl From<u8> for Protocol {
|
||||
impl Into<u8> for Protocol {
|
||||
fn into(self) -> u8 {
|
||||
match self {
|
||||
Protocol::Icmp => 1,
|
||||
Protocol::Igmp => 2,
|
||||
Protocol::Ipv4 => 4,
|
||||
Protocol::Ipv4Broadcast => 201,
|
||||
Protocol::Unknown(val) => val,
|
||||
@@ -34,18 +28,18 @@ impl Into<u8> for Protocol {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BroadcastPacketEnd<B> {
|
||||
pub struct BroadcastPacket<B> {
|
||||
buffer: B,
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> BroadcastPacketEnd<B> {
|
||||
impl<B: AsRef<[u8]>> BroadcastPacket<B> {
|
||||
pub fn unchecked(buffer: B) -> Self {
|
||||
Self { buffer }
|
||||
}
|
||||
pub fn new(buffer: B) -> io::Result<Self> {
|
||||
let len = buffer.as_ref().len();
|
||||
let packet = Self::unchecked(buffer);
|
||||
if len < 1 || packet.len() != len {
|
||||
if len < 2 + 4 || packet.addr_num() == 0 {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"InvalidData",
|
||||
@@ -56,31 +50,36 @@ impl<B: AsRef<[u8]>> BroadcastPacketEnd<B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> BroadcastPacketEnd<B> {
|
||||
pub fn len(&self) -> usize {
|
||||
1 + self.num() as usize * 4
|
||||
}
|
||||
pub fn num(&self) -> u8 {
|
||||
let len = self.buffer.as_ref().len();
|
||||
self.buffer.as_ref()[len - 1]
|
||||
impl<B: AsRef<[u8]>> BroadcastPacket<B> {
|
||||
pub fn addr_num(&self) -> u8 {
|
||||
self.buffer.as_ref()[1]
|
||||
}
|
||||
/// 已经发送给了这些地址
|
||||
/// 从尾往头拿
|
||||
pub fn addresses(&self) -> Vec<Ipv4Addr> {
|
||||
let num = self.num() as usize;
|
||||
let num = self.addr_num() as usize;
|
||||
let mut list = Vec::with_capacity(num);
|
||||
let buf = self.buffer.as_ref();
|
||||
let mut offset = buf.len() + 4 - 2;
|
||||
let mut offset = 1;
|
||||
for _ in 0..num {
|
||||
offset -= 4;
|
||||
list.push(Ipv4Addr::new(buf[offset - 3], buf[offset - 2], buf[offset - 1], buf[offset]));
|
||||
list.push(Ipv4Addr::new(buf[offset], buf[offset + 1], buf[offset + 2], buf[offset + 3]));
|
||||
offset += 4;
|
||||
}
|
||||
list
|
||||
}
|
||||
pub fn data(&self) -> io::Result<&[u8]> {
|
||||
let start = 1 + self.addr_num() as usize * 4;
|
||||
if start > self.buffer.as_ref().len() {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"InvalidData",
|
||||
))
|
||||
} else {
|
||||
Ok(&self.buffer.as_ref()[start..])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]> + AsMut<[u8]>> BroadcastPacketEnd<B> {
|
||||
/// 从头往尾放
|
||||
impl<B: AsRef<[u8]> + AsMut<[u8]>> BroadcastPacket<B> {
|
||||
pub fn set_address(&mut self, addr: &[Ipv4Addr]) -> io::Result<()> {
|
||||
let buf = self.buffer.as_mut();
|
||||
if buf.len() < 1 + addr.len() * 4 || addr.len() > u8::MAX as usize {
|
||||
@@ -89,15 +88,28 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> BroadcastPacketEnd<B> {
|
||||
"InvalidData",
|
||||
))
|
||||
} else {
|
||||
let mut offset = 0;
|
||||
buf[0] = addr.len() as u8;
|
||||
let mut offset = 1;
|
||||
for ip in addr {
|
||||
buf[offset..offset + 4].copy_from_slice(&ip.octets());
|
||||
offset += 4;
|
||||
}
|
||||
self.buffer.as_mut()[offset] = addr.len() as u8;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
pub fn set_data(&mut self, data: &[u8]) -> io::Result<()> {
|
||||
let num = self.addr_num() as usize;
|
||||
let start = 1 + 4 * num;
|
||||
let buf = self.buffer.as_mut();
|
||||
if start > buf.len() || start + data.len() != buf.len() {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"InvalidData",
|
||||
));
|
||||
}
|
||||
buf[start..].copy_from_slice(data);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,11 +1,12 @@
|
||||
use std::net::Ipv4Addr;
|
||||
use std::{fmt, io};
|
||||
use std::net::Ipv4Addr;
|
||||
use crate::protocol::body::ENCRYPTION_RESERVED;
|
||||
|
||||
/*
|
||||
0 15 31
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 版本(8) | 协议(8) | 上层协议(8) | 初始ttl(4) | 生存时间(4) |
|
||||
|e|s|unused| 版本(4) | 协议(8) | 上层协议(8) | 初始ttl(4) | 生存时间(4) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 源ip地址(32) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
@@ -13,8 +14,11 @@ use std::{fmt, io};
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 数据体 |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
注:e为是否加密标志,s为服务端通信包标志
|
||||
*/
|
||||
|
||||
|
||||
pub mod body;
|
||||
pub mod control_packet;
|
||||
pub mod error_packet;
|
||||
pub mod service_packet;
|
||||
@@ -91,32 +95,70 @@ pub const MAX_SOURCE: u8 = 0b11110000;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct NetPacket<B> {
|
||||
data_len: usize,
|
||||
buffer: B,
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> NetPacket<B> {
|
||||
pub fn new(buffer: B) -> io::Result<NetPacket<B>> {
|
||||
let len = buffer.as_ref().len();
|
||||
// 不能大于udp最大载荷长度
|
||||
if len < 12 || len > 65535 - 20 - 8 {
|
||||
let data_len = buffer.as_ref().len();
|
||||
Self::new0(data_len, buffer)
|
||||
}
|
||||
pub fn new_encrypt(buffer: B) -> io::Result<NetPacket<B>> {
|
||||
if 12 + ENCRYPTION_RESERVED > buffer.as_ref().len() {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"length overflow",
|
||||
));
|
||||
}
|
||||
Ok(NetPacket { buffer })
|
||||
//加密需要预留32字节
|
||||
let data_len = buffer.as_ref().len() - ENCRYPTION_RESERVED;
|
||||
Self::new0(data_len, buffer)
|
||||
}
|
||||
pub fn new0(data_len: usize, buffer: B) -> io::Result<NetPacket<B>> {
|
||||
if data_len > buffer.as_ref().len() {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"length overflow",
|
||||
));
|
||||
}
|
||||
// 不能大于udp最大载荷长度
|
||||
if data_len < 12 || buffer.as_ref().len() > 65535 - 20 - 8 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"length overflow",
|
||||
));
|
||||
}
|
||||
Ok(NetPacket { data_len, buffer })
|
||||
}
|
||||
pub fn buffer(&self) -> &[u8] {
|
||||
&self.buffer.as_ref()[..self.data_len]
|
||||
}
|
||||
pub fn raw_buffer(&self) -> &[u8] {
|
||||
self.buffer.as_ref()
|
||||
}
|
||||
pub fn data_len(&self) -> usize {
|
||||
self.data_len
|
||||
}
|
||||
pub fn reserve(&self) -> usize {
|
||||
self.buffer.as_ref().len() - self.data_len
|
||||
}
|
||||
pub fn into_buffer(self) -> B {
|
||||
self.buffer
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> NetPacket<B> {
|
||||
/// 数据加密
|
||||
pub fn is_encrypt(&self) -> bool {
|
||||
self.buffer.as_ref()[0] & 0x80 == 0x80
|
||||
}
|
||||
/// 网关通信的标识
|
||||
pub fn is_gateway(&self) -> bool {
|
||||
self.buffer.as_ref()[0] & 0x50 == 0x50
|
||||
}
|
||||
pub fn version(&self) -> Version {
|
||||
Version::from(self.buffer.as_ref()[0])
|
||||
Version::from(self.buffer.as_ref()[0] & 0x0F)
|
||||
}
|
||||
pub fn protocol(&self) -> Protocol {
|
||||
Protocol::from(self.buffer.as_ref()[1])
|
||||
@@ -139,16 +181,31 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
|
||||
Ipv4Addr::from(tmp)
|
||||
}
|
||||
pub fn payload(&self) -> &[u8] {
|
||||
&self.buffer.as_ref()[12..]
|
||||
&self.buffer.as_ref()[12..self.data_len]
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
|
||||
pub fn buffer_mut(&mut self)->&mut [u8]{
|
||||
pub fn buffer_mut(&mut self) -> &mut [u8] {
|
||||
self.buffer.as_mut()
|
||||
}
|
||||
pub fn set_encrypt_flag(&mut self, is_encrypt: bool) {
|
||||
if is_encrypt {
|
||||
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] | 0x80
|
||||
} else {
|
||||
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0x7F
|
||||
};
|
||||
}
|
||||
pub fn set_gateway_flag(&mut self, is_gateway: bool) {
|
||||
if is_gateway {
|
||||
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] | 0x50
|
||||
} else {
|
||||
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0xBF
|
||||
};
|
||||
}
|
||||
pub fn set_version(&mut self, version: Version) {
|
||||
self.buffer.as_mut()[0] = version.into();
|
||||
let v: u8 = version.into();
|
||||
self.buffer.as_mut()[0] = (self.buffer.as_ref()[0] & 0xF0) | (0x0F & v);
|
||||
}
|
||||
pub fn set_protocol(&mut self, protocol: Protocol) {
|
||||
self.buffer.as_mut()[1] = protocol.into();
|
||||
@@ -171,11 +228,22 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
|
||||
pub fn set_destination(&mut self, destination: Ipv4Addr) {
|
||||
self.buffer.as_mut()[8..12].copy_from_slice(&destination.octets());
|
||||
}
|
||||
pub fn set_payload(&mut self, payload: &[u8]) {
|
||||
self.buffer.as_mut()[12..payload.len() + 12].copy_from_slice(payload);
|
||||
pub fn set_payload(&mut self, payload: &[u8]) -> io::Result<()> {
|
||||
if self.data_len - 12 != payload.len() {
|
||||
return Err(io::Error::new(io::ErrorKind::InvalidData, "data_len - 12 != payload.len"));
|
||||
}
|
||||
self.buffer.as_mut()[12..self.data_len].copy_from_slice(payload);
|
||||
Ok(())
|
||||
}
|
||||
pub fn payload_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.buffer.as_mut()[12..]
|
||||
&mut self.buffer.as_mut()[12..self.data_len]
|
||||
}
|
||||
pub fn set_data_len(&mut self, data_len: usize) -> io::Result<()> {
|
||||
if data_len > self.buffer.as_ref().len() || data_len < 12 {
|
||||
return Err(io::Error::new(io::ErrorKind::InvalidData, "data_len invalid"));
|
||||
}
|
||||
self.data_len = data_len;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -8,6 +8,11 @@ pub enum Protocol {
|
||||
PollDeviceList,
|
||||
/// 推送设备列表
|
||||
PushDeviceList,
|
||||
/// 和服务端握手
|
||||
HandshakeRequest,
|
||||
HandshakeResponse,
|
||||
SecretHandshakeRequest,
|
||||
SecretHandshakeResponse,
|
||||
Unknown(u8),
|
||||
}
|
||||
|
||||
@@ -18,6 +23,10 @@ impl From<u8> for Protocol {
|
||||
2 => Self::RegistrationResponse,
|
||||
3 => Self::PollDeviceList,
|
||||
4 => Self::PushDeviceList,
|
||||
5 => Self::HandshakeRequest,
|
||||
6 => Self::HandshakeResponse,
|
||||
7 => Self::SecretHandshakeRequest,
|
||||
8 => Self::SecretHandshakeResponse,
|
||||
val => Self::Unknown(val),
|
||||
}
|
||||
}
|
||||
@@ -30,6 +39,10 @@ impl Into<u8> for Protocol {
|
||||
Self::RegistrationResponse => 2,
|
||||
Self::PollDeviceList => 3,
|
||||
Self::PushDeviceList => 4,
|
||||
Self::HandshakeRequest => 5,
|
||||
Self::HandshakeResponse => 6,
|
||||
Self::SecretHandshakeRequest => 7,
|
||||
Self::SecretHandshakeResponse => 8,
|
||||
Self::Unknown(val) => val,
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,13 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::sync::Arc;
|
||||
use crate::error::*;
|
||||
use moka::sync::Cache;
|
||||
use packet::igmp::igmp_v2::IgmpV2Packet;
|
||||
use packet::igmp::igmp_v3::{IgmpV3RecordType, IgmpV3ReportPacket};
|
||||
use packet::igmp::IgmpType;
|
||||
use parking_lot::RwLock;
|
||||
use moka::sync::Cache;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use crate::error::*;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
//组播缓存 30分钟 (token,group_address) -> members
|
||||
@@ -16,9 +16,9 @@ lazy_static::lazy_static! {
|
||||
// (token,group_address,member_ip)
|
||||
static ref MULTICAST_MEMBER:Cache<(String,Ipv4Addr,Ipv4Addr), ()> = Cache::builder()
|
||||
.time_to_idle(Duration::from_secs(20*60)).eviction_listener(|k:Arc<(String,Ipv4Addr,Ipv4Addr)>,_,cause|{
|
||||
if cause==moka::notification::RemovalCause::Replaced{
|
||||
return;
|
||||
}
|
||||
if cause==moka::notification::RemovalCause::Replaced{
|
||||
return;
|
||||
}
|
||||
log::info!("MULTICAST_MEMBER eviction {:?}", k);
|
||||
if let Some(v) = MULTICAST.get(&(k.0.clone(),k.1)){
|
||||
let mut lock = v.write();
|
||||
@@ -116,7 +116,8 @@ pub fn handle(buf: &[u8], token: &String, source: Ipv4Addr) -> Result<()> {
|
||||
guard.members.insert(source);
|
||||
guard.map.insert(source, (true, HashSet::from_iter(src)));
|
||||
drop(guard);
|
||||
MULTICAST_MEMBER.insert((token.clone(), multicast_addr, source), ());
|
||||
MULTICAST_MEMBER
|
||||
.insert((token.clone(), multicast_addr, source), ());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,20 +141,18 @@ pub fn handle(buf: &[u8], token: &String, source: Ipv4Addr) -> Result<()> {
|
||||
//在已有源的基础上,接收目标源,如果是排除模式,则删除;是包含模式则添加
|
||||
match group_record.source_addresses() {
|
||||
None => {}
|
||||
Some(src) => {
|
||||
match guard.map.get_mut(&source) {
|
||||
None => {}
|
||||
Some((is_include, set)) => {
|
||||
for ip in src {
|
||||
if *is_include {
|
||||
set.insert(ip);
|
||||
} else {
|
||||
set.remove(&ip);
|
||||
}
|
||||
Some(src) => match guard.map.get_mut(&source) {
|
||||
None => {}
|
||||
Some((is_include, set)) => {
|
||||
for ip in src {
|
||||
if *is_include {
|
||||
set.insert(ip);
|
||||
} else {
|
||||
set.remove(&ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
drop(guard);
|
||||
MULTICAST_MEMBER.insert((token.clone(), multicast_addr, source), ());
|
||||
@@ -162,20 +161,18 @@ pub fn handle(buf: &[u8], token: &String, source: Ipv4Addr) -> Result<()> {
|
||||
//在已有源的基础上,不接收目标源
|
||||
match group_record.source_addresses() {
|
||||
None => {}
|
||||
Some(src) => {
|
||||
match guard.map.get_mut(&source) {
|
||||
None => {}
|
||||
Some((is_include, set)) => {
|
||||
for ip in src {
|
||||
if *is_include {
|
||||
set.remove(&ip);
|
||||
} else {
|
||||
set.insert(ip);
|
||||
}
|
||||
Some(src) => match guard.map.get_mut(&source) {
|
||||
None => {}
|
||||
Some((is_include, set)) => {
|
||||
for ip in src {
|
||||
if *is_include {
|
||||
set.remove(&ip);
|
||||
} else {
|
||||
set.insert(ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
drop(guard);
|
||||
MULTICAST_MEMBER.insert((token.clone(), multicast_addr, source), ());
|
||||
@@ -188,4 +185,4 @@ pub fn handle(buf: &[u8], token: &String, source: Ipv4Addr) -> Result<()> {
|
||||
IgmpType::Unknown(_) => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,56 +1,65 @@
|
||||
use std::collections::HashMap;
|
||||
use std::net::SocketAddr;
|
||||
use moka::sync::Cache;
|
||||
use std::time::Duration;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use crossbeam_skiplist::SkipMap;
|
||||
use moka::sync::Cache;
|
||||
use parking_lot::RwLock;
|
||||
use tokio::sync::mpsc::Sender;
|
||||
|
||||
mod udp_service;
|
||||
mod tcp_service;
|
||||
mod common;
|
||||
pub use udp_service::start_udp;
|
||||
pub use tcp_service::start_tcp;
|
||||
pub use udp_service::start_udp;
|
||||
|
||||
use crate::cipher::Aes256GcmCipher;
|
||||
|
||||
mod common;
|
||||
mod tcp_service;
|
||||
mod udp_service;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
//七天不连接则回收ip
|
||||
static ref DEVICE_ID_SESSION:Cache<(String,String),()> = Cache::builder()
|
||||
.time_to_idle(Duration::from_secs(60*60*24*7)).eviction_listener(|k:Arc<(String,String)>,_,cause|{
|
||||
if cause!=moka::notification::RemovalCause::Expired{
|
||||
return;
|
||||
}
|
||||
static ref DEVICE_ID_SESSION:Cache<(String,String),i64> = Cache::builder()
|
||||
.time_to_idle(Duration::from_secs(60*60*24*7)).eviction_listener(|k:Arc<(String,String)>,id:i64,cause|{
|
||||
if cause!=moka::notification::RemovalCause::Expired{
|
||||
return;
|
||||
}
|
||||
log::info!("DEVICE_ID_SESSION eviction {:?}", k);
|
||||
if let Some(v) = VIRTUAL_NETWORK.get(&k.0){
|
||||
let mut lock = v.write();
|
||||
lock.virtual_ip_map.remove(&k.1);
|
||||
lock.epoch+=1;
|
||||
if let Some(dev) = lock.virtual_ip_map.get(&k.1){
|
||||
if dev.id==id{
|
||||
lock.virtual_ip_map.remove(&k.1);
|
||||
lock.epoch+=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}).build();
|
||||
//七天没有用户则回收网段缓存
|
||||
static ref VIRTUAL_NETWORK:Cache<String, Arc<RwLock<VirtualNetwork>>> = Cache::builder()
|
||||
.time_to_idle(Duration::from_secs(60*60*24*7)).build();
|
||||
static ref DEVICE_ADDRESS:SkipMap<(String,u32), PeerLink> = SkipMap::new();
|
||||
static ref DEVICE_ADDRESS:SkipMap<(String,u32), (PeerLink,Context)> = SkipMap::new();
|
||||
static ref TCP_AES:SkipMap<SocketAddr,Aes256GcmCipher> = SkipMap::new();
|
||||
static ref UDP_AES:Cache<SocketAddr,Aes256GcmCipher> = Cache::builder()
|
||||
.time_to_idle(Duration::from_secs(20)).build();
|
||||
//udp专用 10秒钟没有收到消息则判定为掉线
|
||||
// 地址 -> 注册信息
|
||||
static ref UDP_SESSION:Cache<SocketAddr,Context> = Cache::builder()
|
||||
.time_to_idle(Duration::from_secs(10)).eviction_listener(|_,context:Context,cause|{
|
||||
if cause!=moka::notification::RemovalCause::Expired{
|
||||
return;
|
||||
}
|
||||
log::info!("UDP_SESSION eviction {:?}", context);
|
||||
if cause!=moka::notification::RemovalCause::Expired{
|
||||
return;
|
||||
}
|
||||
log::info!("UDP_SESSION eviction token={},virtual_ip={},device_id={},id={}", context.token,context.virtual_ip,context.device_id,context.id);
|
||||
if let Some(v) = VIRTUAL_NETWORK.get(&context.token){
|
||||
let mut lock = v.write();
|
||||
if let Some(mut item) = lock.virtual_ip_map.get_mut(&context.device_id){
|
||||
if let Some(item) = lock.virtual_ip_map.get_mut(&context.device_id){
|
||||
if item.id!=context.id{
|
||||
return;
|
||||
}
|
||||
item.status = PeerDeviceStatus::Offline;
|
||||
DEVICE_ADDRESS.remove(&(context.token,context.virtual_ip));
|
||||
lock.epoch+=1;
|
||||
}
|
||||
lock.epoch+=1;
|
||||
}
|
||||
}).build();
|
||||
}
|
||||
@@ -61,13 +70,27 @@ pub enum PeerLink {
|
||||
Udp(SocketAddr),
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone)]
|
||||
pub struct Context {
|
||||
token: String,
|
||||
virtual_ip: u32,
|
||||
id: i64,
|
||||
device_id: String,
|
||||
client_secret: bool,
|
||||
address: SocketAddr,
|
||||
}
|
||||
|
||||
impl Default for Context {
|
||||
fn default() -> Self {
|
||||
Context {
|
||||
token: "".to_string(),
|
||||
virtual_ip: 0,
|
||||
id: 0,
|
||||
device_id: "".to_string(),
|
||||
client_secret: false,
|
||||
address: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -83,6 +106,7 @@ pub struct DeviceInfo {
|
||||
ip: u32,
|
||||
name: String,
|
||||
status: PeerDeviceStatus,
|
||||
client_secret: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
@@ -104,7 +128,7 @@ impl From<u8> for PeerDeviceStatus {
|
||||
fn from(value: u8) -> Self {
|
||||
match value {
|
||||
0 => PeerDeviceStatus::Online,
|
||||
_ => PeerDeviceStatus::Offline
|
||||
_ => PeerDeviceStatus::Offline,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,80 +3,124 @@ use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::{TcpListener, UdpSocket};
|
||||
use tokio::net::tcp::OwnedReadHalf;
|
||||
use tokio::net::{TcpListener, UdpSocket};
|
||||
use tokio::sync::mpsc::{channel, Sender};
|
||||
|
||||
use crate::ConfigInfo;
|
||||
use crate::service::main_service::{Context, DEVICE_ADDRESS, PeerDeviceStatus, VIRTUAL_NETWORK};
|
||||
use crate::cipher::{Aes256GcmCipher, RsaCipher};
|
||||
use crate::service::main_service::common::handle;
|
||||
use crate::service::main_service::{
|
||||
Context, PeerDeviceStatus, DEVICE_ADDRESS, TCP_AES, VIRTUAL_NETWORK,
|
||||
};
|
||||
use crate::ConfigInfo;
|
||||
|
||||
pub async fn start_tcp(tcp: TcpListener, main_udp: Arc<UdpSocket>, config: ConfigInfo) -> io::Result<()> {
|
||||
pub async fn start_tcp(
|
||||
tcp: TcpListener,
|
||||
main_udp: Arc<UdpSocket>,
|
||||
config: ConfigInfo,
|
||||
rsa_cipher: Option<RsaCipher>,
|
||||
) {
|
||||
loop {
|
||||
let (stream, addr) = match tcp.accept().await {
|
||||
Ok(rs) => { rs }
|
||||
Ok(rs) => rs,
|
||||
Err(e) => {
|
||||
log::warn!("tcp accept err:{:?}",e);
|
||||
log::warn!("tcp accept err:{:?}", e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
log::info!("tcp连接 {}",addr);
|
||||
log::info!("tcp连接 {}", addr);
|
||||
let (r, mut w) = stream.into_split();
|
||||
|
||||
let (sender, mut receiver) = channel::<Vec<u8>>(100);
|
||||
tokio::spawn(async move {
|
||||
while let Some(mut data) = receiver.recv().await {
|
||||
if data.len() >= 4 {
|
||||
let len = data.len() - 4;
|
||||
data[2] = (len >> 8) as u8;
|
||||
data[3] = (len & 0xFF) as u8;
|
||||
if let Err(e) = w.write_all(&data).await {
|
||||
log::info!("发送失败,链接终止:{:?},{:?}",addr,e);
|
||||
break;
|
||||
}
|
||||
let mut head = [0; 4];
|
||||
while let Some(data) = receiver.recv().await {
|
||||
let len = data.len();
|
||||
head[2] = (len >> 8) as u8;
|
||||
head[3] = (len & 0xFF) as u8;
|
||||
if let Err(e) = w.write_all(&head).await {
|
||||
log::info!("发送失败,链接终止:{:?},{:?}", addr, e);
|
||||
}
|
||||
if let Err(e) = w.write_all(&data).await {
|
||||
log::info!("发送失败,链接终止:{:?},{:?}", addr, e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
let _ = w.shutdown().await;
|
||||
});
|
||||
let main_udp = main_udp.clone();
|
||||
let config = config.clone();
|
||||
let rsa_cipher = rsa_cipher.clone();
|
||||
tokio::spawn(async move {
|
||||
let mut context = Context {
|
||||
token: "".to_string(),
|
||||
virtual_ip: 0,
|
||||
id: 0,
|
||||
device_id: "".to_string(),
|
||||
};
|
||||
if let Err(e) = tcp_handle(&mut context, config, r, addr, sender, main_udp).await {
|
||||
log::info!("接收失败,链接终止:{:?},{:?}",addr,e);
|
||||
let mut context: Option<Context> = None;
|
||||
let mut aes_gcm_cipher: Option<Aes256GcmCipher> = None;
|
||||
if let Err(e) = tcp_handle(
|
||||
rsa_cipher,
|
||||
&mut aes_gcm_cipher,
|
||||
&mut context,
|
||||
config,
|
||||
r,
|
||||
addr,
|
||||
sender,
|
||||
main_udp,
|
||||
)
|
||||
.await
|
||||
{
|
||||
log::info!("接收失败,链接终止:{:?},{:?}", addr, e);
|
||||
}
|
||||
if context.virtual_ip != 0 && context.id != 0 {
|
||||
TCP_AES.remove(&addr);
|
||||
if let Some(context) = context {
|
||||
if let Some(v) = VIRTUAL_NETWORK.get(&context.token) {
|
||||
let mut lock = v.write();
|
||||
if let Some(mut item) = lock.virtual_ip_map.get_mut(&context.device_id) {
|
||||
if let Some(item) = lock.virtual_ip_map.get_mut(&context.device_id) {
|
||||
if item.id != context.id {
|
||||
return;
|
||||
}
|
||||
item.status = PeerDeviceStatus::Offline;
|
||||
DEVICE_ADDRESS.remove(&(context.token, context.virtual_ip));
|
||||
lock.epoch += 1;
|
||||
}
|
||||
lock.epoch += 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async fn tcp_handle(context: &mut Context, config: ConfigInfo, mut read: OwnedReadHalf, addr: SocketAddr, sender: Sender<Vec<u8>>, main_udp: Arc<UdpSocket>) -> io::Result<()> {
|
||||
async fn tcp_handle(
|
||||
rsa_cipher: Option<RsaCipher>,
|
||||
aes_gcm_cipher: &mut Option<Aes256GcmCipher>,
|
||||
context: &mut Option<Context>,
|
||||
config: ConfigInfo,
|
||||
mut read: OwnedReadHalf,
|
||||
addr: SocketAddr,
|
||||
sender: Sender<Vec<u8>>,
|
||||
main_udp: Arc<UdpSocket>,
|
||||
) -> io::Result<()> {
|
||||
let mut head = [0; 4];
|
||||
let mut buf = [0; 10240];
|
||||
loop {
|
||||
read.read_exact(&mut buf[..4]).await?;
|
||||
let len = 4 + (((buf[2] as u16) << 8) | buf[3] as u16) as usize;
|
||||
read.read_exact(&mut buf[4..len]).await?;
|
||||
if let Err(e) = handle(context, &main_udp, &mut buf[..len], addr, &config, Some(&sender)).await {
|
||||
log::info!("tcp数据处理失败:{:?},{:?}",addr,e);
|
||||
read.read_exact(&mut head).await?;
|
||||
let len = (((head[2] as u16) << 8) | head[3] as u16) as usize;
|
||||
if len < 12 || len > buf.len() {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"length overflow",
|
||||
));
|
||||
}
|
||||
read.read_exact(&mut buf[..len]).await?;
|
||||
if let Err(e) = handle(
|
||||
&rsa_cipher,
|
||||
aes_gcm_cipher,
|
||||
context,
|
||||
&main_udp,
|
||||
&mut buf[..len],
|
||||
addr,
|
||||
&config,
|
||||
Some(&sender),
|
||||
)
|
||||
.await
|
||||
{
|
||||
log::info!("tcp数据处理失败:{:?},{:?}", addr, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,31 +1,42 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::cipher::RsaCipher;
|
||||
use tokio::net::UdpSocket;
|
||||
|
||||
use crate::ConfigInfo;
|
||||
use crate::service::main_service::{Context, UDP_SESSION};
|
||||
use crate::service::main_service::common::handle;
|
||||
use crate::service::main_service::{UDP_AES, UDP_SESSION};
|
||||
use crate::ConfigInfo;
|
||||
|
||||
pub async fn start_udp(main_udp: Arc<UdpSocket>, config: ConfigInfo) {
|
||||
pub async fn start_udp(
|
||||
main_udp: Arc<UdpSocket>,
|
||||
config: ConfigInfo,
|
||||
rsa_cipher: Option<RsaCipher>,
|
||||
) {
|
||||
loop {
|
||||
let mut buf = vec![0u8; 10240];
|
||||
match main_udp.recv_from(&mut buf[4..]).await {
|
||||
match main_udp.recv_from(&mut buf).await {
|
||||
Ok((len, addr)) => {
|
||||
let main_udp = main_udp.clone();
|
||||
let config = config.clone();
|
||||
let mut context = UDP_SESSION.get(&addr).unwrap_or_else(|| {
|
||||
Context {
|
||||
token: "".to_string(),
|
||||
virtual_ip: 0,
|
||||
id: 0,
|
||||
device_id: "".to_string(),
|
||||
}
|
||||
});
|
||||
let rsa_cipher = rsa_cipher.clone();
|
||||
let mut context = UDP_SESSION.get(&addr);
|
||||
let mut aes = UDP_AES.get(&addr);
|
||||
tokio::spawn(async move {
|
||||
match handle(&mut context, &main_udp, &mut buf[..len + 4], addr, &config, None).await {
|
||||
match handle(
|
||||
&rsa_cipher,
|
||||
&mut aes,
|
||||
&mut context,
|
||||
&main_udp,
|
||||
&mut buf[..len],
|
||||
addr,
|
||||
&config,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::info!("udp数据处理失败:{:?},{:?}",addr,e);
|
||||
log::info!("udp数据处理失败:{:?},{:?}", addr, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -35,4 +46,4 @@ pub async fn start_udp(main_udp: Arc<UdpSocket>, config: ConfigInfo) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user