diff --git a/src/error.rs b/src/error.rs index 557c29c..46cb62f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -17,6 +17,7 @@ pub enum Kind { #[derive(Copy, Clone, Debug)] pub enum Class { + ClientProtocolError, ClientError, ServerError, } @@ -110,7 +111,7 @@ impl From for Error { kind: Kind::IoError, msg: Some(error.to_string()), desc: Some(error.to_string()), - class: Class::ClientError, + class: Class::ClientProtocolError, } } } @@ -121,7 +122,7 @@ impl From for Error { kind: Kind::JsonParseError, msg: Some("Unable to parse JSON data".to_string()), desc: Some(error.to_string()), - class: Class::ClientError, + class: Class::ClientProtocolError, } } } @@ -156,7 +157,7 @@ impl From for Error { kind: Kind::Utf8DecodeError, msg: Some("Unable to decode UTF-8 data".to_string()), desc: Some(error.to_string()), - class: Class::ClientError, + class: Class::ClientProtocolError, } } } diff --git a/src/http/handler.rs b/src/http/handler.rs index 61647be..3c88f8d 100644 --- a/src/http/handler.rs +++ b/src/http/handler.rs @@ -75,10 +75,10 @@ fn request_handler(client: &mut super::HttpStream) { _ => { res.status(405); res.header.add_field("Allow", "POST"); - error = Some(Error::new(Kind::UsimpProtocolError, Class::ClientError)) + error = Some(Error::new(Kind::UsimpProtocolError, Class::ClientProtocolError)) } }, - _ => error = Some(Error::new(Kind::InvalidEndpointError, Class::ClientError)), + _ => error = Some(Error::new(Kind::InvalidEndpointError, Class::ClientProtocolError)), } if let Some(error) = error { @@ -112,10 +112,15 @@ fn request_handler(client: &mut super::HttpStream) { pub fn error_handler(client: &mut super::HttpStream, mut res: super::Response, error: Error) { println!("{}", error.to_string()); match &error.class() { - Class::ClientError => { + Class::ClientProtocolError => { if res.status.code < 400 || res.status.code >= 499 { res.status(400) } + }, + Class::ClientError => { + if res.status.code < 200 || res.status.code >= 299 { + res.status(200) + } } Class::ServerError => { if res.status.code < 500 || res.status.code > 599 { @@ -128,6 +133,7 @@ pub fn error_handler(client: &mut super::HttpStream, mut res: super::Response, e let mut obj = serde_json::Value::Object(serde_json::Map::new()); obj["status"] = serde_json::Value::String("error".to_string()); obj["message"] = serde_json::Value::String(error.to_string()); + obj["data"] = serde_json::Value::Null; let buf = obj.to_string() + "\r\n"; let length = buf.as_bytes().len(); @@ -157,7 +163,7 @@ fn endpoint_handler( return error_handler( client, res, - Error::new(Kind::HttpRequestParseError, Class::ClientError) + Error::new(Kind::HttpRequestParseError, Class::ClientProtocolError) .set_desc("field 'Content-Length' missing".to_string()), ) } @@ -169,7 +175,7 @@ fn endpoint_handler( return error_handler( client, res, - Error::new(Kind::HttpRequestParseError, Class::ClientError).set_desc( + Error::new(Kind::HttpRequestParseError, Class::ClientProtocolError).set_desc( format!("unable to parse field 'Content-Length': {}", &e).to_string(), ), ) @@ -198,7 +204,7 @@ fn endpoint_handler( return error_handler( client, res, - Error::new(Kind::UsimpProtocolError, Class::ClientError) + Error::new(Kind::UsimpProtocolError, Class::ClientProtocolError) .set_desc("Unable to find field 'From-Domain'".to_string()) ); } @@ -210,7 +216,7 @@ fn endpoint_handler( return error_handler( client, res, - Error::new(Kind::UsimpProtocolError, Class::ClientError) + Error::new(Kind::UsimpProtocolError, Class::ClientProtocolError) .set_desc("Unable to find field 'To-Domain'".to_string()) ); } diff --git a/src/http/parser.rs b/src/http/parser.rs index c7a5818..168347c 100644 --- a/src/http/parser.rs +++ b/src/http/parser.rs @@ -43,7 +43,7 @@ pub fn parse_response(stream: &mut http::Stream) -> Result() { Ok(v) => v, Err(error) => { - return Err(Error::new(Kind::HttpRequestParseError, Class::ClientError) + return Err(Error::new(Kind::HttpRequestParseError, Class::ClientProtocolError) .set_desc(error.to_string())) } }; @@ -132,7 +132,7 @@ impl Parser<'_> { match self.state { State::Finish => return Ok(self.header_size), State::Error => { - return Err(Error::new(Kind::HttpRequestParseError, Class::ClientError) + return Err(Error::new(Kind::HttpRequestParseError, Class::ClientProtocolError) .set_desc(format!( "invalid character at position {}", self.header_size - 1 @@ -141,7 +141,7 @@ impl Parser<'_> { _ => {} } } - return Err(Error::new(Kind::HttpRequestParseError, Class::ClientError) + return Err(Error::new(Kind::HttpRequestParseError, Class::ClientProtocolError) .set_desc("input too short".to_string())); } diff --git a/src/usimp/mod.rs b/src/usimp/mod.rs index e0eebcc..e4b2752 100644 --- a/src/usimp/mod.rs +++ b/src/usimp/mod.rs @@ -16,14 +16,21 @@ pub struct Envelope { pub fn endpoint(envelope: Envelope) -> Result { // TODO check authorization - // TODO domain_check - match envelope.endpoint.as_str() { - "echo" => Ok(serde_json::to_value(echo(serde_json::from_value(envelope.data)?)?)?), - "authenticate" => Ok(serde_json::to_value(authenticate(serde_json::from_value(envelope.data)?)?)?), - "subscribe" => Ok(serde_json::to_value(subscribe(serde_json::from_value(envelope.data)?)?)?), - "send_event" => Ok(serde_json::to_value(send_event(serde_json::from_value(envelope.data)?)?)?), - _ => return Err(Error::new(Kind::InvalidEndpointError, Class::ClientError)), - } + // TODO check from/to domain + let out = match envelope.endpoint.as_str() { + "echo" => serde_json::to_value(echo(serde_json::from_value(envelope.data)?)?)?, + "authenticate" => serde_json::to_value(authenticate(serde_json::from_value(envelope.data)?)?)?, + "subscribe" => serde_json::to_value(subscribe(serde_json::from_value(envelope.data)?)?)?, + "send_event" => serde_json::to_value(send_event(serde_json::from_value(envelope.data)?)?)?, + _ => return Err(Error::new(Kind::InvalidEndpointError, Class::ClientProtocolError)), + }; + + let mut envelope = serde_json::Value::Object(serde_json::Map::new()); + envelope["status"] = serde_json::Value::String("success".to_string()); + envelope["message"] = serde_json::Value::Null; + envelope["data"] = out; + + Ok(envelope) } pub fn get_id(input: &str) -> String { diff --git a/src/websocket/handler.rs b/src/websocket/handler.rs index dfecb54..574fd9d 100644 --- a/src/websocket/handler.rs +++ b/src/websocket/handler.rs @@ -15,10 +15,10 @@ pub fn recv_message(client: &mut http::HttpStream) -> Result { // FIXME control frames may show up in a fragmented stream if msg_type != 0 && header.opcode != 0 { - return Err(Error::new(Kind::WebSocketError, Class::ClientError) + return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError) .set_desc("continuation frame expected".to_string())); } else if header.opcode >= 8 && (!header.fin || header.payload_len >= 126) { - return Err(Error::new(Kind::WebSocketError, Class::ClientError) + return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError) .set_desc("invalid control frame".to_string())); } @@ -26,12 +26,12 @@ pub fn recv_message(client: &mut http::HttpStream) -> Result { 0 => {}, // cont 1 => {}, // text 2 => // binary - return Err(Error::new(Kind::UsimpProtocolError, Class::ClientError) + return Err(Error::new(Kind::UsimpProtocolError, Class::ClientProtocolError) .set_desc("binary frames must not be sent on a usimp connection".to_string())), 8 => {}, // close 9 => {}, // ping 10 => {}, // pong - _ => return Err(Error::new(Kind::WebSocketError, Class::ClientError) + _ => return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError) .set_desc("invalid opcode".to_string())), } @@ -101,37 +101,37 @@ pub fn handshake( } else { res.status(405); res.header.add_field("Allow", "GET"); - return Err(Error::new(Kind::WebSocketError, Class::ClientError) + return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError) .set_desc("method not allowed".to_string())); } if let Some(_) = req.header.find_field("Connection") { if !req.header.field_has_value("Connection", "upgrade") { - return Err(Error::new(Kind::WebSocketError, Class::ClientError) + return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError) .set_desc("invalid value for header field 'Connection'".to_string())); } } else { - return Err(Error::new(Kind::WebSocketError, Class::ClientError) + return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError) .set_desc("unable to find header field 'Connection'".to_string())); } if let Some(upgrade) = req.header.find_field("Upgrade") { if !upgrade.eq_ignore_ascii_case("websocket") { - return Err(Error::new(Kind::WebSocketError, Class::ClientError) + return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError) .set_desc("invalid value for header field 'Upgrade'".to_string())); } } else { - return Err(Error::new(Kind::WebSocketError, Class::ClientError) + return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError) .set_desc("unable to find header field 'Upgrade'".to_string())); } if let Some(version) = req.header.find_field("Sec-WebSocket-Version") { if !version.eq("13") { - return Err(Error::new(Kind::WebSocketError, Class::ClientError) + return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError) .set_desc("invalid value for header field 'Sec-WebSocket-Key'".to_string())); } } else { - return Err(Error::new(Kind::WebSocketError, Class::ClientError) + return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError) .set_desc("unable to find header field 'Sec-WebSocket-Version'".to_string())); } @@ -145,7 +145,7 @@ pub fn handshake( let key = base64::encode(result); res.header.add_field("Sec-WebSocket-Accept", key.as_str()); } else { - return Err(Error::new(Kind::WebSocketError, Class::ClientError) + return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError) .set_desc("unable to find header field 'Sec-WebSocket-Key'".to_string())); }