msp/conf.rs
1use crate::{
2 query, server, BedrockServer, LegacyBetaServer, LegacyServer, MspErr, NettyServer, QueryBasic,
3 QueryFull, Server,
4};
5use std::{
6 net::{Ipv4Addr, SocketAddr, ToSocketAddrs},
7 time::Duration,
8};
9
10/// Main struct used for configuring the connection.
11///
12/// By default, the port number for Java Edition is 25565,
13/// and for Bedrock Edition (including Pocket Edition), it is 19132.
14#[derive(Debug, Clone)]
15pub struct Conf {
16 /// Server IP address or a domain name.
17 pub host: String,
18 /// Server port.
19 pub port: u16,
20 /// See [SocketConf].
21 pub socket_conf: SocketConf,
22}
23
24/// Additional socket configuration.
25#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct SocketConf {
27 /// Set the read timeout for socket.
28 pub read_time_out: Option<Duration>,
29 /// Set the write timeout for socket.
30 pub write_timeout: Option<Duration>,
31 /// Specify the address for creating a UDP connection.
32 /// The default value is [Ipv4Addr::UNSPECIFIED].
33 pub rep_udp_ipv4: Ipv4Addr,
34 /// Specify the port for creating a UDP connection.
35 /// The default value is 8000.
36 pub rep_udp_port: u16,
37}
38
39impl Default for SocketConf {
40 fn default() -> Self {
41 Self {
42 read_time_out: None,
43 write_timeout: None,
44 rep_udp_ipv4: Ipv4Addr::UNSPECIFIED,
45 rep_udp_port: 5000,
46 }
47 }
48}
49
50impl ToSocketAddrs for Conf {
51 type Iter = std::vec::IntoIter<SocketAddr>;
52
53 fn to_socket_addrs(&self) -> std::io::Result<Self::Iter> {
54 (&*self.host, self.port).to_socket_addrs()
55 }
56}
57
58impl Conf {
59 /// Create a connection configuration using the default port.
60 ///
61 /// Default port is based on Java Edition(25565), to create a default port based on
62 /// Bedrock Edition(19132), use [Conf::create_with_port] to manually specify it.
63 ///
64 /// # Examples
65 ///
66 /// ```
67 /// # use msp::{Conf, SocketConf};
68 /// #
69 /// let conf = Conf::create("www.example.com");
70 /// #
71 /// # assert_eq!(conf.host, "www.example.com");
72 /// # assert_eq!(conf.port, 25565);
73 /// # assert_eq!(conf.socket_conf, SocketConf::default());
74 /// ```
75 pub fn create(host: &str) -> Self {
76 Self {
77 host: host.trim().into(),
78 port: 25565,
79 socket_conf: SocketConf::default(),
80 }
81 }
82
83 /// Create a connection configuration using the specified port.
84 ///
85 /// # Example
86 ///
87 /// ```
88 /// # use msp::{Conf};
89 /// #
90 /// let conf = Conf::create_with_port("www.example.com", 19132);
91 /// #
92 /// # assert_eq!(conf.port, 19132);
93 /// ```
94 pub fn create_with_port(host: &str, port: u16) -> Self {
95 Self {
96 host: host.trim().into(),
97 port,
98 socket_conf: SocketConf::default(),
99 }
100 }
101
102 /// Create a connection configuration by using a string.
103 ///
104 /// Attempting to split the given string into two parts,
105 /// with the first part being the host of the server and
106 /// the second part being the port of the server. If the port
107 /// cannot be converted to [u16], it will throw a [MspErr] error.
108 ///
109 /// # Example
110 ///
111 /// ```
112 /// # use msp::{Conf, MspErr};
113 /// #
114 /// # fn main() -> Result<(), MspErr> {
115 /// let conf = Conf::create_from_str("www.example.com:25565")?;
116 /// #
117 /// # assert_eq!(conf.host, "www.example.com");
118 /// # assert_eq!(conf.port, 25565);
119 /// #
120 /// # let conf = Conf::create_from_str("25565");
121 /// # assert!(conf.is_err());
122 /// # let conf = Conf::create_from_str("www.example.com:-1");
123 /// # assert!(conf.is_err());
124 /// # Ok(())
125 /// # }
126 /// ```
127 pub fn create_from_str(addr: &str) -> Result<Self, MspErr> {
128 let addr_split = addr.split(":").map(|x| x.trim()).collect::<Vec<_>>();
129
130 if addr_split.len() != 2 {
131 return Err(MspErr::DataErr(format!(
132 "Invalid IPv4 socket address syntax: {}",
133 addr
134 )));
135 }
136
137 match addr_split[1].parse::<u16>() {
138 Ok(port) => Ok(Self {
139 host: addr_split[0].into(),
140 port,
141 socket_conf: SocketConf::default(),
142 }),
143 Err(_) => Err(MspErr::DataErr(format!("Invalid port: {}", addr_split[1]))),
144 }
145 }
146
147 /// Get info from a modern Java Edition server.
148 ///
149 /// Using the [Server List Ping](https://wiki.vg/Server_List_Ping#Current_.281.7.2B.29) protocol.
150 /// Suitable for Java Edition servers version 1.7 and above. Return type is [Server].
151 ///
152 /// # Example
153 ///
154 /// ```no_run
155 /// use msp::{Conf, MspErr};
156 ///
157 /// fn main() -> Result<(), MspErr> {
158 /// let server = Conf::create("www.example.com");
159 /// let info = server.get_bedrock_server_status()?;
160 ///
161 /// Ok(())
162 /// }
163 /// ```
164 pub fn get_server_status(&self) -> Result<Server, MspErr> {
165 server::get_server_status(self)
166 }
167
168 /// Get info from a legacy Java Edition server.
169 ///
170 /// This uses a protocol which is compatible with the
171 /// client-server protocol as it was before the Netty rewrite.
172 /// Suitable for Java Edition servers version 1.6 and above. Return type is [NettyServer].
173 ///
174 /// # Example
175 ///
176 /// ```no_run
177 /// use msp::{Conf, MspErr};
178 ///
179 /// fn main() -> Result<(), MspErr> {
180 /// let server = Conf::create("www.example.com");
181 /// let info = server.get_netty_server_status()?;
182 ///
183 /// Ok(())
184 /// }
185 /// ```
186 pub fn get_netty_server_status(&self) -> Result<NettyServer, MspErr> {
187 server::get_netty_server_status(self)
188 }
189
190 /// Get info from a legacy Java Edition server.
191 ///
192 /// Suitable for Java Edition servers version 1.4 to 1.5. Return type is [LegacyServer].
193 /// # Example
194 ///
195 /// ```no_run
196 /// use msp::{Conf, MspErr};
197 ///
198 /// fn main() -> Result<(), MspErr> {
199 /// let server = Conf::create("www.example.com");
200 /// let info = server.get_legacy_server_status()?;
201 ///
202 /// Ok(())
203 /// }
204 /// ```
205 pub fn get_legacy_server_status(&self) -> Result<LegacyServer, MspErr> {
206 server::get_legacy_server_status(self)
207 }
208
209 /// Get info from a beta legacy Java Edition server in beta release.
210 ///
211 /// Suitable for Java Edition servers version beta 1.8 to 1.3.
212 /// Return type is [LegacyBetaServer].
213 ///
214 /// # Example
215 ///
216 /// ```no_run
217 /// use msp::{Conf, MspErr};
218 ///
219 /// fn main() -> Result<(), MspErr> {
220 /// let server = Conf::create("www.example.com");
221 /// let info = server.get_beta_legacy_server_status()?;
222 ///
223 /// Ok(())
224 /// }
225 /// ```
226 pub fn get_beta_legacy_server_status(&self) -> Result<LegacyBetaServer, MspErr> {
227 server::get_beta_legacy_server_status(&self)
228 }
229
230 /// Get **basic** info from a modern Java Edition server using the [Query](https://wiki.vg/Query) protocol.
231 ///
232 /// To use this protocol, you need to enable the enable-query option on the server side.
233 /// See [Server Config](https://wiki.vg/Query#Server_Config). Return type is [QueryBasic].
234 ///
235 /// # Example
236 ///
237 /// ```no_run
238 /// use msp::{Conf, MspErr};
239 ///
240 /// fn main() -> Result<(), MspErr> {
241 /// let server = Conf::create_with_port("www.example.com", 25565);
242 /// let info = server.query()?;
243 ///
244 /// Ok(())
245 /// }
246 /// ```
247 pub fn query(&self) -> Result<QueryBasic, MspErr> {
248 query::query_basic_status(self)
249 }
250
251 /// Get **full** info from a modern Java Edition server using the [Query](https://wiki.vg/Query) protocol.
252 ///
253 /// To use this protocol, you need to enable the enable-query option on the server side.
254 /// See [Server Config](https://wiki.vg/Query#Server_Config). Return type is [QueryFull].
255 ///
256 /// # Example
257 ///
258 /// ```no_run
259 /// use msp::{Conf, MspErr};
260 ///
261 /// fn main() -> Result<(), MspErr> {
262 /// let server = Conf::create_with_port("www.example.com", 25565);
263 /// let info = server.query_full()?;
264 ///
265 /// Ok(())
266 /// }
267 /// ```
268 pub fn query_full(&self) -> Result<QueryFull, MspErr> {
269 query::query_full_status(self)
270 }
271
272 /// Get info from a modern Bedrock Edition servers using the [RakNet](https://wiki.vg/Raknet_Protocol) protocol
273 ///
274 /// Suitable for Bedrock Edition servers version 1.16.220(protocol 431) and above.
275 ///
276 /// # Example
277 ///
278 /// ```no_run
279 /// use msp::{Conf, MspErr};
280 ///
281 /// fn main() -> Result<(), MspErr> {
282 /// let server = Conf::create_with_port("www.example.com", 19132);
283 /// let info = server.get_bedrock_server_status()?;
284 ///
285 /// Ok(())
286 /// }
287 /// ```
288 pub fn get_bedrock_server_status(&self) -> Result<BedrockServer, MspErr> {
289 server::get_bedrock_server_status(self)
290 }
291}