Skip to content

Commit e5ed549

Browse files
author
Danny Browning
committed
Tokio2
Bring in tokio 0.2, converting to async/await. Futures next makes PacketProvider redundant, so remove. Use lefthook for commit hooks, setup travis, use criterion for benches. Crate is now renamed to pcap-async.
1 parent 4444d6d commit e5ed549

15 files changed

+690
-393
lines changed

.travis.yml

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
---
2+
language: rust
3+
rust:
4+
- nightly
5+
sudo: true
6+
cache:
7+
- apt
8+
- cargo
9+
10+
matrix:
11+
include:
12+
- os: linux
13+
addons:
14+
apt:
15+
update: true
16+
packages:
17+
- libpcap-dev
18+
env: TARGET=i686-unknown-linux-gnu
19+
20+
before_script:
21+
- cargo +nightly install --force rustfmt-nightly
22+
23+
script:
24+
- export PATH="/usr/include:$PATH"
25+
- cargo +nightly fmt --all -- --check
26+
- cargo test
27+
- cargo doc --no-deps
28+
29+
notifications:
30+
email:
31+
on_success: never
32+

Cargo.toml

+36-11
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,42 @@
11
[package]
2-
name = "pcap"
3-
version = "0.1.0"
4-
authors = ["Danny Browning <[email protected]>"]
2+
name = "pcap-async"
53
edition = "2018"
4+
# When releasing to crates.io:
5+
# - Update html_root_url.
6+
# - Update CHANGELOG.md.
7+
# - Update doc URL.
8+
# - Create "v0.1.x" git tag.
9+
version = "0.1.0-alpha.1"
10+
license = "MIT"
11+
readme = "README.md"
12+
description = """
13+
Async/Stream Extensions for libpcap
14+
"""
15+
authors = ["Danny Browning <[email protected]>"]
16+
categories = ["asynchronous", "network-programming"]
17+
documentation = "https://docs.rs/pcap-async/"
18+
repository = "https://github.com/dbcfd/pcap-async"
619

720
[dependencies]
8-
failure = "~0.1"
9-
failure_derive = "~0.1"
10-
futures-preview = { version ="0.3.0-alpha.14", features = ["compat"] }
11-
libc = "~0.2"
12-
log = "~0.4"
13-
pcap-sys = { git = "https://github.com/protectwise/pcap-sys.git" }
14-
tokio-timer = "~0.2"
21+
byteorder = "1.3"
22+
failure = "0.1"
23+
failure_derive = "0.1"
24+
futures-preview = { version ="0.3.0-alpha.19", features = ["async-await"] }
25+
libc = "0.2"
26+
log = "0.4"
27+
pin-project = "0.4.0-alpha.9"
28+
pcap-sys = { git = "https://github.com/protectwise/pcap-sys.git", tag = "v0.2.0" }
29+
tokio-timer = "0.3.0-alpha.6"
1530

1631
[dev-dependencies]
17-
env_logger = "~0.6"
32+
criterion = "0.2"
33+
env_logger = "0.6"
34+
tokio = "0.2.0-alpha.6"
35+
36+
[lib]
37+
path = "src/lib.rs"
38+
39+
[[bench]]
40+
path = "benches/bench_capture.rs"
41+
name = "bench_capture"
42+
harness = false

LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2018 Danny Browning
3+
Copyright (c) 2019 Danny Browning
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

+46-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,47 @@
1-
# PCAP
1+
# pcap-async
22

