lib.rs (3482B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2024, 2025, 2026 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Affero General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. 12 13 You should have received a copy of the GNU Affero General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 17 use std::{fs::Permissions, io::ErrorKind, net::SocketAddr, os::unix::fs::PermissionsExt as _}; 18 19 use listenfd::ListenFd; 20 use tokio::net::{TcpListener, UnixListener}; 21 use tracing::info; 22 23 pub mod api; 24 pub mod auth; 25 pub mod config; 26 pub mod constants; 27 pub mod crypto; 28 pub mod db; 29 pub mod error; 30 pub mod extract; 31 pub mod notification; 32 pub mod subject; 33 #[cfg(test)] 34 pub mod test; 35 36 pub enum Serve { 37 Tcp(SocketAddr), 38 Unix { 39 path: String, 40 permission: Permissions, 41 }, 42 Systemd, 43 } 44 45 impl Serve { 46 /// Resolve listener from a config and environment 47 fn resolve(&self) -> Result<Listener, std::io::Error> { 48 match self { 49 Serve::Tcp(socket_addr) => { 50 info!(target: "api", "Server listening on {socket_addr}"); 51 let listener = std::net::TcpListener::bind(socket_addr)?; 52 listener.set_nonblocking(true)?; 53 Ok(Listener::Tcp(TcpListener::from_std(listener)?)) 54 } 55 Serve::Unix { path, permission } => { 56 info!(target: "api", 57 "Server listening on unxis domain socket {path} {:o}", 58 permission.mode() 59 ); 60 if let Err(e) = std::fs::remove_file(path) { 61 let kind = e.kind(); 62 if kind != ErrorKind::NotFound { 63 return Err(e); 64 } 65 } 66 let listener = std::os::unix::net::UnixListener::bind(path)?; 67 std::fs::set_permissions(path, permission.clone())?; 68 listener.set_nonblocking(true)?; 69 Ok(Listener::Unix(UnixListener::from_std(listener)?)) 70 } 71 Serve::Systemd => { 72 let mut listenfd = ListenFd::from_env(); 73 if let Ok(Some(unix)) = listenfd.take_unix_listener(0) { 74 info!(target: "api", 75 "Server listening on activated unix socket {:?}", 76 unix.local_addr()? 77 ); 78 unix.set_nonblocking(true)?; 79 Ok(Listener::Unix(UnixListener::from_std(unix)?)) 80 } else if let Ok(Some(tcp)) = listenfd.take_tcp_listener(0) { 81 info!(target: "api", 82 "Server listening on activated TCP socket {:?}", 83 tcp.local_addr()? 84 ); 85 tcp.set_nonblocking(true)?; 86 Ok(Listener::Tcp(TcpListener::from_std(tcp)?)) 87 } else { 88 Err(std::io::Error::other("Missing systemd activated socket")) 89 } 90 } 91 } 92 } 93 } 94 95 enum Listener { 96 Tcp(TcpListener), 97 Unix(UnixListener), 98 }