annotate src/lib.rs @ 6:a7893294e9b2

Make the crate compilable on non-linux systems This makes the crate compile on other operating systems. Since systemd is only supported on Linux, it simply disables systemd features on other systems. The API is still the same, just parsing `systemd://` string will return an error.
author Martin Habovstiak <martin.habovstiak@gmail.com>
date Fri, 27 Nov 2020 16:15:57 +0100
parents 66c0e10c89fc
children 9731ff589d9c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
1 //! A convenience crate for optionally supporting systemd socket activation.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
2 //!
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
3 //! ## About
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
4 //!
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
5 //! The goal of this crate is to make socket activation with systemd in your project trivial.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
6 //! It provides a replacement for `std::net::SocketAddr` that allows parsing the bind address from string just like the one from `std`
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
7 //! but on top of that also allows `systemd://socket_name` format that tells it to use systemd activation with given socket name.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
8 //! Then it provides a method to bind the address which will return the socket from systemd if available.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
9 //!
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
10 //! The provided type supports conversions from various types of strings and also `serde` and `parse_arg` via feature flag.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
11 //! Thanks to this the change to your code should be minimal - parsing will continue to work, it'll just allow a new format.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
12 //! You only need to change the code to use `SocketAddr::bind()` instead of `TcpListener::bind()` for binding.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
13 //!
6
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
14 //! You also don't need to worry about conditional compilation to ensure OS compatibility.
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
15 //! This crate handles that for you by disabling systemd on non-linux systems.
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
16 //!
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
17 //! Further, the crate also provides methods for binding `tokio` 0.2, 0.3, and `async_std` sockets if the appropriate features are
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
18 //! activated.
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
19 //!
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
20 //! ## Example
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
21 //!
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
22 //! ```no_run
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
23 //! use systemd_socket::SocketAddr;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
24 //! use std::convert::TryFrom;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
25 //! use std::io::Write;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
26 //!
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
27 //! let mut args = std::env::args_os();
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
28 //! let program_name = args.next().expect("unknown program name");
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
29 //! let socket_addr = args.next().expect("missing socket address");
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
30 //! let socket_addr = SocketAddr::try_from(socket_addr).expect("failed to parse socket address");
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
31 //! let socket = socket_addr.bind().expect("failed to bind socket");
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
32 //!
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
33 //! loop {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
34 //! let _ = socket
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
35 //! .accept()
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
36 //! .expect("failed to accept connection")
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
37 //! .0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
38 //! .write_all(b"Hello world!")
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
39 //! .map_err(|err| eprintln!("Failed to send {}", err));
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
40 //! }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
41 //! ```
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
42 //!
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
43 //! ## Features
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
44 //!
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
45 //! * `serde` - implements `serde::Deserialize` for `SocketAddr`
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
46 //! * `parse_arg` - implements `parse_arg::ParseArg` for `SocketAddr`
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
47 //! * `tokio_0_2` - adds `bind_tokio_0_2` method to `SocketAddr`
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
48 //! * `tokio_0_3` - adds `bind_tokio_0_3` method to `SocketAddr`
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
49 //! * `async_std` - adds `bind_async_std` method to `SocketAddr`
3
0edcde404b02 Added information about MSRV
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 2
diff changeset
50 //!
0edcde404b02 Added information about MSRV
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 2
diff changeset
51 //! ## MSRV
0edcde404b02 Added information about MSRV
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 2
diff changeset
52 //!
0edcde404b02 Added information about MSRV
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 2
diff changeset
53 //! This crate must always compile with the latest Rust available in the latest Debian stable.
0edcde404b02 Added information about MSRV
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 2
diff changeset
54 //! That is currently Rust 1.41.1. (Debian 10 - Buster)
0edcde404b02 Added information about MSRV
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 2
diff changeset
55
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
56
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
57 #![deny(missing_docs)]
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
58
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
59 pub mod error;
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
60 mod resolv_addr;
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
61
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
62 use std::convert::{TryFrom, TryInto};
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
63 use std::fmt;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
64 use std::ffi::{OsStr, OsString};
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
65 use crate::error::*;
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
66 use crate::resolv_addr::ResolvAddr;
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
67
6
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
68 #[cfg(not(linux))]
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
69 use std::convert::Infallible as Never;
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
70
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
71 #[cfg(linux)]
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
72 pub(crate) mod systemd_sockets {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
73 use std::fmt;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
74 use std::sync::Mutex;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
75 use libsystemd::activation::FileDescriptor;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
76 use libsystemd::errors::Error as LibSystemdError;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
77 use libsystemd::errors::Result as LibSystemdResult;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
78
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
79 #[derive(Debug)]
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
80 pub(crate) struct Error(&'static Mutex<LibSystemdError>);
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
81
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
82 impl fmt::Display for Error {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
83 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
84 fmt::Display::fmt(&*self.0.lock().expect("mutex poisoned"), f)
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
85 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
86 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
87
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
88 // No source we can't keep the mutex locked
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
89 impl std::error::Error for Error {}
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
90
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
91 pub(crate) fn take(name: &str) -> Result<Option<FileDescriptor>, Error> {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
92 match &*SYSTEMD_SOCKETS {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
93 Ok(sockets) => Ok(sockets.take(name)),
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
94 Err(error) => Err(Error(error))
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
95 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
96 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
97
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
98 struct SystemdSockets(std::sync::Mutex<std::collections::HashMap<String, FileDescriptor>>);
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
99
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
100 impl SystemdSockets {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
101 fn new() -> LibSystemdResult<Self> {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
102 // MUST BE true FOR SAFETY!!!
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
103 let map = libsystemd::activation::receive_descriptors_with_names(/*unset env = */ true)?.into_iter().map(|(fd, name)| (name, fd)).collect();
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
104 Ok(SystemdSockets(Mutex::new(map)))
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
105 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
106
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
107 fn take(&self, name: &str) -> Option<FileDescriptor> {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
108 // MUST remove THE SOCKET FOR SAFETY!!!
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
109 self.0.lock().expect("poisoned mutex").remove(name)
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
110 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
111 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
112
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
113 lazy_static::lazy_static! {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
114 // We don't panic in order to let the application handle the error later
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
115 static ref SYSTEMD_SOCKETS: Result<SystemdSockets, Mutex<LibSystemdError>> = SystemdSockets::new().map_err(Mutex::new);
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
116 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
117 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
118
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
119 /// Socket address that can be an ordinary address or a systemd socket
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
120 ///
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
121 /// This is the core type of this crate that abstracts possible addresses.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
122 /// It can be (fallibly) converted from various types of strings or deserialized with `serde`.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
123 /// After it's created, it can be bound as `TcpListener` from `std` or even `tokio` or `async_std`
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
124 /// if the appropriate feature is enabled.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
125 ///
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
126 /// Optional dependencies on `parse_arg` and `serde` make it trivial to use with
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
127 /// [`configure_me`](https://crates.io/crates/configure_me).
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
128 #[derive(Debug)]
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
129 #[cfg_attr(feature = "serde", derive(serde_crate::Deserialize), serde(crate = "serde_crate", try_from = "serde_str_helpers::DeserBorrowStr"))]
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
130 pub struct SocketAddr(SocketAddrInner);
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
131
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
132 impl SocketAddr {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
133 /// Creates `std::net::TcpListener`
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
134 ///
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
135 /// This method either `binds` the socket, if the address was provided or uses systemd socket
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
136 /// if the socket name was provided.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
137 pub fn bind(self) -> Result<std::net::TcpListener, BindError> {
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
138 match self.0 {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
139 SocketAddrInner::Ordinary(addr) => match std::net::TcpListener::bind(addr) {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
140 Ok(socket) => Ok(socket),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
141 Err(error) => Err(BindErrorInner::BindFailed { addr, error, }.into()),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
142 },
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
143 SocketAddrInner::WithHostname(addr) => match std::net::TcpListener::bind(addr.as_str()) {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
144 Ok(socket) => Ok(socket),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
145 Err(error) => Err(BindErrorInner::BindOrResolvFailed { addr, error, }.into()),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
146 },
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
147 SocketAddrInner::Systemd(socket_name) => Self::get_systemd(socket_name).map(|(socket, _)| socket),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
148 }
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
149 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
150
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
151 /// Creates `tokio::net::TcpListener`
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
152 ///
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
153 /// To be specific, it binds the socket or converts systemd socket to `tokio` 0.2 socket.
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
154 ///
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
155 /// This method either `binds` the socket, if the address was provided or uses systemd socket
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
156 /// if the socket name was provided.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
157 #[cfg(feature = "tokio_0_2")]
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
158 pub async fn bind_tokio_0_2(self) -> Result<tokio_0_2::net::TcpListener, TokioBindError> {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
159 match self.0 {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
160 SocketAddrInner::Ordinary(addr) => match tokio_0_2::net::TcpListener::bind(addr).await {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
161 Ok(socket) => Ok(socket),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
162 Err(error) => Err(TokioBindError::Bind(BindErrorInner::BindFailed { addr, error, }.into())),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
163 },
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
164 SocketAddrInner::WithHostname(addr) => match tokio_0_2::net::TcpListener::bind(addr.as_str()).await {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
165 Ok(socket) => Ok(socket),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
166 Err(error) => Err(TokioBindError::Bind(BindErrorInner::BindOrResolvFailed { addr, error, }.into())),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
167 },
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
168 SocketAddrInner::Systemd(socket_name) => {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
169 let (socket, addr) = Self::get_systemd(socket_name)?;
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
170 socket.try_into().map_err(|error| TokioConversionError { addr, error, }.into())
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
171 },
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
172 }
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
173 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
174
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
175 /// Creates `tokio::net::TcpListener`
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
176 ///
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
177 /// To be specific, it binds the socket or converts systemd socket to `tokio` 0.3 socket.
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
178 ///
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
179 /// This method either `binds` the socket, if the address was provided or uses systemd socket
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
180 /// if the socket name was provided.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
181 #[cfg(feature = "tokio_0_3")]
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
182 pub async fn bind_tokio_0_3(self) -> Result<tokio_0_3::net::TcpListener, TokioBindError> {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
183 match self.0 {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
184 SocketAddrInner::Ordinary(addr) => match tokio_0_3::net::TcpListener::bind(addr).await {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
185 Ok(socket) => Ok(socket),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
186 Err(error) => Err(TokioBindError::Bind(BindErrorInner::BindFailed { addr, error, }.into())),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
187 },
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
188 SocketAddrInner::WithHostname(addr) => match tokio_0_3::net::TcpListener::bind(addr.as_str()).await {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
189 Ok(socket) => Ok(socket),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
190 Err(error) => Err(TokioBindError::Bind(BindErrorInner::BindOrResolvFailed { addr, error, }.into())),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
191 },
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
192 SocketAddrInner::Systemd(socket_name) => {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
193 let (socket, addr) = Self::get_systemd(socket_name)?;
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
194 socket.try_into().map_err(|error| TokioConversionError { addr, error, }.into())
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
195 },
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
196 }
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
197 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
198
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
199 /// Creates `async_std::net::TcpListener`
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
200 ///
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
201 /// To be specific, it binds the socket or converts systemd socket to `async_std` socket.
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
202 ///
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
203 /// This method either `binds` the socket, if the address was provided or uses systemd socket
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
204 /// if the socket name was provided.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
205 #[cfg(feature = "async-std")]
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
206 pub async fn bind_async_std(self) -> Result<async_std::net::TcpListener, BindError> {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
207 match self.0 {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
208 SocketAddrInner::Ordinary(addr) => match async_std::net::TcpListener::bind(addr).await {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
209 Ok(socket) => Ok(socket),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
210 Err(error) => Err(BindErrorInner::BindFailed { addr, error, }.into()),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
211 },
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
212 SocketAddrInner::WithHostname(addr) => match async_std::net::TcpListener::bind(addr.as_str()).await {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
213 Ok(socket) => Ok(socket),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
214 Err(error) => Err(BindErrorInner::BindOrResolvFailed { addr, error, }.into()),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
215 },
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
216 SocketAddrInner::Systemd(socket_name) => {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
217 let (socket, _) = Self::get_systemd(socket_name)?;
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
218 Ok(socket.into())
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
219 },
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
220 }
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
221 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
222
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
223 // We can't impl<T: Deref<Target=str> + Into<String>> TryFrom<T> for SocketAddr because of orphan
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
224 // rules.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
225 fn try_from_generic<'a, T>(string: T) -> Result<Self, ParseError> where T: 'a + std::ops::Deref<Target=str> + Into<String> {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
226 if string.starts_with(SYSTEMD_PREFIX) {
6
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
227 #[cfg(linux)]
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
228 {
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
229 let name_len = string.len() - SYSTEMD_PREFIX.len();
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
230 match string[SYSTEMD_PREFIX.len()..].chars().enumerate().find(|(_, c)| !c.is_ascii() || *c < ' ' || *c == ':') {
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
231 None if name_len <= 255 => Ok(SocketAddr(SocketAddrInner::Systemd(string.into()))),
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
232 None => Err(ParseErrorInner::LongSocketName { string: string.into(), len: name_len }.into()),
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
233 Some((pos, c)) => Err(ParseErrorInner::InvalidCharacter { string: string.into(), c, pos, }.into()),
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
234 }
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
235 }
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
236 #[cfg(not(linux))]
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
237 {
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
238 Err(ParseErrorInner::SystemdUnsupported(string.into()).into())
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
239 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
240 } else {
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
241 match string.parse() {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
242 Ok(addr) => Ok(SocketAddr(SocketAddrInner::Ordinary(addr))),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
243 Err(_) => Ok(SocketAddr(SocketAddrInner::WithHostname(ResolvAddr::try_from_generic(string).map_err(ParseErrorInner::ResolvAddr)?))),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
244 }
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
245 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
246 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
247
6
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
248 #[cfg(linux)]
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
249 fn get_systemd(socket_name: String) -> Result<(std::net::TcpListener, SocketAddrInner), BindError> {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
250 use libsystemd::activation::IsType;
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
251 use std::os::unix::io::{FromRawFd, IntoRawFd};
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
252
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
253 let socket = systemd_sockets::take(&socket_name[SYSTEMD_PREFIX.len()..]).map_err(BindErrorInner::ReceiveDescriptors)?;
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
254 // Safety: The environment variable is unset, so that no other calls can get the
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
255 // descriptors. The descriptors are taken from the map, not cloned, so they can't
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
256 // be duplicated.
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
257 unsafe {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
258 // match instead of combinators to avoid cloning socket_name
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
259 match socket {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
260 Some(socket) if socket.is_inet() => Ok((std::net::TcpListener::from_raw_fd(socket.into_raw_fd()), SocketAddrInner::Systemd(socket_name))),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
261 Some(_) => Err(BindErrorInner::NotInetSocket(socket_name).into()),
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
262 None => Err(BindErrorInner::MissingDescriptor(socket_name).into())
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
263 }
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
264 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
265 }
6
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
266
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
267 // This approach makes the rest of the code much simpler as it doesn't require sprinkling it
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
268 // with #[cfg(linux)] yet still statically guarantees it won't execute.
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
269 #[cfg(not(linux))]
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
270 fn get_systemd(socket_name: Never) -> Result<(std::net::TcpListener, SocketAddrInner), BindError> {
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
271 match socket_name {}
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
272 }
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
273 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
274
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
275 /// Displays the address in format that can be parsed again.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
276 ///
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
277 /// **Important: While I don't expect this impl to change, don't rely on it!**
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
278 /// It should be used mostly for debugging/logging.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
279 impl fmt::Display for SocketAddr {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
280 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
281 fmt::Display::fmt(&self.0, f)
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
282 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
283 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
284
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
285 impl fmt::Display for SocketAddrInner {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
286 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
287 match self {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
288 SocketAddrInner::Ordinary(addr) => fmt::Display::fmt(addr, f),
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
289 SocketAddrInner::Systemd(addr) => fmt::Display::fmt(addr, f),
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
290 SocketAddrInner::WithHostname(addr) => fmt::Display::fmt(addr, f),
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
291 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
292 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
293 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
294
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
295 // PartialEq for testing, I'm not convinced it should be exposed
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
296 #[derive(Debug, PartialEq)]
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
297 enum SocketAddrInner {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
298 Ordinary(std::net::SocketAddr),
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
299 WithHostname(resolv_addr::ResolvAddr),
6
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
300 #[cfg(linux)]
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
301 Systemd(String),
6
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
302 #[cfg(not(linux))]
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
303 #[allow(dead_code)]
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
304 Systemd(Never),
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
305 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
306
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
307 const SYSTEMD_PREFIX: &str = "systemd://";
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
308
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
309 impl std::str::FromStr for SocketAddr {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
310 type Err = ParseError;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
311
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
312 fn from_str(s: &str) -> Result<Self, Self::Err> {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
313 SocketAddr::try_from_generic(s)
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
314 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
315 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
316
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
317 impl<'a> TryFrom<&'a str> for SocketAddr {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
318 type Error = ParseError;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
319
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
320 fn try_from(s: &'a str) -> Result<Self, Self::Error> {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
321 SocketAddr::try_from_generic(s)
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
322 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
323 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
324
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
325 impl TryFrom<String> for SocketAddr {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
326 type Error = ParseError;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
327
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
328 fn try_from(s: String) -> Result<Self, Self::Error> {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
329 SocketAddr::try_from_generic(s)
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
330 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
331 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
332
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
333 impl<'a> TryFrom<&'a OsStr> for SocketAddr {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
334 type Error = ParseOsStrError;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
335
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
336 fn try_from(s: &'a OsStr) -> Result<Self, Self::Error> {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
337 s.to_str().ok_or(ParseOsStrError::InvalidUtf8)?.try_into().map_err(Into::into)
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
338 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
339 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
340
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
341 impl TryFrom<OsString> for SocketAddr {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
342 type Error = ParseOsStrError;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
343
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
344 fn try_from(s: OsString) -> Result<Self, Self::Error> {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
345 s.into_string().map_err(|_| ParseOsStrError::InvalidUtf8)?.try_into().map_err(Into::into)
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
346 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
347 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
348
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
349 #[cfg(feature = "serde")]
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
350 impl<'a> TryFrom<serde_str_helpers::DeserBorrowStr<'a>> for SocketAddr {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
351 type Error = ParseError;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
352
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
353 fn try_from(s: serde_str_helpers::DeserBorrowStr<'a>) -> Result<Self, Self::Error> {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
354 SocketAddr::try_from_generic(std::borrow::Cow::from(s))
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
355 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
356 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
357
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
358 #[cfg(feature = "parse_arg")]
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
359 impl parse_arg::ParseArg for SocketAddr {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
360 type Error = ParseOsStrError;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
361
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
362 fn describe_type<W: fmt::Write>(mut writer: W) -> fmt::Result {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
363 std::net::SocketAddr::describe_type(&mut writer)?;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
364 write!(writer, " or a systemd socket name prefixed with systemd://")
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
365 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
366
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
367 fn parse_arg(arg: &OsStr) -> Result<Self, Self::Error> {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
368 arg.try_into()
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
369 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
370
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
371 fn parse_owned_arg(arg: OsString) -> Result<Self, Self::Error> {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
372 arg.try_into()
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
373 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
374 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
375
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
376 #[cfg(test)]
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
377 mod tests {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
378 use super::{SocketAddr, SocketAddrInner};
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
379
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
380 #[test]
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
381 fn parse_ordinary() {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
382 assert_eq!("127.0.0.1:42".parse::<SocketAddr>().unwrap().0, SocketAddrInner::Ordinary(([127, 0, 0, 1], 42).into()));
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
383 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
384
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
385 #[test]
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
386 fn parse_systemd() {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
387 assert_eq!("systemd://foo".parse::<SocketAddr>().unwrap().0, SocketAddrInner::Systemd("systemd://foo".to_owned()));
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
388 }
2
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
389
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
390 #[test]
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
391 #[should_panic]
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
392 fn parse_systemd_fail_control() {
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
393 "systemd://foo\n".parse::<SocketAddr>().unwrap();
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
394 }
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
395
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
396 #[test]
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
397 #[should_panic]
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
398 fn parse_systemd_fail_colon() {
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
399 "systemd://foo:".parse::<SocketAddr>().unwrap();
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
400 }
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
401
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
402 #[test]
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
403 #[should_panic]
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
404 fn parse_systemd_fail_non_ascii() {
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
405 "systemd://fooĆ”".parse::<SocketAddr>().unwrap();
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
406 }
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
407
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
408 #[test]
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
409 #[should_panic]
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
410 fn parse_systemd_fail_too_long() {
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
411 "systemd://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".parse::<SocketAddr>().unwrap();
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
412 }
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
413 }