1+ extern crate crossbeam_channel;
12extern crate hex;
23extern crate hexplay;
34extern crate pnet;
@@ -8,6 +9,7 @@ use pnet::datalink::{self, Config, NetworkInterface};
89use structopt:: StructOpt ;
910
1011use std:: io;
12+ use std:: thread;
1113use std:: time:: { Duration , Instant } ;
1214
1315fn print_interfaces ( ) {
@@ -36,6 +38,14 @@ struct Opt {
3638 #[ structopt( short = "t" , long = "timeout" ) ]
3739 timeout : Option < u64 > ,
3840
41+ /// Number of packet to transmit before exiting
42+ #[ structopt( short = "s" , long = "send" , default_value = "1" ) ]
43+ tx_send : u64 ,
44+
45+ /// Rate to transmit packets Num per Second
46+ #[ structopt( short = "r" , long = "rate" ) ]
47+ tx_rate : Option < f64 > ,
48+
3949 /// The network interface to listen on
4050 #[ structopt( name = "interface" ) ]
4151 interface : Option < String > ,
@@ -51,26 +61,25 @@ fn main() {
5161 // println!("{:?}", opt);
5262
5363 // If the user did not specify any interface. List some to be helpful
54- if let None = opt. interface {
64+ if opt. interface . is_none ( ) {
5565 print_interfaces ( ) ;
5666 std:: process:: exit ( 0 ) ;
5767 } ;
5868
59- let rx_timeout = opt. timeout . map ( |time| Duration :: from_secs ( time ) ) ;
69+ let rx_timeout = opt. timeout . map ( Duration :: from_secs) ;
6070 let mut rx_countlimit = opt. count ;
6171
6272 // Find the network interface with the provided name
6373 let interfaces = datalink:: interfaces ( ) ;
6474 let interface = interfaces
6575 . into_iter ( )
6676 // Safe to unwrap since print_interfaces will exit above
67- . filter ( |iface : & NetworkInterface | iface. name == * opt. interface . as_ref ( ) . unwrap ( ) )
68- . next ( )
77+ . find ( |iface : & NetworkInterface | iface. name == * opt. interface . as_ref ( ) . unwrap ( ) )
6978 . expect ( "Could not find the network interface" ) ;
7079
7180 // Set the timeout of the socket read to 10ms
7281 let mut datalink_config = Config :: default ( ) ;
73- datalink_config. read_timeout = Some ( std :: time :: Duration :: new ( 0 , 1e7 as u32 ) ) ;
82+ datalink_config. read_timeout = Some ( Duration :: from_millis ( 10 ) ) ;
7483
7584 // Create a new channel, dealing with layer 2 packets
7685 let ( mut tx, mut rx) = match datalink:: channel ( & interface, datalink_config) {
@@ -88,13 +97,27 @@ fn main() {
8897 std:: process:: exit ( 1 ) ;
8998 }
9099 } ;
91- // Transmit those bytes
92- println ! ( "Sending bytes: {:X?}" , bytes) ;
93- let res = tx. send_to ( & bytes, None ) . unwrap ( ) ;
94- if let Err ( error) = res {
95- println ! ( "{:?}" , error) ;
96- std:: process:: exit ( 1 ) ;
97- } ;
100+
101+ let rate = opt. tx_rate ;
102+ let count = opt. tx_send ;
103+ thread:: spawn ( move || {
104+ // Transmit those bytes
105+ let ticker = rate
106+ . map ( |rate| crossbeam_channel:: tick ( Duration :: from_micros ( ( 1e6 / rate) as u64 ) ) ) ;
107+
108+ for _ in 0 ..count {
109+ println ! ( "Sending bytes: {:X?}" , bytes) ;
110+ let res = tx. send_to ( & bytes, None ) . unwrap ( ) ;
111+ if let Err ( error) = res {
112+ println ! ( "{:?}" , error) ;
113+ std:: process:: exit ( 1 ) ;
114+ } ;
115+
116+ if let Some ( tick) = & ticker {
117+ tick. recv ( ) . expect ( "Ticker died?" ) ;
118+ }
119+ }
120+ } ) ;
98121 }
99122
100123 // Now do the Rx part
0 commit comments