use futures::channel::mpsc;
use futures::prelude::*;
use std::convert::AsRef;
use std::fs;
use std::io;
use std::path::Path;
use crate::cpus;
use crate::load::map_io::PerfMessageStream;
use crate::{Error, KProbe, Map, Module, PerfMap, SocketFilter, 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(|e| LoaderError::ParseError(e))?;
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(|e| LoaderError::FileError(e))?)
}
}
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.maps.iter().find(|m| m.name == name)
}
pub fn map_mut(&mut self, name: &str) -> Option<&mut Map> {
self.module.maps.iter_mut().find(|m| m.name == name)
}
pub fn kprobes_mut(&mut self) -> impl Iterator<Item = &mut KProbe> {
self.module.kprobes_mut()
}
pub fn uprobes_mut(&mut self) -> impl Iterator<Item = &mut UProbe> {
self.module.uprobes_mut()
}
pub fn xdps_mut(&mut self) -> impl Iterator<Item = &mut XDP> {
self.module.xdps_mut()
}
pub fn socket_filters_mut(&mut self) -> impl Iterator<Item = &mut SocketFilter> {
self.module.socket_filters_mut()
}
}