use futures::channel::mpsc;
use futures::prelude::*;
use std::convert::AsRef;
use std::fs;
use std::io;
use std::path::Path;
use crate::load::map_io::PerfMessageStream;
use crate::{cpus, Program};
use crate::{
Error, KProbe, Map, Module, PerfMap, SkLookup, SocketFilter, StreamParser, StreamVerdict,
TaskIter, UProbe, XDP,
};
#[derive(Debug)]
pub enum LoaderError {
FileError(io::Error),
ParseError(Error),
LoadError(String, Error),
}
pub struct Loader {}
impl Loader {
pub fn load(data: &[u8]) -> Result<Loaded, LoaderError> {
let mut module = Module::parse(&data).map_err(LoaderError::ParseError)?;
for program in module.programs.iter_mut() {
program
.load(module.version, module.license.clone())
.map_err(|e| LoaderError::LoadError(program.name().to_string(), e))?;
}
let online_cpus = cpus::get_online().unwrap();
let (sender, receiver) = mpsc::unbounded();
for m in module.maps.iter_mut().filter(|m| m.kind == 4) {
for cpuid in online_cpus.iter() {
let name = m.name.clone();
let map = PerfMap::bind(m, -1, *cpuid, 16, -1, 0).unwrap();
let stream = PerfMessageStream::new(name.clone(), map);
let mut s = sender.clone();
let fut = stream.for_each(move |events| {
s.start_send((name.clone(), events)).unwrap();
future::ready(())
});
tokio::spawn(fut);
}
}
Ok(Loaded {
module,
events: receiver,
})
}
pub fn load_file<P: AsRef<Path>>(file: P) -> Result<Loaded, LoaderError> {
Loader::load(&fs::read(file).map_err(LoaderError::FileError)?)
}
}
pub struct Loaded {
pub module: Module,
pub events: mpsc::UnboundedReceiver<(String, <PerfMessageStream as Stream>::Item)>,
}
impl Loaded {
pub fn map(&self, name: &str) -> Option<&Map> {
self.module.map(name)
}
pub fn map_mut(&mut self, name: &str) -> Option<&mut Map> {
self.module.map_mut(name)
}
pub fn program(&self, name: &str) -> Option<&Program> {
self.module.program(name)
}
pub fn program_mut(&mut self, name: &str) -> Option<&mut Program> {
self.module.program_mut(name)
}
pub fn kprobes_mut(&mut self) -> impl Iterator<Item = &mut KProbe> {
self.module.kprobes_mut()
}
pub fn kprobe_mut(&mut self, name: &str) -> Option<&mut KProbe> {
self.module.kprobe_mut(name)
}
pub fn uprobes_mut(&mut self) -> impl Iterator<Item = &mut UProbe> {
self.module.uprobes_mut()
}
pub fn uprobe_mut(&mut self, name: &str) -> Option<&mut UProbe> {
self.module.uprobe_mut(name)
}
pub fn xdps_mut(&mut self) -> impl Iterator<Item = &mut XDP> {
self.module.xdps_mut()
}
pub fn xdp_mut(&mut self, name: &str) -> Option<&mut XDP> {
self.module.xdp_mut(name)
}
pub fn socket_filters_mut(&mut self) -> impl Iterator<Item = &mut SocketFilter> {
self.module.socket_filters_mut()
}
pub fn socket_filter_mut(&mut self, name: &str) -> Option<&mut SocketFilter> {
self.module.socket_filter_mut(name)
}
pub fn stream_parsers(&self) -> impl Iterator<Item = &StreamParser> {
self.module.stream_parsers()
}
pub fn stream_parsers_mut(&mut self) -> impl Iterator<Item = &mut StreamParser> {
self.module.stream_parsers_mut()
}
pub fn stream_parser_mut(&mut self, name: &str) -> Option<&mut StreamParser> {
self.module.stream_parser_mut(name)
}
pub fn stream_verdicts(&self) -> impl Iterator<Item = &StreamVerdict> {
self.module.stream_verdicts()
}
pub fn stream_verdicts_mut(&mut self) -> impl Iterator<Item = &mut StreamVerdict> {
self.module.stream_verdicts_mut()
}
pub fn stream_verdict_mut(&mut self, name: &str) -> Option<&mut StreamVerdict> {
self.module.stream_verdict_mut(name)
}
pub fn sk_lookups_mut(&mut self) -> impl Iterator<Item = &mut SkLookup> {
self.module.sk_lookups_mut()
}
pub fn sk_lookup_mut(&mut self, name: &str) -> Option<&mut SkLookup> {
self.module.sk_lookup_mut(name)
}
pub fn task_iters(&self) -> impl Iterator<Item = &TaskIter> {
self.module.task_iters()
}
pub fn bpf_iters_mut(&mut self) -> impl Iterator<Item = &mut TaskIter> {
self.module.task_iters_mut()
}
pub fn task_iter_mut(&mut self, name: &str) -> Option<&mut TaskIter> {
self.module.task_iter_mut(name)
}
}