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
|
// -*- coding: utf-8 -*-
//
// Copyright (C) 2024 Michael Büsch <m@bues.ch>
//
// Licensed under the Apache License version 2.0
// or the MIT license, at your option.
// SPDX-License-Identifier: Apache-2.0 OR MIT
use crate::ConfigRef;
use anyhow::{self as ah, Context as _};
use letmein_proto::Message;
use letmein_systemd::{systemd_notify_ready, tcp_from_systemd};
use std::net::SocketAddr;
use tokio::net::{TcpListener, TcpStream};
pub trait ConnectionOps {
fn addr(&self) -> SocketAddr;
async fn recv_msg(&mut self) -> ah::Result<Option<Message>>;
async fn send_msg(&mut self, msg: Message) -> ah::Result<()>;
}
pub struct Connection {
stream: TcpStream,
addr: SocketAddr,
}
impl Connection {
fn new(stream: TcpStream, addr: SocketAddr) -> ah::Result<Self> {
Ok(Self { stream, addr })
}
}
impl ConnectionOps for Connection {
fn addr(&self) -> SocketAddr {
self.addr
}
async fn recv_msg(&mut self) -> ah::Result<Option<Message>> {
Message::recv(&mut self.stream).await
}
async fn send_msg(&mut self, msg: Message) -> ah::Result<()> {
msg.send(&mut self.stream).await
}
}
pub struct Server {
listener: TcpListener,
}
impl Server {
pub async fn new(conf: &ConfigRef<'_>, no_systemd: bool) -> ah::Result<Self> {
// Get socket from systemd?
if !no_systemd {
if let Some(listener) = tcp_from_systemd()? {
println!("Using socket from systemd.");
listener
.set_nonblocking(true)
.context("Set socket non-blocking")?;
let listener = TcpListener::from_std(listener)
.context("Convert std TcpListener to tokio TcpListener")?;
systemd_notify_ready()?;
return Ok(Self { listener });
}
}
// Without systemd.
// TCP bind.
let listener = TcpListener::bind(("::0", conf.port()))
.await
.context("Bind")?;
Ok(Self { listener })
}
pub async fn accept(&self) -> ah::Result<Connection> {
let (stream, addr) = self.listener.accept().await?;
Connection::new(stream, addr)
}
}
// vim: ts=4 sw=4 expandtab
|