2018-06-19 21:40:44 -07:00
|
|
|
extern crate bincode;
|
2018-11-14 18:57:34 -08:00
|
|
|
extern crate byteorder;
|
2018-08-26 21:13:49 -07:00
|
|
|
extern crate bytes;
|
2018-08-06 20:51:12 -07:00
|
|
|
#[macro_use]
|
2018-07-04 13:23:25 -07:00
|
|
|
extern crate clap;
|
2018-09-04 10:48:23 -07:00
|
|
|
extern crate log;
|
2018-06-19 21:40:44 -07:00
|
|
|
extern crate serde_json;
|
|
|
|
extern crate solana;
|
2018-11-16 08:45:59 -08:00
|
|
|
extern crate solana_metrics;
|
2018-06-19 21:40:44 -07:00
|
|
|
extern crate tokio;
|
|
|
|
extern crate tokio_codec;
|
|
|
|
|
2018-08-26 21:13:49 -07:00
|
|
|
use bincode::{deserialize, serialize};
|
2018-11-14 18:57:34 -08:00
|
|
|
use byteorder::{ByteOrder, LittleEndian};
|
2018-08-26 21:13:49 -07:00
|
|
|
use bytes::Bytes;
|
2018-07-04 13:23:25 -07:00
|
|
|
use clap::{App, Arg};
|
2018-07-18 12:38:18 -07:00
|
|
|
use solana::drone::{Drone, DroneRequest, DRONE_PORT};
|
2018-07-27 21:37:53 -07:00
|
|
|
use solana::logger;
|
2018-07-12 15:02:14 -07:00
|
|
|
use solana::signature::read_keypair;
|
2018-08-20 13:03:36 -07:00
|
|
|
use std::error;
|
2018-08-31 00:40:43 -07:00
|
|
|
use std::io;
|
2018-08-31 00:10:39 -07:00
|
|
|
use std::net::{Ipv4Addr, SocketAddr};
|
2018-08-20 13:03:36 -07:00
|
|
|
use std::sync::{Arc, Mutex};
|
2018-06-19 23:49:54 -07:00
|
|
|
use std::thread;
|
2018-06-19 21:40:44 -07:00
|
|
|
use tokio::net::TcpListener;
|
|
|
|
use tokio::prelude::*;
|
2018-06-19 23:49:54 -07:00
|
|
|
use tokio_codec::{BytesCodec, Decoder};
|
2018-06-19 21:40:44 -07:00
|
|
|
|
2018-08-31 00:10:39 -07:00
|
|
|
macro_rules! socketaddr {
|
|
|
|
($ip:expr, $port:expr) => {
|
|
|
|
SocketAddr::from((Ipv4Addr::from($ip), $port))
|
|
|
|
};
|
|
|
|
($str:expr) => {{
|
|
|
|
let a: SocketAddr = $str.parse().unwrap();
|
|
|
|
a
|
|
|
|
}};
|
|
|
|
}
|
|
|
|
|
2018-08-20 13:03:36 -07:00
|
|
|
fn main() -> Result<(), Box<error::Error>> {
|
2018-07-27 21:37:53 -07:00
|
|
|
logger::setup();
|
2018-11-16 08:45:59 -08:00
|
|
|
solana_metrics::set_panic_hook("drone");
|
2018-07-17 11:00:01 -07:00
|
|
|
let matches = App::new("drone")
|
2018-08-06 20:51:12 -07:00
|
|
|
.version(crate_version!())
|
2018-07-04 13:23:25 -07:00
|
|
|
.arg(
|
2018-07-12 15:02:14 -07:00
|
|
|
Arg::with_name("keypair")
|
|
|
|
.short("k")
|
|
|
|
.long("keypair")
|
2018-07-04 13:23:25 -07:00
|
|
|
.value_name("PATH")
|
|
|
|
.takes_value(true)
|
2018-07-12 15:02:14 -07:00
|
|
|
.required(true)
|
2018-09-14 15:32:57 -07:00
|
|
|
.help("File from which to read the mint's keypair"),
|
2018-09-14 16:25:14 -07:00
|
|
|
).arg(
|
2018-08-20 13:03:36 -07:00
|
|
|
Arg::with_name("slice")
|
|
|
|
.long("slice")
|
2018-09-14 15:32:57 -07:00
|
|
|
.value_name("SECS")
|
2018-07-04 13:23:25 -07:00
|
|
|
.takes_value(true)
|
2018-08-20 13:03:36 -07:00
|
|
|
.help("Time slice over which to limit requests to drone"),
|
2018-09-14 16:25:14 -07:00
|
|
|
).arg(
|
2018-07-04 13:23:25 -07:00
|
|
|
Arg::with_name("cap")
|
|
|
|
.long("cap")
|
2018-09-14 15:32:57 -07:00
|
|
|
.value_name("NUM")
|
2018-07-04 13:23:25 -07:00
|
|
|
.takes_value(true)
|
2018-08-20 13:03:36 -07:00
|
|
|
.help("Request limit for time slice"),
|
2018-09-14 16:25:14 -07:00
|
|
|
).get_matches();
|
2018-07-04 13:23:25 -07:00
|
|
|
|
2018-07-12 15:02:14 -07:00
|
|
|
let mint_keypair =
|
2018-08-31 00:10:39 -07:00
|
|
|
read_keypair(matches.value_of("keypair").unwrap()).expect("failed to read client keypair");
|
2018-07-12 15:02:14 -07:00
|
|
|
|
2018-06-19 21:40:44 -07:00
|
|
|
let time_slice: Option<u64>;
|
2018-08-20 13:03:36 -07:00
|
|
|
if let Some(secs) = matches.value_of("slice") {
|
2018-08-31 00:10:39 -07:00
|
|
|
time_slice = Some(secs.to_string().parse().expect("failed to parse slice"));
|
2018-06-19 23:49:54 -07:00
|
|
|
} else {
|
2018-06-19 21:40:44 -07:00
|
|
|
time_slice = None;
|
|
|
|
}
|
|
|
|
let request_cap: Option<u64>;
|
2018-07-04 13:23:25 -07:00
|
|
|
if let Some(c) = matches.value_of("cap") {
|
2018-08-31 00:10:39 -07:00
|
|
|
request_cap = Some(c.to_string().parse().expect("failed to parse cap"));
|
2018-06-19 23:49:54 -07:00
|
|
|
} else {
|
2018-06-19 21:40:44 -07:00
|
|
|
request_cap = None;
|
|
|
|
}
|
2018-06-24 00:37:18 -07:00
|
|
|
|
2018-08-31 00:10:39 -07:00
|
|
|
let drone_addr = socketaddr!(0, DRONE_PORT);
|
2018-08-28 16:52:10 -07:00
|
|
|
|
2018-06-19 23:49:54 -07:00
|
|
|
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();
|
|
|
|
});
|
|
|
|
|
2018-08-28 16:52:10 -07:00
|
|
|
let socket = TcpListener::bind(&drone_addr).unwrap();
|
2018-06-19 23:49:54 -07:00
|
|
|
println!("Drone started. Listening on: {}", drone_addr);
|
2018-06-19 21:40:44 -07:00
|
|
|
let done = socket
|
|
|
|
.incoming()
|
|
|
|
.map_err(|e| println!("failed to accept socket; error = {:?}", e))
|
|
|
|
.for_each(move |socket| {
|
2018-06-19 23:49:54 -07:00
|
|
|
let drone2 = drone.clone();
|
|
|
|
// let client_ip = socket.peer_addr().expect("drone peer_addr").ip();
|
2018-06-19 21:40:44 -07:00
|
|
|
let framed = BytesCodec::new().framed(socket);
|
2018-08-26 21:13:49 -07:00
|
|
|
let (writer, reader) = framed.split();
|
2018-06-19 21:40:44 -07:00
|
|
|
|
2018-08-26 21:13:49 -07:00
|
|
|
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),
|
|
|
|
))
|
|
|
|
})?;
|
2018-07-29 22:20:26 -07:00
|
|
|
|
2018-11-14 18:57:34 -08:00
|
|
|
println!("Airdrop transaction requested...{:?}", req);
|
2018-08-26 21:13:49 -07:00
|
|
|
// let res = drone2.lock().unwrap().check_rate_limit(client_ip);
|
2018-11-14 18:57:34 -08:00
|
|
|
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)
|
|
|
|
}
|
2018-08-26 21:13:49 -07:00
|
|
|
}
|
|
|
|
});
|
|
|
|
let server = writer
|
|
|
|
.send_all(processor.or_else(|err| {
|
|
|
|
Err(io::Error::new(
|
|
|
|
io::ErrorKind::Other,
|
|
|
|
format!("Drone response: {:?}", err),
|
|
|
|
))
|
2018-09-14 16:25:14 -07:00
|
|
|
})).then(|_| Ok(()));
|
2018-08-26 21:13:49 -07:00
|
|
|
tokio::spawn(server)
|
2018-06-19 21:40:44 -07:00
|
|
|
});
|
|
|
|
tokio::run(done);
|
2018-08-20 13:03:36 -07:00
|
|
|
Ok(())
|
2018-06-19 21:40:44 -07:00
|
|
|
}
|