use std::net::Ipv4Addr;
use std::sync::Arc;
use std::time::{Duration, Instant};
use pnet::packet::Packet;
use pnet::packet::ethernet::{EtherTypes, EthernetPacket};
use pnet::packet::ip::IpNextHeaderProtocols;
use pnet::packet::ipv4::Ipv4Packet;
use tokio::time;
use crate::general::create_datalink_channel;
use crate::observer::EventObserver;
use crate::packet::VrrpPacket;
use crate::pkt::handlers::{handle_incoming_arp_pkt, handle_incoming_vrrp_pkt};
use crate::state_machine::{Event, State};
use crate::{NetResult, checksum, network};
pub(crate) async fn network_process(items: crate::TaskItems) -> NetResult<()> {
let interface = items.generator.interface;
let (_sender, mut receiver) = create_datalink_channel(&interface)?;
let vrouter = items.vrouter;
loop {
let buff = match receiver.next() {
Ok(buf) => buf,
Err(_) => {
log::warn!("Error Receiving Packet");
continue;
}
};
let incoming_eth_pkt = match EthernetPacket::new(buff) {
Some(incoming_eth_pkt) => incoming_eth_pkt,
None => continue,
};
match incoming_eth_pkt.get_ethertype() {
EtherTypes::Ipv4 => {
let incoming_ip_pkt =
match Ipv4Packet::new(incoming_eth_pkt.payload()) {
Some(pkt) => pkt,
None => {
log::warn!("Unable to read IP packet");
continue;
}
};
if incoming_ip_pkt.get_next_level_protocol()
== IpNextHeaderProtocols::Vrrp
{
match handle_incoming_vrrp_pkt(
&incoming_eth_pkt,
Arc::clone(&vrouter),
) {
Ok(_) => {}
Err(_) => continue,
}
}
}
EtherTypes::Arp => {
match handle_incoming_arp_pkt(
&incoming_eth_pkt,
Arc::clone(&vrouter),
) {
Ok(_) => {}
Err(err) => {
log::error!("problem handing incoming ARP packet");
log::error!("{err}");
}
}
}
_ => {
let lock = &vrouter.lock();
let net_vr = match lock {
Ok(net_vr) => net_vr,
Err(err) => {
log::warn!("Cannot Get router mutex");
log::warn!("{err}");
continue;
}
};
if net_vr.fsm.state == State::Master {}
}
}
}
}
pub(crate) async fn timer_process(items: crate::TaskItems) -> NetResult<()> {
let mut interval = time::interval(Duration::from_millis(100));
let vrouter = items.vrouter;
loop {
interval.tick().await;
let mut vrouter = match vrouter.lock() {
Ok(vrouter) => vrouter,
Err(_) => {
log::error!("Unable to get mutex for vrouter");
continue;
}
};
let timer = vrouter.fsm.timer;
match timer.t_type {
crate::state_machine::TimerType::MasterDown => {
match vrouter.fsm.timer.waiting_for {
Some(waiting) => {
if Instant::now() > waiting {
match EventObserver::notify_mut(
vrouter,
Event::MasterDown,
) {
Ok(info) => info,
Err(err) => return Err(err),
}
}
}
None => {
log::warn!("No timer being waited for.");
continue;
}
};
}
crate::state_machine::TimerType::Adver => {
match vrouter.fsm.timer.waiting_for {
Some(waiting) => {
if Instant::now() > waiting {
let mut addresses: Vec<Ipv4Addr> = vec![];
vrouter.ip_addresses.iter().for_each(|ip| {
addresses.push(ip.addr());
});
let mut pkt = VrrpPacket {
vrid: vrouter.vrid,
priority: vrouter.priority,
count_ip: vrouter.ip_addresses.len() as u8,
adver_int: vrouter.advert_interval,
checksum: 0,
ip_addresses: addresses,
};
pkt.checksum =
checksum::calculate(&pkt.encode(), 3);
let _ = network::send_vrrp_packet(
&vrouter.network_interface,
pkt,
);
let advert_time = vrouter.advert_interval as f32;
vrouter.fsm.set_advert_timer(advert_time);
}
}
None => {
log::warn!("No timer being waited for.");
continue;
}
};
}
crate::state_machine::TimerType::Null => {}
}
}
}