mirror of
https://github.com/Astatin3/unshell-nodes-rs.git
synced 2026-06-08 16:18:08 -06:00
Move files around, add UI
This commit is contained in:
+9
-2
@@ -1,10 +1,17 @@
|
||||
[package]
|
||||
name = "unshell-rs"
|
||||
name = "server"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.22.1"
|
||||
clap = { version = "4.5.39", features = ["derive"] }
|
||||
log = "0.4.27"
|
||||
pretty_env_logger = "0.5.0"
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
serde_json = "1.0.140"
|
||||
slint = "1.11.0"
|
||||
unshell-rs-lib = { path = "./unshell-rs-lib" }
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
slint-build = "1.11.0"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
- Probably out of scope
|
||||
- Build targets
|
||||
- To achieve a minimal size, there should probably be a way to pack diffrent features with the actual result binary.
|
||||
- There should also be a way to update one of the hosts with the new functionality.
|
||||
|
||||
### Network
|
||||
- Diffrent traffic obfuscators:
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
slint_build::compile("ui/app-window.slint").expect("Slint build failed");
|
||||
}
|
||||
+2
-1
@@ -4,5 +4,6 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
serde_json = "1.0.140"
|
||||
# libc = "0.2.172"
|
||||
unshell-rs = { path = "../" }
|
||||
unshell-rs-lib = { path = "../unshell-rs-lib" }
|
||||
|
||||
+55
-11
@@ -2,20 +2,64 @@
|
||||
// mod execute;
|
||||
|
||||
use std::error::Error;
|
||||
use unshell_rs::{
|
||||
networkers::{TCPClient, TCPConnection},
|
||||
payload::run_client,
|
||||
|
||||
use std::{
|
||||
sync::{Arc, Mutex},
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
// /// Pipe streams are blocking, we need separate threads to monitor them without blocking the primary thread.
|
||||
// fn child_stream_to_vec<R>(mut stream: R) -> Arc<Mutex<Vec<u8>>>
|
||||
// where
|
||||
// R: Read + Send + 'static,
|
||||
// {
|
||||
// let out = Arc::new(Mutex::new(Vec::new()));
|
||||
// let vec = out.clone();
|
||||
use unshell_rs_lib::{
|
||||
networkers::{ClientTrait, Connection, TCPClient, TCPConnection},
|
||||
packets::Packet,
|
||||
};
|
||||
|
||||
// }
|
||||
// Generic client function
|
||||
pub fn run_client<C, Cl>(address: &str) -> Result<(), Box<dyn std::error::Error>>
|
||||
where
|
||||
Cl: ClientTrait<C>,
|
||||
C: Connection + 'static,
|
||||
Cl::Error: std::error::Error + 'static,
|
||||
C::Error: std::error::Error + 'static,
|
||||
{
|
||||
let recv_conn = Arc::new(Mutex::new(Cl::connect(address)?));
|
||||
let transmit_vec: Arc<Mutex<Vec<Packet>>> = Arc::new(Mutex::new(Vec::new()));
|
||||
|
||||
let transmit_conn = Arc::clone(&recv_conn);
|
||||
let transmit_vec_clone = Arc::clone(&transmit_vec);
|
||||
|
||||
thread::spawn(move || {
|
||||
loop {
|
||||
let mut transmit_vec_lock = transmit_vec.lock().unwrap();
|
||||
if transmit_vec_lock.len() > 0 {
|
||||
let mut conn_lock = recv_conn.lock().unwrap();
|
||||
if let Ok(json) = serde_json::to_string(&transmit_vec_lock.pop().unwrap()) {
|
||||
conn_lock.write(&json).expect("Failed to send packet!");
|
||||
}
|
||||
} else {
|
||||
thread::sleep(Duration::from_millis(10));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
loop {
|
||||
let mut conn_lock = transmit_conn.lock().unwrap();
|
||||
let data = conn_lock.read();
|
||||
drop(conn_lock);
|
||||
match data {
|
||||
Ok(data_json) => {
|
||||
if data_json.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let packet = serde_json::from_str::<Packet>(data_json.as_str());
|
||||
println!("{:?}", packet);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Error reading, {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
run_client::<TCPConnection, TCPClient>("127.0.0.1:3000")?;
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
[package]
|
||||
name = "server"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
unshell-rs = { path = "../" }
|
||||
@@ -1,14 +0,0 @@
|
||||
use std::error::Error;
|
||||
|
||||
use unshell_rs::{
|
||||
listeners::Listener,
|
||||
networkers::{ServerTrait, TCPServer},
|
||||
};
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let mut server = Listener::new(TCPServer::bind("0.0.0.0:3000")?);
|
||||
|
||||
server.run_listener()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
use slint::{ModelRc, VecModel};
|
||||
use std::error::Error;
|
||||
use unshell_rs_lib::config::listeners::ListenerConfig;
|
||||
|
||||
pub struct Unshell_Gui;
|
||||
|
||||
slint::include_modules!();
|
||||
impl Unshell_Gui {
|
||||
pub fn start() -> Result<Self, Box<dyn Error>> {
|
||||
let ui = AppWindow::new()?;
|
||||
|
||||
// ui.
|
||||
|
||||
let ui_handle = ui.as_weak();
|
||||
ui.on_tab_clicked(move |index| {
|
||||
let ui = ui_handle.unwrap();
|
||||
ui.set_current_tab(index);
|
||||
trace!("Tab {} selected", index);
|
||||
});
|
||||
|
||||
ui.set_app_info({
|
||||
(String::new()
|
||||
+ "Unshell\n"
|
||||
+ "Version "
|
||||
+ env!("CARGO_PKG_VERSION")
|
||||
+ "\n\n View the source code at:\n https://github.com/astatin3/unshell-rs")
|
||||
.into()
|
||||
});
|
||||
|
||||
let listeners: Vec<ListenerConfig> = vec![ListenerConfig::Tcp {
|
||||
enabled: true,
|
||||
name: "test".to_string(),
|
||||
remote_host: "127.0.0.1".to_string(),
|
||||
port: 25565,
|
||||
layers: Vec::new(),
|
||||
}];
|
||||
|
||||
ui.set_listeners(ModelRc::new(VecModel::from(
|
||||
listeners
|
||||
.iter()
|
||||
.map(|l| match l {
|
||||
ListenerConfig::Tcp {
|
||||
enabled,
|
||||
name,
|
||||
remote_host,
|
||||
port,
|
||||
layers,
|
||||
} => UITcpListener {
|
||||
enabled: *enabled,
|
||||
name: name.clone().into(),
|
||||
remote_host: remote_host.clone().into(),
|
||||
port: *port as i32,
|
||||
},
|
||||
})
|
||||
.collect::<Vec<UITcpListener>>(),
|
||||
)));
|
||||
|
||||
ui.run()?;
|
||||
|
||||
Ok(Self {})
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
pub mod layers;
|
||||
pub mod listeners;
|
||||
pub mod networkers;
|
||||
pub mod packets;
|
||||
pub mod payload;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
mod gui;
|
||||
mod server;
|
||||
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
use std::error::Error;
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use log::trace;
|
||||
use slint::{ModelRc, VecModel};
|
||||
use unshell_rs_lib::{
|
||||
config::listeners::ListenerConfig,
|
||||
listeners::Listener,
|
||||
networkers::{ServerTrait, TCPServer},
|
||||
};
|
||||
|
||||
/// The default port that this program looks for
|
||||
pub static DEFAULT_SERVICE_PORT: u16 = 13370;
|
||||
/// The default website port that this program looks for
|
||||
pub static DEFAULT_WEB_PORT: u16 = 8082;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[command(name = "unshell-rs")]
|
||||
#[command(about = "Slick reverse shell tool in rust", long_about = None)]
|
||||
struct Args {
|
||||
#[command(subcommand)]
|
||||
command: Commands,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
enum Commands {
|
||||
/// Run as a service, and potentially hosting a website
|
||||
#[command(arg_required_else_help = true)]
|
||||
Serve {
|
||||
/// Only listen for command clients locally
|
||||
#[arg(short, long, default_value_t = false)]
|
||||
local: bool,
|
||||
|
||||
/// Port listen to for command clients
|
||||
#[arg(short, long, default_value_t = DEFAULT_SERVICE_PORT)]
|
||||
service_port: u16,
|
||||
// /// Port to listen for website traffic (0 is disabled)
|
||||
// #[arg(short, long, default_value_t = DEFAULT_SERVICE_PORT)]
|
||||
// web_port: u16,
|
||||
},
|
||||
Gui {
|
||||
/// Listen for command clients remotely aswell
|
||||
#[arg(short, long, default_value_t = true)]
|
||||
remote: bool,
|
||||
|
||||
/// Port listen to for command clients
|
||||
#[arg(short, long, default_value_t = DEFAULT_SERVICE_PORT)]
|
||||
service_port: u16,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
pretty_env_logger::init();
|
||||
let args = Args::parse();
|
||||
|
||||
match args.command {
|
||||
Commands::Gui {
|
||||
remote,
|
||||
service_port,
|
||||
} => {}
|
||||
Commands::Serve {
|
||||
local,
|
||||
service_port,
|
||||
// web_port,
|
||||
} => {}
|
||||
}
|
||||
|
||||
// let mut server = Listener::new(TCPServer::bind("0.0.0.0:3000")?);
|
||||
|
||||
// server.run_listener()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
use std::{
|
||||
sync::{Arc, Mutex},
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
networkers::{ClientTrait, Connection},
|
||||
packets::Packet,
|
||||
};
|
||||
|
||||
// Generic client function
|
||||
pub fn run_client<C, Cl>(address: &str) -> Result<(), Box<dyn std::error::Error>>
|
||||
where
|
||||
Cl: ClientTrait<C>,
|
||||
C: Connection + 'static,
|
||||
Cl::Error: std::error::Error + 'static,
|
||||
C::Error: std::error::Error + 'static,
|
||||
{
|
||||
let recv_conn = Arc::new(Mutex::new(Cl::connect(address)?));
|
||||
let transmit_vec: Arc<Mutex<Vec<Packet>>> = Arc::new(Mutex::new(Vec::new()));
|
||||
|
||||
let transmit_conn = Arc::clone(&recv_conn);
|
||||
let transmit_vec_clone = Arc::clone(&transmit_vec);
|
||||
|
||||
thread::spawn(move || {
|
||||
loop {
|
||||
let mut transmit_vec_lock = transmit_vec.lock().unwrap();
|
||||
if transmit_vec_lock.len() > 0 {
|
||||
let mut conn_lock = recv_conn.lock().unwrap();
|
||||
if let Ok(json) = serde_json::to_string(&transmit_vec_lock.pop().unwrap()) {
|
||||
conn_lock.write(&json).expect("Failed to send packet!");
|
||||
}
|
||||
} else {
|
||||
thread::sleep(Duration::from_millis(10));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
loop {
|
||||
let mut conn_lock = transmit_conn.lock().unwrap();
|
||||
let data = conn_lock.read();
|
||||
drop(conn_lock);
|
||||
match data {
|
||||
Ok(data_json) => {
|
||||
if data_json.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let packet = serde_json::from_str::<Packet>(data_json.as_str());
|
||||
println!("{:?}", packet);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Error reading, {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// loop {
|
||||
// let mut input = String::new();
|
||||
// stdin.read_line(&mut input)?;
|
||||
// let input = input.trim();
|
||||
|
||||
// if input == "quit" {
|
||||
// conn.write(input)?;
|
||||
// break;
|
||||
// }
|
||||
|
||||
// if !input.is_empty() {
|
||||
// conn.write(input)?;
|
||||
|
||||
// match conn.read() {
|
||||
// Ok(response) => println!("Server: {}", response),
|
||||
// Err(e) => {
|
||||
// eprintln!("Failed to read response: {:?}", e);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
import { Button, HorizontalBox, VerticalBox, Slider, StandardButton } from "std-widgets.slint";
|
||||
import { DashboardPage } from "pages/dashboard.slint";
|
||||
import { ListenersPage } from "pages/listeners.slint";
|
||||
import { ClientsPage } from "pages/clients.slint";
|
||||
import { ToolsPage } from "pages/tools.slint";
|
||||
import { UITcpListener } from "structs.slint";
|
||||
import { BorderedRectangle } from "components.slint";
|
||||
|
||||
component SideButton inherits Button {
|
||||
in property <length> sidebar_size: 40px;
|
||||
|
||||
preferred-width: sidebar_size;
|
||||
height: sidebar_size;
|
||||
}
|
||||
|
||||
export component AppWindow inherits Window {
|
||||
|
||||
in-out property <int> current-tab: 0;
|
||||
in-out property <[UITcpListener]> listeners;
|
||||
|
||||
in-out property <string> app-info;
|
||||
|
||||
callback tab-clicked(int);
|
||||
|
||||
tab-clicked(index) => {
|
||||
current-tab = index;
|
||||
}
|
||||
|
||||
// background: @linear-gradient(20deg, #1a161d 0%, #27222a 100%);
|
||||
MenuBar {
|
||||
|
||||
Menu {
|
||||
title: @tr("File");
|
||||
MenuItem {
|
||||
title: @tr("New");
|
||||
activated => {
|
||||
// file-new();
|
||||
}
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
title: @tr("Open");
|
||||
activated => {
|
||||
// file-open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Menu {
|
||||
title: @tr("Edit");
|
||||
|
||||
MenuItem {
|
||||
title: @tr("Copy");
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
title: @tr("Paste");
|
||||
}
|
||||
|
||||
MenuSeparator { }
|
||||
|
||||
Menu {
|
||||
title: @tr("Find");
|
||||
MenuItem {
|
||||
title: @tr("Find in document...");
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
title: @tr("Find Next");
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
title: @tr("Find Previous");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
callback request-increase-value();
|
||||
HorizontalLayout {
|
||||
|
||||
BorderedRectangle {
|
||||
VerticalLayout {
|
||||
spacing: 5px;
|
||||
padding: 10px;
|
||||
|
||||
Text {
|
||||
text: "Unshell";
|
||||
font-size: 14px;
|
||||
font-weight: 1000;
|
||||
horizontal-alignment: center;
|
||||
}
|
||||
|
||||
for entry[i] in [
|
||||
{ name: "Dashboard" },
|
||||
{ name: "Listeners" },
|
||||
{ name: "Clients" },
|
||||
{ name: "Tools" },
|
||||
]: SideButton {
|
||||
text: entry.name;
|
||||
|
||||
clicked => {
|
||||
root.tab-clicked(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Strechy
|
||||
Rectangle { }
|
||||
|
||||
SideButton {
|
||||
text: "Info";
|
||||
|
||||
clicked => {
|
||||
info-window.visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Text {
|
||||
// text: "Counter: \{root.counter}";
|
||||
// }
|
||||
|
||||
Rectangle {
|
||||
|
||||
if current-tab == 0: DashboardPage { }
|
||||
if current-tab == 1: ListenersPage {
|
||||
listeners: listeners;
|
||||
}
|
||||
if current-tab == 2: ClientsPage { }
|
||||
if current-tab == 3: ToolsPage { }
|
||||
}
|
||||
|
||||
callback file-new();
|
||||
callback file-open();
|
||||
}
|
||||
|
||||
info-window := Dialog {
|
||||
visible: false;
|
||||
|
||||
BorderedRectangle {
|
||||
VerticalLayout {
|
||||
padding: 10px;
|
||||
spacing: 10px;
|
||||
|
||||
Text {
|
||||
font-size: 20px;
|
||||
text: app-info;
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
kind: ok;
|
||||
clicked => {
|
||||
info-window.visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
export component BorderedRectangle inherits Rectangle {
|
||||
background: #2a232a;
|
||||
border-width: 1px;
|
||||
border-color: darkslateblue;
|
||||
}
|
||||
|
||||
export component BoolText inherits Text {
|
||||
in property <bool> state;
|
||||
|
||||
text: state ? "TRUE" : "FALSE";
|
||||
color: state ? #00ff00 : #ff0000;
|
||||
}
|
||||
|
||||
export component TitleText inherits HorizontalLayout {
|
||||
in property <string> text;
|
||||
|
||||
alignment: start;
|
||||
|
||||
Text {
|
||||
text: text;
|
||||
font-weight: 700;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
@children
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { VerticalBox } from "std-widgets.slint";
|
||||
export component Page inherits VerticalBox {
|
||||
padding: 20px;
|
||||
alignment: start;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { Page } from "../page.slint";
|
||||
|
||||
export component ClientsPage inherits Page {
|
||||
Text {
|
||||
text: "Clients";
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import { Page } from "../page.slint";
|
||||
|
||||
export component DashboardPage inherits Page { }
|
||||
@@ -0,0 +1,64 @@
|
||||
import { Page } from "../page.slint";
|
||||
import { UITcpListener } from "../structs.slint";
|
||||
import { ScrollView, GridBox, Button } from "std-widgets.slint";
|
||||
import { BorderedRectangle, BoolText, TitleText } from "../components.slint";
|
||||
|
||||
|
||||
component ListenerCard inherits BorderedRectangle {
|
||||
in property <UITcpListener> listener;
|
||||
|
||||
VerticalLayout {
|
||||
padding: 10px;
|
||||
|
||||
Text {
|
||||
text: listener.name;
|
||||
font-weight: 700;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
TitleText {
|
||||
text: "Enabled: ";
|
||||
BoolText {
|
||||
state: listener.enabled;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
TitleText {
|
||||
text: "Remote Host: ";
|
||||
Text {
|
||||
text: listener.remote-host;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
TitleText {
|
||||
text: "Port: ";
|
||||
|
||||
Text {
|
||||
text: listener.port;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export component ListenersPage inherits Page {
|
||||
in-out property <[UITcpListener]> listeners;
|
||||
|
||||
ScrollView {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
VerticalLayout {
|
||||
|
||||
for listener[i] in listeners: ListenerCard {
|
||||
listener: listener;
|
||||
}
|
||||
|
||||
Rectangle { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import { Page } from "../page.slint";
|
||||
|
||||
export component ToolsPage inherits Page { }
|
||||
@@ -0,0 +1,6 @@
|
||||
export struct UITcpListener {
|
||||
enabled: bool,
|
||||
name: string,
|
||||
remote_host: string,
|
||||
port: int,
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "unshell-rs-lib"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.22.1"
|
||||
log = "0.4.27"
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
serde_json = "1.0.140"
|
||||
@@ -0,0 +1,6 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CampignConfig {
|
||||
name: String,
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum LayerConfig {}
|
||||
@@ -0,0 +1,14 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::config::layers::LayerConfig;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum ListenerConfig {
|
||||
Tcp {
|
||||
enabled: bool,
|
||||
name: String,
|
||||
remote_host: String,
|
||||
port: u16,
|
||||
layers: Vec<LayerConfig>,
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
pub mod campaign;
|
||||
pub mod layers;
|
||||
pub mod listeners;
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::layers::Layer;
|
||||
use base64;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Serialize, Deserialize)]
|
||||
pub struct Base64;
|
||||
|
||||
impl Layer for Base64 {
|
||||
@@ -1,4 +1,4 @@
|
||||
pub trait Layer {
|
||||
pub trait Layer: Serialize + Deserialize<'static> + Sized {
|
||||
fn encode(&mut self, data: &[u8]) -> Vec<u8>;
|
||||
fn decode(&mut self, data: &[u8]) -> Vec<u8>;
|
||||
}
|
||||
@@ -6,3 +6,4 @@ pub trait Layer {
|
||||
pub mod base64;
|
||||
|
||||
pub use base64::Base64;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -0,0 +1,8 @@
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
pub mod config;
|
||||
pub mod layers;
|
||||
pub mod listeners;
|
||||
pub mod networkers;
|
||||
pub mod packets;
|
||||
@@ -1,3 +1,5 @@
|
||||
use crate::layers::Layer;
|
||||
|
||||
mod client;
|
||||
mod server;
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
use log::{info, trace, warn};
|
||||
|
||||
use std::{
|
||||
io::{self, Write},
|
||||
sync::{Arc, Mutex},
|
||||
thread,
|
||||
};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::{
|
||||
listeners::client::{self, Client},
|
||||
listeners::client::Client,
|
||||
networkers::{Connection, ServerTrait},
|
||||
packets::Packet,
|
||||
};
|
||||
|
||||
pub struct Listener<S, C> {
|
||||
@@ -41,7 +34,7 @@ impl<S, C> Listener<S, C> {
|
||||
clients_lock.push(Client::new(conn));
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Failed to accept connection: {:?}", e);
|
||||
error!("Failed to accept connection: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user