# rscamper
A safe Rust interface to [CAIDA's scamper](https://www.caida.org/catalog/software/scamper/)
network measurement tool.
`rscamper` wraps the scamper C libraries (`libscamperfile` and `libscamperctrl`) through Rust
FFI, providing idiomatic Rust types for all measurement data structures and a safe async-friendly
control loop.
## Features
- **File I/O** — read and write scamper warts/JSON files via `ScamperFile`
- **Control loop** — connect to a running scamper daemon and issue measurements via `ScamperCtrl`
- **All measurement types** — `trace`, `ping`, `tracelb`, `dealias`, `host`, `http`, `tbit`,
`sniff`, `udpprobe`, `owamp`, `sting`, `neighbourdisc`
- **Mux / VP support** — enumerate and connect to vantage points via `ScamperMux` and `ScamperVp`
## Prerequisites
`rscamper` links against `libscamperfile` and `libscamperctrl`, which are part of the scamper
distribution. Build and install scamper from source following the
[official instructions](https://www.caida.org/catalog/software/scamper/).
By default, the libraries are searched for in `/usr/local/lib` and `/usr/lib`. If you installed
scamper to a custom prefix, set the `SCAMPER_LIB_DIR` environment variable at build time:
```sh
SCAMPER_LIB_DIR=/opt/scamper/lib cargo build
```
## Installation
Add `rscamper` to your `Cargo.toml`:
```toml
[dependencies]
rscamper = "0.1"
```
## Usage
### Reading a warts file
```rust
use rscamper::{ScamperFile, ScamperObject};
let file = ScamperFile::open("results.warts", 'r', None).unwrap();
for obj in file {
if let ScamperObject::Ping(ping) = obj {
println!("{}", ping.to_json().unwrap_or_default());
}
}
```
### Running a measurement via scamper daemon
```rust
use std::time::Duration;
use rscamper::{ScamperCtrl, ScamperObject};
let mut ctrl = ScamperCtrl::new(false, None).unwrap();
// Connect to a scamper daemon listening on TCP port 31337.
let inst = ctrl.add_inet(31337, None).unwrap();
ctrl.do_ping(
&inst, "1.1.1.1",
None, None, None, None, None, None, None, None,
None, None, None, None, None, None, None, None,
None, None, None, None, None,
).unwrap();
inst.done();
for item in ctrl.responses(Some(Duration::from_secs(10))) {
if let ScamperObject::Ping(ping) = item.obj {
if let Some(stats) = ping.stats() {
println!("min RTT: {:?}", stats.min_rtt());
}
}
}
```
### Mux / vantage points
```rust
use rscamper::ScamperCtrl;
let mut ctrl = ScamperCtrl::new(false, None).unwrap();
let _mux_inst = ctrl.add_inet(31337, None).unwrap();
for vp in ctrl.vps() {
let inst = ctrl.add_vp(&vp).unwrap();
// issue measurements on inst ...
inst.done();
}
```
## License
GPL-3.0-only — see the [GNU General Public License](https://www.gnu.org/licenses/gpl-3.0.html)
for details.