use std::fs;
use std::fmt::{Debug};
use std::clone::{Clone};
use libc::{gid_t, uid_t};
use tokio::prelude::*;
use tokio::spawn;
use tokio_codec::{Encoder, Decoder};
use tokio_uds::{UnixListener, UnixStream};
use crate::server::Server;
use crate::connection::Connection;
use crate::error::Error;
use users::{User, Group, get_group_by_gid, get_user_by_uid};
pub type UnixServer<C> = Server<UnixStream, C, UnixInfo>;
pub type UnixConnection<C> = Connection<UnixStream, C>;
impl <C> UnixConnection<C>
where
C: Encoder + Decoder + Clone + Send + 'static,
<C as Decoder>::Item: Send,
<C as Decoder>::Error: Send + Debug,
{
pub fn new(path: &str, codec: C) -> impl Future<Item=UnixConnection<C>, Error=Error> {
debug!("[connector] creating connection (unix path: {})", path);
UnixStream::connect(&path)
.map(|s| {
Connection::from_socket(s, codec)
}).map_err(|e| e.into() )
}
pub fn close(self) {
self.shutdown();
}
}
#[derive(Clone, Debug)]
pub struct UnixInfo {
pub user: User,
pub group: Group,
}
impl UnixInfo {
pub fn new(uid: uid_t, gid: gid_t) -> UnixInfo {
let user = get_user_by_uid(uid).unwrap();
let group = get_group_by_gid(gid).unwrap();
UnixInfo{user, group}
}
}
impl<C> UnixServer<C>
where
C: Encoder + Decoder + Clone + Send + 'static,
<C as Decoder>::Item: Clone + Send + Debug,
<C as Decoder>::Error: Send + Debug,
<C as Encoder>::Item: Clone + Send + Debug,
<C as Encoder>::Error: Send + Debug,
{
pub fn new(path: &str, codec: C) -> Result<UnixServer<C>, Error> {
let _res = fs::remove_file(&path);
let server = Server::base(codec);
let socket = UnixListener::bind(&path)?;
let exit_rx = server.exit_rx.lock().unwrap().take();
let mut server_int = server.clone();
let tokio_server = socket
.incoming()
.for_each(move |s| {
let creds = s.peer_cred().unwrap();
let info = UnixInfo::new(creds.uid, creds.gid);
server_int.bind(info, s);
Ok(())
})
.map_err(|err| {
error!("[server] accept error: {:?}", err);
})
.select2(exit_rx)
.then(|_| {
debug!("[server] closing listener");
Ok(())
});
spawn(tokio_server);
Ok(server)
}
pub fn shutdown(&self) {
}
}