Refactor print functions into new module
This commit is contained in:
222
src/main.rs
222
src/main.rs
@@ -8,7 +8,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use ax25::frame::{Ax25Frame, CommandResponse, FrameContent};
|
use ax25::frame::Ax25Frame;
|
||||||
use pcap_file::{
|
use pcap_file::{
|
||||||
pcap::{PcapHeader, PcapPacket, PcapWriter},
|
pcap::{PcapHeader, PcapPacket, PcapWriter},
|
||||||
DataLink,
|
DataLink,
|
||||||
@@ -18,6 +18,8 @@ use std::net::TcpStream;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
|
mod print_frame;
|
||||||
|
use print_frame::PrintFrame;
|
||||||
struct KissPkt {
|
struct KissPkt {
|
||||||
timestamp: Duration,
|
timestamp: Duration,
|
||||||
orig_len: u32,
|
orig_len: u32,
|
||||||
@@ -147,221 +149,3 @@ fn main() -> Result<()> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
trait PrintData {
|
|
||||||
fn type_str_short(&self) -> &'static str;
|
|
||||||
fn print_short(&self);
|
|
||||||
fn print_long(&self);
|
|
||||||
}
|
|
||||||
impl PrintData for Ax25Frame {
|
|
||||||
fn type_str_short(&self) -> &'static str {
|
|
||||||
match self.content {
|
|
||||||
FrameContent::Information(_) => "Info",
|
|
||||||
FrameContent::ReceiveReady(_) => "RecvRdy",
|
|
||||||
FrameContent::ReceiveNotReady(_) => "RecvNotRdy",
|
|
||||||
FrameContent::Reject(_) => "Reject",
|
|
||||||
FrameContent::SetAsynchronousBalancedMode(_) => "AsyncBalMode", //12 long
|
|
||||||
FrameContent::Disconnect(_) => "Disconnect",
|
|
||||||
FrameContent::DisconnectedMode(_) => "DisconMode",
|
|
||||||
FrameContent::UnnumberedAcknowledge(_) => "UnNumAck",
|
|
||||||
FrameContent::FrameReject(_) => "FrameReject",
|
|
||||||
FrameContent::UnnumberedInformation(_) => "UnNumInfo",
|
|
||||||
FrameContent::UnknownContent(_) => "Unknown",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn print_short(&self) {
|
|
||||||
//Format: "[source] -> [dest] via [..] [CMD/RSP/NIL] [frameType]: [DATA str rep]"
|
|
||||||
let src = self.source.to_string();
|
|
||||||
let dst = self.destination.to_string();
|
|
||||||
//let via: String = self.route.iter().map(|re| format!(" {} ", re.repeater.to_string())).collect(); //todo
|
|
||||||
let rsp = match self.command_or_response {
|
|
||||||
Some(CommandResponse::Command) => "CMD",
|
|
||||||
Some(CommandResponse::Response) => "RSP",
|
|
||||||
None => "NIL",
|
|
||||||
};
|
|
||||||
let ftype = self.type_str_short();
|
|
||||||
let mut routed = false;
|
|
||||||
for route in self.route.iter() {
|
|
||||||
if route.has_repeated {
|
|
||||||
routed = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let arrow_shaft = if routed { "=" } else { "-" };
|
|
||||||
|
|
||||||
//let mut rawdata;
|
|
||||||
let (rawdata, finfo) = match &self.content {
|
|
||||||
FrameContent::Information(_i) => (
|
|
||||||
_i.info.clone(),
|
|
||||||
format!(
|
|
||||||
"pid: {:?}, seq: {}/{}, info: ",
|
|
||||||
_i.pid, _i.send_sequence, _i.receive_sequence
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FrameContent::ReceiveReady(rr) => (
|
|
||||||
vec![],
|
|
||||||
format!(
|
|
||||||
"seq: {}, poll/final: {}",
|
|
||||||
rr.receive_sequence, rr.poll_or_final
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FrameContent::ReceiveNotReady(rnr) => (
|
|
||||||
vec![],
|
|
||||||
format!(
|
|
||||||
"seq: {}, poll/final: {}",
|
|
||||||
rnr.receive_sequence, rnr.poll_or_final
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FrameContent::Reject(rnr) => (
|
|
||||||
vec![],
|
|
||||||
format!(
|
|
||||||
"seq: {}, poll/final: {}",
|
|
||||||
rnr.receive_sequence, rnr.poll_or_final
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FrameContent::SetAsynchronousBalancedMode(abm) => {
|
|
||||||
(vec![], format!("poll: {}", abm.poll))
|
|
||||||
}
|
|
||||||
FrameContent::Disconnect(abm) => (vec![], format!("poll: {}", abm.poll)),
|
|
||||||
FrameContent::DisconnectedMode(abm) => {
|
|
||||||
(vec![], format!("final bit: {}", abm.final_bit))
|
|
||||||
}
|
|
||||||
FrameContent::UnnumberedAcknowledge(abm) => {
|
|
||||||
(vec![], format!("final bit: {}", abm.final_bit))
|
|
||||||
}
|
|
||||||
FrameContent::FrameReject(fr) => (
|
|
||||||
vec![],
|
|
||||||
format!(
|
|
||||||
"[{}{}{}{}], seq: {}/{}, raw: {}, cmdRsp: {}, final: {}",
|
|
||||||
if fr.z { "Z" } else { "" },
|
|
||||||
if fr.y { "Y" } else { "" },
|
|
||||||
if fr.x { "X" } else { "" },
|
|
||||||
if fr.w { "W" } else { "" },
|
|
||||||
fr.send_sequence,
|
|
||||||
fr.receive_sequence,
|
|
||||||
fr.rejected_control_field_raw,
|
|
||||||
match fr.command_response {
|
|
||||||
CommandResponse::Command => "CMD",
|
|
||||||
CommandResponse::Response => "RSP",
|
|
||||||
},
|
|
||||||
fr.final_bit
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FrameContent::UnnumberedInformation(ui) => {
|
|
||||||
(ui.info.clone(), format!("pid: {:?} info:", ui.pid))
|
|
||||||
}
|
|
||||||
FrameContent::UnknownContent(ukn) => (ukn.raw.clone(), format!("")),
|
|
||||||
};
|
|
||||||
let mut data = String::new();
|
|
||||||
for byte in rawdata.iter() {
|
|
||||||
//if byte >= ' '.into() && byte <= '~'.into() {
|
|
||||||
if *byte >= 32 && *byte <= 126 {
|
|
||||||
data.push((*byte).into());
|
|
||||||
} else {
|
|
||||||
data.push_str(&format!("\\{:x?} ", *byte));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!(
|
|
||||||
"AX.25 {:12} {} {:9} {}> {:9} {}",
|
|
||||||
ftype,
|
|
||||||
rsp,
|
|
||||||
src,
|
|
||||||
arrow_shaft,
|
|
||||||
dst,
|
|
||||||
if !data.is_empty() { data } else { finfo }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
fn print_long(&self) {
|
|
||||||
//Format: "[source] -> [dest] via [..] [CMD/RSP/NIL] [frameType]: [DATA str rep]"
|
|
||||||
let src = self.source.to_string();
|
|
||||||
let dst = self.destination.to_string();
|
|
||||||
let via: String = self
|
|
||||||
.route
|
|
||||||
.iter()
|
|
||||||
.map(|re| format!(" {} ", re.repeater.to_string()))
|
|
||||||
.collect(); //todo
|
|
||||||
let rsp = match self.command_or_response {
|
|
||||||
Some(CommandResponse::Command) => "CMD",
|
|
||||||
Some(CommandResponse::Response) => "RSP",
|
|
||||||
None => "NIL",
|
|
||||||
};
|
|
||||||
let ftype = self.type_str_short();
|
|
||||||
|
|
||||||
//let mut rawdata;
|
|
||||||
let (rawdata, finfo) = match &self.content {
|
|
||||||
FrameContent::Information(_i) => (
|
|
||||||
_i.info.clone(),
|
|
||||||
format!(
|
|
||||||
"pid: {:?}, seq: {}/{}, info: ",
|
|
||||||
_i.pid, _i.send_sequence, _i.receive_sequence
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FrameContent::ReceiveReady(rr) => (
|
|
||||||
vec![],
|
|
||||||
format!(
|
|
||||||
"seq: {}, poll/final: {}",
|
|
||||||
rr.receive_sequence, rr.poll_or_final
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FrameContent::ReceiveNotReady(rnr) => (
|
|
||||||
vec![],
|
|
||||||
format!(
|
|
||||||
"seq: {}, poll/final: {}",
|
|
||||||
rnr.receive_sequence, rnr.poll_or_final
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FrameContent::Reject(rnr) => (
|
|
||||||
vec![],
|
|
||||||
format!(
|
|
||||||
"seq: {}, poll/final: {}",
|
|
||||||
rnr.receive_sequence, rnr.poll_or_final
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FrameContent::SetAsynchronousBalancedMode(abm) => {
|
|
||||||
(vec![], format!("poll: {}", abm.poll))
|
|
||||||
}
|
|
||||||
FrameContent::Disconnect(abm) => (vec![], format!("poll: {}", abm.poll)),
|
|
||||||
FrameContent::DisconnectedMode(abm) => {
|
|
||||||
(vec![], format!("final bit: {}", abm.final_bit))
|
|
||||||
}
|
|
||||||
FrameContent::UnnumberedAcknowledge(abm) => {
|
|
||||||
(vec![], format!("final bit: {}", abm.final_bit))
|
|
||||||
}
|
|
||||||
FrameContent::FrameReject(fr) => (
|
|
||||||
vec![],
|
|
||||||
format!(
|
|
||||||
"[{}{}{}{}], seq: {}/{}, raw: {}, cmdRsp: {}, final: {}",
|
|
||||||
if fr.z { "Z" } else { "" },
|
|
||||||
if fr.y { "Y" } else { "" },
|
|
||||||
if fr.x { "X" } else { "" },
|
|
||||||
if fr.w { "W" } else { "" },
|
|
||||||
fr.send_sequence,
|
|
||||||
fr.receive_sequence,
|
|
||||||
fr.rejected_control_field_raw,
|
|
||||||
match fr.command_response {
|
|
||||||
CommandResponse::Command => "CMD",
|
|
||||||
CommandResponse::Response => "RSP",
|
|
||||||
},
|
|
||||||
fr.final_bit
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FrameContent::UnnumberedInformation(ui) => {
|
|
||||||
(ui.info.clone(), format!("pid: {:?} info:", ui.pid))
|
|
||||||
}
|
|
||||||
FrameContent::UnknownContent(ukn) => (ukn.raw.clone(), format!("")),
|
|
||||||
};
|
|
||||||
let mut data = String::new();
|
|
||||||
for byte in rawdata.iter() {
|
|
||||||
//if byte >= ' '.into() && byte <= '~'.into() {
|
|
||||||
if *byte >= 32 && *byte <= 126 {
|
|
||||||
data.push((*byte).into());
|
|
||||||
} else {
|
|
||||||
data.push_str(&format!("\\{:x?} ", *byte));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!(
|
|
||||||
"AX.25 {:12} {} {:9} -> {:9} via [{}] {} {}",
|
|
||||||
ftype, rsp, src, dst, via, finfo, data
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
218
src/print_frame.rs
Normal file
218
src/print_frame.rs
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
use ax25::frame::{Ax25Frame, CommandResponse, FrameContent};
|
||||||
|
pub trait PrintFrame {
|
||||||
|
fn type_str_short(&self) -> &'static str;
|
||||||
|
fn print_short(&self);
|
||||||
|
fn print_long(&self);
|
||||||
|
}
|
||||||
|
impl PrintFrame for Ax25Frame {
|
||||||
|
fn type_str_short(&self) -> &'static str {
|
||||||
|
match self.content {
|
||||||
|
FrameContent::Information(_) => "Info",
|
||||||
|
FrameContent::ReceiveReady(_) => "RecvRdy",
|
||||||
|
FrameContent::ReceiveNotReady(_) => "RecvNotRdy",
|
||||||
|
FrameContent::Reject(_) => "Reject",
|
||||||
|
FrameContent::SetAsynchronousBalancedMode(_) => "AsyncBalMode", //12 long
|
||||||
|
FrameContent::Disconnect(_) => "Disconnect",
|
||||||
|
FrameContent::DisconnectedMode(_) => "DisconMode",
|
||||||
|
FrameContent::UnnumberedAcknowledge(_) => "UnNumAck",
|
||||||
|
FrameContent::FrameReject(_) => "FrameReject",
|
||||||
|
FrameContent::UnnumberedInformation(_) => "UnNumInfo",
|
||||||
|
FrameContent::UnknownContent(_) => "Unknown",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn print_short(&self) {
|
||||||
|
//Format: "[source] -> [dest] via [..] [CMD/RSP/NIL] [frameType]: [DATA str rep]"
|
||||||
|
let src = self.source.to_string();
|
||||||
|
let dst = self.destination.to_string();
|
||||||
|
//let via: String = self.route.iter().map(|re| format!(" {} ", re.repeater.to_string())).collect(); //todo
|
||||||
|
let rsp = match self.command_or_response {
|
||||||
|
Some(CommandResponse::Command) => "CMD",
|
||||||
|
Some(CommandResponse::Response) => "RSP",
|
||||||
|
None => "NIL",
|
||||||
|
};
|
||||||
|
let ftype = self.type_str_short();
|
||||||
|
let mut routed = false;
|
||||||
|
for route in self.route.iter() {
|
||||||
|
if route.has_repeated {
|
||||||
|
routed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let arrow_shaft = if routed { "=" } else { "-" };
|
||||||
|
|
||||||
|
//let mut rawdata;
|
||||||
|
let (rawdata, finfo) = match &self.content {
|
||||||
|
FrameContent::Information(_i) => (
|
||||||
|
_i.info.clone(),
|
||||||
|
format!(
|
||||||
|
"pid: {:?}, seq: {}/{}, info: ",
|
||||||
|
_i.pid, _i.send_sequence, _i.receive_sequence
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FrameContent::ReceiveReady(rr) => (
|
||||||
|
vec![],
|
||||||
|
format!(
|
||||||
|
"seq: {}, poll/final: {}",
|
||||||
|
rr.receive_sequence, rr.poll_or_final
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FrameContent::ReceiveNotReady(rnr) => (
|
||||||
|
vec![],
|
||||||
|
format!(
|
||||||
|
"seq: {}, poll/final: {}",
|
||||||
|
rnr.receive_sequence, rnr.poll_or_final
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FrameContent::Reject(rnr) => (
|
||||||
|
vec![],
|
||||||
|
format!(
|
||||||
|
"seq: {}, poll/final: {}",
|
||||||
|
rnr.receive_sequence, rnr.poll_or_final
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FrameContent::SetAsynchronousBalancedMode(abm) => {
|
||||||
|
(vec![], format!("poll: {}", abm.poll))
|
||||||
|
}
|
||||||
|
FrameContent::Disconnect(abm) => (vec![], format!("poll: {}", abm.poll)),
|
||||||
|
FrameContent::DisconnectedMode(abm) => {
|
||||||
|
(vec![], format!("final bit: {}", abm.final_bit))
|
||||||
|
}
|
||||||
|
FrameContent::UnnumberedAcknowledge(abm) => {
|
||||||
|
(vec![], format!("final bit: {}", abm.final_bit))
|
||||||
|
}
|
||||||
|
FrameContent::FrameReject(fr) => (
|
||||||
|
vec![],
|
||||||
|
format!(
|
||||||
|
"[{}{}{}{}], seq: {}/{}, raw: {}, cmdRsp: {}, final: {}",
|
||||||
|
if fr.z { "Z" } else { "" },
|
||||||
|
if fr.y { "Y" } else { "" },
|
||||||
|
if fr.x { "X" } else { "" },
|
||||||
|
if fr.w { "W" } else { "" },
|
||||||
|
fr.send_sequence,
|
||||||
|
fr.receive_sequence,
|
||||||
|
fr.rejected_control_field_raw,
|
||||||
|
match fr.command_response {
|
||||||
|
CommandResponse::Command => "CMD",
|
||||||
|
CommandResponse::Response => "RSP",
|
||||||
|
},
|
||||||
|
fr.final_bit
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FrameContent::UnnumberedInformation(ui) => {
|
||||||
|
(ui.info.clone(), format!("pid: {:?} info:", ui.pid))
|
||||||
|
}
|
||||||
|
FrameContent::UnknownContent(ukn) => (ukn.raw.clone(), format!("")),
|
||||||
|
};
|
||||||
|
let mut data = String::new();
|
||||||
|
for byte in rawdata.iter() {
|
||||||
|
//if byte >= ' '.into() && byte <= '~'.into() {
|
||||||
|
if *byte >= 32 && *byte <= 126 {
|
||||||
|
data.push((*byte).into());
|
||||||
|
} else {
|
||||||
|
data.push_str(&format!("\\{:x?} ", *byte));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!(
|
||||||
|
"AX.25 {:12} {} {:9} {}> {:9} {}",
|
||||||
|
ftype,
|
||||||
|
rsp,
|
||||||
|
src,
|
||||||
|
arrow_shaft,
|
||||||
|
dst,
|
||||||
|
if !data.is_empty() { data } else { finfo }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
fn print_long(&self) {
|
||||||
|
//Format: "[source] -> [dest] via [..] [CMD/RSP/NIL] [frameType]: [DATA str rep]"
|
||||||
|
let src = self.source.to_string();
|
||||||
|
let dst = self.destination.to_string();
|
||||||
|
let via: String = self
|
||||||
|
.route
|
||||||
|
.iter()
|
||||||
|
.map(|re| format!(" {} ", re.repeater.to_string()))
|
||||||
|
.collect(); //todo
|
||||||
|
let rsp = match self.command_or_response {
|
||||||
|
Some(CommandResponse::Command) => "CMD",
|
||||||
|
Some(CommandResponse::Response) => "RSP",
|
||||||
|
None => "NIL",
|
||||||
|
};
|
||||||
|
let ftype = self.type_str_short();
|
||||||
|
|
||||||
|
//let mut rawdata;
|
||||||
|
let (rawdata, finfo) = match &self.content {
|
||||||
|
FrameContent::Information(_i) => (
|
||||||
|
_i.info.clone(),
|
||||||
|
format!(
|
||||||
|
"pid: {:?}, seq: {}/{}, info: ",
|
||||||
|
_i.pid, _i.send_sequence, _i.receive_sequence
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FrameContent::ReceiveReady(rr) => (
|
||||||
|
vec![],
|
||||||
|
format!(
|
||||||
|
"seq: {}, poll/final: {}",
|
||||||
|
rr.receive_sequence, rr.poll_or_final
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FrameContent::ReceiveNotReady(rnr) => (
|
||||||
|
vec![],
|
||||||
|
format!(
|
||||||
|
"seq: {}, poll/final: {}",
|
||||||
|
rnr.receive_sequence, rnr.poll_or_final
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FrameContent::Reject(rnr) => (
|
||||||
|
vec![],
|
||||||
|
format!(
|
||||||
|
"seq: {}, poll/final: {}",
|
||||||
|
rnr.receive_sequence, rnr.poll_or_final
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FrameContent::SetAsynchronousBalancedMode(abm) => {
|
||||||
|
(vec![], format!("poll: {}", abm.poll))
|
||||||
|
}
|
||||||
|
FrameContent::Disconnect(abm) => (vec![], format!("poll: {}", abm.poll)),
|
||||||
|
FrameContent::DisconnectedMode(abm) => {
|
||||||
|
(vec![], format!("final bit: {}", abm.final_bit))
|
||||||
|
}
|
||||||
|
FrameContent::UnnumberedAcknowledge(abm) => {
|
||||||
|
(vec![], format!("final bit: {}", abm.final_bit))
|
||||||
|
}
|
||||||
|
FrameContent::FrameReject(fr) => (
|
||||||
|
vec![],
|
||||||
|
format!(
|
||||||
|
"[{}{}{}{}], seq: {}/{}, raw: {}, cmdRsp: {}, final: {}",
|
||||||
|
if fr.z { "Z" } else { "" },
|
||||||
|
if fr.y { "Y" } else { "" },
|
||||||
|
if fr.x { "X" } else { "" },
|
||||||
|
if fr.w { "W" } else { "" },
|
||||||
|
fr.send_sequence,
|
||||||
|
fr.receive_sequence,
|
||||||
|
fr.rejected_control_field_raw,
|
||||||
|
match fr.command_response {
|
||||||
|
CommandResponse::Command => "CMD",
|
||||||
|
CommandResponse::Response => "RSP",
|
||||||
|
},
|
||||||
|
fr.final_bit
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FrameContent::UnnumberedInformation(ui) => {
|
||||||
|
(ui.info.clone(), format!("pid: {:?} info:", ui.pid))
|
||||||
|
}
|
||||||
|
FrameContent::UnknownContent(ukn) => (ukn.raw.clone(), format!("")),
|
||||||
|
};
|
||||||
|
let mut data = String::new();
|
||||||
|
for byte in rawdata.iter() {
|
||||||
|
//if byte >= ' '.into() && byte <= '~'.into() {
|
||||||
|
if *byte >= 32 && *byte <= 126 {
|
||||||
|
data.push((*byte).into());
|
||||||
|
} else {
|
||||||
|
data.push_str(&format!("\\{:x?} ", *byte));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!(
|
||||||
|
"AX.25 {:12} {} {:9} -> {:9} via [{}] {} {}",
|
||||||
|
ftype, rsp, src, dst, via, finfo, data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user