use tokio::net::UdpSocket;
use tokio::runtime::Handle;
use tokio::sync::Mutex;
use tokio::time::{sleep, Duration}; use tracing::*;
use crate::error::Error;
use postcard::*;
use std::sync::Arc;
use chrono::Utc;
use crate::host::GenericStore;
use crate::prelude::*;
use std::convert::TryInto;
#[tracing::instrument(skip(db))]
#[inline]
pub async fn process_udp(
rt_handle: Handle,
socket: UdpSocket,
mut db: sled::Db,
max_buffer_size: usize,
) {
let mut buf = vec![0u8; max_buffer_size];
let s = Arc::new(socket);
loop {
let s = s.clone();
match s.recv_from(&mut buf).await {
Ok((0, _)) => break, Ok((n, return_addr)) => {
let bytes = &buf[..n];
let msg: GenericMsg = match from_bytes(bytes) {
Ok(msg) => msg,
Err(e) => {
error!("Had received Msg of {} bytes: {:?}, Error: {}", n, bytes, e);
continue;
}
};
match msg.msg_type {
MsgType::Set => {
if let Err(e) = db.insert_generic(msg) {
error!("{}", e);
}
}
MsgType::Get => {
let response = match db.get_generic_nth(&msg.topic, 0) {
Ok(g) => g,
Err(e) => GenericMsg::result(Err(e)),
};
if let Ok(return_bytes) = response.as_bytes() {
if let Ok(()) = s.writable().await {
if let Err(e) = s.try_send_to(&return_bytes, return_addr) {
error!("Error sending data back on UDP/GET: {}", e)
};
};
}
}
MsgType::GetNth(n) => {
let response = match db.get_generic_nth(&msg.topic, n) {
Ok(g) => g,
Err(e) => GenericMsg::result(Err(e)),
};
if let Ok(return_bytes) = response.as_bytes() {
if let Ok(()) = s.writable().await {
if let Err(e) = s.try_send_to(&return_bytes, return_addr) {
error!("Error sending data back on UDP/GET: {}", e)
};
};
}
}
MsgType::Topics => {
let response = match db.topics() {
Ok(mut topics) => {
topics.sort();
let msg = Msg::new(MsgType::Topics, "", topics);
match msg.to_generic() {
Ok(msg) => msg,
Err(e) => GenericMsg::result(Err(e)),
}
}
Err(e) => GenericMsg::result(Err(e)),
};
if let Ok(return_bytes) = response.as_bytes() {
if let Ok(()) = s.writable().await {
if let Err(e) = s.try_send_to(&return_bytes, return_addr) {
error!("Error sending data back on UDP/GET: {}", e)
};
};
}
}
MsgType::Subscribe => {
let specialized: Msg<Duration> = msg.clone().try_into().unwrap();
let rate = specialized.data;
let db = db.clone();
rt_handle.spawn(async move {
loop {
let response = match db.get_generic_nth(&msg.topic, 0) {
Ok(g) => g,
Err(e) => GenericMsg::result(Err(e)),
};
if let Ok(return_bytes) = response.as_bytes() {
if let Ok(()) = s.writable().await {
if let Err(e) = s.try_send_to(&return_bytes, return_addr) {
error!("Error sending data back on UDP/GET: {}", e)
};
};
}
sleep(rate).await;
}
});
}
_ => {}
}
}
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
continue;
}
Err(e) => {
error!("Error: {:?}", e);
}
}
}
}