v1.1
This commit is contained in:
@@ -1,139 +1,136 @@
|
||||
use std::io;
|
||||
use std::net::{SocketAddr, UdpSocket};
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
use std::sync::atomic::{AtomicI64, Ordering};
|
||||
use std::time::Duration;
|
||||
|
||||
use chrono::Local;
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use parking_lot::RwLock;
|
||||
use protobuf::Message;
|
||||
use nat_traversal::channel::Channel;
|
||||
use nat_traversal::channel::sender::Sender;
|
||||
|
||||
use crate::error::*;
|
||||
use crate::handle::ConnectStatus;
|
||||
use crate::proto::message::{RegistrationRequest, RegistrationResponse};
|
||||
use crate::protocol::error_packet::InErrorPacket;
|
||||
use crate::protocol::{service_packet, NetPacket, Protocol, Version};
|
||||
use crate::protocol::{service_packet, NetPacket, Protocol, Version, MAX_TTL};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref REQUEST:RwLock<Option<(String,String,String)>> = parking_lot::const_rwlock(None);
|
||||
static ref REGISTRATION_TIME:AtomicI64=AtomicI64::new(0);
|
||||
pub(crate) static ref CONNECTION_STATUS:AtomicCell<ConnectStatus> = AtomicCell::new(ConnectStatus::Connecting);
|
||||
}
|
||||
|
||||
///向中继服务器注册,token标识一个虚拟网关,mac_address防止多次注册时得到的ip不一致
|
||||
///向中继服务器注册,token标识一个虚拟网关,device_id防止多次注册时得到的ip不一致
|
||||
pub fn registration(
|
||||
udp: &UdpSocket,
|
||||
channel: &mut Channel<Ipv4Addr>,
|
||||
server_address: SocketAddr,
|
||||
token: String,
|
||||
mac_address: String,
|
||||
device_id: String,
|
||||
name: String,
|
||||
) -> Result<RegistrationResponse> {
|
||||
// todo 和服务器通信加密
|
||||
let request_packet =
|
||||
registration_request_packet(token.clone(), mac_address.clone(), name.clone(), false)?;
|
||||
registration_request_packet(token.clone(), device_id.clone(), name.clone(), false)?;
|
||||
let buf = request_packet.buffer();
|
||||
let mut counter = 0;
|
||||
let mut recv_buf = [0u8; 10240];
|
||||
udp.set_read_timeout(Some(Duration::from_millis(500)))?;
|
||||
loop {
|
||||
counter += 1;
|
||||
if counter & 10 == 10 {
|
||||
return Err(Error::Stop("注册请求超时".to_string()));
|
||||
}
|
||||
udp.send_to(buf, server_address)?;
|
||||
let (len, addr) = match udp.recv_from(&mut recv_buf) {
|
||||
Ok(ok) => ok,
|
||||
Err(e) => {
|
||||
if e.kind() == io::ErrorKind::WouldBlock || e.kind() == io::ErrorKind::TimedOut {
|
||||
continue;
|
||||
}
|
||||
return Err(Error::Io(e));
|
||||
}
|
||||
};
|
||||
if server_address != addr {
|
||||
continue;
|
||||
}
|
||||
let net_packet = NetPacket::new(&recv_buf[..len])?;
|
||||
match net_packet.protocol() {
|
||||
Protocol::Service => {
|
||||
match service_packet::Protocol::from(net_packet.transport_protocol()) {
|
||||
service_packet::Protocol::RegistrationResponse => {
|
||||
let response =
|
||||
RegistrationResponse::parse_from_bytes(net_packet.payload())?;
|
||||
let _ = REQUEST.write().replace((token, mac_address, name));
|
||||
udp.set_read_timeout(None)?;
|
||||
CONNECTION_STATUS.store(ConnectStatus::Connected);
|
||||
return Ok(response);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Protocol::Error => {
|
||||
return match InErrorPacket::new(
|
||||
net_packet.transport_protocol(),
|
||||
net_packet.payload(),
|
||||
) {
|
||||
Ok(e) => match e {
|
||||
InErrorPacket::TokenError => Err(Error::Stop("token错误".to_string())),
|
||||
InErrorPacket::Disconnect => Err(Error::Stop("断开连接".to_string())),
|
||||
InErrorPacket::AddressExhausted => Err(Error::Stop("地址用尽".to_string())),
|
||||
InErrorPacket::OtherError(e) => match e.message() {
|
||||
Ok(str) => Err(Error::Stop(str)),
|
||||
Err(e) => Err(Error::Stop(format!("{:?}", e))),
|
||||
},
|
||||
},
|
||||
Err(e) => Err(Error::Stop(format!("{:?}", e))),
|
||||
};
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::Stop(format!("数据错误:{:?}", net_packet)));
|
||||
}
|
||||
}
|
||||
channel.send_to_addr(buf, server_address)?;
|
||||
let (len, route) = channel.recv_from(&mut recv_buf, Some(Duration::from_millis(300)))?;
|
||||
if server_address != route.addr {
|
||||
return Err(Error::Warn(format!("数据来源错误:{:?}", route.addr)));
|
||||
}
|
||||
let net_packet = NetPacket::new(&recv_buf[..len])?;
|
||||
return match net_packet.protocol() {
|
||||
Protocol::Service => {
|
||||
match service_packet::Protocol::from(net_packet.transport_protocol()) {
|
||||
service_packet::Protocol::RegistrationResponse => {
|
||||
let response =
|
||||
RegistrationResponse::parse_from_bytes(net_packet.payload())?;
|
||||
Ok(response)
|
||||
}
|
||||
_ => {
|
||||
Err(Error::Warn(format!("数据错误:{:?}", net_packet)))
|
||||
}
|
||||
}
|
||||
}
|
||||
Protocol::Error => {
|
||||
match InErrorPacket::new(
|
||||
net_packet.transport_protocol(),
|
||||
net_packet.payload(),
|
||||
) {
|
||||
Ok(e) => match e {
|
||||
InErrorPacket::TokenError => Err(Error::Stop("token错误".to_string())),
|
||||
InErrorPacket::Disconnect => Err(Error::Warn("断开连接".to_string())),
|
||||
InErrorPacket::AddressExhausted => Err(Error::Stop("地址用尽".to_string())),
|
||||
InErrorPacket::OtherError(e) => match e.message() {
|
||||
Ok(str) => Err(Error::Warn(str)),
|
||||
Err(e) => Err(Error::Warn(format!("{:?}", e))),
|
||||
},
|
||||
},
|
||||
Err(e) => Err(Error::Warn(format!("{:?}", e))),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
Err(Error::Warn(format!("数据错误:{:?}", net_packet)))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn registration_request_packet(
|
||||
token: String,
|
||||
mac_address: String,
|
||||
device_id: String,
|
||||
name: String,
|
||||
is_fast: bool,
|
||||
) -> Result<NetPacket<Vec<u8>>> {
|
||||
) -> crate::Result<NetPacket<Vec<u8>>> {
|
||||
let mut request = RegistrationRequest::new();
|
||||
request.token = token;
|
||||
request.mac_address = mac_address;
|
||||
request.device_id = device_id;
|
||||
request.name = name;
|
||||
request.is_fast = is_fast;
|
||||
let bytes = request.write_to_bytes()?;
|
||||
let buf = vec![0u8; 4 + bytes.len()];
|
||||
let buf = vec![0u8; 12 + bytes.len()];
|
||||
let mut net_packet = NetPacket::new(buf)?;
|
||||
net_packet.set_version(Version::V1);
|
||||
net_packet.set_protocol(Protocol::Service);
|
||||
net_packet.set_transport_protocol(service_packet::Protocol::RegistrationRequest.into());
|
||||
net_packet.set_ttl(255);
|
||||
net_packet.first_set_ttl(MAX_TTL);
|
||||
net_packet.set_payload(&bytes);
|
||||
Ok(net_packet)
|
||||
}
|
||||
|
||||
pub fn fast_registration(udp: &UdpSocket, server_address: SocketAddr) -> Result<()> {
|
||||
let last = REGISTRATION_TIME.load(Ordering::Relaxed);
|
||||
let new = Local::now().timestamp_millis();
|
||||
if new - last < 2000
|
||||
|| REGISTRATION_TIME
|
||||
pub struct Register {
|
||||
sender: Sender<Ipv4Addr>,
|
||||
server_address: SocketAddr,
|
||||
token: String,
|
||||
device_id: String,
|
||||
name: String,
|
||||
time: AtomicI64,
|
||||
}
|
||||
|
||||
impl Register {
|
||||
pub fn new(sender: Sender<Ipv4Addr>,
|
||||
server_address: SocketAddr,
|
||||
token: String,
|
||||
device_id: String,
|
||||
name: String, ) -> Self {
|
||||
Self {
|
||||
sender,
|
||||
server_address,
|
||||
token,
|
||||
device_id,
|
||||
name,
|
||||
time: AtomicI64::new(0),
|
||||
}
|
||||
}
|
||||
pub fn fast_register(&self) -> io::Result<()> {
|
||||
let last = self.time.load(Ordering::Relaxed);
|
||||
let new = Local::now().timestamp_millis();
|
||||
if new - last < 1000
|
||||
|| self.time
|
||||
.compare_exchange(last, new, Ordering::Relaxed, Ordering::Relaxed)
|
||||
.is_err()
|
||||
{
|
||||
//短时间不重复注册
|
||||
return Ok(());
|
||||
{
|
||||
//短时间不重复注册
|
||||
return Ok(());
|
||||
}
|
||||
log::info!("重新连接");
|
||||
let request_packet =
|
||||
registration_request_packet(self.token.clone(),
|
||||
self.device_id.clone(),
|
||||
self.name.clone(), false).unwrap();
|
||||
let buf = request_packet.buffer();
|
||||
self.sender.send_to_addr(buf, self.server_address)?;
|
||||
Ok(())
|
||||
}
|
||||
CONNECTION_STATUS.store(ConnectStatus::Connecting);
|
||||
let lock = REQUEST.read();
|
||||
let option = lock.clone();
|
||||
drop(lock);
|
||||
if let Some((token, mac_address, name)) = option {
|
||||
let request_packet = registration_request_packet(token, mac_address, name, true)?;
|
||||
udp.send_to(request_packet.buffer(), server_address)?;
|
||||
REGISTRATION_TIME.store(Local::now().timestamp_millis(), Ordering::Relaxed);
|
||||
return Ok(());
|
||||
}
|
||||
return Err(Error::Stop("注册信息不存在".to_string()));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user