extern crate bincode; extern crate byteorder; extern crate bytes; #[macro_use] extern crate clap; extern crate log; #[macro_use] extern crate solana_drone; extern crate solana_metrics; extern crate solana_sdk; extern crate tokio; extern crate tokio_codec; use bincode::{deserialize, serialize}; use byteorder::{ByteOrder, LittleEndian}; use bytes::Bytes; use clap::{App, Arg}; use solana_drone::drone::{Drone, DroneRequest, DRONE_PORT}; //use solana::logger; use solana_sdk::signature::read_keypair; use std::error; use std::io; use std::net::{Ipv4Addr, SocketAddr}; use std::sync::{Arc, Mutex}; use std::thread; use tokio::net::TcpListener; use tokio::prelude::*; use tokio_codec::{BytesCodec, Decoder}; fn main() -> Result<(), Box> { //logger::setup(); solana_metrics::set_panic_hook("drone"); let matches = App::new("drone") .version(crate_version!()) .arg( Arg::with_name("keypair") .short("k") .long("keypair") .value_name("PATH") .takes_value(true) .required(true) .help("File from which to read the mint's keypair"), ) .arg( Arg::with_name("slice") .long("slice") .value_name("SECS") .takes_value(true) .help("Time slice over which to limit requests to drone"), ) .arg( Arg::with_name("cap") .long("cap") .value_name("NUM") .takes_value(true) .help("Request limit for time slice"), ) .get_matches(); let mint_keypair = read_keypair(matches.value_of("keypair").unwrap()).expect("failed to read client keypair"); let time_slice: Option; if let Some(secs) = matches.value_of("slice") { time_slice = Some(secs.to_string().parse().expect("failed to parse slice")); } else { time_slice = None; } let request_cap: Option; if let Some(c) = matches.value_of("cap") { request_cap = Some(c.to_string().parse().expect("failed to parse cap")); } else { request_cap = None; } let drone_addr = socketaddr!(0, DRONE_PORT); let drone = Arc::new(Mutex::new(Drone::new( mint_keypair, time_slice, request_cap, ))); let drone1 = drone.clone(); thread::spawn(move || loop { let time = drone1.lock().unwrap().time_slice; thread::sleep(time); drone1.lock().unwrap().clear_request_count(); }); let socket = TcpListener::bind(&drone_addr).unwrap(); println!("Drone started. Listening on: {}", drone_addr); let done = socket .incoming() .map_err(|e| println!("failed to accept socket; error = {:?}", e)) .for_each(move |socket| { let drone2 = drone.clone(); // let client_ip = socket.peer_addr().expect("drone peer_addr").ip(); let framed = BytesCodec::new().framed(socket); let (writer, reader) = framed.split(); let processor = reader.and_then(move |bytes| { let req: DroneRequest = deserialize(&bytes).or_else(|err| { Err(io::Error::new( io::ErrorKind::Other, format!("deserialize packet in drone: {:?}", err), )) })?; println!("Airdrop transaction requested...{:?}", req); // let res = drone2.lock().unwrap().check_rate_limit(client_ip); let res = drone2.lock().unwrap().build_airdrop_transaction(req); match res { Ok(tx) => { let response_vec = serialize(&tx).or_else(|err| { Err(io::Error::new( io::ErrorKind::Other, format!("deserialize packet in drone: {:?}", err), )) })?; let mut response_vec_with_length = vec![0; 2]; LittleEndian::write_u16( &mut response_vec_with_length, response_vec.len() as u16, ); response_vec_with_length.extend_from_slice(&response_vec); let response_bytes = Bytes::from(response_vec_with_length); println!("Airdrop transaction granted"); Ok(response_bytes) } Err(err) => { println!("Airdrop transaction failed: {:?}", err); Err(err) } } }); let server = writer .send_all(processor.or_else(|err| { Err(io::Error::new( io::ErrorKind::Other, format!("Drone response: {:?}", err), )) })) .then(|_| Ok(())); tokio::spawn(server) }); tokio::run(done); Ok(()) }