Skip to content
Snippets Groups Projects
Commit cd7703ca authored by jocutajar's avatar jocutajar
Browse files

Adding more #1 docummentation

parent 61aa20f3
No related branches found
No related tags found
No related merge requests found
[package]
name = "samotop"
version = "0.4.2"
version = "0.4.3"
authors = ["jocutajar <tellnoone@robajz.info>"]
build = "src/peg.rs"
exclude = [
"downloads/*"
]
description = "SMTP server and library built on tokio"
documentation = "https://gitlab.com/BrightOpen/BackYard/Samotop/"
documentation = "https://docs.rs/samotop/"
homepage = "https://gitlab.com/BrightOpen/BackYard/Samotop/"
repository = "https://gitlab.com/BrightOpen/BackYard/Samotop/"
readme = "README.md"
......
//! # Status
//!
//! The API is still very much subject to change. Until you see the release of version 1.0.0, don't expect much stability.
//! See the README.md file and project open issues for current status.
//!
//! # Usage
//!
//! The use case of running the server as a standalone application should be described in the README.md (tbd)
//! Here we focus on using the library.
//!
//! # Installation
//!
//! Add this to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! samotop = "0.4"
//! ```
//!
//! # Usage
//!
//! There are a few interesting provisions one could take away here:
//! * The server (through `samotop::builder()`) - it takes IP:port's to listen `on()` and you can use it `with()` your own implementation of `TcpService`.
//! * The SMTP service (`SamotopService`) - it takes a `tokio::net::TcpStream` into the `Sink` created by `start()`.
......@@ -19,7 +30,7 @@
//! # Builder
//! The simplest way is to run the server with a builder:
//!
//! ```
//! ```no_run
//! extern crate env_logger;
//! extern crate samotop;
//! extern crate tokio;
......
......@@ -9,11 +9,23 @@ use tokio::io;
use tokio::net::{TcpListener, TcpStream};
use tokio::prelude::*;
/// Create a builder that can configure a samotop server and make it runnable as a task.
/// Each listener is executed as a separate task, but they are all joined into one future.
///
/// Example of creating a samotop server task (`Future<Item=(),Error=()>`):
/// ```
/// samotop::builder()
/// // SamotopService is the default, but you can set your own name here.
/// .with(samotop::service::samotop::SamotopService::new("MySamotop"))
/// .on("1.1.1.1:25")
/// .as_task();
/// ```
pub fn builder() -> SamotopBuilder<SamotopService> {
SamotopBuilder::new("localhost:25", SamotopService::new("Samotop"))
}
pub fn serve<S>(server: SamotopServer<S>) -> impl Future<Item = (), Error = ()>
/// Start the server, spawning each listener as a separate task.
pub(crate) fn serve<S>(server: SamotopServer<S>) -> impl Future<Item = (), Error = ()>
where
S: Clone + Send + 'static,
S: TcpService,
......@@ -25,7 +37,10 @@ where
.for_each(|port| tokio::spawn(bind(port).and_then(accept)))
}
pub fn resolve<S>(server: SamotopServer<S>) -> impl Stream<Item = SamotopPort<S>, Error = io::Error>
/// Resolve `SamotopServer` addr into `SamotopPort`s
pub(crate) fn resolve<S>(
server: SamotopServer<S>,
) -> impl Stream<Item = SamotopPort<S>, Error = io::Error>
where
S: Clone,
S: TcpService,
......@@ -47,7 +62,8 @@ where
})
}
pub fn bind<S>(port: SamotopPort<S>) -> impl Future<Item = SamotopListener<S>, Error = ()>
// Bind the samotop TCP port
pub(crate) fn bind<S>(port: SamotopPort<S>) -> impl Future<Item = SamotopListener<S>, Error = ()>
where
S: Clone,
S: TcpService,
......@@ -68,7 +84,8 @@ where
})
}
pub fn accept<S>(listener: SamotopListener<S>) -> impl Future<Item = (), Error = ()>
/// Accept incomming TCP connections and forward them to the handler sink created by TcpService
pub(crate) fn accept<S>(listener: SamotopListener<S>) -> impl Future<Item = (), Error = ()>
where
S: TcpService,
S::Handler: Sink<SinkItem = TcpStream, SinkError = io::Error>,
......
......@@ -4,9 +4,88 @@ pub mod samotop;
use model::session::Session;
/** Handles TCP connections */
/**
An object implementing this trait handles TCP connections.
The caller would first `start()` the `Handler`, then pass tcp connections to the handler.
Here's a dead simple implementation that returns the `DeadHandler` as a handler:
```
# extern crate samotop;
# extern crate tokio;
# use samotop;
# use samotop::service::*;
# use tokio::io;
# use tokio::net::TcpStream;
# use tokio::prelude::*;
#
#[derive(Clone, Debug)]
pub struct DeadService;
impl TcpService for DeadService {
type Handler = DeadHandler;
fn start(&self) -> Self::Handler {
DeadHandler
}
}
pub struct DeadHandler;
```
While this would satisfy the trait, you'll want some more magic.
For it to be usable in Samotop, implement `Sink` for the `DeadHandler`.
The sink accepts `tokio::net::TcpStream` and we work with `io::Error`.
```
# extern crate samotop;
# extern crate tokio;
# use samotop;
# use samotop::service::*;
# use tokio::io;
# use tokio::net::TcpStream;
# use tokio::prelude::*;
#
# #[derive(Clone, Debug)]
# pub struct DeadService;
#
# impl TcpService for DeadService {
# type Handler = DeadHandler;
# fn start(&self) -> Self::Handler {
# DeadHandler
# }
# }
# pub struct DeadHandler;
impl Sink for DeadHandler {
type SinkItem = TcpStream;
type SinkError = io::Error;
fn start_send(&mut self, _item: Self::SinkItem)
-> io::Result<AsyncSink<Self::SinkItem>> {
println!("got an item");
Ok(AsyncSink::Ready)
}
fn poll_complete(&mut self) -> io::Result<Async<()>> {
Ok(Async::Ready(()))
}
}
# fn test () {
# let task = samotop::builder()
# .with(DeadService)
# .as_task();
# }
```
You can then use this `DeadService` in samotop:
```
# use samotop::service::dead::DeadService;
let task = samotop::builder()
.with(DeadService)
.as_task();
```
*/
pub trait TcpService {
/// The handler that receives TCP connections.
/// Typically a `Sink<SinkItem = tokio::net::TcpStream,
/// SinkError = io::Error>` implementation.
type Handler;
/// Start the `Handler`.
fn start(&self) -> Self::Handler;
}
......
extern crate samotop;
extern crate tokio;
#[test]
#[ignore]
fn use_dead_service() {
let service = samotop::service::dead::DeadService;
let server = samotop::model::server::SamotopServer {
addr: "invalid name:99999999".into(),
service,
};
let task = samotop::server::serve(server);
tokio::run(task);
let _ = samotop::builder()
.with(samotop::service::dead::DeadService)
.as_task();
}
#[test]
fn use_samotop_service() {
let _ = samotop::builder()
.with(samotop::service::samotop::SamotopService::new("name"))
.as_task();
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment