上报状态

This commit is contained in:
lubeilin
2024-03-24 21:50:47 +08:00
parent 5569c67ba4
commit b26c4b97b2
10 changed files with 532 additions and 59 deletions
+65 -53
View File
@@ -1,66 +1,78 @@
syntax = "proto3";
message HandshakeRequest{
string version = 1;
bool secret = 2;
message HandshakeRequest {
string version = 1;
bool secret = 2;
}
message HandshakeResponse{
string version = 1;
bool secret = 2;
bytes public_key = 3;
string key_finger = 4;
message HandshakeResponse {
string version = 1;
bool secret = 2;
bytes public_key = 3;
string key_finger = 4;
}
message SecretHandshakeRequest{
string token = 1;
bytes key = 2;
message SecretHandshakeRequest {
string token = 1;
bytes key = 2;
}
message RegistrationRequest{
string token = 1;
string device_id = 2;
string name = 3;
bool is_fast = 4;
string version = 5;
fixed32 virtual_ip = 6;
bool allow_ip_change = 7;
bool client_secret = 8;
message RegistrationRequest {
string token = 1;
string device_id = 2;
string name = 3;
bool is_fast = 4;
string version = 5;
fixed32 virtual_ip = 6;
bool allow_ip_change = 7;
bool client_secret = 8;
}
message RegistrationResponse{
fixed32 virtual_ip = 1;
fixed32 virtual_gateway = 2;
fixed32 virtual_netmask = 3;
uint32 epoch = 4;
repeated DeviceInfo device_info_list = 5;
fixed32 public_ip = 6;
uint32 public_port = 7;
bytes public_ipv6 = 8;
message RegistrationResponse {
fixed32 virtual_ip = 1;
fixed32 virtual_gateway = 2;
fixed32 virtual_netmask = 3;
uint32 epoch = 4;
repeated DeviceInfo device_info_list = 5;
fixed32 public_ip = 6;
uint32 public_port = 7;
bytes public_ipv6 = 8;
}
message DeviceInfo{
string name = 1;
fixed32 virtual_ip = 2;
uint32 device_status = 3;
bool client_secret = 4;
message DeviceInfo {
string name = 1;
fixed32 virtual_ip = 2;
uint32 device_status = 3;
bool client_secret = 4;
}
message DeviceList{
uint32 epoch = 1;
repeated DeviceInfo device_info_list = 2;
message DeviceList {
uint32 epoch = 1;
repeated DeviceInfo device_info_list = 2;
}
message PunchInfo{
repeated fixed32 public_ip_list = 2;
uint32 public_port = 3;
uint32 public_port_range = 4;
PunchNatType nat_type = 5;
bool reply = 6;
fixed32 local_ip = 7;
uint32 local_port = 8;
bytes ipv6 = 9;
uint32 ipv6_port = 10;
uint32 tcp_port = 11;
repeated uint32 udp_ports = 12;
repeated uint32 public_ports = 13;
message PunchInfo {
repeated fixed32 public_ip_list = 2;
uint32 public_port = 3;
uint32 public_port_range = 4;
PunchNatType nat_type = 5;
bool reply = 6;
fixed32 local_ip = 7;
uint32 local_port = 8;
bytes ipv6 = 9;
uint32 ipv6_port = 10;
uint32 tcp_port = 11;
repeated uint32 udp_ports = 12;
repeated uint32 public_ports = 13;
}
enum PunchNatType{
Symmetric = 0;
Cone = 1;
enum PunchNatType {
Symmetric = 0;
Cone = 1;
}
/// 向服务器上报客户端状态信息
message ClientStatusInfo {
fixed32 source = 1;
repeated RouteItem p2p_list = 2;
uint64 up_stream = 3;
uint64 down_stream = 4;
PunchNatType nat_type = 5;
}
message RouteItem {
fixed32 next_ip = 1;
}
+2 -1
View File
@@ -482,9 +482,10 @@ impl RouteTable {
let table = self.route_table.read();
let mut list = Vec::with_capacity(8);
for (ip, (_, routes)) in table.iter() {
if let Some((route, _)) = routes.first() {
for (route, _) in routes.iter() {
if route.is_p2p() {
list.push((*ip, *route));
break;
}
}
}
+7 -1
View File
@@ -188,8 +188,14 @@ where
NOTIFY => return Ok(()),
Token(index) => index - 1,
};
let udp = if let Some(udp) = udps.get(index) {
udp
} else {
log::error!("{:?}", x);
continue;
};
loop {
match udps[index].recv_from(&mut buf) {
match udp.recv_from(&mut buf) {
Ok((len, addr)) => {
recv_handler.handle(
&mut buf[..len],
+13
View File
@@ -205,6 +205,8 @@ impl Vnt {
let context = context.clone();
let nat_test = nat_test.clone();
let device_list = device_list.clone();
let down_count_watcher = down_count_watcher.clone();
let up_count_watcher = up_count_watcher.clone();
let current_device = current_device.clone();
if !config.use_channel_type.is_only_relay() {
// 定时nat探测
@@ -229,6 +231,8 @@ impl Vnt {
config_info,
punch,
callback,
down_count_watcher,
up_count_watcher,
);
});
}
@@ -259,6 +263,8 @@ pub fn start<Call: VntCallback>(
config_info: BaseConfigInfo,
punch: Punch,
callback: Call,
down_count_watcher: WatchU64Adder,
up_count_watcher: WatchSingleU64Adder,
) {
// 定时心跳
maintain::heartbeat(
@@ -310,6 +316,13 @@ pub fn start<Call: VntCallback>(
punch,
);
}
maintain::up_status(
scheduler,
context.clone(),
current_device.clone(),
down_count_watcher,
up_count_watcher,
)
}
impl Vnt {
+3
View File
@@ -14,3 +14,6 @@ pub use punch::*;
mod idle;
pub use idle::idle_gateway;
pub use idle::idle_route;
mod up_status;
pub use up_status::*;
-1
View File
@@ -1,4 +1,3 @@
use std::cmp::Ordering;
use std::net::Ipv4Addr;
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
use std::sync::Arc;
+104
View File
@@ -0,0 +1,104 @@
use crate::channel::context::Context;
use crate::handle::CurrentDeviceInfo;
use crate::proto::message::{ClientStatusInfo, PunchNatType, RouteItem};
use crate::protocol::body::ENCRYPTION_RESERVED;
use crate::protocol::{service_packet, NetPacket, Protocol, Version, HEAD_LEN, MAX_TTL};
use crate::util::{Scheduler, WatchSingleU64Adder, WatchU64Adder};
use crossbeam_utils::atomic::AtomicCell;
use protobuf::Message;
use std::io;
use std::sync::Arc;
use std::time::Duration;
/// 上报状态给服务器
pub fn up_status(
scheduler: &Scheduler,
context: Context,
current_device_info: Arc<AtomicCell<CurrentDeviceInfo>>,
down_count_watcher: WatchU64Adder,
up_count_watcher: WatchSingleU64Adder,
) {
let _ = scheduler.timeout(Duration::from_secs(60), move |x| {
up_status0(
x,
context,
current_device_info,
down_count_watcher,
up_count_watcher,
)
});
}
fn up_status0(
scheduler: &Scheduler,
context: Context,
current_device_info: Arc<AtomicCell<CurrentDeviceInfo>>,
down_count_watcher: WatchU64Adder,
up_count_watcher: WatchSingleU64Adder,
) {
if let Err(e) = send_up_status_packet(
&context,
&current_device_info,
&down_count_watcher,
&up_count_watcher,
) {
log::warn!("{:?}", e)
}
let rs = scheduler.timeout(Duration::from_secs(10 * 60), move |x| {
up_status0(
x,
context,
current_device_info,
down_count_watcher,
up_count_watcher,
)
});
if !rs {
log::info!("定时任务停止");
}
}
fn send_up_status_packet(
context: &Context,
current_device_info: &AtomicCell<CurrentDeviceInfo>,
down_count_watcher: &WatchU64Adder,
up_count_watcher: &WatchSingleU64Adder,
) -> io::Result<()> {
let device_info = current_device_info.load();
if device_info.status.offline() {
return Ok(());
}
let routes = context.route_table.route_table_p2p();
if routes.is_empty() {
return Ok(());
}
let mut message = ClientStatusInfo::new();
message.source = device_info.virtual_ip.into();
for (ip, _) in routes {
let mut item = RouteItem::new();
item.next_ip = ip.into();
message.p2p_list.push(item);
}
message.up_stream = up_count_watcher.get();
message.down_stream = down_count_watcher.get();
message.nat_type = protobuf::EnumOrUnknown::new(if context.is_cone() {
PunchNatType::Cone
} else {
PunchNatType::Symmetric
});
let buf = message
.write_to_bytes()
.map_err(|e| io::Error::new(io::ErrorKind::Other, format!("up_status_packet {:?}", e)))?;
let mut net_packet =
NetPacket::new_encrypt(vec![0; HEAD_LEN + buf.len() + ENCRYPTION_RESERVED])?;
net_packet.set_version(Version::V1);
net_packet.set_gateway_flag(true);
net_packet.set_protocol(Protocol::Service);
net_packet.set_transport_protocol_into(service_packet::Protocol::ClientStatusInfo);
net_packet.first_set_ttl(MAX_TTL);
net_packet.set_source(device_info.virtual_ip);
net_packet.set_destination(device_info.virtual_gateway);
net_packet.set_payload(&buf)?;
context.send_default(net_packet.buffer(), device_info.connect_server)?;
Ok(())
}
+328 -3
View File
@@ -1622,6 +1622,323 @@ impl ::protobuf::reflect::ProtobufValue for PunchInfo {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:ClientStatusInfo)
pub struct ClientStatusInfo {
// message fields
// @@protoc_insertion_point(field:ClientStatusInfo.source)
pub source: u32,
// @@protoc_insertion_point(field:ClientStatusInfo.p2p_list)
pub p2p_list: ::std::vec::Vec<RouteItem>,
// @@protoc_insertion_point(field:ClientStatusInfo.up_stream)
pub up_stream: u64,
// @@protoc_insertion_point(field:ClientStatusInfo.down_stream)
pub down_stream: u64,
// @@protoc_insertion_point(field:ClientStatusInfo.nat_type)
pub nat_type: ::protobuf::EnumOrUnknown<PunchNatType>,
// special fields
// @@protoc_insertion_point(special_field:ClientStatusInfo.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a ClientStatusInfo {
fn default() -> &'a ClientStatusInfo {
<ClientStatusInfo as ::protobuf::Message>::default_instance()
}
}
impl ClientStatusInfo {
pub fn new() -> ClientStatusInfo {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(5);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"source",
|m: &ClientStatusInfo| { &m.source },
|m: &mut ClientStatusInfo| { &mut m.source },
));
fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>(
"p2p_list",
|m: &ClientStatusInfo| { &m.p2p_list },
|m: &mut ClientStatusInfo| { &mut m.p2p_list },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"up_stream",
|m: &ClientStatusInfo| { &m.up_stream },
|m: &mut ClientStatusInfo| { &mut m.up_stream },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"down_stream",
|m: &ClientStatusInfo| { &m.down_stream },
|m: &mut ClientStatusInfo| { &mut m.down_stream },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"nat_type",
|m: &ClientStatusInfo| { &m.nat_type },
|m: &mut ClientStatusInfo| { &mut m.nat_type },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<ClientStatusInfo>(
"ClientStatusInfo",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for ClientStatusInfo {
const NAME: &'static str = "ClientStatusInfo";
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 {
13 => {
self.source = is.read_fixed32()?;
},
18 => {
self.p2p_list.push(is.read_message()?);
},
24 => {
self.up_stream = is.read_uint64()?;
},
32 => {
self.down_stream = is.read_uint64()?;
},
40 => {
self.nat_type = is.read_enum_or_unknown()?;
},
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.source != 0 {
my_size += 1 + 4;
}
for value in &self.p2p_list {
let len = value.compute_size();
my_size += 1 + ::protobuf::rt::compute_raw_varint64_size(len) + len;
};
if self.up_stream != 0 {
my_size += ::protobuf::rt::uint64_size(3, self.up_stream);
}
if self.down_stream != 0 {
my_size += ::protobuf::rt::uint64_size(4, self.down_stream);
}
if self.nat_type != ::protobuf::EnumOrUnknown::new(PunchNatType::Symmetric) {
my_size += ::protobuf::rt::int32_size(5, self.nat_type.value());
}
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.source != 0 {
os.write_fixed32(1, self.source)?;
}
for v in &self.p2p_list {
::protobuf::rt::write_message_field_with_cached_size(2, v, os)?;
};
if self.up_stream != 0 {
os.write_uint64(3, self.up_stream)?;
}
if self.down_stream != 0 {
os.write_uint64(4, self.down_stream)?;
}
if self.nat_type != ::protobuf::EnumOrUnknown::new(PunchNatType::Symmetric) {
os.write_enum(5, ::protobuf::EnumOrUnknown::value(&self.nat_type))?;
}
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() -> ClientStatusInfo {
ClientStatusInfo::new()
}
fn clear(&mut self) {
self.source = 0;
self.p2p_list.clear();
self.up_stream = 0;
self.down_stream = 0;
self.nat_type = ::protobuf::EnumOrUnknown::new(PunchNatType::Symmetric);
self.special_fields.clear();
}
fn default_instance() -> &'static ClientStatusInfo {
static instance: ClientStatusInfo = ClientStatusInfo {
source: 0,
p2p_list: ::std::vec::Vec::new(),
up_stream: 0,
down_stream: 0,
nat_type: ::protobuf::EnumOrUnknown::from_i32(0),
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for ClientStatusInfo {
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("ClientStatusInfo").unwrap()).clone()
}
}
impl ::std::fmt::Display for ClientStatusInfo {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for ClientStatusInfo {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:RouteItem)
pub struct RouteItem {
// message fields
// @@protoc_insertion_point(field:RouteItem.next_ip)
pub next_ip: u32,
// special fields
// @@protoc_insertion_point(special_field:RouteItem.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a RouteItem {
fn default() -> &'a RouteItem {
<RouteItem as ::protobuf::Message>::default_instance()
}
}
impl RouteItem {
pub fn new() -> RouteItem {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(1);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"next_ip",
|m: &RouteItem| { &m.next_ip },
|m: &mut RouteItem| { &mut m.next_ip },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<RouteItem>(
"RouteItem",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for RouteItem {
const NAME: &'static str = "RouteItem";
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 {
13 => {
self.next_ip = is.read_fixed32()?;
},
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.next_ip != 0 {
my_size += 1 + 4;
}
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.next_ip != 0 {
os.write_fixed32(1, self.next_ip)?;
}
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() -> RouteItem {
RouteItem::new()
}
fn clear(&mut self) {
self.next_ip = 0;
self.special_fields.clear();
}
fn default_instance() -> &'static RouteItem {
static instance: RouteItem = RouteItem {
next_ip: 0,
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for RouteItem {
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("RouteItem").unwrap()).clone()
}
}
impl ::std::fmt::Display for RouteItem {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for RouteItem {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
// @@protoc_insertion_point(enum:PunchNatType)
pub enum PunchNatType {
@@ -1713,8 +2030,14 @@ static file_descriptor_proto_data: &'static [u8] = b"\
6\x18\t\x20\x01(\x0cR\x04ipv6\x12\x1b\n\tipv6_port\x18\n\x20\x01(\rR\x08\
ipv6Port\x12\x19\n\x08tcp_port\x18\x0b\x20\x01(\rR\x07tcpPort\x12\x1b\n\
\tudp_ports\x18\x0c\x20\x03(\rR\x08udpPorts\x12!\n\x0cpublic_ports\x18\r\
\x20\x03(\rR\x0bpublicPorts*'\n\x0cPunchNatType\x12\r\n\tSymmetric\x10\0\
\x12\x08\n\x04Cone\x10\x01b\x06proto3\
\x20\x03(\rR\x0bpublicPorts\"\xb9\x01\n\x10ClientStatusInfo\x12\x16\n\
\x06source\x18\x01\x20\x01(\x07R\x06source\x12%\n\x08p2p_list\x18\x02\
\x20\x03(\x0b2\n.RouteItemR\x07p2pList\x12\x1b\n\tup_stream\x18\x03\x20\
\x01(\x04R\x08upStream\x12\x1f\n\x0bdown_stream\x18\x04\x20\x01(\x04R\nd\
ownStream\x12(\n\x08nat_type\x18\x05\x20\x01(\x0e2\r.PunchNatTypeR\x07na\
tType\"$\n\tRouteItem\x12\x17\n\x07next_ip\x18\x01\x20\x01(\x07R\x06next\
Ip*'\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
@@ -1732,7 +2055,7 @@ 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(8);
let mut messages = ::std::vec::Vec::with_capacity(10);
messages.push(HandshakeRequest::generated_message_descriptor_data());
messages.push(HandshakeResponse::generated_message_descriptor_data());
messages.push(SecretHandshakeRequest::generated_message_descriptor_data());
@@ -1741,6 +2064,8 @@ pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor {
messages.push(DeviceInfo::generated_message_descriptor_data());
messages.push(DeviceList::generated_message_descriptor_data());
messages.push(PunchInfo::generated_message_descriptor_data());
messages.push(ClientStatusInfo::generated_message_descriptor_data());
messages.push(RouteItem::generated_message_descriptor_data());
let mut enums = ::std::vec::Vec::with_capacity(1);
enums.push(PunchNatType::generated_enum_descriptor_data());
::protobuf::reflect::GeneratedFileDescriptor::new_generated(
+6
View File
@@ -183,6 +183,9 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
pub fn payload(&self) -> &[u8] {
&self.buffer.as_ref()[12..self.data_len]
}
pub fn head(&self) -> &[u8] {
&self.buffer.as_ref()[..12]
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
@@ -214,6 +217,9 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
pub fn set_transport_protocol(&mut self, transport_protocol: u8) {
self.buffer.as_mut()[2] = transport_protocol;
}
pub fn set_transport_protocol_into<P: Into<u8>>(&mut self, transport_protocol: P) {
self.buffer.as_mut()[2] = transport_protocol.into();
}
pub fn first_set_ttl(&mut self, ttl: u8) {
self.buffer.as_mut()[3] = ttl << 4 | ttl;
}
+4
View File
@@ -13,6 +13,8 @@ pub enum Protocol {
HandshakeResponse,
SecretHandshakeRequest,
SecretHandshakeResponse,
/// 客户端上报状态
ClientStatusInfo,
Unknown(u8),
}
@@ -27,6 +29,7 @@ impl From<u8> for Protocol {
6 => Self::HandshakeResponse,
7 => Self::SecretHandshakeRequest,
8 => Self::SecretHandshakeResponse,
9 => Self::ClientStatusInfo,
val => Self::Unknown(val),
}
}
@@ -43,6 +46,7 @@ impl Into<u8> for Protocol {
Self::HandshakeResponse => 6,
Self::SecretHandshakeRequest => 7,
Self::SecretHandshakeResponse => 8,
Self::ClientStatusInfo => 9,
Self::Unknown(val) => val,
}
}