-
Notifications
You must be signed in to change notification settings - Fork 144
Expand file tree
/
Copy pathlib.rs
More file actions
148 lines (131 loc) · 3.99 KB
/
lib.rs
File metadata and controls
148 lines (131 loc) · 3.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#![forbid(unsafe_code)]
//! The networking implementation for the server, based on async/await
//! and Tokio. Contains a listener task which accepts new connections
//! and a worker task for each client which reads and writes packets.
pub const PROTOCOL_VERSION: u32 = 404;
pub const SERVER_VERSION: &str = "Feather 1.13.2";
#[macro_use]
extern crate feather_core;
use derivative::Derivative;
use feather_core::anvil::player::PlayerData;
use feather_core::util::Position;
use feather_server_types::{
Config, PacketBuffers, ServerToWorkerMessage, Uuid, WorkerToServerMessage, WrappedBanInfo,
};
use fecs::Entity;
use once_cell::sync::Lazy;
use parking_lot::Mutex;
use std::net::SocketAddr;
use std::sync::atomic::AtomicU32;
use std::sync::Arc;
use tokio::net::TcpListener;
mod initial_handler;
mod listener;
mod worker;
#[derive(Debug)]
#[allow(clippy::large_enum_variant)]
pub enum ListenerToServerMessage {
/// Notifies the server thread that a new client connected.
///
/// This message is sent after initial handling completes.
NewClient(NewClientInfo),
/// Requests that the server create an empty `Entity` and send
/// it to the listener. This entity will later be used as a player.
RequestEntity,
/// Tells the server that a requested entity is no longer needed
/// and may be deleted.
///
/// This typically happens when a connection comes in the form
/// of a status ping, where the entity is no longer needed
/// but has never served any purpose.
DeleteEntity(Entity),
}
#[derive(Debug)]
pub enum ServerToListenerMessage {
/// Sends an entity to the listener as a response
/// to `ListenerToServerMessage::RequestEntity`.
Entity(Entity),
}
#[derive(Derivative)]
#[derivative(Debug)]
pub struct NewClientInfo {
pub ip: SocketAddr,
pub username: String,
pub profile: Vec<mojang_api::ProfileProperty>,
pub uuid: Uuid,
pub data: PlayerData,
pub position: Position,
#[derivative(Debug = "ignore")]
pub sender: flume::Sender<ServerToWorkerMessage>,
#[derivative(Debug = "ignore")]
pub receiver: flume::Receiver<WorkerToServerMessage>,
pub entity: Entity,
}
pub struct NetworkIoManager {
pub rx: Mutex<flume::Receiver<ListenerToServerMessage>>,
pub tx: flume::Sender<ServerToListenerMessage>,
/// Used for testing
pub listener_tx: flume::Sender<ListenerToServerMessage>,
}
impl NetworkIoManager {
/// Starts a new IO listener.
pub fn start(
listener: TcpListener,
config: Arc<Config>,
ban_info: WrappedBanInfo,
player_count: Arc<AtomicU32>,
server_icon: Arc<Option<String>>,
packet_buffers: Arc<PacketBuffers>,
) -> Self {
let (listener_tx, rx) = flume::bounded(16);
let (tx, listener_rx) = flume::bounded(16);
let future = run_listener(
listener,
listener_tx.clone(),
listener_rx,
(config, ban_info),
player_count,
server_icon,
packet_buffers,
);
if cfg!(test) {
let rt = tokio::runtime::Runtime::new().unwrap();
rt.spawn(future);
} else {
tokio::spawn(future);
}
Self {
rx: Mutex::new(rx),
tx,
listener_tx,
}
}
}
/// Initializes certain static variables.
pub fn init() {
Lazy::force(&initial_handler::RSA_KEY);
}
async fn run_listener(
listener: TcpListener,
tx: flume::Sender<ListenerToServerMessage>,
rx: flume::Receiver<ServerToListenerMessage>,
config_bans: (Arc<Config>, WrappedBanInfo),
player_count: Arc<AtomicU32>,
server_icon: Arc<Option<String>>,
packet_buffers: Arc<PacketBuffers>,
) {
if let Err(e) = listener::run_listener(
listener,
tx,
rx,
config_bans,
player_count,
server_icon,
packet_buffers,
)
.await
{
log::error!("An error occurred while binding to socket: {:?}", e);
std::process::exit(1);
}
}