Workspacify
This commit is contained in:
78
server/src/socket.rs
Normal file
78
server/src/socket.rs
Normal file
@@ -0,0 +1,78 @@
|
||||
use crate::TopLevelError;
|
||||
use error_stack::ResultExt;
|
||||
use tokio::net::{UnixListener, UnixStream};
|
||||
use tracing::Instrument;
|
||||
|
||||
pub struct SocketServer {
|
||||
name: String,
|
||||
path: String,
|
||||
num_sessions_run: u64,
|
||||
listener: UnixListener,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
impl SocketServer {
|
||||
/// Create a new server that will handle inputs from the client program.
|
||||
///
|
||||
/// This function will just generate the function required, without starting the
|
||||
/// underlying task. To start the task, use [`SocketServer::start`], although that
|
||||
/// method will take ownership of the object.
|
||||
pub fn new(name: String, listener: UnixListener) -> Self {
|
||||
let path = listener
|
||||
.local_addr()
|
||||
.map(|x| x.as_pathname().map(|p| format!("{}", p.display())))
|
||||
.unwrap_or_else(|_| None)
|
||||
.unwrap_or_else(|| "<unknown>".to_string());
|
||||
|
||||
tracing::trace!(%name, %path, "Creating new socket listener");
|
||||
|
||||
SocketServer {
|
||||
name,
|
||||
path,
|
||||
num_sessions_run: 0,
|
||||
listener,
|
||||
}
|
||||
}
|
||||
|
||||
/// Start running the service, returning a handle that will pass on an error if
|
||||
/// one occurs in the core of this task.
|
||||
///
|
||||
/// Typically, errors shouldn't happen in the core task, as all it does is listen
|
||||
/// for new connections and then spawn other tasks based on them. If errors occur
|
||||
/// there, the core task should be unaffected.
|
||||
pub async fn start(mut self) -> error_stack::Result<(), TopLevelError> {
|
||||
loop {
|
||||
let (stream, addr) = self
|
||||
.listener
|
||||
.accept()
|
||||
.await
|
||||
.change_context(TopLevelError::SocketHandlerFailure)?;
|
||||
let remote_addr = addr
|
||||
.as_pathname()
|
||||
.map(|x| x.display())
|
||||
.map(|x| format!("{}", x))
|
||||
.unwrap_or("<unknown>".to_string());
|
||||
|
||||
let span = tracing::debug_span!(
|
||||
"unix socket handler",
|
||||
socket_name = %self.name,
|
||||
socket_path = %self.path,
|
||||
session_no = %self.num_sessions_run,
|
||||
%remote_addr,
|
||||
);
|
||||
|
||||
self.num_sessions_run += 1;
|
||||
|
||||
tokio::task::spawn(Self::run_session(stream).instrument(span))
|
||||
.await
|
||||
.change_context(TopLevelError::SocketHandlerFailure)?;
|
||||
}
|
||||
}
|
||||
|
||||
/// Run a session.
|
||||
///
|
||||
/// This is here because it's convenient, not because it shares state (obviously,
|
||||
/// given the type signature). But it's somewhat logically associated with this type,
|
||||
/// so it seems reasonable to make it an associated function.
|
||||
async fn run_session(handle: UnixStream) {}
|
||||
}
|
||||
Reference in New Issue
Block a user