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}