annotate src/lib.rs @ 5:27456533853e

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