Mercurial > crates > systemd-socket
annotate src/lib.rs @ 26:0feab4f4c2ce
Relax version requirements and update MSRV
The MSRV was accidentally increased without documentation. Increase
itself is fine since it satisfies "latest stable Debian" condition but
given there are soundness issues this relaxes the version requirements
to work on 1.48 and also documents it.
author | Martin Habovstiak <martin.habovstiak@gmail.com> |
---|---|
date | Fri, 28 Feb 2025 23:10:11 +0100 |
parents | 8e20daee41ed |
children | cfef4593e207 e15210d1e534 |
rev | line source |
---|---|
0 | 1 //! A convenience crate for optionally supporting systemd socket activation. |
2 //! | |
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! |
0 | 7 //! |
8 //! The goal of this crate is to make socket activation with systemd in your project trivial. | |
9 //! It provides a replacement for `std::net::SocketAddr` that allows parsing the bind address from string just like the one from `std` | |
10 //! but on top of that also allows `systemd://socket_name` format that tells it to use systemd activation with given socket name. | |
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 | 13 //! The provided type supports conversions from various types of strings and also `serde` and `parse_arg` via feature flag. |
14 //! Thanks to this the change to your code should be minimal - parsing will continue to work, it'll just allow a new format. | |
15 //! You only need to change the code to use `SocketAddr::bind()` instead of `TcpListener::bind()` for binding. | |
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. |
0 | 22 //! |
23 //! ## Example | |
24 //! | |
25 //! ```no_run | |
26 //! use systemd_socket::SocketAddr; | |
27 //! use std::convert::TryFrom; | |
28 //! use std::io::Write; | |
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 | 31 //! let mut args = std::env::args_os(); |
32 //! let program_name = args.next().expect("unknown program name"); | |
33 //! let socket_addr = args.next().expect("missing socket address"); | |
34 //! let socket_addr = SocketAddr::try_from(socket_addr).expect("failed to parse socket address"); | |
35 //! let socket = socket_addr.bind().expect("failed to bind socket"); | |
36 //! | |
37 //! loop { | |
38 //! let _ = socket | |
39 //! .accept() | |
40 //! .expect("failed to accept connection") | |
41 //! .0 | |
42 //! .write_all(b"Hello world!") | |
43 //! .map_err(|err| eprintln!("Failed to send {}", err)); | |
44 //! } | |
45 //! ``` | |
46 //! | |
47 //! ## Features | |
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 | 52 //! * `serde` - implements `serde::Deserialize` for `SocketAddr` |
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 | 79 |
80 #![deny(missing_docs)] | |
81 | |
82 pub mod error; | |
4
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
83 mod resolv_addr; |
0 | 84 |
85 use std::convert::{TryFrom, TryInto}; | |
86 use std::fmt; | |
87 use std::ffi::{OsStr, OsString}; | |
88 use crate::error::*; | |
4
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
89 use crate::resolv_addr::ResolvAddr; |
0 | 90 |
16
bc76507dd878
Fixed conditional compilation based on OS
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
13
diff
changeset
|
91 #[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
|
92 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
|
93 |
16
bc76507dd878
Fixed conditional compilation based on OS
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
13
diff
changeset
|
94 #[cfg(all(target_os = "linux", feature = "enable_systemd"))] |
0 | 95 pub(crate) mod systemd_sockets { |
96 use std::fmt; | |
97 use std::sync::Mutex; | |
98 use libsystemd::activation::FileDescriptor; | |
20
2b78a483f84b
Update `libsystemd`
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
18
diff
changeset
|
99 use libsystemd::errors::SdError as LibSystemdError; |
0 | 100 |
101 #[derive(Debug)] | |
24
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
102 pub(crate) struct Error(&'static Mutex<InitError>); |
0 | 103 |
104 impl fmt::Display for Error { | |
105 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
|
106 use std::error::Error as _; |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
107 |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
108 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
|
109 fmt::Display::fmt(&*guard, f)?; |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
110 let mut source_opt = guard.source(); |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
111 while let Some(source) = source_opt { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
112 write!(f, ": {}", source)?; |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
113 source_opt = source.source(); |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
114 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
115 Ok(()) |
0 | 116 } |
117 } | |
118 | |
25
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
119 type StoredSocket = Result<Socket, ()>; |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
120 |
0 | 121 // No source we can't keep the mutex locked |
122 impl std::error::Error for Error {} | |
123 | |
24
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
124 pub(crate) unsafe fn init(protected: bool) -> Result<(), InitError> { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
125 SYSTEMD_SOCKETS.get_or_try_init(|| SystemdSockets::new(protected, true).map(Ok)).map(drop) |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
126 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
127 |
25
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
128 pub(crate) fn take(name: &str) -> Result<Option<StoredSocket>, Error> { |
24
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
129 let sockets = SYSTEMD_SOCKETS.get_or_init(|| SystemdSockets::new_protected(false).map_err(Mutex::new)); |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
130 match sockets { |
0 | 131 Ok(sockets) => Ok(sockets.take(name)), |
132 Err(error) => Err(Error(error)) | |
133 } | |
134 } | |
135 | |
24
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
136 #[derive(Debug)] |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
137 pub(crate) enum InitError { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
138 OpenStatus(std::io::Error), |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
139 ReadStatus(std::io::Error), |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
140 ThreadCountNotFound, |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
141 MultipleThreads, |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
142 LibSystemd(LibSystemdError), |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
143 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
144 |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
145 impl From<LibSystemdError> for InitError { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
146 fn from(value: LibSystemdError) -> Self { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
147 Self::LibSystemd(value) |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
148 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
149 } |
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 impl fmt::Display for InitError { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
152 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
|
153 match self { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
154 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
|
155 Self::ReadStatus(_) => write!(f, "failed to read /proc/self/status"), |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
156 Self::ThreadCountNotFound => write!(f, "/proc/self/status doesn't contain Threads entry"), |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
157 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
|
158 // 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
|
159 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
|
160 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
161 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
162 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
163 |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
164 impl std::error::Error for InitError { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
165 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
|
166 match self { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
167 Self::OpenStatus(error) => Some(error), |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
168 Self::ReadStatus(error) => Some(error), |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
169 Self::ThreadCountNotFound => None, |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
170 Self::MultipleThreads => None, |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
171 // 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
|
172 Self::LibSystemd(error) => error.source(), |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
173 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
174 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
175 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
176 |
25
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
177 pub(crate) enum Socket { |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
178 TcpListener(std::net::TcpListener), |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
179 } |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
180 |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
181 impl std::convert::TryFrom<FileDescriptor> for Socket { |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
182 type Error = (); |
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 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
|
185 use libsystemd::activation::IsType; |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
186 use std::os::unix::io::{FromRawFd, IntoRawFd, AsRawFd}; |
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 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
|
189 // SAFETY: The function is a harmless syscall |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
190 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
|
191 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
|
192 // 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
|
193 // 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
|
194 // a sound operation. |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
195 unsafe { |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
196 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
|
197 } |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
198 } |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
199 } |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
200 |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
201 if value.is_inet() { |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
202 // 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
|
203 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
|
204 set_cloexec(socket.as_raw_fd()); |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
205 Ok(Socket::TcpListener(socket)) |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
206 } else { |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
207 // 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
|
208 set_cloexec(value.into_raw_fd()); |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
209 Err(()) |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
210 } |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
211 } |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
212 } |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
213 |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
214 struct SystemdSockets(std::sync::Mutex<std::collections::HashMap<String, StoredSocket>>); |
0 | 215 |
216 impl SystemdSockets { | |
24
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
217 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
|
218 unsafe { Self::new(true, explicit) } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
219 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
220 |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
221 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
|
222 use std::convert::TryFrom; |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
223 |
24
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
224 if explicit { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
225 if std::env::var_os("LISTEN_PID").is_none() && std::env::var_os("LISTEN_FDS").is_none() && std::env::var_os("LISTEN_FDNAMES").is_none() { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
226 // 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
|
227 return Ok(SystemdSockets(Mutex::new(Default::default()))); |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
228 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
229 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
230 |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
231 if protected { Self::check_single_thread()? } |
0 | 232 // MUST BE true FOR SAFETY!!! |
25
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
233 let map = libsystemd::activation::receive_descriptors_with_names(/*unset env = */ protected)?.into_iter().map(|(fd, name)| { |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
234 (name, Socket::try_from(fd)) |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
235 }).collect(); |
0 | 236 Ok(SystemdSockets(Mutex::new(map))) |
237 } | |
238 | |
24
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
239 fn check_single_thread() -> Result<(), InitError> { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
240 use std::io::BufRead; |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
241 |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
242 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
|
243 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
|
244 let mut line = String::new(); |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
245 loop { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
246 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
|
247 return Err(InitError::ThreadCountNotFound); |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
248 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
249 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
|
250 if threads.trim() == "1" { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
251 break; |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
252 } else { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
253 return Err(InitError::MultipleThreads); |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
254 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
255 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
256 line.clear(); |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
257 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
258 Ok(()) |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
259 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
260 |
25
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
261 fn take(&self, name: &str) -> Option<StoredSocket> { |
0 | 262 // MUST remove THE SOCKET FOR SAFETY!!! |
263 self.0.lock().expect("poisoned mutex").remove(name) | |
264 } | |
265 } | |
266 | |
24
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
267 static SYSTEMD_SOCKETS: once_cell::sync::OnceCell<Result<SystemdSockets, Mutex<InitError>>> = once_cell::sync::OnceCell::new(); |
0 | 268 } |
269 | |
270 /// Socket address that can be an ordinary address or a systemd socket | |
271 /// | |
272 /// This is the core type of this crate that abstracts possible addresses. | |
273 /// It can be (fallibly) converted from various types of strings or deserialized with `serde`. | |
274 /// After it's created, it can be bound as `TcpListener` from `std` or even `tokio` or `async_std` | |
275 /// if the appropriate feature is enabled. | |
276 /// | |
277 /// Optional dependencies on `parse_arg` and `serde` make it trivial to use with | |
278 /// [`configure_me`](https://crates.io/crates/configure_me). | |
279 #[derive(Debug)] | |
280 #[cfg_attr(feature = "serde", derive(serde_crate::Deserialize), serde(crate = "serde_crate", try_from = "serde_str_helpers::DeserBorrowStr"))] | |
281 pub struct SocketAddr(SocketAddrInner); | |
282 | |
283 impl SocketAddr { | |
17
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
284 /// 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
|
285 /// |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
286 /// 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
|
287 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
|
288 Self::inner_from_systemd_name(name.into(), false) |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
289 } |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
290 |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
291 #[cfg(all(target_os = "linux", feature = "enable_systemd"))] |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
292 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
|
293 let real_systemd_name = if prefixed { |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
294 &name[SYSTEMD_PREFIX.len()..] |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
295 } else { |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
296 &name |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
297 }; |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
298 |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
299 let name_len = real_systemd_name.len(); |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
300 match real_systemd_name.chars().enumerate().find(|(_, c)| !c.is_ascii() || *c < ' ' || *c == ':') { |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
301 None if name_len <= 255 && prefixed => Ok(SocketAddr(SocketAddrInner::Systemd(name))), |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
302 None if name_len <= 255 && !prefixed => Ok(SocketAddr(SocketAddrInner::SystemdNoPrefix(name))), |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
303 None => Err(ParseErrorInner::LongSocketName { string: name, len: name_len }.into()), |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
304 Some((pos, c)) => Err(ParseErrorInner::InvalidCharacter { string: name, c, pos, }.into()), |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
305 } |
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 |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
309 #[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
|
310 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
|
311 Err(ParseError(ParseErrorInner::SystemdUnsupported(name))) |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
312 } |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
313 |
0 | 314 /// Creates `std::net::TcpListener` |
315 /// | |
316 /// This method either `binds` the socket, if the address was provided or uses systemd socket | |
317 /// if the socket name was provided. | |
318 pub fn bind(self) -> Result<std::net::TcpListener, BindError> { | |
4
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
319 match self.0 { |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
320 SocketAddrInner::Ordinary(addr) => match std::net::TcpListener::bind(addr) { |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
321 Ok(socket) => Ok(socket), |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
322 Err(error) => Err(BindErrorInner::BindFailed { addr, error, }.into()), |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
323 }, |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
324 SocketAddrInner::WithHostname(addr) => match std::net::TcpListener::bind(addr.as_str()) { |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
325 Ok(socket) => Ok(socket), |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
326 Err(error) => Err(BindErrorInner::BindOrResolvFailed { addr, error, }.into()), |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
327 }, |
17
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
328 SocketAddrInner::Systemd(socket_name) => Self::get_systemd(socket_name, true).map(|(socket, _)| socket), |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
329 SocketAddrInner::SystemdNoPrefix(socket_name) => Self::get_systemd(socket_name, false).map(|(socket, _)| socket), |
4
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
330 } |
0 | 331 } |
332 | |
333 /// Creates `tokio::net::TcpListener` | |
334 /// | |
21
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
335 /// 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
|
336 /// |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
337 /// This method either `binds` the socket, if the address was provided or uses systemd socket |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
338 /// if the socket name was provided. |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
339 #[cfg(feature = "tokio")] |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
340 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
|
341 match self.0 { |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
342 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
|
343 Ok(socket) => Ok(socket), |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
344 Err(error) => Err(TokioBindError::Bind(BindErrorInner::BindFailed { addr, error, }.into())), |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
345 }, |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
346 SocketAddrInner::WithHostname(addr) => match tokio::net::TcpListener::bind(addr.as_str()).await { |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
347 Ok(socket) => Ok(socket), |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
348 Err(error) => Err(TokioBindError::Bind(BindErrorInner::BindOrResolvFailed { addr, error, }.into())), |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
349 }, |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
350 SocketAddrInner::Systemd(socket_name) => { |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
351 let (socket, addr) = Self::get_systemd(socket_name, true)?; |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
352 socket.try_into().map_err(|error| TokioConversionError { addr, error, }.into()) |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
353 }, |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
354 SocketAddrInner::SystemdNoPrefix(socket_name) => { |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
355 let (socket, addr) = Self::get_systemd(socket_name, false)?; |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
356 socket.try_into().map_err(|error| TokioConversionError { addr, error, }.into()) |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
357 }, |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
358 } |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
359 } |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
360 |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
361 /// Creates `tokio::net::TcpListener` |
f6334887e3c8
Support `tokio` 1.0
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
20
diff
changeset
|
362 /// |
4
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
363 /// To be specific, it binds the socket or converts systemd socket to `tokio` 0.2 socket. |
0 | 364 /// |
365 /// This method either `binds` the socket, if the address was provided or uses systemd socket | |
366 /// if the socket name was provided. | |
367 #[cfg(feature = "tokio_0_2")] | |
4
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
368 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
|
369 match self.0 { |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
370 SocketAddrInner::Ordinary(addr) => match tokio_0_2::net::TcpListener::bind(addr).await { |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
371 Ok(socket) => Ok(socket), |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
372 Err(error) => Err(TokioBindError::Bind(BindErrorInner::BindFailed { addr, error, }.into())), |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
373 }, |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
374 SocketAddrInner::WithHostname(addr) => match tokio_0_2::net::TcpListener::bind(addr.as_str()).await { |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
375 Ok(socket) => Ok(socket), |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
376 Err(error) => Err(TokioBindError::Bind(BindErrorInner::BindOrResolvFailed { addr, error, }.into())), |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
377 }, |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
378 SocketAddrInner::Systemd(socket_name) => { |
17
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
379 let (socket, addr) = Self::get_systemd(socket_name, true)?; |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
380 socket.try_into().map_err(|error| TokioConversionError { addr, error, }.into()) |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
381 }, |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
382 SocketAddrInner::SystemdNoPrefix(socket_name) => { |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
383 let (socket, addr) = Self::get_systemd(socket_name, false)?; |
4
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
384 socket.try_into().map_err(|error| TokioConversionError { addr, error, }.into()) |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
385 }, |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
386 } |
0 | 387 } |
388 | |
389 /// Creates `tokio::net::TcpListener` | |
390 /// | |
4
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
391 /// To be specific, it binds the socket or converts systemd socket to `tokio` 0.3 socket. |
0 | 392 /// |
393 /// This method either `binds` the socket, if the address was provided or uses systemd socket | |
394 /// if the socket name was provided. | |
395 #[cfg(feature = "tokio_0_3")] | |
4
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
396 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
|
397 match self.0 { |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
398 SocketAddrInner::Ordinary(addr) => match tokio_0_3::net::TcpListener::bind(addr).await { |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
399 Ok(socket) => Ok(socket), |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
400 Err(error) => Err(TokioBindError::Bind(BindErrorInner::BindFailed { addr, error, }.into())), |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
401 }, |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
402 SocketAddrInner::WithHostname(addr) => match tokio_0_3::net::TcpListener::bind(addr.as_str()).await { |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
403 Ok(socket) => Ok(socket), |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
404 Err(error) => Err(TokioBindError::Bind(BindErrorInner::BindOrResolvFailed { addr, error, }.into())), |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
405 }, |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
406 SocketAddrInner::Systemd(socket_name) => { |
17
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
407 let (socket, addr) = Self::get_systemd(socket_name, true)?; |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
408 socket.try_into().map_err(|error| TokioConversionError { addr, error, }.into()) |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
409 }, |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
410 SocketAddrInner::SystemdNoPrefix(socket_name) => { |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
411 let (socket, addr) = Self::get_systemd(socket_name, false)?; |
4
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
412 socket.try_into().map_err(|error| TokioConversionError { addr, error, }.into()) |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
413 }, |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
414 } |
0 | 415 } |
416 | |
417 /// Creates `async_std::net::TcpListener` | |
418 /// | |
4
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
419 /// To be specific, it binds the socket or converts systemd socket to `async_std` socket. |
0 | 420 /// |
421 /// This method either `binds` the socket, if the address was provided or uses systemd socket | |
422 /// if the socket name was provided. | |
423 #[cfg(feature = "async-std")] | |
4
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
424 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
|
425 match self.0 { |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
426 SocketAddrInner::Ordinary(addr) => match async_std::net::TcpListener::bind(addr).await { |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
427 Ok(socket) => Ok(socket), |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
428 Err(error) => Err(BindErrorInner::BindFailed { addr, error, }.into()), |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
429 }, |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
430 SocketAddrInner::WithHostname(addr) => match async_std::net::TcpListener::bind(addr.as_str()).await { |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
431 Ok(socket) => Ok(socket), |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
432 Err(error) => Err(BindErrorInner::BindOrResolvFailed { addr, error, }.into()), |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
433 }, |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
434 SocketAddrInner::Systemd(socket_name) => { |
17
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
435 let (socket, _) = Self::get_systemd(socket_name, true)?; |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
436 Ok(socket.into()) |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
437 }, |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
438 SocketAddrInner::SystemdNoPrefix(socket_name) => { |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
439 let (socket, _) = Self::get_systemd(socket_name, false)?; |
4
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
440 Ok(socket.into()) |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
441 }, |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
442 } |
0 | 443 } |
444 | |
445 // We can't impl<T: Deref<Target=str> + Into<String>> TryFrom<T> for SocketAddr because of orphan | |
446 // rules. | |
447 fn try_from_generic<'a, T>(string: T) -> Result<Self, ParseError> where T: 'a + std::ops::Deref<Target=str> + Into<String> { | |
448 if string.starts_with(SYSTEMD_PREFIX) { | |
17
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
449 Self::inner_from_systemd_name(string.into(), true) |
0 | 450 } else { |
4
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
451 match string.parse() { |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
452 Ok(addr) => Ok(SocketAddr(SocketAddrInner::Ordinary(addr))), |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
453 Err(_) => Ok(SocketAddr(SocketAddrInner::WithHostname(ResolvAddr::try_from_generic(string).map_err(ParseErrorInner::ResolvAddr)?))), |
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
454 } |
0 | 455 } |
456 } | |
457 | |
16
bc76507dd878
Fixed conditional compilation based on OS
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
13
diff
changeset
|
458 #[cfg(all(target_os = "linux", feature = "enable_systemd"))] |
17
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
459 fn get_systemd(socket_name: String, prefixed: bool) -> Result<(std::net::TcpListener, SocketAddrInner), BindError> { |
25
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
460 use systemd_sockets::Socket; |
0 | 461 |
17
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
462 let real_systemd_name = if prefixed { |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
463 &socket_name[SYSTEMD_PREFIX.len()..] |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
464 } else { |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
465 &socket_name |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
466 }; |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
467 |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
468 let socket = 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
|
469 // 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
|
470 match socket { |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
471 Some(Ok(Socket::TcpListener(socket))) => Ok((socket, SocketAddrInner::Systemd(socket_name))), |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
472 Some(_) => Err(BindErrorInner::NotInetSocket(socket_name).into()), |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
473 None => Err(BindErrorInner::MissingDescriptor(socket_name).into()) |
0 | 474 } |
475 } | |
6
a7893294e9b2
Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
4
diff
changeset
|
476 |
a7893294e9b2
Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
4
diff
changeset
|
477 // 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
|
478 // 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
|
479 #[cfg(not(all(target_os = "linux", feature = "enable_systemd")))] |
17
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
480 fn get_systemd(socket_name: Never, _prefixed: bool) -> 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
|
481 match socket_name {} |
a7893294e9b2
Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
4
diff
changeset
|
482 } |
0 | 483 } |
484 | |
24
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
485 /// 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
|
486 /// |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
487 /// 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
|
488 /// 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
|
489 /// 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
|
490 /// 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
|
491 /// and returns a more idiomatic error type. |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
492 /// |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
493 /// 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
|
494 /// 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
|
495 /// 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
|
496 /// 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
|
497 #[inline] |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
498 pub fn init() -> Result<(), error::InitError> { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
499 #[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
|
500 { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
501 // Calling with true is always sound |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
502 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
|
503 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
504 #[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
|
505 { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
506 Ok(()) |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
507 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
508 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
509 |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
510 /// 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
|
511 /// |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
512 /// 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
|
513 /// 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
|
514 /// 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
|
515 /// |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
516 /// 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
|
517 /// (and this should be almost never) you may call this method if you've ensured that no other part |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
518 /// of your codebase is operating on systemd-provided file descriptors stored in the environment |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
519 /// variables. |
25
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
520 /// |
8e20daee41ed
Set CLOEXEC flag on the descriptors
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
24
diff
changeset
|
521 /// 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
|
522 /// 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
|
523 /// clean up the file descriptors yourself. |
24
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
524 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
|
525 #[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
|
526 { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
527 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
|
528 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
529 #[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
|
530 { |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
531 Ok(()) |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
532 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
533 } |
1941e9d9819c
Fix unsound manipulation of env vars
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
22
diff
changeset
|
534 |
0 | 535 /// Displays the address in format that can be parsed again. |
536 /// | |
537 /// **Important: While I don't expect this impl to change, don't rely on it!** | |
538 /// It should be used mostly for debugging/logging. | |
539 impl fmt::Display for SocketAddr { | |
540 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
541 fmt::Display::fmt(&self.0, f) | |
542 } | |
543 } | |
544 | |
545 impl fmt::Display for SocketAddrInner { | |
546 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
547 match self { | |
548 SocketAddrInner::Ordinary(addr) => fmt::Display::fmt(addr, f), | |
549 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
|
550 SocketAddrInner::SystemdNoPrefix(addr) => write!(f, "{}{}", SYSTEMD_PREFIX, addr), |
4
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
551 SocketAddrInner::WithHostname(addr) => fmt::Display::fmt(addr, f), |
0 | 552 } |
553 } | |
554 } | |
555 | |
556 // PartialEq for testing, I'm not convinced it should be exposed | |
557 #[derive(Debug, PartialEq)] | |
558 enum SocketAddrInner { | |
559 Ordinary(std::net::SocketAddr), | |
4
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
3
diff
changeset
|
560 WithHostname(resolv_addr::ResolvAddr), |
16
bc76507dd878
Fixed conditional compilation based on OS
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
13
diff
changeset
|
561 #[cfg(all(target_os = "linux", feature = "enable_systemd"))] |
0 | 562 Systemd(String), |
16
bc76507dd878
Fixed conditional compilation based on OS
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
13
diff
changeset
|
563 #[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
|
564 #[allow(dead_code)] |
a7893294e9b2
Make the crate compilable on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
4
diff
changeset
|
565 Systemd(Never), |
17
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
566 #[cfg(all(target_os = "linux", feature = "enable_systemd"))] |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
567 #[allow(dead_code)] |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
568 SystemdNoPrefix(String), |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
569 #[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
|
570 #[allow(dead_code)] |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
571 SystemdNoPrefix(Never), |
0 | 572 } |
573 | |
574 const SYSTEMD_PREFIX: &str = "systemd://"; | |
575 | |
11
13e2a5545167
Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
9
diff
changeset
|
576 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
|
577 fn from(value: (I, u16)) -> Self { |
13e2a5545167
Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
9
diff
changeset
|
578 SocketAddr(SocketAddrInner::Ordinary(value.into())) |
13e2a5545167
Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
9
diff
changeset
|
579 } |
13e2a5545167
Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
9
diff
changeset
|
580 } |
13e2a5545167
Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
9
diff
changeset
|
581 |
18
db1dc99252e2
Added From<std::net::SocketAddr>
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
17
diff
changeset
|
582 impl From<std::net::SocketAddr> for SocketAddr { |
db1dc99252e2
Added From<std::net::SocketAddr>
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
17
diff
changeset
|
583 fn from(value: std::net::SocketAddr) -> Self { |
db1dc99252e2
Added From<std::net::SocketAddr>
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
17
diff
changeset
|
584 SocketAddr(SocketAddrInner::Ordinary(value)) |
db1dc99252e2
Added From<std::net::SocketAddr>
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
17
diff
changeset
|
585 } |
db1dc99252e2
Added From<std::net::SocketAddr>
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
17
diff
changeset
|
586 } |
db1dc99252e2
Added From<std::net::SocketAddr>
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
17
diff
changeset
|
587 |
11
13e2a5545167
Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
9
diff
changeset
|
588 impl From<std::net::SocketAddrV4> for SocketAddr { |
13e2a5545167
Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
9
diff
changeset
|
589 fn from(value: std::net::SocketAddrV4) -> Self { |
13e2a5545167
Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
9
diff
changeset
|
590 SocketAddr(SocketAddrInner::Ordinary(value.into())) |
13e2a5545167
Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
9
diff
changeset
|
591 } |
13e2a5545167
Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
9
diff
changeset
|
592 } |
13e2a5545167
Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
9
diff
changeset
|
593 |
13e2a5545167
Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
9
diff
changeset
|
594 impl From<std::net::SocketAddrV6> for SocketAddr { |
13e2a5545167
Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
9
diff
changeset
|
595 fn from(value: std::net::SocketAddrV6) -> Self { |
13e2a5545167
Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
9
diff
changeset
|
596 SocketAddr(SocketAddrInner::Ordinary(value.into())) |
13e2a5545167
Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
9
diff
changeset
|
597 } |
13e2a5545167
Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
9
diff
changeset
|
598 } |
13e2a5545167
Implement From conversions
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
9
diff
changeset
|
599 |
0 | 600 impl std::str::FromStr for SocketAddr { |
601 type Err = ParseError; | |
602 | |
603 fn from_str(s: &str) -> Result<Self, Self::Err> { | |
604 SocketAddr::try_from_generic(s) | |
605 } | |
606 } | |
607 | |
608 impl<'a> TryFrom<&'a str> for SocketAddr { | |
609 type Error = ParseError; | |
610 | |
611 fn try_from(s: &'a str) -> Result<Self, Self::Error> { | |
612 SocketAddr::try_from_generic(s) | |
613 } | |
614 } | |
615 | |
616 impl TryFrom<String> for SocketAddr { | |
617 type Error = ParseError; | |
618 | |
619 fn try_from(s: String) -> Result<Self, Self::Error> { | |
620 SocketAddr::try_from_generic(s) | |
621 } | |
622 } | |
623 | |
624 impl<'a> TryFrom<&'a OsStr> for SocketAddr { | |
625 type Error = ParseOsStrError; | |
626 | |
627 fn try_from(s: &'a OsStr) -> Result<Self, Self::Error> { | |
628 s.to_str().ok_or(ParseOsStrError::InvalidUtf8)?.try_into().map_err(Into::into) | |
629 } | |
630 } | |
631 | |
632 impl TryFrom<OsString> for SocketAddr { | |
633 type Error = ParseOsStrError; | |
634 | |
635 fn try_from(s: OsString) -> Result<Self, Self::Error> { | |
636 s.into_string().map_err(|_| ParseOsStrError::InvalidUtf8)?.try_into().map_err(Into::into) | |
637 } | |
638 } | |
639 | |
640 #[cfg(feature = "serde")] | |
641 impl<'a> TryFrom<serde_str_helpers::DeserBorrowStr<'a>> for SocketAddr { | |
642 type Error = ParseError; | |
643 | |
644 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
|
645 SocketAddr::try_from_generic(s) |
0 | 646 } |
647 } | |
648 | |
649 #[cfg(feature = "parse_arg")] | |
650 impl parse_arg::ParseArg for SocketAddr { | |
651 type Error = ParseOsStrError; | |
652 | |
653 fn describe_type<W: fmt::Write>(mut writer: W) -> fmt::Result { | |
654 std::net::SocketAddr::describe_type(&mut writer)?; | |
655 write!(writer, " or a systemd socket name prefixed with systemd://") | |
656 } | |
657 | |
658 fn parse_arg(arg: &OsStr) -> Result<Self, Self::Error> { | |
659 arg.try_into() | |
660 } | |
661 | |
662 fn parse_owned_arg(arg: OsString) -> Result<Self, Self::Error> { | |
663 arg.try_into() | |
664 } | |
665 } | |
666 | |
667 #[cfg(test)] | |
668 mod tests { | |
669 use super::{SocketAddr, SocketAddrInner}; | |
670 | |
671 #[test] | |
672 fn parse_ordinary() { | |
673 assert_eq!("127.0.0.1:42".parse::<SocketAddr>().unwrap().0, SocketAddrInner::Ordinary(([127, 0, 0, 1], 42).into())); | |
674 } | |
675 | |
676 #[test] | |
16
bc76507dd878
Fixed conditional compilation based on OS
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
13
diff
changeset
|
677 #[cfg(all(target_os = "linux", feature = "enable_systemd"))] |
0 | 678 fn parse_systemd() { |
679 assert_eq!("systemd://foo".parse::<SocketAddr>().unwrap().0, SocketAddrInner::Systemd("systemd://foo".to_owned())); | |
680 } | |
2
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
681 |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
682 #[test] |
16
bc76507dd878
Fixed conditional compilation based on OS
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
13
diff
changeset
|
683 #[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
|
684 #[should_panic] |
9731ff589d9c
Fix tests on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
6
diff
changeset
|
685 fn parse_systemd() { |
9731ff589d9c
Fix tests on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
6
diff
changeset
|
686 "systemd://foo".parse::<SocketAddr>().unwrap(); |
9731ff589d9c
Fix tests on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
6
diff
changeset
|
687 } |
9731ff589d9c
Fix tests on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
6
diff
changeset
|
688 |
9731ff589d9c
Fix tests on non-linux systems
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
6
diff
changeset
|
689 #[test] |
2
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
690 #[should_panic] |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
691 fn parse_systemd_fail_control() { |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
692 "systemd://foo\n".parse::<SocketAddr>().unwrap(); |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
693 } |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
694 |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
695 #[test] |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
696 #[should_panic] |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
697 fn parse_systemd_fail_colon() { |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
698 "systemd://foo:".parse::<SocketAddr>().unwrap(); |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
699 } |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
700 |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
701 #[test] |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
702 #[should_panic] |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
703 fn parse_systemd_fail_non_ascii() { |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
704 "systemd://fooá".parse::<SocketAddr>().unwrap(); |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
705 } |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
706 |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
707 #[test] |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
708 #[should_panic] |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
709 fn parse_systemd_fail_too_long() { |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
710 "systemd://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".parse::<SocketAddr>().unwrap(); |
cabc4aafdd85
Added length check and a few tests
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
0
diff
changeset
|
711 } |
17
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
712 |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
713 #[test] |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
714 #[cfg_attr(not(all(target_os = "linux", feature = "enable_systemd")), should_panic)] |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
715 fn no_prefix_parse_systemd() { |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
716 SocketAddr::from_systemd_name("foo").unwrap(); |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
717 } |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
718 |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
719 #[test] |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
720 #[should_panic] |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
721 fn no_prefix_parse_systemd_fail_non_ascii() { |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
722 SocketAddr::from_systemd_name("fooá").unwrap(); |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
723 } |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
724 |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
725 #[test] |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
726 #[should_panic] |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
727 fn no_prefix_parse_systemd_fail_too_long() { |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
728 SocketAddr::from_systemd_name("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx").unwrap(); |
dfb727367934
Allow specifying systemd name directly
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
16
diff
changeset
|
729 } |
0 | 730 } |