Complete networking integration gate (#58)
All checks were successful
Native code generation / deterministic (push) Successful in 12m1s
Imaging and meshing gate / native (push) Successful in 4m3s
Native Rust workspace compile / compile (push) Successful in 4m6s

This commit is contained in:
2026-08-09 19:45:06 +00:00
parent 1fd127bd8a
commit c8b2317e13
13 changed files with 978 additions and 397 deletions

View File

@@ -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();
}
}