annotate src/lib.rs @ 29:efc69e99db70

Set socket to nonblocking before passing it to tokio.
author Paul Fisher <paul@pfish.zone>
date Sat, 19 Apr 2025 01:41:25 -0400
parents cfef4593e207
children
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.
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
2 //!
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
3 //! ## About
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
4 //!
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
5 //! **Important:** because of various reasons it is recommended to call the [`init`] function at
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
6 //! the start of your program!
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
7 //!
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
8 //! 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
9 //! 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
10 //! 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
11 //! Then it provides a method to bind the address which will return the socket from systemd if available.
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
12 //!
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
13 //! 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
14 //! 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
15 //! 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
16 //!
6
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
17 //! 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
18 //! 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
19 //!
21
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
20 //! Further, the crate also provides methods for binding `tokio` 1.0, 0.2, 0.3, and `async_std` sockets if the appropriate features are
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
21 //! activated.
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
22 //!
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
23 //! ## Example
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
24 //!
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
25 //! ```no_run
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
26 //! use systemd_socket::SocketAddr;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
27 //! use std::convert::TryFrom;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
28 //! use std::io::Write;
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
29 //!
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
30 //! systemd_socket::init().expect("Failed to initialize systemd sockets");
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
31 //! let mut args = std::env::args_os();
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
32 //! let program_name = args.next().expect("unknown program name");
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
33 //! let socket_addr = args.next().expect("missing socket address");
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
34 //! 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
35 //! let socket = socket_addr.bind().expect("failed to bind socket");
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
36 //!
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
37 //! loop {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
38 //! let _ = socket
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
39 //! .accept()
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
40 //! .expect("failed to accept connection")
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
41 //! .0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
42 //! .write_all(b"Hello world!")
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
43 //! .map_err(|err| eprintln!("Failed to send {}", err));
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 //! ```
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
46 //!
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
47 //! ## Features
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
48 //!
13
f740dadd2948 Added enable_systemd feature
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 11
diff changeset
49 //! * `enable_systemd` - on by default, the existence of this feature can allow your users to turn
f740dadd2948 Added enable_systemd feature
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 11
diff changeset
50 //! off systemd support if they don't need it. Note that it's already disabled on non-linux
f740dadd2948 Added enable_systemd feature
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 11
diff changeset
51 //! systems, so you don't need to care about that.
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
52 //! * `serde` - implements `serde::Deserialize` for `SocketAddr`
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
53 //! * `parse_arg` - implements `parse_arg::ParseArg` for `SocketAddr`
21
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
54 //! * `tokio` - adds `bind_tokio` method to `SocketAddr` (tokio 1.0)
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
55 //! * `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
56 //! * `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
57 //! * `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
58 //!
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
59 //! ## Soundness
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
60 //!
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
61 //! The systemd file descriptors are transferred using environment variables and since they are
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
62 //! file descriptors, they should have move semantics. However environment variables in Rust do not
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
63 //! have move semantics and even modifying them is very dangerous.
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
64 //!
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
65 //! Because of this, the crate only allows initialization when there's only one thread running.
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
66 //! However that still doesn't prevent all possible problems: if some other code closes file
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
67 //! descriptors stored in those environment variables you can get an invalid socket.
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
68 //!
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
69 //! This situation is obviously ridiculous because there shouldn't be a reason to use another
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
70 //! library to do the same thing. It could also be argued that whichever code doesn't clear the
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
71 //! evironment variable is broken (even though understandably) and it's not a fault of this library.
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
72 //!
3
0edcde404b02 Added information about MSRV
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 2
diff changeset
73 //! ## MSRV
0edcde404b02 Added information about MSRV
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 2
diff changeset
74 //!
0edcde404b02 Added information about MSRV
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 2
diff changeset
75 //! This crate must always compile with the latest Rust available in the latest Debian stable.
26
0feab4f4c2ce Relax version requirements and update MSRV
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 25
diff changeset
76 //! That is currently Rust 1.48.0. (Debian 11 - Bullseye)
3
0edcde404b02 Added information about MSRV
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 2
diff changeset
77
22
f33e2c048104 Enable `doc_auto_cfg` in docs.rs builds
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 21
diff changeset
78 #![cfg_attr(docsrs, feature(doc_auto_cfg))]
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
79 #![deny(missing_docs)]
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
80
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
81 pub mod error;
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
82 mod resolv_addr;
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
83
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
84 use crate::error::*;
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
85 use crate::resolv_addr::ResolvAddr;
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
86 use std::convert::{TryFrom, TryInto};
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
87 use std::ffi::{OsStr, OsString};
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
88 use std::fmt;
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
89
16
bc76507dd878 Fixed conditional compilation based on OS
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 13
diff changeset
90 #[cfg(not(all(target_os = "linux", feature = "enable_systemd")))]
6
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
91 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
92
16
bc76507dd878 Fixed conditional compilation based on OS
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 13
diff changeset
93 #[cfg(all(target_os = "linux", feature = "enable_systemd"))]
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
94 pub(crate) mod systemd_sockets {
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
95 use libsystemd::activation::FileDescriptor;
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
96 use libsystemd::errors::SdError as LibSystemdError;
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
97 use std::fmt;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
98 use std::sync::Mutex;
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 #[derive(Debug)]
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
101 pub(crate) struct Error(&'static Mutex<InitError>);
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
102
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
103 impl fmt::Display for Error {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
104 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
105 use std::error::Error as _;
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
106
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
107 let guard = self.0.lock().expect("mutex poisoned");
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
108 fmt::Display::fmt(&*guard, f)?;
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
109 let mut source_opt = guard.source();
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
110 while let Some(source) = source_opt {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
111 write!(f, ": {}", source)?;
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
112 source_opt = source.source();
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
113 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
114 Ok(())
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
115 }
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
25
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
118 type StoredSocket = Result<Socket, ()>;
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
119
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
120 // No source we can't keep the mutex locked
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
121 impl std::error::Error for Error {}
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
122
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
123 pub(crate) unsafe fn init(protected: bool) -> Result<(), InitError> {
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
124 SYSTEMD_SOCKETS
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
125 .get_or_try_init(|| SystemdSockets::new(protected, true).map(Ok))
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
126 .map(drop)
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
127 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
128
25
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
129 pub(crate) fn take(name: &str) -> Result<Option<StoredSocket>, Error> {
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
130 let sockets = SYSTEMD_SOCKETS
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
131 .get_or_init(|| SystemdSockets::new_protected(false).map_err(Mutex::new));
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
132 match sockets {
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
133 Ok(sockets) => Ok(sockets.take(name)),
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
134 Err(error) => Err(Error(error)),
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
135 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
136 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
137
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
138 #[derive(Debug)]
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
139 pub(crate) enum InitError {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
140 OpenStatus(std::io::Error),
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
141 ReadStatus(std::io::Error),
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
142 ThreadCountNotFound,
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
143 MultipleThreads,
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
144 LibSystemd(LibSystemdError),
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
145 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
146
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
147 impl From<LibSystemdError> for InitError {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
148 fn from(value: LibSystemdError) -> Self {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
149 Self::LibSystemd(value)
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
150 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
151 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
152
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
153 impl fmt::Display for InitError {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
154 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
155 match self {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
156 Self::OpenStatus(_) => write!(f, "failed to open /proc/self/status"),
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
157 Self::ReadStatus(_) => write!(f, "failed to read /proc/self/status"),
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
158 Self::ThreadCountNotFound => {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
159 write!(f, "/proc/self/status doesn't contain Threads entry")
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
160 }
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
161 Self::MultipleThreads => write!(f, "there is more than one thread running"),
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
162 // We have nothing to say about the error, let's flatten it
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
163 Self::LibSystemd(error) => fmt::Display::fmt(error, f),
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
164 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
165 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
166 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
167
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
168 impl std::error::Error for InitError {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
169 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
170 match self {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
171 Self::OpenStatus(error) => Some(error),
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
172 Self::ReadStatus(error) => Some(error),
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
173 Self::ThreadCountNotFound => None,
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
174 Self::MultipleThreads => None,
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
175 // We have nothing to say about the error, let's flatten it
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
176 Self::LibSystemd(error) => error.source(),
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
177 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
178 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
179 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
180
25
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
181 pub(crate) enum Socket {
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
182 TcpListener(std::net::TcpListener),
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
183 }
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
184
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
185 impl std::convert::TryFrom<FileDescriptor> for Socket {
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
186 type Error = ();
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
187
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
188 fn try_from(value: FileDescriptor) -> Result<Self, Self::Error> {
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
189 use libsystemd::activation::IsType;
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
190 use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
25
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
191
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
192 fn set_cloexec(fd: std::os::unix::io::RawFd) {
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
193 // SAFETY: The function is a harmless syscall
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
194 let flags = unsafe { libc::fcntl(fd, libc::F_GETFD) };
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
195 if flags != -1 && flags & libc::FD_CLOEXEC == 0 {
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
196 // We ignore errors, since the FD is still usable
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
197 // SAFETY: socket is definitely a valid file descriptor and setting CLOEXEC is
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
198 // a sound operation.
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
199 unsafe {
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
200 libc::fcntl(fd, libc::F_SETFD, flags | libc::FD_CLOEXEC);
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
201 }
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
202 }
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
203 }
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
204
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
205 if value.is_inet() {
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
206 // SAFETY: FileDescriptor is obtained from systemd, so it should be valid.
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
207 let socket = unsafe { std::net::TcpListener::from_raw_fd(value.into_raw_fd()) };
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
208 set_cloexec(socket.as_raw_fd());
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
209 Ok(Socket::TcpListener(socket))
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
210 } else {
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
211 // We still need to make the filedescriptor harmless.
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
212 set_cloexec(value.into_raw_fd());
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
213 Err(())
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
214 }
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
215 }
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
216 }
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
217
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
218 struct SystemdSockets(std::sync::Mutex<std::collections::HashMap<String, StoredSocket>>);
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
219
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
220 impl SystemdSockets {
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
221 fn new_protected(explicit: bool) -> Result<Self, InitError> {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
222 unsafe { Self::new(true, explicit) }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
223 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
224
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
225 unsafe fn new(protected: bool, explicit: bool) -> Result<Self, InitError> {
25
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
226 use std::convert::TryFrom;
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
227
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
228 if explicit {
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
229 if std::env::var_os("LISTEN_PID").is_none()
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
230 && std::env::var_os("LISTEN_FDS").is_none()
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
231 && std::env::var_os("LISTEN_FDNAMES").is_none()
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
232 {
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
233 // Systemd is not used - make the map empty
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
234 return Ok(SystemdSockets(Mutex::new(Default::default())));
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
235 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
236 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
237
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
238 if protected {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
239 Self::check_single_thread()?
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
240 }
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
241 // MUST BE true FOR SAFETY!!!
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
242 let map = libsystemd::activation::receive_descriptors_with_names(
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
243 /*unset env = */ protected,
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
244 )?
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
245 .into_iter()
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
246 .map(|(fd, name)| (name, Socket::try_from(fd)))
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
247 .collect();
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
248 Ok(SystemdSockets(Mutex::new(map)))
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
249 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
250
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
251 fn check_single_thread() -> Result<(), InitError> {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
252 use std::io::BufRead;
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
253
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
254 let status = std::fs::File::open("/proc/self/status").map_err(InitError::OpenStatus)?;
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
255 let mut status = std::io::BufReader::new(status);
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
256 let mut line = String::new();
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
257 loop {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
258 if status.read_line(&mut line).map_err(InitError::ReadStatus)? == 0 {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
259 return Err(InitError::ThreadCountNotFound);
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
260 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
261 if let Some(threads) = line.strip_prefix("Threads:") {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
262 if threads.trim() == "1" {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
263 break;
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
264 } else {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
265 return Err(InitError::MultipleThreads);
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
266 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
267 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
268 line.clear();
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
269 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
270 Ok(())
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
271 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
272
25
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
273 fn take(&self, name: &str) -> Option<StoredSocket> {
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
274 // MUST remove THE SOCKET FOR SAFETY!!!
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
275 self.0.lock().expect("poisoned mutex").remove(name)
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 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
278
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
279 static SYSTEMD_SOCKETS: once_cell::sync::OnceCell<Result<SystemdSockets, Mutex<InitError>>> =
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
280 once_cell::sync::OnceCell::new();
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
281 }
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 /// Socket address that can be an ordinary address or a systemd socket
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 /// This is the core type of this crate that abstracts possible addresses.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
286 /// 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
287 /// 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
288 /// if the appropriate feature is enabled.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
289 ///
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
290 /// 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
291 /// [`configure_me`](https://crates.io/crates/configure_me).
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
292 #[derive(Debug)]
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
293 #[cfg_attr(
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
294 feature = "serde",
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
295 derive(serde_crate::Deserialize),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
296 serde(crate = "serde_crate", try_from = "serde_str_helpers::DeserBorrowStr")
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
297 )]
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
298 pub struct SocketAddr(SocketAddrInner);
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
299
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
300 impl SocketAddr {
17
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
301 /// Creates SocketAddr from systemd name directly, without requiring `systemd://` prefix.
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
302 ///
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
303 /// Always fails with systemd unsupported error if systemd is not supported.
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
304 pub fn from_systemd_name<T: Into<String>>(name: T) -> Result<Self, ParseError> {
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
305 Self::inner_from_systemd_name(name.into(), false)
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
306 }
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
307
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
308 #[cfg(all(target_os = "linux", feature = "enable_systemd"))]
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
309 fn inner_from_systemd_name(name: String, prefixed: bool) -> Result<Self, ParseError> {
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
310 let real_systemd_name = if prefixed {
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
311 &name[SYSTEMD_PREFIX.len()..]
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
312 } else {
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
313 &name
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
314 };
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
315
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
316 let name_len = real_systemd_name.len();
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
317 match real_systemd_name
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
318 .chars()
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
319 .enumerate()
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
320 .find(|(_, c)| !c.is_ascii() || *c < ' ' || *c == ':')
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
321 {
17
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
322 None if name_len <= 255 && prefixed => Ok(SocketAddr(SocketAddrInner::Systemd(name))),
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
323 None if name_len <= 255 && !prefixed => {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
324 Ok(SocketAddr(SocketAddrInner::SystemdNoPrefix(name)))
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
325 }
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
326 None => Err(ParseErrorInner::LongSocketName {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
327 string: name,
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
328 len: name_len,
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
329 }
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
330 .into()),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
331 Some((pos, c)) => Err(ParseErrorInner::InvalidCharacter {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
332 string: name,
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
333 c,
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
334 pos,
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
335 }
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
336 .into()),
17
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
337 }
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
338 }
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
339
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
340 #[cfg(not(all(target_os = "linux", feature = "enable_systemd")))]
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
341 fn inner_from_systemd_name(name: String, _prefixed: bool) -> Result<Self, ParseError> {
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
342 Err(ParseError(ParseErrorInner::SystemdUnsupported(name)))
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
343 }
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
344
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
345 /// Creates `std::net::TcpListener`
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 /// 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
348 /// if the socket name was provided.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
349 pub fn bind(self) -> Result<std::net::TcpListener, BindError> {
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
350 match self.0 {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
351 SocketAddrInner::Ordinary(addr) => match std::net::TcpListener::bind(addr) {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
352 Ok(socket) => Ok(socket),
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
353 Err(error) => Err(BindErrorInner::BindFailed { addr, error }.into()),
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
354 },
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
355 SocketAddrInner::WithHostname(addr) => match std::net::TcpListener::bind(addr.as_str())
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
356 {
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
357 Ok(socket) => Ok(socket),
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
358 Err(error) => Err(BindErrorInner::BindOrResolvFailed { addr, error }.into()),
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
359 },
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
360 SocketAddrInner::Systemd(socket_name) => {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
361 Self::get_systemd(socket_name, true).map(|(socket, _)| socket)
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
362 }
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
363 SocketAddrInner::SystemdNoPrefix(socket_name) => {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
364 Self::get_systemd(socket_name, false).map(|(socket, _)| socket)
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
365 }
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
366 }
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
367 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
368
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
369 /// Creates `tokio::net::TcpListener`
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
370 ///
21
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
371 /// To be specific, it binds the socket or converts systemd socket to `tokio` 1.0 socket.
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
372 ///
29
efc69e99db70 Set socket to nonblocking before passing it to tokio.
Paul Fisher <paul@pfish.zone>
parents: 28
diff changeset
373 /// This method either `bind`s the socket, if the address was provided or uses systemd socket
21
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
374 /// if the socket name was provided.
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
375 #[cfg(feature = "tokio")]
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
376 pub async fn bind_tokio(self) -> Result<tokio::net::TcpListener, TokioBindError> {
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
377 match self.0 {
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
378 SocketAddrInner::Ordinary(addr) => match tokio::net::TcpListener::bind(addr).await {
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
379 Ok(socket) => Ok(socket),
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
380 Err(error) => Err(TokioBindError::Bind(
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
381 BindErrorInner::BindFailed { addr, error }.into(),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
382 )),
21
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
383 },
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
384 SocketAddrInner::WithHostname(addr) => {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
385 match tokio::net::TcpListener::bind(addr.as_str()).await {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
386 Ok(socket) => Ok(socket),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
387 Err(error) => Err(TokioBindError::Bind(
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
388 BindErrorInner::BindOrResolvFailed { addr, error }.into(),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
389 )),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
390 }
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
391 }
21
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
392 SocketAddrInner::Systemd(socket_name) => {
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
393 let (socket, addr) = Self::get_systemd(socket_name, true)?;
29
efc69e99db70 Set socket to nonblocking before passing it to tokio.
Paul Fisher <paul@pfish.zone>
parents: 28
diff changeset
394 Self::wrap_tokio(socket)
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
395 .map_err(|error| TokioConversionError { addr, error }.into())
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
396 }
21
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
397 SocketAddrInner::SystemdNoPrefix(socket_name) => {
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
398 let (socket, addr) = Self::get_systemd(socket_name, false)?;
29
efc69e99db70 Set socket to nonblocking before passing it to tokio.
Paul Fisher <paul@pfish.zone>
parents: 28
diff changeset
399 Self::wrap_tokio(socket)
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
400 .map_err(|error| TokioConversionError { addr, error }.into())
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
401 }
21
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
402 }
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
403 }
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
404
29
efc69e99db70 Set socket to nonblocking before passing it to tokio.
Paul Fisher <paul@pfish.zone>
parents: 28
diff changeset
405 #[cfg(feature = "tokio")]
efc69e99db70 Set socket to nonblocking before passing it to tokio.
Paul Fisher <paul@pfish.zone>
parents: 28
diff changeset
406 fn wrap_tokio(socket: std::net::TcpListener) -> Result<tokio::net::TcpListener, std::io::Error> {
efc69e99db70 Set socket to nonblocking before passing it to tokio.
Paul Fisher <paul@pfish.zone>
parents: 28
diff changeset
407 socket.set_nonblocking(true)?;
efc69e99db70 Set socket to nonblocking before passing it to tokio.
Paul Fisher <paul@pfish.zone>
parents: 28
diff changeset
408 socket.try_into()
efc69e99db70 Set socket to nonblocking before passing it to tokio.
Paul Fisher <paul@pfish.zone>
parents: 28
diff changeset
409 }
efc69e99db70 Set socket to nonblocking before passing it to tokio.
Paul Fisher <paul@pfish.zone>
parents: 28
diff changeset
410
21
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
411 /// Creates `tokio::net::TcpListener`
f6334887e3c8 Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 20
diff changeset
412 ///
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
413 /// 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
414 ///
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
415 /// 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
416 /// if the socket name was provided.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
417 #[cfg(feature = "tokio_0_2")]
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
418 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
419 match self.0 {
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
420 SocketAddrInner::Ordinary(addr) => {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
421 match tokio_0_2::net::TcpListener::bind(addr).await {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
422 Ok(socket) => Ok(socket),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
423 Err(error) => Err(TokioBindError::Bind(
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
424 BindErrorInner::BindFailed { addr, error }.into(),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
425 )),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
426 }
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
427 }
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
428 SocketAddrInner::WithHostname(addr) => {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
429 match tokio_0_2::net::TcpListener::bind(addr.as_str()).await {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
430 Ok(socket) => Ok(socket),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
431 Err(error) => Err(TokioBindError::Bind(
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
432 BindErrorInner::BindOrResolvFailed { addr, error }.into(),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
433 )),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
434 }
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
435 }
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
436 SocketAddrInner::Systemd(socket_name) => {
17
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
437 let (socket, addr) = Self::get_systemd(socket_name, true)?;
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
438 socket
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
439 .try_into()
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
440 .map_err(|error| TokioConversionError { addr, error }.into())
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
441 }
17
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
442 SocketAddrInner::SystemdNoPrefix(socket_name) => {
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
443 let (socket, addr) = Self::get_systemd(socket_name, false)?;
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
444 socket
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
445 .try_into()
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
446 .map_err(|error| TokioConversionError { addr, error }.into())
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
447 }
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
448 }
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
449 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
450
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
451 /// Creates `tokio::net::TcpListener`
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
452 ///
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
453 /// 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
454 ///
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
455 /// 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
456 /// if the socket name was provided.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
457 #[cfg(feature = "tokio_0_3")]
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
458 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
459 match self.0 {
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
460 SocketAddrInner::Ordinary(addr) => {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
461 match tokio_0_3::net::TcpListener::bind(addr).await {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
462 Ok(socket) => Ok(socket),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
463 Err(error) => Err(TokioBindError::Bind(
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
464 BindErrorInner::BindFailed { addr, error }.into(),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
465 )),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
466 }
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
467 }
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
468 SocketAddrInner::WithHostname(addr) => {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
469 match tokio_0_3::net::TcpListener::bind(addr.as_str()).await {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
470 Ok(socket) => Ok(socket),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
471 Err(error) => Err(TokioBindError::Bind(
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
472 BindErrorInner::BindOrResolvFailed { addr, error }.into(),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
473 )),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
474 }
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
475 }
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
476 SocketAddrInner::Systemd(socket_name) => {
17
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
477 let (socket, addr) = Self::get_systemd(socket_name, true)?;
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
478 socket
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
479 .try_into()
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
480 .map_err(|error| TokioConversionError { addr, error }.into())
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
481 }
17
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
482 SocketAddrInner::SystemdNoPrefix(socket_name) => {
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
483 let (socket, addr) = Self::get_systemd(socket_name, false)?;
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
484 socket
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
485 .try_into()
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
486 .map_err(|error| TokioConversionError { addr, error }.into())
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
487 }
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
488 }
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
489 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
490
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
491 /// Creates `async_std::net::TcpListener`
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
492 ///
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
493 /// 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
494 ///
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
495 /// 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
496 /// if the socket name was provided.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
497 #[cfg(feature = "async-std")]
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
498 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
499 match self.0 {
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
500 SocketAddrInner::Ordinary(addr) => {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
501 match async_std::net::TcpListener::bind(addr).await {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
502 Ok(socket) => Ok(socket),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
503 Err(error) => Err(BindErrorInner::BindFailed { addr, error }.into()),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
504 }
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
505 }
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
506 SocketAddrInner::WithHostname(addr) => {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
507 match async_std::net::TcpListener::bind(addr.as_str()).await {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
508 Ok(socket) => Ok(socket),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
509 Err(error) => Err(BindErrorInner::BindOrResolvFailed { addr, error }.into()),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
510 }
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
511 }
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
512 SocketAddrInner::Systemd(socket_name) => {
17
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
513 let (socket, _) = Self::get_systemd(socket_name, true)?;
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
514 Ok(socket.into())
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
515 }
17
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
516 SocketAddrInner::SystemdNoPrefix(socket_name) => {
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
517 let (socket, _) = Self::get_systemd(socket_name, false)?;
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
518 Ok(socket.into())
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
519 }
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
520 }
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
521 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
522
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
523 // 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
524 // rules.
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
525 fn try_from_generic<'a, T>(string: T) -> Result<Self, ParseError>
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
526 where
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
527 T: 'a + std::ops::Deref<Target = str> + Into<String>,
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
528 {
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
529 if string.starts_with(SYSTEMD_PREFIX) {
17
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
530 Self::inner_from_systemd_name(string.into(), true)
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
531 } else {
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
532 match string.parse() {
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
533 Ok(addr) => Ok(SocketAddr(SocketAddrInner::Ordinary(addr))),
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
534 Err(_) => Ok(SocketAddr(SocketAddrInner::WithHostname(
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
535 ResolvAddr::try_from_generic(string).map_err(ParseErrorInner::ResolvAddr)?,
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
536 ))),
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
537 }
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
538 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
539 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
540
16
bc76507dd878 Fixed conditional compilation based on OS
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 13
diff changeset
541 #[cfg(all(target_os = "linux", feature = "enable_systemd"))]
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
542 fn get_systemd(
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
543 socket_name: String,
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
544 prefixed: bool,
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
545 ) -> Result<(std::net::TcpListener, SocketAddrInner), BindError> {
25
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
546 use systemd_sockets::Socket;
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
547
17
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
548 let real_systemd_name = if prefixed {
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
549 &socket_name[SYSTEMD_PREFIX.len()..]
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
550 } else {
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
551 &socket_name
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
552 };
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
553
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
554 let socket =
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
555 systemd_sockets::take(real_systemd_name).map_err(BindErrorInner::ReceiveDescriptors)?;
25
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
556 // match instead of combinators to avoid cloning socket_name
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
557 match socket {
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
558 Some(Ok(Socket::TcpListener(socket))) => {
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
559 Ok((socket, SocketAddrInner::Systemd(socket_name)))
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
560 }
25
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
561 Some(_) => Err(BindErrorInner::NotInetSocket(socket_name).into()),
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
562 None => Err(BindErrorInner::MissingDescriptor(socket_name).into()),
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
563 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
564 }
6
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
565
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
566 // This approach makes the rest of the code much simpler as it doesn't require sprinkling it
16
bc76507dd878 Fixed conditional compilation based on OS
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 13
diff changeset
567 // with #[cfg(all(target_os = "linux", feature = "enable_systemd"))] yet still statically guarantees it won't execute.
bc76507dd878 Fixed conditional compilation based on OS
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 13
diff changeset
568 #[cfg(not(all(target_os = "linux", feature = "enable_systemd")))]
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
569 fn get_systemd(
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
570 socket_name: Never,
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
571 _prefixed: bool,
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
572 ) -> Result<(std::net::TcpListener, SocketAddrInner), BindError> {
6
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
573 match socket_name {}
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
574 }
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
575 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
576
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
577 /// Initializes the library while there's only a single thread.
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
578 ///
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
579 /// Unfortunately, this library has to be initialized and, for soundness, this initialization must
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
580 /// happen when no other threads are running. This is attempted automatically when trying to bind a
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
581 /// systemd socket but at that time there may be other threads running and error reporting also
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
582 /// faces some restrictions. This function provides better control over the initialization point
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
583 /// and returns a more idiomatic error type.
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
584 ///
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
585 /// You should generally call this at around the top of `main`, where no threads were created yet.
25
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
586 /// While technically, you may spawn a thread and call this function after that thread terminated,
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
587 /// this has the additional problem that the descriptors are still around, so if that thread (or the
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
588 /// current one!) forks and execs the descriptors will leak into the child.
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
589 #[inline]
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
590 pub fn init() -> Result<(), error::InitError> {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
591 #[cfg(all(target_os = "linux", feature = "enable_systemd"))]
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
592 {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
593 // Calling with true is always sound
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
594 unsafe { systemd_sockets::init(true) }.map_err(error::InitError)
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
595 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
596 #[cfg(not(all(target_os = "linux", feature = "enable_systemd")))]
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
597 {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
598 Ok(())
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
599 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
600 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
601
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
602 /// Initializes the library without protection against double close.
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
603 ///
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
604 /// Unfortunately, this library has to be initialized and, because double closing file descriptors
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
605 /// is unsound, the library has some protections against double close. However these protections
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
606 /// come with the limitation that the library must be initailized with a single thread.
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
607 ///
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
608 /// If for any reason you're unable to call `init` in a single thread at around the top of `main`
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
609 /// (and this should be almost never) you may call this method if you've ensured that no other part
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
610 /// of your codebase is operating on systemd-provided file descriptors stored in the environment
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
611 /// variables.
25
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
612 ///
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
613 /// Note however that doing so uncovers another problem: if another thread forks and execs the
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
614 /// systemd file descriptors will get passed into that program! In such case you somehow need to
8e20daee41ed Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 24
diff changeset
615 /// clean up the file descriptors yourself.
24
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
616 pub unsafe fn init_unprotected() -> Result<(), error::InitError> {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
617 #[cfg(all(target_os = "linux", feature = "enable_systemd"))]
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
618 {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
619 systemd_sockets::init(false).map_err(error::InitError)
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
620 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
621 #[cfg(not(all(target_os = "linux", feature = "enable_systemd")))]
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
622 {
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
623 Ok(())
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
624 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
625 }
1941e9d9819c Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 22
diff changeset
626
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
627 /// Displays the address in format that can be parsed again.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
628 ///
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
629 /// **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
630 /// It should be used mostly for debugging/logging.
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
631 impl fmt::Display for SocketAddr {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
632 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
633 fmt::Display::fmt(&self.0, f)
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
634 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
635 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
636
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
637 impl fmt::Display for SocketAddrInner {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
638 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
639 match self {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
640 SocketAddrInner::Ordinary(addr) => fmt::Display::fmt(addr, f),
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
641 SocketAddrInner::Systemd(addr) => fmt::Display::fmt(addr, f),
17
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
642 SocketAddrInner::SystemdNoPrefix(addr) => write!(f, "{}{}", SYSTEMD_PREFIX, addr),
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
643 SocketAddrInner::WithHostname(addr) => fmt::Display::fmt(addr, f),
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
644 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
645 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
646 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
647
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
648 // PartialEq for testing, I'm not convinced it should be exposed
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
649 #[derive(Debug, PartialEq)]
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
650 enum SocketAddrInner {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
651 Ordinary(std::net::SocketAddr),
4
66c0e10c89fc Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 3
diff changeset
652 WithHostname(resolv_addr::ResolvAddr),
16
bc76507dd878 Fixed conditional compilation based on OS
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 13
diff changeset
653 #[cfg(all(target_os = "linux", feature = "enable_systemd"))]
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
654 Systemd(String),
16
bc76507dd878 Fixed conditional compilation based on OS
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 13
diff changeset
655 #[cfg(not(all(target_os = "linux", feature = "enable_systemd")))]
6
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
656 #[allow(dead_code)]
a7893294e9b2 Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 4
diff changeset
657 Systemd(Never),
17
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
658 #[cfg(all(target_os = "linux", feature = "enable_systemd"))]
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
659 #[allow(dead_code)]
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
660 SystemdNoPrefix(String),
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
661 #[cfg(not(all(target_os = "linux", feature = "enable_systemd")))]
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
662 #[allow(dead_code)]
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
663 SystemdNoPrefix(Never),
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
664 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
665
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
666 const SYSTEMD_PREFIX: &str = "systemd://";
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
667
11
13e2a5545167 Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 9
diff changeset
668 impl<I: Into<std::net::IpAddr>> From<(I, u16)> for SocketAddr {
13e2a5545167 Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 9
diff changeset
669 fn from(value: (I, u16)) -> Self {
13e2a5545167 Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 9
diff changeset
670 SocketAddr(SocketAddrInner::Ordinary(value.into()))
13e2a5545167 Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 9
diff changeset
671 }
13e2a5545167 Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 9
diff changeset
672 }
13e2a5545167 Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 9
diff changeset
673
18
db1dc99252e2 Added From<std::net::SocketAddr>
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 17
diff changeset
674 impl From<std::net::SocketAddr> for SocketAddr {
db1dc99252e2 Added From<std::net::SocketAddr>
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 17
diff changeset
675 fn from(value: std::net::SocketAddr) -> Self {
db1dc99252e2 Added From<std::net::SocketAddr>
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 17
diff changeset
676 SocketAddr(SocketAddrInner::Ordinary(value))
db1dc99252e2 Added From<std::net::SocketAddr>
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 17
diff changeset
677 }
db1dc99252e2 Added From<std::net::SocketAddr>
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 17
diff changeset
678 }
db1dc99252e2 Added From<std::net::SocketAddr>
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 17
diff changeset
679
11
13e2a5545167 Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 9
diff changeset
680 impl From<std::net::SocketAddrV4> for SocketAddr {
13e2a5545167 Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 9
diff changeset
681 fn from(value: std::net::SocketAddrV4) -> Self {
13e2a5545167 Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 9
diff changeset
682 SocketAddr(SocketAddrInner::Ordinary(value.into()))
13e2a5545167 Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 9
diff changeset
683 }
13e2a5545167 Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 9
diff changeset
684 }
13e2a5545167 Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 9
diff changeset
685
13e2a5545167 Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 9
diff changeset
686 impl From<std::net::SocketAddrV6> for SocketAddr {
13e2a5545167 Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 9
diff changeset
687 fn from(value: std::net::SocketAddrV6) -> Self {
13e2a5545167 Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 9
diff changeset
688 SocketAddr(SocketAddrInner::Ordinary(value.into()))
13e2a5545167 Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 9
diff changeset
689 }
13e2a5545167 Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 9
diff changeset
690 }
13e2a5545167 Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 9
diff changeset
691
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
692 impl std::str::FromStr for SocketAddr {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
693 type Err = ParseError;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
694
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
695 fn from_str(s: &str) -> Result<Self, Self::Err> {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
696 SocketAddr::try_from_generic(s)
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
697 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
698 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
699
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
700 impl<'a> TryFrom<&'a str> for SocketAddr {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
701 type Error = ParseError;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
702
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
703 fn try_from(s: &'a str) -> Result<Self, Self::Error> {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
704 SocketAddr::try_from_generic(s)
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
705 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
706 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
707
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
708 impl TryFrom<String> for SocketAddr {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
709 type Error = ParseError;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
710
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
711 fn try_from(s: String) -> Result<Self, Self::Error> {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
712 SocketAddr::try_from_generic(s)
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
713 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
714 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
715
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
716 impl<'a> TryFrom<&'a OsStr> for SocketAddr {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
717 type Error = ParseOsStrError;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
718
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
719 fn try_from(s: &'a OsStr) -> Result<Self, Self::Error> {
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
720 s.to_str()
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
721 .ok_or(ParseOsStrError::InvalidUtf8)?
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
722 .try_into()
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
723 .map_err(Into::into)
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
724 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
725 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
726
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
727 impl TryFrom<OsString> for SocketAddr {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
728 type Error = ParseOsStrError;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
729
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
730 fn try_from(s: OsString) -> Result<Self, Self::Error> {
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
731 s.into_string()
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
732 .map_err(|_| ParseOsStrError::InvalidUtf8)?
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
733 .try_into()
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
734 .map_err(Into::into)
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
735 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
736 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
737
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
738 #[cfg(feature = "serde")]
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
739 impl<'a> TryFrom<serde_str_helpers::DeserBorrowStr<'a>> for SocketAddr {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
740 type Error = ParseError;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
741
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
742 fn try_from(s: serde_str_helpers::DeserBorrowStr<'a>) -> Result<Self, Self::Error> {
9
4fb70ca820a6 Upgrade serde_str_helpers
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 7
diff changeset
743 SocketAddr::try_from_generic(s)
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
744 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
745 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
746
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
747 #[cfg(feature = "parse_arg")]
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
748 impl parse_arg::ParseArg for SocketAddr {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
749 type Error = ParseOsStrError;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
750
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
751 fn describe_type<W: fmt::Write>(mut writer: W) -> fmt::Result {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
752 std::net::SocketAddr::describe_type(&mut writer)?;
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
753 write!(writer, " or a systemd socket name prefixed with systemd://")
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
754 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
755
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
756 fn parse_arg(arg: &OsStr) -> Result<Self, Self::Error> {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
757 arg.try_into()
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
758 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
759
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
760 fn parse_owned_arg(arg: OsString) -> Result<Self, Self::Error> {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
761 arg.try_into()
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
762 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
763 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
764
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
765 #[cfg(test)]
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
766 mod tests {
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
767 use super::{SocketAddr, SocketAddrInner};
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
768
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
769 #[test]
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
770 fn parse_ordinary() {
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
771 assert_eq!(
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
772 "127.0.0.1:42".parse::<SocketAddr>().unwrap().0,
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
773 SocketAddrInner::Ordinary(([127, 0, 0, 1], 42).into())
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
774 );
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
775 }
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
776
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
777 #[test]
16
bc76507dd878 Fixed conditional compilation based on OS
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 13
diff changeset
778 #[cfg(all(target_os = "linux", feature = "enable_systemd"))]
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
779 fn parse_systemd() {
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
780 assert_eq!(
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
781 "systemd://foo".parse::<SocketAddr>().unwrap().0,
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
782 SocketAddrInner::Systemd("systemd://foo".to_owned())
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
783 );
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
784 }
2
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
785
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
786 #[test]
16
bc76507dd878 Fixed conditional compilation based on OS
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 13
diff changeset
787 #[cfg(not(all(target_os = "linux", feature = "enable_systemd")))]
7
9731ff589d9c Fix tests on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 6
diff changeset
788 #[should_panic]
9731ff589d9c Fix tests on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 6
diff changeset
789 fn parse_systemd() {
9731ff589d9c Fix tests on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 6
diff changeset
790 "systemd://foo".parse::<SocketAddr>().unwrap();
9731ff589d9c Fix tests on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 6
diff changeset
791 }
9731ff589d9c Fix tests on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 6
diff changeset
792
9731ff589d9c Fix tests on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 6
diff changeset
793 #[test]
2
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
794 #[should_panic]
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
795 fn parse_systemd_fail_control() {
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
796 "systemd://foo\n".parse::<SocketAddr>().unwrap();
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
797 }
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
798
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
799 #[test]
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
800 #[should_panic]
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
801 fn parse_systemd_fail_colon() {
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
802 "systemd://foo:".parse::<SocketAddr>().unwrap();
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
803 }
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
804
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
805 #[test]
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
806 #[should_panic]
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
807 fn parse_systemd_fail_non_ascii() {
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
808 "systemd://fooá".parse::<SocketAddr>().unwrap();
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
809 }
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
810
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
811 #[test]
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
812 #[should_panic]
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
813 fn parse_systemd_fail_too_long() {
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
814 "systemd://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".parse::<SocketAddr>().unwrap();
cabc4aafdd85 Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 0
diff changeset
815 }
17
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
816
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
817 #[test]
28
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
818 #[cfg_attr(
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
819 not(all(target_os = "linux", feature = "enable_systemd")),
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
820 should_panic
cfef4593e207 Run `cargo fmt`.
Paul Fisher <paul@pfish.zone>
parents: 26
diff changeset
821 )]
17
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
822 fn no_prefix_parse_systemd() {
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
823 SocketAddr::from_systemd_name("foo").unwrap();
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
824 }
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
825
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
826 #[test]
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
827 #[should_panic]
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
828 fn no_prefix_parse_systemd_fail_non_ascii() {
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
829 SocketAddr::from_systemd_name("fooá").unwrap();
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
830 }
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
831
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
832 #[test]
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
833 #[should_panic]
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
834 fn no_prefix_parse_systemd_fail_too_long() {
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
835 SocketAddr::from_systemd_name("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx").unwrap();
dfb727367934 Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents: 16
diff changeset
836 }
0
a65053246c29 Initial commit
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff changeset
837 }