implement Network Handler Logic
This commit is contained in:
parent
ca4fde0b50
commit
0e06fb1df4
|
@ -11,6 +11,8 @@ use crate::model::*;
|
|||
mod protocol_connection;
|
||||
use self::protocol_connection::*;
|
||||
|
||||
use super::results::*;
|
||||
|
||||
pub fn listen_forever<H>(handler: H, config: &ProtocolConfig) -> io::Result<()>
|
||||
where
|
||||
H: 'static + ProtocolHandler + Sized,
|
||||
|
@ -26,37 +28,34 @@ where
|
|||
stream.set_write_timeout(Duration::from_secs(config.read_timeout_s).into())
|
||||
});
|
||||
|
||||
let mut handler = handler.clone();
|
||||
let handler = handler.clone();
|
||||
let _ = thread::spawn(move || client_loop(connection?, handler));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn client_loop<H>(connection: TcpStream, handler: H) -> io::Result<()>
|
||||
fn client_loop<H>(connection: TcpStream, mut handler: H) -> io::Result<()>
|
||||
where
|
||||
H: 'static + ProtocolHandler + Sized,
|
||||
{
|
||||
let mut connection = Connection::from_tcp(connection)?;
|
||||
loop {
|
||||
'outer: loop {
|
||||
let package = connection.receive()?;
|
||||
|
||||
match package {
|
||||
Package::Error(_, _) => {
|
||||
// Just clone the connection.
|
||||
// Just close the connection.
|
||||
break;
|
||||
}
|
||||
|
||||
Package::Binary(_) => {
|
||||
connection.send(&Package::Error(400, "Unexpected Binary".to_string()))?;
|
||||
break;
|
||||
}
|
||||
|
||||
Package::JsonTrue | Package::JsonFalse | Package::JsonNull => {
|
||||
connection.send(&Package::Error(
|
||||
400,
|
||||
"Unexpected true, false or null. ".to_string(),
|
||||
))?;
|
||||
Package::JsonTrue
|
||||
| Package::JsonFalse
|
||||
| Package::JsonNull
|
||||
| Package::JsonTexture(_)
|
||||
| Package::JsonTextureArray(_)
|
||||
| Package::Binary(_) => {
|
||||
connection.send(&Package::Error(400, "Expected Command.".to_string()))?;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -68,8 +67,81 @@ where
|
|||
// Ignore
|
||||
}
|
||||
|
||||
// TODO: lots
|
||||
_ => unimplemented!(),
|
||||
Package::Json(Command::Query { query }) => {
|
||||
connection.send(&Package::from(handler.query(&query[..])))?;
|
||||
}
|
||||
|
||||
Package::Json(Command::GetTexture { id, name }) => match (id, name) {
|
||||
(Some(id), None) => {
|
||||
connection.send(&Package::from(handler.get_texture_by_id(&id)))?;
|
||||
}
|
||||
(None, Some(name)) => {
|
||||
connection.send(&Package::from(handler.get_texture_by_name(&name)))?;
|
||||
}
|
||||
_ => {
|
||||
connection.send(&Package::from(ProtocolError::BadRequest(
|
||||
"Either 'id' or 'name' must be set!".to_string(),
|
||||
)))?;
|
||||
}
|
||||
},
|
||||
|
||||
Package::Json(Command::GetTextureData { texture_hash }) => {
|
||||
connection.send(&Package::from(handler.get_texture_file(texture_hash)))?;
|
||||
}
|
||||
|
||||
Package::Json(Command::GetTexturePreview {
|
||||
texture_hash,
|
||||
desired_format,
|
||||
}) => {
|
||||
connection.send(&Package::from(
|
||||
handler.get_texture_preview(texture_hash, desired_format),
|
||||
))?;
|
||||
}
|
||||
|
||||
// TODO: use less nesting.
|
||||
Package::Json(Command::ReplaceTexture { old, new }) => {
|
||||
match handler.replace_texture(old.clone(), new.clone(), None) {
|
||||
Ok(ReplaceTextureStatus::Ok) => {
|
||||
connection.send(&Package::JsonTrue)?;
|
||||
}
|
||||
Ok(ReplaceTextureStatus::NeedTextureData(hash)) => {
|
||||
connection.send(&Package::Json(Command::GetTextureData {
|
||||
texture_hash: hash,
|
||||
}))?;
|
||||
|
||||
let pkg = connection.receive()?;
|
||||
match pkg {
|
||||
Package::Binary(data) => {
|
||||
match handler.replace_texture(old.clone(), new.clone(), Some(data))
|
||||
{
|
||||
Ok(ReplaceTextureStatus::Ok) => {
|
||||
connection.send(&Package::JsonTrue)?;
|
||||
}
|
||||
Ok(ReplaceTextureStatus::NeedTextureData(hash)) => {
|
||||
panic!("Contract Violation: handler must not return NeedTextureData \
|
||||
when data is given.");
|
||||
}
|
||||
Err(err) => {
|
||||
connection.send(&Package::from(err))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Package::Error(_, _) => {
|
||||
// Just close the connection.
|
||||
break 'outer;
|
||||
}
|
||||
_ => {
|
||||
connection.send(&Package::from(ProtocolError::BadRequest(
|
||||
"Expected Texture Data!".to_string(),
|
||||
)))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
connection.send(&Package::from(err))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ use crate::model::*;
|
|||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
// TODO: put conversion and these enums in own file.
|
||||
|
||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
||||
pub enum Package {
|
||||
JsonNull,
|
||||
|
@ -41,6 +43,56 @@ pub enum Command {
|
|||
},
|
||||
}
|
||||
|
||||
use super::results::*;
|
||||
|
||||
impl From<ProtocolError> for Package {
|
||||
fn from(item: ProtocolError) -> Self {
|
||||
match item {
|
||||
ProtocolError::BadRequest(msg) => Package::Error(400, msg),
|
||||
ProtocolError::FileNotFound(msg) => Package::Error(404, msg),
|
||||
ProtocolError::Conflict(msg) => Package::Error(409, msg),
|
||||
ProtocolError::InternalServerError(_err) => {
|
||||
Package::Error(500, "Internal Server Error.".to_string())
|
||||
}
|
||||
ProtocolError::NotImplemented => Package::Error(
|
||||
501,
|
||||
"Well, I'm sorry, \
|
||||
but this feature is still a Todo :/"
|
||||
.to_string(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ProtocolResult<Vec<Texture>>> for Package {
|
||||
fn from(item: ProtocolResult<Vec<Texture>>) -> Self {
|
||||
match item {
|
||||
Ok(textures) => Package::JsonTextureArray(textures),
|
||||
Err(err) => Package::from(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ProtocolResult<Option<Texture>>> for Package {
|
||||
fn from(item: ProtocolResult<Option<Texture>>) -> Self {
|
||||
match item {
|
||||
Ok(Some(texture)) => Package::JsonTexture(texture),
|
||||
Ok(None) => Package::JsonNull,
|
||||
Err(err) => Package::from(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ProtocolResult<Vec<u8>>> for Package {
|
||||
fn from(item: ProtocolResult<Vec<u8>>) -> Self {
|
||||
match item {
|
||||
Ok(bin) => Package::Binary(bin),
|
||||
Err(err) => Package::from(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use crate::protocol::results::ProtocolResult;
|
||||
use std::io::*;
|
||||
use std::net::*;
|
||||
|
||||
|
@ -56,12 +108,13 @@ const PACKAGE_TYPE_ERROR: u8 = 0;
|
|||
const PACKAGE_TYPE_JSON: u8 = 1;
|
||||
const PACKAGE_TYPE_BIN: u8 = 2;
|
||||
|
||||
impl Connection<BufReader<TcpStream>, BufWriter<TcpStream>> {
|
||||
impl Connection<BufReader<TcpStream>, TcpStream> {
|
||||
pub fn from_tcp(connection: TcpStream) -> Result<Self> {
|
||||
let reader = BufReader::new(connection.try_clone()?);
|
||||
let writer = BufWriter::new(connection);
|
||||
|
||||
Ok(Connection { reader, writer })
|
||||
Ok(Connection {
|
||||
reader,
|
||||
writer: connection,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,13 +17,17 @@ use std::sync::Arc;
|
|||
pub trait ProtocolHandler: Send + Sync + Clone {
|
||||
fn query(&mut self, query: &[String]) -> ProtocolResult<Vec<Texture>>;
|
||||
|
||||
fn get_texture_by_id(&mut self, id: String) -> ProtocolResult<Option<Texture>>;
|
||||
fn get_texture_by_id(&mut self, id: &str) -> ProtocolResult<Option<Texture>>;
|
||||
|
||||
fn get_texture_by_name(&mut self, id: String) -> ProtocolResult<Option<Texture>>;
|
||||
fn get_texture_by_name(&mut self, name: &str) -> ProtocolResult<Option<Texture>>;
|
||||
|
||||
fn get_texture_file(&mut self, hash: Sha256) -> ProtocolResult<Arc<Vec<u8>>>;
|
||||
fn get_texture_file(&mut self, hash: Sha256) -> ProtocolResult<Vec<u8>>;
|
||||
|
||||
fn get_texture_preview(&mut self, hash: Sha256) -> ProtocolResult<Arc<Vec<u8>>>;
|
||||
fn get_texture_preview(
|
||||
&mut self,
|
||||
hash: Sha256,
|
||||
format: TextureFormat,
|
||||
) -> ProtocolResult<Vec<u8>>;
|
||||
|
||||
fn replace_texture(
|
||||
&mut self,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use crate::model::*;
|
||||
|
||||
pub enum ReplaceTextureStatus {
|
||||
// Call Again With Texture Binary
|
||||
NeedTextureData,
|
||||
NeedTextureData(Sha256),
|
||||
// Done.
|
||||
Ok,
|
||||
}
|
||||
|
|
|
@ -18,19 +18,23 @@ impl ProtocolHandler for ServerState {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_texture_by_id(&mut self, id: String) -> ProtocolResult<Option<Texture>> {
|
||||
fn get_texture_by_id(&mut self, id: &str) -> ProtocolResult<Option<Texture>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_texture_by_name(&mut self, id: String) -> ProtocolResult<Option<Texture>> {
|
||||
fn get_texture_by_name(&mut self, name: &str) -> ProtocolResult<Option<Texture>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_texture_file(&mut self, hash: Sha256) -> ProtocolResult<Arc<Vec<u8>>> {
|
||||
fn get_texture_file(&mut self, hash: Sha256) -> ProtocolResult<Vec<u8>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_texture_preview(&mut self, hash: Sha256) -> ProtocolResult<Arc<Vec<u8>>> {
|
||||
fn get_texture_preview(
|
||||
&mut self,
|
||||
hash: Sha256,
|
||||
format: TextureFormat,
|
||||
) -> ProtocolResult<Vec<u8>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
|
@ -40,6 +44,7 @@ impl ProtocolHandler for ServerState {
|
|||
insert: Option<Texture>,
|
||||
insert_texture_data: Option<Vec<u8>>,
|
||||
) -> ProtocolResult<ReplaceTextureStatus> {
|
||||
// NOTE: must also check if insert_texture_data fits sha256!
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue