2019-10-02 11:40:20 +03:00
|
|
|
// Copyright 2019 The Grin Developers
|
2018-11-03 09:46:12 +03:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
use super::utils::w;
|
2019-02-18 15:15:32 +03:00
|
|
|
use crate::p2p::types::{PeerAddr, PeerInfoDisplay, ReasonForBan};
|
2019-12-06 13:57:53 +03:00
|
|
|
use crate::p2p::{self, PeerData};
|
|
|
|
use crate::rest::*;
|
2018-12-08 02:59:40 +03:00
|
|
|
use crate::router::{Handler, ResponseFuture};
|
|
|
|
use crate::web::*;
|
2018-11-03 09:46:12 +03:00
|
|
|
use hyper::{Body, Request, StatusCode};
|
2019-12-06 13:57:53 +03:00
|
|
|
use std::net::SocketAddr;
|
2018-11-03 09:46:12 +03:00
|
|
|
use std::sync::Weak;
|
|
|
|
|
|
|
|
pub struct PeersAllHandler {
|
|
|
|
pub peers: Weak<p2p::Peers>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Handler for PeersAllHandler {
|
|
|
|
fn get(&self, _req: Request<Body>) -> ResponseFuture {
|
2019-03-18 21:34:35 +03:00
|
|
|
let peers = &w_fut!(&self.peers).all_peers();
|
2018-11-03 09:46:12 +03:00
|
|
|
json_response_pretty(&peers)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct PeersConnectedHandler {
|
|
|
|
pub peers: Weak<p2p::Peers>,
|
|
|
|
}
|
|
|
|
|
2019-12-06 13:57:53 +03:00
|
|
|
impl PeersConnectedHandler {
|
|
|
|
pub fn get_connected_peers(&self) -> Result<Vec<PeerInfoDisplay>, Error> {
|
|
|
|
let peers = w(&self.peers)?
|
|
|
|
.connected_peers()
|
|
|
|
.iter()
|
|
|
|
.map(|p| p.info.clone().into())
|
|
|
|
.collect::<Vec<PeerInfoDisplay>>();
|
|
|
|
Ok(peers)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-03 09:46:12 +03:00
|
|
|
impl Handler for PeersConnectedHandler {
|
|
|
|
fn get(&self, _req: Request<Body>) -> ResponseFuture {
|
2019-03-18 21:34:35 +03:00
|
|
|
let peers: Vec<PeerInfoDisplay> = w_fut!(&self.peers)
|
2019-02-16 00:17:00 +03:00
|
|
|
.connected_peers()
|
|
|
|
.iter()
|
|
|
|
.map(|p| p.info.clone().into())
|
|
|
|
.collect();
|
2018-11-03 09:46:12 +03:00
|
|
|
json_response(&peers)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Peer operations
|
|
|
|
/// GET /v1/peers/10.12.12.13
|
|
|
|
/// POST /v1/peers/10.12.12.13/ban
|
|
|
|
/// POST /v1/peers/10.12.12.13/unban
|
|
|
|
pub struct PeerHandler {
|
|
|
|
pub peers: Weak<p2p::Peers>,
|
|
|
|
}
|
|
|
|
|
2019-12-06 13:57:53 +03:00
|
|
|
impl PeerHandler {
|
|
|
|
pub fn get_peers(&self, addr: Option<SocketAddr>) -> Result<Vec<PeerData>, Error> {
|
|
|
|
if let Some(addr) = addr {
|
|
|
|
let peer_addr = PeerAddr(addr);
|
|
|
|
let peer_data: PeerData = w(&self.peers)?.get_peer(peer_addr).map_err(|e| {
|
|
|
|
let e: Error = ErrorKind::Internal(format!("get peer error: {:?}", e)).into();
|
|
|
|
e
|
|
|
|
})?;
|
|
|
|
return Ok(vec![peer_data]);
|
|
|
|
}
|
|
|
|
let peers = w(&self.peers)?.all_peers();
|
|
|
|
Ok(peers)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn ban_peer(&self, addr: SocketAddr) -> Result<(), Error> {
|
|
|
|
let peer_addr = PeerAddr(addr);
|
|
|
|
w(&self.peers)?
|
|
|
|
.ban_peer(peer_addr, ReasonForBan::ManualBan)
|
|
|
|
.map_err(|e| ErrorKind::Internal(format!("ban peer error: {:?}", e)).into())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn unban_peer(&self, addr: SocketAddr) -> Result<(), Error> {
|
|
|
|
let peer_addr = PeerAddr(addr);
|
|
|
|
w(&self.peers)?
|
|
|
|
.unban_peer(peer_addr)
|
|
|
|
.map_err(|e| ErrorKind::Internal(format!("unban peer error: {:?}", e)).into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-03 09:46:12 +03:00
|
|
|
impl Handler for PeerHandler {
|
|
|
|
fn get(&self, req: Request<Body>) -> ResponseFuture {
|
2019-02-16 00:17:00 +03:00
|
|
|
let command = right_path_element!(req);
|
2019-02-18 15:15:32 +03:00
|
|
|
|
|
|
|
// We support both "ip" and "ip:port" here for peer_addr.
|
|
|
|
// "ip:port" is only really useful for local usernet testing on loopback address.
|
|
|
|
// Normally we map peers to ip and only allow a single peer per ip address.
|
|
|
|
let peer_addr;
|
|
|
|
if let Ok(ip_addr) = command.parse() {
|
|
|
|
peer_addr = PeerAddr::from_ip(ip_addr);
|
|
|
|
} else if let Ok(addr) = command.parse() {
|
|
|
|
peer_addr = PeerAddr(addr);
|
2018-11-03 09:46:12 +03:00
|
|
|
} else {
|
2019-02-18 15:15:32 +03:00
|
|
|
return response(
|
2018-11-03 09:46:12 +03:00
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
format!("peer address unrecognized: {}", req.uri().path()),
|
2019-02-18 15:15:32 +03:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-03-18 21:34:35 +03:00
|
|
|
match w_fut!(&self.peers).get_peer(peer_addr) {
|
2019-02-18 15:15:32 +03:00
|
|
|
Ok(peer) => json_response(&peer),
|
|
|
|
Err(_) => response(StatusCode::NOT_FOUND, "peer not found"),
|
2018-11-03 09:46:12 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
fn post(&self, req: Request<Body>) -> ResponseFuture {
|
2019-03-11 06:13:42 +03:00
|
|
|
let mut path_elems = req.uri().path().trim_end_matches('/').rsplit('/');
|
2018-11-03 09:46:12 +03:00
|
|
|
let command = match path_elems.next() {
|
|
|
|
None => return response(StatusCode::BAD_REQUEST, "invalid url"),
|
|
|
|
Some(c) => c,
|
|
|
|
};
|
|
|
|
let addr = match path_elems.next() {
|
|
|
|
None => return response(StatusCode::BAD_REQUEST, "invalid url"),
|
2019-02-18 15:15:32 +03:00
|
|
|
Some(a) => {
|
|
|
|
if let Ok(ip_addr) = a.parse() {
|
|
|
|
PeerAddr::from_ip(ip_addr)
|
|
|
|
} else if let Ok(addr) = a.parse() {
|
|
|
|
PeerAddr(addr)
|
|
|
|
} else {
|
2018-11-03 09:46:12 +03:00
|
|
|
return response(
|
|
|
|
StatusCode::BAD_REQUEST,
|
2019-02-18 15:15:32 +03:00
|
|
|
format!("invalid peer address: {}", req.uri().path()),
|
2019-01-25 13:09:32 +03:00
|
|
|
);
|
2018-11-03 09:46:12 +03:00
|
|
|
}
|
2019-02-18 15:15:32 +03:00
|
|
|
}
|
2018-11-03 09:46:12 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
match command {
|
2019-10-05 01:00:49 +03:00
|
|
|
"ban" => match w_fut!(&self.peers).ban_peer(addr, ReasonForBan::ManualBan) {
|
|
|
|
Ok(_) => response(StatusCode::OK, "{}"),
|
|
|
|
Err(e) => response(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
format!("ban failed: {:?}", e),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
"unban" => match w_fut!(&self.peers).unban_peer(addr) {
|
|
|
|
Ok(_) => response(StatusCode::OK, "{}"),
|
|
|
|
Err(e) => response(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
format!("unban failed: {:?}", e),
|
|
|
|
),
|
|
|
|
},
|
2018-11-03 09:46:12 +03:00
|
|
|
_ => return response(StatusCode::BAD_REQUEST, "invalid command"),
|
|
|
|
};
|
|
|
|
|
2019-02-11 21:54:21 +03:00
|
|
|
response(StatusCode::OK, "{}")
|
2018-11-03 09:46:12 +03:00
|
|
|
}
|
|
|
|
}
|