summaryrefslogtreecommitdiff
path: root/src/main.rs
blob: a8e33b2ab677660761b73bd5e0903a0e521c160f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use std::io::{BufRead, BufReader};
use std::net::Shutdown;
use std::os::fd::FromRawFd;
use std::os::unix::net::UnixStream;
use std::str::FromStr;

use varlink::{ConnectionHandler, ErrorKind, Stream, VarlinkService};

mod cmd;
#[path = "de_jmhoffmann_jwebmail_mail-storage.rs"]
mod de_jmhoffmann_jwebmail_mailstorage;
mod rfc822;

use cmd::MailStorage;

fn main() {
    simplelog::TermLogger::init(
        simplelog::LevelFilter::Info,
        simplelog::Config::default(),
        simplelog::TerminalMode::Stderr,
        simplelog::ColorChoice::Never,
    )
    .unwrap();

    let mail_storage = MailStorage::default();

    let myinterface = de_jmhoffmann_jwebmail_mailstorage::new(Box::new(mail_storage));
    let service = VarlinkService::new(
        "de.jmhoffmann.jwebmail.mail-storage.varlink",
        "jwebmails storage service",
        "1.0.1",
        "https://fehcom.de/cgit/jwebmail2/",
        vec![Box::new(myinterface)],
    );

    if let Ok(listen_fds) = std::env::var("LISTEN_FDS") {
        let lfds = u8::from_str(&listen_fds).expect("env variable `LISTEN_FDS` must be an integer");
        if lfds < 1 {
            log::error!("No file descriptor to receive commands from!");
            return;
        } else if lfds == 1 {
            let uds = unsafe { UnixStream::from_raw_fd(3) };
            accept_con(&service, uds);
        } else {
            let listen_fdnames = std::env::var("LISTEN_FDNAMES")
                .expect("when multiple `LISTEN_FDS` are available `LISTEN_FDNAMES` must be set");
            listen_fdnames
                .split(':')
                .enumerate()
                .filter(|(_, name)| *name == "varlink")
                .for_each(|(i, _)| {
                    accept_con(&service, unsafe { UnixStream::from_raw_fd(3 + i as i32) })
                });
        }
    } else {
        log::error!("No file descriptor to receive commands from!");
    }
}

/// mostly a copy from varlink::listen
fn accept_con(service: &VarlinkService, mut uds: UnixStream) {
    let (r, mut w) = uds.split().unwrap();
    let mut br = BufReader::new(r);
    let mut iface: Option<String> = None;
    loop {
        match service.handle(&mut br, &mut w, iface.clone()) {
            Ok((_, i)) => {
                iface = i;
                match br.fill_buf() {
                    Err(_) => break,
                    Ok(buf) if buf.is_empty() => break,
                    _ => {}
                }
            }
            Err(err) => {
                match err.kind() {
                    ErrorKind::ConnectionClosed | ErrorKind::SerdeJsonDe(_) => {}
                    _ => {
                        eprintln!("Worker error: {:?}", err);
                    }
                }
                let _ = uds.shutdown(Shutdown::Both);
                break;
            }
        }
    }
}