use std::time::Duration;
use std::net::SocketAddr;
use fire_stream_api::{
server::{Server, Config as ServerConfig},
client::{Client, Config as ClientConfig}
};
use tokio::net::{TcpListener, TcpStream};
use crypto::signature::Keypair;
mod api {
use std::fmt;
use serde::{Serialize, Deserialize};
use fire_stream_api::{
IntoMessage, FromMessage, Action,
error::{ApiError, RequestError, MessageError},
request::Request
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Action)]
#[repr(u16)]
pub enum Action {
Act1 = 1,
Act2 = 2,
MyAddress = 3,
AlwaysError = 4
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(IntoMessage, FromMessage)]
#[message(json)]
pub enum Error {
MyError,
RequestError(String),
MessageError(String)
}
impl ApiError for Error {
fn from_request_error(e: RequestError) -> Self {
Self::RequestError(e.to_string())
}
fn from_message_error(e: MessageError) -> Self {
Self::MessageError(e.to_string())
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
}
impl std::error::Error for Error {}
#[derive(Debug, Clone, Serialize, Deserialize, IntoMessage, FromMessage)]
#[message(json)]
pub struct Act1Req;
#[derive(Debug, Clone, Serialize, Deserialize, IntoMessage, FromMessage)]
#[message(json)]
pub struct Act1 {
pub hello: String
}
impl Request for Act1Req {
type Action = Action;
type Response = Act1;
type Error = Error;
const ACTION: Action = Action::Act1;
}
#[derive(Debug, Clone, Serialize, Deserialize, IntoMessage, FromMessage)]
#[message(json)]
pub struct Act2Req {
pub hi: String
}
#[derive(Debug, Clone, Serialize, Deserialize, IntoMessage, FromMessage)]
#[message(json)]
pub struct Act2 {
pub numbers: u64
}
impl Request for Act2Req {
type Action = Action;
type Response = Act2;
type Error = Error;
const ACTION: Action = Action::Act2;
}
#[derive(Debug, Clone, Serialize, Deserialize, IntoMessage, FromMessage)]
#[message(json)]
pub struct MyAddressReq;
#[derive(Debug, Clone, Serialize, Deserialize, IntoMessage, FromMessage)]
#[message(json)]
pub struct MyAddress {
pub addr: String
}
impl Request for MyAddressReq {
type Action = Action;
type Response = MyAddress;
type Error = Error;
const ACTION: Action = Action::MyAddress;
}
#[derive(Debug, Clone, Serialize, Deserialize, IntoMessage, FromMessage)]
#[message(json)]
pub struct AlwaysErrorReq;
#[derive(Debug, Clone, Serialize, Deserialize, IntoMessage, FromMessage)]
#[message(json)]
pub struct AlwaysError {
pub addr: String
}
impl Request for AlwaysErrorReq {
type Action = Action;
type Response = AlwaysError;
type Error = Error;
const ACTION: Action = Action::AlwaysError;
}
}
mod handlers {
use super::MyAddr;
use crate::api::*;
use fire_stream_api::{api};
type Result<T> = std::result::Result<T, Error>;
#[api(Act1Req)]
pub fn act_1() -> Result<Act1> {
Ok(Act1 {
hello: format!("Hello, World!")
})
}
#[api(Act2Req)]
pub async fn act_2(
req: Act2Req
) -> Result<Act2> {
Ok(Act2 {
numbers: req.hi.len() as u64
})
}
#[api(MyAddressReq)]
pub fn my_address(addr: &MyAddr) -> Result<MyAddress> {
Ok(MyAddress { addr: addr.0.to_string() })
}
#[api(AlwaysErrorReq)]
pub fn always_error() -> Result<AlwaysError> {
Err(Error::MyError)
}
}
struct MyAddr(SocketAddr);
#[tokio::test]
async fn main() {
let listener = TcpListener::bind(("127.0.0.1", 0)).await.unwrap();
let addr = listener.local_addr().unwrap();
let priv_key = Keypair::new();
let pub_key = priv_key.public().clone();
let my_addr = MyAddr(addr.clone());
tokio::spawn(async move {
let mut server = Server::new_encrypted(listener, ServerConfig {
timeout: Duration::from_secs(10),
body_limit: 0
}, priv_key);
server.register_data(my_addr);
server.register_request(handlers::act_1);
server.register_request(handlers::act_2);
server.register_request(handlers::my_address);
server.register_request(handlers::always_error);
server.run().await.unwrap();
});
let stream = TcpStream::connect(addr.clone()).await.unwrap();
let client = Client::new_encrypted(stream, ClientConfig {
timeout: Duration::from_secs(10),
body_limit: 0
}, None, pub_key);
let r = client.request(api::Act1Req).await.unwrap();
assert_eq!(r.hello, "Hello, World!");
let r = client.request(api::Act2Req {
hi: "12345".into()
}).await.unwrap();
assert_eq!(r.numbers, 5);
let r = client.request(api::MyAddressReq).await.unwrap();
assert_eq!(r.addr, addr.to_string());
let e = client.request(api::AlwaysErrorReq).await.unwrap_err();
assert_eq!(e, api::Error::MyError);
client.close().await.unwrap();
}