moved master to embedded

This commit is contained in:
Aravinth Manivannan 2021-06-03 18:08:43 +05:30
parent d7c9130f5f
commit b0cf17aaa5
Signed by: realaravinth
GPG Key ID: AD9F0F08E855ED88
9 changed files with 86 additions and 18 deletions

View File

@ -8,6 +8,9 @@
internet. Ideally `mCaptcha` should automatically generate random internet. Ideally `mCaptcha` should automatically generate random
salt and rotate periodically, maybe in the next version. salt and rotate periodically, maybe in the next version.
- `master::Master` is moved to `master::embedded::Master` in preparation
for Redis based implementation.
## 0.1.3 ## 0.1.3
## Added ## Added

2
Cargo.lock generated
View File

@ -618,7 +618,7 @@ checksum = "56d855069fafbb9b344c0f962150cd2c1187975cb1c22c1522c240d8c4986714"
[[package]] [[package]]
name = "libmcaptcha" name = "libmcaptcha"
version = "0.1.3" version = "0.1.4"
dependencies = [ dependencies = [
"actix", "actix",
"actix-rt", "actix-rt",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "libmcaptcha" name = "libmcaptcha"
version = "0.1.3" version = "0.1.4"
authors = ["realaravinth <realaravinth@batsense.net>"] authors = ["realaravinth <realaravinth@batsense.net>"]
description = "core of mCaptcha captcha system" description = "core of mCaptcha captcha system"
keywords = ["DDoS", "mcaptcha", "captcha", "pow"] keywords = ["DDoS", "mcaptcha", "captcha", "pow"]

View File

@ -21,9 +21,10 @@ If someone wants to hammer your site, they will have to do more work to
send requests than your server will have to do to respond to their send requests than your server will have to do to respond to their
request. request.
> **NOTE:** `0.1` is out, expect breaking changes as ergonomics and > **NOTE:** `0.1.x` is out, expect breaking changes as ergonomics and
> performance is improved. Checkout [changelog](./CHANGELOG.md) for > performance is improved. Checkout [changelog](./CHANGELOG.md) for
> changes and migration pointers. > changes and migration pointers. Breaking changes will be frequent
> through `0.1.x`.
## Why use mCaptcha? ## Why use mCaptcha?

View File

@ -1,6 +1,6 @@
use libmcaptcha::{ use libmcaptcha::{
cache::{messages::VerifyCaptchaResult, HashCache}, cache::{messages::VerifyCaptchaResult, HashCache},
master::{AddSiteBuilder, Master}, master::embedded::{AddSiteBuilder, Master},
pow::{ConfigBuilder, Work}, pow::{ConfigBuilder, Work},
system::SystemBuilder, system::SystemBuilder,
DefenseBuilder, LevelBuilder, MCaptchaBuilder, DefenseBuilder, LevelBuilder, MCaptchaBuilder,

View File

@ -48,7 +48,7 @@
//! ```rust //! ```rust
//! use libmcaptcha::{ //! use libmcaptcha::{
//! cache::{messages::VerifyCaptchaResult, HashCache}, //! cache::{messages::VerifyCaptchaResult, HashCache},
//! master::{AddSiteBuilder, Master}, //! master::embedded::{AddSiteBuilder, Master},
//! pow::{ConfigBuilder, Work}, //! pow::{ConfigBuilder, Work},
//! system::SystemBuilder, //! system::SystemBuilder,
//! DefenseBuilder, LevelBuilder, MCaptchaBuilder, //! DefenseBuilder, LevelBuilder, MCaptchaBuilder,

View File

@ -17,6 +17,7 @@
*/ */
//! [Master] actor module that manages [MCaptcha] actors //! [Master] actor module that manages [MCaptcha] actors
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::sync::mpsc::channel;
use std::time::Duration; use std::time::Duration;
//use actix::clock::sleep; //use actix::clock::sleep;
@ -25,18 +26,21 @@ use actix::dev::*;
use derive_builder::Builder; use derive_builder::Builder;
use log::info; use log::info;
use super::*;
use crate::mcaptcha::MCaptcha; use crate::mcaptcha::MCaptcha;
/// This Actor manages the [MCaptcha] actors. /// This Actor manages the [MCaptcha] actors.
/// A service can have several [MCaptcha] actors with /// A service can have several [MCaptcha] actors with
/// varying [Defense][crate::defense::Defense] configurations /// varying [Defense][crate::defense::Defense] configurations
/// so a "master" actor is needed to manage them all /// so a "master" actor is needed to manage them all
#[derive(Clone)] #[derive(Clone, Default)]
pub struct Master { pub struct Master {
sites: BTreeMap<String, (Option<()>, Addr<MCaptcha>)>, sites: BTreeMap<String, (Option<()>, Addr<MCaptcha>)>,
gc: u64, gc: u64,
} }
impl Counter for Master {}
impl Master { impl Master {
/// add [MCaptcha] actor to [Master] /// add [MCaptcha] actor to [Master]
pub fn add_site(&mut self, details: AddSite) { pub fn add_site(&mut self, details: AddSite) {
@ -82,6 +86,31 @@ impl Actor for Master {
} }
} }
impl Handler<AddVisitor> for Master {
type Result = MessageResult<AddVisitor>;
fn handle(&mut self, m: AddVisitor, ctx: &mut Self::Context) -> Self::Result {
let addr = self.get_site(&m.0);
if addr.is_none() {
return MessageResult(None);
} else {
let (tx, rx) = channel();
let fut = async move {
let config = addr
.unwrap()
.send(crate::mcaptcha::AddVisitor)
.await
.unwrap();
tx.send(config).unwrap();
}
.into_actor(self);
ctx.spawn(fut);
return MessageResult(Some(rx));
}
}
}
/// Message to get an [MCaptcha] actor from master /// Message to get an [MCaptcha] actor from master
#[derive(Message)] #[derive(Message)]
#[rtype(result = "Option<Addr<MCaptcha>>")] #[rtype(result = "Option<Addr<MCaptcha>>")]

31
src/master/mod.rs Normal file
View File

@ -0,0 +1,31 @@
/*
* mCaptcha - A proof of work based DoS protection system
* Copyright © 2021 Aravinth Manivannan <realravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! [Master] actor module that manages [MCaptcha] actors
use std::sync::mpsc::Receiver;
use actix::dev::*;
pub mod embedded;
/// Describes actor handler trait impls that are required by a cache implementation
pub trait Counter: actix::Actor + actix::Handler<AddVisitor> {}
/// Message to add visitor to an [MCaptcha] actor
#[derive(Message)]
#[rtype(result = "Option<Receiver<crate::mcaptcha::AddVisitorResult>>")]
pub struct AddVisitor(pub String);

View File

@ -23,35 +23,39 @@ use pow_sha256::Config;
use crate::cache::messages::*; use crate::cache::messages::*;
use crate::cache::Save; use crate::cache::Save;
use crate::errors::*; use crate::errors::*;
use crate::master::Master; use crate::master::Counter;
use crate::pow::*; use crate::pow::*;
/// struct describing various bits of data required for an mCaptcha system /// struct describing various bits of data required for an mCaptcha system
#[derive(Clone, Builder)] #[derive(Clone, Builder)]
pub struct System<T: Save> { pub struct System<T: Save, X: Counter> {
pub master: Addr<Master>, pub master: Addr<X>,
cache: Addr<T>, cache: Addr<T>,
pow: Config, pow: Config,
} }
impl<T> System<T> impl<T, X> System<T, X>
where where
T: Save, T: Save,
<T as actix::Actor>::Context: ToEnvelope<T, CachePoW> <T as actix::Actor>::Context: ToEnvelope<T, CachePoW>
+ ToEnvelope<T, RetrivePoW> + ToEnvelope<T, RetrivePoW>
+ ToEnvelope<T, CacheResult> + ToEnvelope<T, CacheResult>
+ ToEnvelope<T, VerifyCaptchaResult>, + ToEnvelope<T, VerifyCaptchaResult>,
X: Counter,
<X as actix::Actor>::Context: ToEnvelope<X, crate::master::AddVisitor>,
{ {
/// utility function to get difficulty factor of site `id` and cache it /// utility function to get difficulty factor of site `id` and cache it
pub async fn get_pow(&self, id: String) -> Option<PoWConfig> { pub async fn get_pow(&self, id: String) -> Option<PoWConfig> {
use crate::master::GetSite; use crate::master::AddVisitor;
use crate::mcaptcha::AddVisitor;
let site_addr = self.master.send(GetSite(id.clone())).await.unwrap(); let rx = self.master.send(AddVisitor(id.clone())).await.unwrap();
if site_addr.is_none() {
if rx.is_none() {
return None; return None;
} }
let mcaptcha = site_addr.unwrap().send(AddVisitor).await.unwrap();
let mcaptcha = rx.unwrap().recv().unwrap();
let pow_config = PoWConfig::new(mcaptcha.difficulty_factor, self.pow.salt.clone()); let pow_config = PoWConfig::new(mcaptcha.difficulty_factor, self.pow.salt.clone());
let cache_msg = CachePoWBuilder::default() let cache_msg = CachePoWBuilder::default()
@ -119,12 +123,12 @@ mod tests {
use super::System; use super::System;
use super::*; use super::*;
use crate::cache::HashCache; use crate::cache::HashCache;
use crate::master::*; use crate::master::embedded::*;
use crate::mcaptcha::tests::*; use crate::mcaptcha::tests::*;
const MCAPTCHA_NAME: &str = "batsense.net"; const MCAPTCHA_NAME: &str = "batsense.net";
async fn boostrap_system(gc: u64) -> System<HashCache> { async fn boostrap_system(gc: u64) -> System<HashCache, Master> {
let master = Master::new(gc).start(); let master = Master::new(gc).start();
let mcaptcha = get_counter().start(); let mcaptcha = get_counter().start();
let pow = get_config(); let pow = get_config();