1use libp2prs_core::PeerId;
22use libp2prs_runtime::task;
23use libp2prs_swarm::Control;
24use serde::{Deserialize, Serialize};
25use std::str::FromStr;
26use tide::http::mime;
27use tide::{Body, Request, Response, Server};
28
29#[macro_use]
30extern crate lazy_static;
31
32lazy_static! {
33 static ref NON_PARAM_ROUTE: Vec<String> = {
34 vec![
35 "".to_string(),
36 "/recv".to_string(),
37 "/send".to_string(),
38 "/peer".to_string(),
39 "/connection".to_string(),
40 ]
41 };
42 static ref PARAM_ROUTE: Vec<String> = vec!["/peer/_".to_string(), "/protocol?protocol_id=_".to_string()];
43}
44
45#[derive(Serialize, Deserialize)]
47struct ResponseBody {
48 status: i64,
49 message: String,
50 result: Vec<String>,
51}
52
53pub struct InfoServer {
55 monitor: Server<Control>,
56 }
58
59#[derive(Serialize, Deserialize)]
61struct PackageInfo {
62 package_count: usize,
63 package_bytes: usize,
64}
65
66#[derive(Serialize, Deserialize)]
68struct SpecInfo {
69 package_in: usize,
70 package_out: usize,
71}
72
73#[derive(Serialize, Deserialize, Debug)]
75struct Protocol {
76 protocol_id: String,
77}
78
79#[derive(Serialize, Deserialize, Debug)]
81struct Peer {
82 count: usize,
83}
84
85#[derive(Serialize, Deserialize, Debug)]
87struct NetworkConnectionStatus {
88 num_connections: usize,
90 num_connections_pending: usize,
92 num_connections_established: usize,
94 num_active_streams: usize,
96 connection_info: Vec<NetworkConnectionInfo>,
98}
99
100#[derive(Serialize, Deserialize, Debug)]
102struct NetworkConnectionInfo {
103 la: Vec<u8>,
104 ra: Vec<u8>,
105 local_peer_id: String,
106 remote_peer_id: String,
107 num_inbound_streams: usize,
108 num_outbound_streams: usize,
109}
110
111impl InfoServer {
112 pub fn new(control: Control) -> Self {
113 let mut monitor = tide::with_state(control);
114
115 monitor.at("").get(get_all);
116 monitor.at("/recv").get(get_recv_pkg);
117 monitor.at("/send").get(get_sent_pkg);
118 monitor.at("/protocol").get(get_protocol_info);
119 monitor.at("/peer").get(get_peer_count).at("/:peer_id").get(get_peer_info);
120 monitor.at("/connection").get(get_connection_info);
121
122 InfoServer { monitor }
123 }
124
125 pub fn start(self, addr: String) {
126 task::spawn(async move {
127 let r = self.monitor.listen(addr).await;
128 log::info!("Info server started result={:?}", r);
129 });
130 }
131}
132
133async fn get_all(req: Request<Control>) -> tide::Result {
135 let addr = req.local_addr().unwrap();
136
137 let mut available = "<h3>Available Endpoints:</h3></br>".to_string();
138 for item in NON_PARAM_ROUTE.iter() {
139 let route = addr.to_owned() + item;
140 available = available + &format!("<a href=//{}>{}</a></br>", route, route);
141 }
142
143 let mut argument = "<h3>Endpoints that require arguments:</h3></br>".to_string();
144 for item in PARAM_ROUTE.iter() {
145 let route = addr.to_owned() + item;
146 argument += &format!("<a href=//{}>{}</a></br>", route, route);
147 }
148
149 let res_body =
150 "<head><link rel=\"icon\" href=\"data:;base64,=\"></head>".to_string() + "<body>" + &available + &argument + "</body>";
151
152 let response = Response::builder(200).content_type(mime::HTML).body(res_body).build();
153 Ok(response)
154}
155
156async fn get_peer_count(req: Request<Control>) -> tide::Result {
158 let mut control = req.state().clone();
159
160 let network_info = control.retrieve_networkinfo().await.map_err(|e| {
161 log::error!("{:?}", e);
162 tide::Error::new(500, e)
163 })?;
164
165 let peer = serde_json::to_string(&Peer {
166 count: network_info.num_peers,
167 })
168 .unwrap();
169
170 let result_body = Body::from_json(&ResponseBody {
171 status: 0,
172 message: "".to_string(),
173 result: vec![peer],
174 })?;
175 let response = Response::builder(200).body(result_body).build();
176 Ok(response)
177}
178
179async fn get_connection_info(req: Request<Control>) -> tide::Result {
181 let mut control = req.state().clone();
182
183 let network_info = control.retrieve_networkinfo().await.map_err(|e| {
184 log::error!("{:?}", e);
185 tide::Error::new(500, e)
186 })?;
187 let cis = control.dump_connections(None).await.map_err(|e| {
188 log::error!("{:?}", e);
189 tide::Error::new(500, e)
190 })?;
191
192 let mut connection_info = Vec::new();
193 for item in cis {
194 let info = NetworkConnectionInfo {
195 la: item.info.la.to_vec(),
196 ra: item.info.ra.to_vec(),
197 local_peer_id: item.info.local_peer_id.to_string(),
198 remote_peer_id: item.info.remote_peer_id.to_string(),
199 num_inbound_streams: item.info.num_inbound_streams,
200 num_outbound_streams: item.info.num_outbound_streams,
201 };
202 connection_info.push(info);
203 }
204
205 let network_connection_status = NetworkConnectionStatus {
206 num_connections: network_info.num_connections,
207 num_connections_pending: network_info.num_connections_pending,
208 num_connections_established: network_info.num_connections_established,
209 num_active_streams: network_info.num_active_streams,
210 connection_info,
211 };
212
213 let result_body = Body::from_json(&ResponseBody {
214 status: 0,
215 message: "".to_string(),
216 result: vec![serde_json::to_string(&network_connection_status).unwrap()],
217 })?;
218 let response = Response::builder(200).body(result_body).build();
219 Ok(response)
220}
221
222async fn get_recv_pkg(req: Request<Control>) -> tide::Result {
224 let (package_count, package_bytes) = req.state().get_recv_count_and_size();
225
226 let package = PackageInfo {
227 package_count,
228 package_bytes,
229 };
230
231 let result_body = Body::from_json(&package)?;
232 let response = Response::builder(200).body(result_body).build();
233 Ok(response)
234}
235
236async fn get_sent_pkg(req: Request<Control>) -> tide::Result {
238 let (package_count, package_bytes) = req.state().get_sent_count_and_size();
239
240 let package = PackageInfo {
241 package_count,
242 package_bytes,
243 };
244
245 let result_body = Body::from_json(&ResponseBody {
246 status: 0,
247 message: "".to_string(),
248 result: vec![serde_json::to_string(&package).unwrap()],
249 })?;
250 let response = Response::builder(200).body(result_body).build();
251 Ok(response)
252}
253
254async fn get_protocol_info(req: Request<Control>) -> tide::Result {
256 let protocol: Protocol = req.query()?;
257 let (receive, send) = req.state().get_protocol_in_and_out(&protocol.protocol_id);
258
259 let mut spec_info = SpecInfo {
260 package_in: 0,
261 package_out: 0,
262 };
263 if let Some(value) = receive {
264 spec_info.package_in = value
265 }
266 if let Some(value) = send {
267 spec_info.package_out = value
268 }
269
270 let result_body = Body::from_json(&ResponseBody {
271 status: 0,
272 message: "".to_string(),
273 result: vec![serde_json::to_string(&spec_info).unwrap()],
274 })?;
275 let response = Response::builder(200).body(result_body).build();
276 Ok(response)
277}
278
279async fn get_peer_info(req: Request<Control>) -> tide::Result {
281 let peer = req.param("peer_id")?;
282 let peer_id = match PeerId::from_str(peer) {
283 Ok(info) => info,
284 Err(e) => {
285 let err_body = Body::from_json(&ResponseBody {
286 status: 1,
287 message: format!("Cannot parse : {:?}", e),
288 result: vec![],
289 })?;
290 return Ok(Response::builder(400).body(err_body).build());
291 }
292 };
293
294 let (receive, send) = req.state().get_peer_in_and_out(&peer_id);
295
296 let mut spec_info = SpecInfo {
297 package_in: 0,
298 package_out: 0,
299 };
300 if let Some(value) = receive {
301 spec_info.package_in = value
302 }
303 if let Some(value) = send {
304 spec_info.package_out = value
305 }
306
307 let result_body = Body::from_json(&ResponseBody {
308 status: 0,
309 message: "".to_string(),
310 result: vec![serde_json::to_string(&spec_info).unwrap()],
311 })?;
312 let response = Response::builder(200).body(result_body).build();
313 Ok(response)
314}