Complete networking integration gate (#58)
This commit is contained in:
@@ -16,7 +16,7 @@ use crate::packets::{
|
||||
AgentPausePacket, AgentResumePacket, CloseCircuitPacket, CompleteAgentMovementPacket,
|
||||
CompletePingCheckPacket, GenericStreamingMessagePacket, KickUserPacket, LogoutReplyPacket,
|
||||
LogoutRequestPacket, Packet, PacketType, RegionHandshakePacket, RegionHandshakeReplyPacket,
|
||||
StartPingCheckPacket, UseCircuitCodePacket,
|
||||
SimStatsPacket, StartPingCheckPacket, UseCircuitCodePacket,
|
||||
};
|
||||
use crate::udp_transport::{UDPBase, UDPPacketBuffer, UdpPacketHandler, UdpTransportConfig};
|
||||
use crate::{
|
||||
@@ -35,7 +35,7 @@ use std::fmt;
|
||||
use std::panic::{AssertUnwindSafe, catch_unwind};
|
||||
use std::sync::atomic::{AtomicBool, AtomicI32, AtomicU8, AtomicU32, AtomicU64, Ordering};
|
||||
use std::sync::mpsc::{Receiver, RecvTimeoutError, SyncSender, sync_channel};
|
||||
use std::sync::{Arc, Condvar, Mutex, RwLock, Weak};
|
||||
use std::sync::{Arc, Condvar, Mutex, OnceLock, RwLock, Weak};
|
||||
use std::thread::{self, JoinHandle};
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -96,6 +96,13 @@ fn positive_millisecond_duration(value: i32) -> Duration {
|
||||
Duration::from_millis(u64::try_from(value.max(1)).unwrap_or(1))
|
||||
}
|
||||
|
||||
fn environment_tick_count() -> i32 {
|
||||
static START: OnceLock<std::time::Instant> = OnceLock::new();
|
||||
let elapsed = START.get_or_init(std::time::Instant::now).elapsed();
|
||||
let wrapped = u32::try_from(elapsed.as_millis() & u128::from(u32::MAX)).unwrap_or_default();
|
||||
wrapped.cast_signed()
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
enum LogoutWaitOutcome {
|
||||
Reply,
|
||||
@@ -1011,7 +1018,6 @@ pub struct SimulatorData {
|
||||
manager: Mutex<Weak<NetworkManagerInner>>,
|
||||
transport: UDPBase,
|
||||
transport_thread: Mutex<Option<TransportThread>>,
|
||||
ping_id: AtomicU32,
|
||||
pause_serial: AtomicU32,
|
||||
}
|
||||
|
||||
@@ -1138,7 +1144,7 @@ impl Simulator {
|
||||
sim_version: String::new(),
|
||||
size_x: size_x.unwrap_or(Self::DEFAULT_REGION_SIZE_X),
|
||||
size_y: size_y.unwrap_or(Self::DEFAULT_REGION_SIZE_Y),
|
||||
stats: SimulatorSimStats,
|
||||
stats: SimulatorSimStats::default(),
|
||||
terrain: Vec::new(),
|
||||
terrain_base0: UUID::zero(),
|
||||
terrain_base1: UUID::zero(),
|
||||
@@ -1174,7 +1180,6 @@ impl Simulator {
|
||||
manager: Mutex::new(Weak::new()),
|
||||
transport,
|
||||
transport_thread: Mutex::new(None),
|
||||
ping_id: AtomicU32::new(0),
|
||||
pause_serial: AtomicU32::new(0),
|
||||
});
|
||||
*mutex(&simulator_reference) = Arc::downgrade(&data);
|
||||
@@ -1265,6 +1270,7 @@ impl Simulator {
|
||||
}
|
||||
}
|
||||
self.connected.store(true, Ordering::Release);
|
||||
self.stats.set_connect_time(environment_tick_count())?;
|
||||
self.handshake_complete.store(false, Ordering::Release);
|
||||
drop(transport_thread);
|
||||
self.native_use_circuit_code(true)?;
|
||||
@@ -1401,8 +1407,9 @@ impl Simulator {
|
||||
|
||||
pub fn native_send_ping(&self) -> Result<(), Error> {
|
||||
let mut ping = StartPingCheckPacket::new_with_constructor()?;
|
||||
ping.ping_id.ping_id = self.ping_id.fetch_add(1, Ordering::Relaxed).to_le_bytes()[0];
|
||||
ping.ping_id.ping_id = self.stats.get_and_increment_last_ping_id()?.to_le_bytes()[0];
|
||||
ping.ping_id.oldest_unacked = 0;
|
||||
self.stats.set_last_ping_sent(environment_tick_count())?;
|
||||
let data = ping.to_bytes_with_method()?;
|
||||
self.native_send_packet_data(
|
||||
data.clone(),
|
||||
@@ -1658,6 +1665,16 @@ impl UdpPacketHandler for SimulatorUdpHandler {
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let _ = simulator
|
||||
.stats
|
||||
.add_recv_bytes(i64::from(buffer.data_length));
|
||||
let _ = simulator.stats.increment_recv_packets();
|
||||
if payload
|
||||
.first()
|
||||
.is_some_and(|flags| flags & Helpers::MSG_RESENT != 0)
|
||||
{
|
||||
let _ = simulator.stats.increment_received_resends();
|
||||
}
|
||||
simulator.note_packet_received(packet.type_);
|
||||
let manager = mutex(&simulator.manager).upgrade();
|
||||
if let Some(manager) = manager {
|
||||
@@ -1674,11 +1691,29 @@ impl UdpPacketHandler for SimulatorUdpHandler {
|
||||
return;
|
||||
};
|
||||
let simulator = Simulator { caps: None, data };
|
||||
let _ = simulator
|
||||
.stats
|
||||
.add_sent_bytes(i64::try_from(bytes_sent).unwrap_or(i64::MAX));
|
||||
let _ = simulator.stats.increment_sent_packets();
|
||||
if buffer
|
||||
.data
|
||||
.first()
|
||||
.is_some_and(|flags| flags & Helpers::MSG_RESENT != 0)
|
||||
{
|
||||
let _ = simulator.stats.increment_resent_packets();
|
||||
}
|
||||
let manager = mutex(&simulator.manager).upgrade();
|
||||
if let Some(manager) = manager {
|
||||
manager.raise_packet_sent(buffer.data, bytes_sent, simulator);
|
||||
}
|
||||
}
|
||||
|
||||
fn packet_dropped(&self) {
|
||||
let Some(data) = mutex(&self.simulator).upgrade() else {
|
||||
return;
|
||||
};
|
||||
let _ = data.stats.increment_dropped_packets();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -1929,6 +1964,9 @@ impl NetworkManagerInner {
|
||||
simulator.handshake_complete.store(true, Ordering::Release);
|
||||
simulator.handshake_wait.notify_all();
|
||||
}
|
||||
PacketType::CompletePingCheck => {
|
||||
simulator.stats.record_pong(environment_tick_count());
|
||||
}
|
||||
PacketType::StartPingCheck => {
|
||||
let Some(raw_data) = raw_data else {
|
||||
return;
|
||||
@@ -2022,6 +2060,40 @@ impl NetworkManagerInner {
|
||||
"ClientInitiated".to_owned(),
|
||||
);
|
||||
}
|
||||
PacketType::SimStats => {
|
||||
if !self.client.settings_ref().packets.enable_sim_stats {
|
||||
return;
|
||||
}
|
||||
let Some(raw_data) = raw_data else {
|
||||
return;
|
||||
};
|
||||
let Ok(mut incoming) = SimStatsPacket::new_with_constructor() else {
|
||||
return;
|
||||
};
|
||||
let Ok(mut packet_end) = i32::try_from(raw_data.len()) else {
|
||||
return;
|
||||
};
|
||||
packet_end -= 1;
|
||||
let mut position = 0;
|
||||
let mut zero_buffer =
|
||||
vec![0_u8; UdpTransportConfig::default().max_decoded_packet_size];
|
||||
if incoming
|
||||
.from_bytes_with_bytes_int32_int32_bytes(
|
||||
raw_data.to_vec(),
|
||||
&mut position,
|
||||
&mut packet_end,
|
||||
Some(&mut zero_buffer),
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
return;
|
||||
}
|
||||
for stat in incoming.stat {
|
||||
simulator
|
||||
.stats
|
||||
.apply_server_stat(stat.stat_id, stat.stat_value);
|
||||
}
|
||||
}
|
||||
PacketType::DisableSimulator => {
|
||||
let _ = self.disconnect_simulator(simulator.clone(), false);
|
||||
}
|
||||
@@ -2196,8 +2268,8 @@ impl NetworkManagerInner {
|
||||
crate::NetworkManagerDisconnectType::NetworkTimeout,
|
||||
"NetworkTimeout".to_owned(),
|
||||
);
|
||||
} else {
|
||||
let _ = current.native_send_ping();
|
||||
} else if current.native_send_ping().is_ok() {
|
||||
let _ = current.stats.increment_sent_pings();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user