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,
message::{IntoMessage, FromMessage, Message, PacketBytes}
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Action)]
#[repr(u16)]
pub enum Action {
RawReq = 1
}
#[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)]
pub struct RawReq<B> {
inner: Message<Action, B>
}
impl<B: PacketBytes> RawReq<B> {
pub fn new(len: usize) -> Self {
let mut msg = Message::new();
msg.body_mut().resize(len);
Self {
inner: msg
}
}
pub fn body_len(&self) -> usize {
self.inner.body().len()
}
}
impl<B> IntoMessage<Action, B> for RawReq<B>
where B: PacketBytes {
fn into_message(self) -> Result<Message<Action, B>, MessageError> {
Ok(self.inner)
}
}
impl<B> FromMessage<Action, B> for RawReq<B>
where B: PacketBytes {
fn from_message(msg: Message<Action, B>) -> Result<Self, MessageError> {
Ok(Self { inner: msg })
}
}
#[derive(Debug, Clone, Serialize, Deserialize, IntoMessage, FromMessage)]
#[message(json)]
pub struct RawResp {
pub status: String
}
impl<B> Request for RawReq<B> {
type Action = Action;
type Response = RawResp;
type Error = Error;
const ACTION: Action = Action::RawReq;
}
}
mod handlers {
use crate::api::*;
use fire_stream_api::{api};
type Result<T> = std::result::Result<T, Error>;
#[api(RawReq<B>)]
pub fn raw_request(req: RawReq<B>) -> Result<RawResp> {
Ok(RawResp { status: format!("worked {}", req.body_len()) })
}
}
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::raw_request);
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 e = client.request(api::RawReq::new(10)).await.unwrap();
assert_eq!(e.status, "worked 10");
client.close().await.unwrap();
}