taler-rust

GNU Taler code in Rust. Largely core banking integrations.
Log | Files | Refs | Submodules | README | LICENSE

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 }