3-
Rust wrapper around [pcap-sys](https://github.com/protectwise/pcap-sys)
3+
[![build status][travis-badge]][travis-url]
4+
[![crates.io version][crates-badge]][crates-url]
5+
[![docs.rs docs][docs-badge]][docs-url]
6+
[![MIT licensed][mit-badge]][mit-url]
7+
8+
Rust async wrapper around [pcap-sys](https://github.com/protectwise/pcap-sys). Utilizes [Futures 0.3](https://github.com/rust-lang-nursery/futures-rs) and [Tokio](https://github.com/tokio-rs/tokio).
9+
10+
[Documentation](https://docs.rs/pcap-async/latest/)
11+
12+
[travis-badge]: https://travis-ci.com/dbcfd/pcap-async.svg?branch=master
13+
[travis-url]: https://travis-ci.com/dbcfd/pcap-async
14+
[crates-badge]: https://img.shields.io/crates/v/pcap-async.svg?style=flat-square
15+
[crates-url]: https://crates.io/crates/pcap-async
16+
[docs-badge]: https://img.shields.io/badge/docs.rs-latest-blue.svg?style=flat-square
17+
[docs-url]: https://docs.rs/pcap-async
18+
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square
19+
[mit-url]: LICENSE-MIT
20+
21+
## Usage
22+
23+
First, add this to your `Cargo.toml`:
24+
25+
```toml
26+
[dependencies]
27+
channel-async = "0.1.0-alpha.1"
28+
```
29+
30+
Next, add this to your crate:
31+
32+
```rust
33+
use futures::StreamExt;
34+
use pcap_async::{Config, Handle, PacketStream};
35+
36+
#[tokio::main]
37+
async fn main() {
38+
let handle = Handle::lookup().expect("No handle created");
39+
let mut provider = PacketProvider::new(Config::default(), handle)
40+
.expect("Could not create provider")
41+
.fuse();
42+
while let Some(packets) = provider.next().await {
43+
44+
}
45+
handle.interrupt();
46+
}
47+
```

benches/bench_capture.rs

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#![deny(unused_must_use, unused_imports, bare_trait_objects)]
2+
use criterion::{criterion_group, criterion_main, Bencher, Criterion};
3+
use futures::StreamExt;
4+
use log::*;
5+
use pcap_async::{Config, Handle, PacketStream};
6+
use std::path::PathBuf;
7+
8+
fn bench_stream_from_large_file(b: &mut Bencher) {
9+
let _ = env_logger::try_init();
10+
11+
let pcap_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
12+
.join("resources")
13+
.join("4SICS-GeekLounge-151020.pcap");
14+
15+
info!("Benchmarking against {:?}", pcap_path.clone());
16+
17+
b.iter(|| {
18+
let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
19+
20+
let clone_path = pcap_path.clone();
21+
22+
let handle = Handle::file_capture(clone_path.to_str().expect("No path found"))
23+
.expect("No handle created");
24+
25+
let mut cfg = Config::default();
26+
cfg.with_max_packets_read(5000);
27+
28+
let packet_provider = PacketStream::new(Config::default(), std::sync::Arc::clone(&handle))
29+
.expect("Failed to build");
30+
let packets = rt.block_on(packet_provider.collect::<Vec<_>>());
31+
let packets: Result<Vec<_>, pcap_async::Error> = packets.into_iter().collect();
32+
let packets = packets
33+
.expect("Failed to get packets")
34+
.iter()
35+
.flatten()
36+
.count();
37+
38+
handle.interrupt();
39+
40+
assert_eq!(packets, 246137);
41+
});
42+
}
43+
44+
fn bench_stream(c: &mut Criterion) {
45+
let benchmark = criterion::Benchmark::new("4sics", bench_stream_from_large_file);
46+
47+
c.bench(
48+
"stream",
49+
benchmark
50+
.sample_size(20)
51+
.nresamples(1)
52+
.measurement_time(std::time::Duration::from_secs(15)),
53+
);
54+
}
55+
56+
fn bench_stream_next_from_large_file(b: &mut Bencher) {
57+
let _ = env_logger::try_init();
58+
59+
let pcap_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
60+
.join("resources")
61+
.join("4SICS-GeekLounge-151020.pcap");
62+
63+
info!("Benchmarking against {:?}", pcap_path.clone());
64+
65+
b.iter(|| {
66+
let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
67+
68+
let clone_path = pcap_path.clone();
69+
70+
let handle = Handle::file_capture(clone_path.to_str().expect("No path found"))
71+
.expect("No handle created");
72+
73+
let mut cfg = Config::default();
74+
cfg.with_max_packets_read(5000);
75+
76+
let packet_provider = PacketStream::new(Config::default(), std::sync::Arc::clone(&handle))
77+
.expect("Failed to build");
78+
let fut_packets = async move {
79+
let mut packet_provider = packet_provider.boxed();
80+
let mut packets = vec![];
81+
while let Some(p) = packet_provider.next().await {
82+
let p = p.expect("Could not get packets");
83+
packets.extend(p);
84+
}
85+
packets
86+
};
87+
let packets = rt.block_on(fut_packets).len();
88+
89+
handle.interrupt();
90+
91+
assert_eq!(packets, 246137);
92+
});
93+
}
94+
95+
fn bench_stream_next(c: &mut Criterion) {
96+
let benchmark = criterion::Benchmark::new("4sics", bench_stream_next_from_large_file);
97+
98+
c.bench(
99+
"stream_next",
100+
benchmark
101+
.sample_size(20)
102+
.nresamples(1)
103+
.measurement_time(std::time::Duration::from_secs(15)),
104+
);
105+
}
106+
107+
criterion_group!(benches, bench_stream, bench_stream_next);
108+
109+
// Benchmark: cargo bench --verbose
110+
111+
criterion_main!(benches);

lefthook.yml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
format:
2+
piped: true
3+
commands:
4+
1_install:
5+
run: rustup component add rustfmt
6+
2_cargo_fmt:
7+
run: cargo +nightly fmt --all
8+
9+
pre-push:
10+
piped: true
11+
commands:
12+
1_install:
13+
run: rustup component add rustfmt
14+
2_fmt:
15+
run: cargo +nightly fmt --all -- --check

src/bpf.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ pub struct Bpf {
66

77
impl Bpf {
88
pub fn new(inner: pcap_sys::bpf_program) -> Bpf {
9-
Bpf {
10-
inner
11-
}
9+
Bpf { inner }
1210
}
1311
pub fn inner_mut(&mut self) -> &mut pcap_sys::bpf_program {
1412
&mut self.inner
@@ -21,4 +19,4 @@ impl Drop for Bpf {
2119
pcap_sys::pcap_freecode(&mut self.inner);
2220
}
2321
}
24-
}
22+
}

src/errors.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ pub enum Error {
1010
FfiNul(#[fail(cause)] std::ffi::FromBytesWithNulError),
1111
#[fail(display = "Utf8 conversion error")]
1212
Utf8(#[fail(cause)] std::str::Utf8Error),
13-
#[fail(display = "TokioTimer error")]
14-
TokioTimer(#[fail(cause)] tokio_timer::Error),
13+
#[fail(display = "Time conversion error")]
14+
Time(#[fail(cause)] std::time::SystemTimeError),
1515
#[fail(display = "Null ptr returned")]
1616
NullPtr,
1717
#[fail(display = "Libpcap failed populate header")]

0 commit comments

Comments
 (0)