2019-04-15 10:05:22 +08:00
|
|
|
use std::error;
|
2019-12-07 23:59:24 +06:00
|
|
|
use std::pin::Pin;
|
|
|
|
use std::sync::{Arc, RwLock};
|
2019-04-15 10:05:22 +08:00
|
|
|
use std::time::Duration;
|
|
|
|
|
2019-12-07 23:59:24 +06:00
|
|
|
use actix_rt::time::delay_for;
|
2020-03-27 21:57:23 -03:00
|
|
|
use actix_web::{middleware, web, App, Error, HttpResponse, HttpServer};
|
2019-12-07 23:59:24 +06:00
|
|
|
use bytes::Bytes;
|
|
|
|
use futures::{Future, FutureExt};
|
2019-04-15 10:05:22 +08:00
|
|
|
use serde_json;
|
|
|
|
use serde_json::Value;
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
mod convention;
|
|
|
|
|
|
|
|
/// The main handler for JSONRPC server.
|
2020-03-27 21:57:23 -03:00
|
|
|
async fn rpc_handler(
|
|
|
|
body: Bytes,
|
|
|
|
app_state: web::Data<AppState>,
|
|
|
|
) -> Result<HttpResponse, Error> {
|
2019-12-07 23:59:24 +06:00
|
|
|
let reqjson: convention::Request = match serde_json::from_slice(body.as_ref()) {
|
|
|
|
Ok(ok) => ok,
|
|
|
|
Err(_) => {
|
|
|
|
let r = convention::Response {
|
|
|
|
jsonrpc: String::from(convention::JSONRPC_VERSION),
|
|
|
|
result: Value::Null,
|
|
|
|
error: Some(convention::ErrorData::std(-32700)),
|
|
|
|
id: Value::Null,
|
|
|
|
};
|
|
|
|
return Ok(HttpResponse::Ok()
|
|
|
|
.content_type("application/json")
|
|
|
|
.body(r.dump()));
|
2019-04-15 10:05:22 +08:00
|
|
|
}
|
2019-12-07 23:59:24 +06:00
|
|
|
};
|
|
|
|
let mut result = convention::Response::default();
|
|
|
|
result.id = reqjson.id.clone();
|
|
|
|
|
|
|
|
match rpc_select(&app_state, reqjson.method.as_str(), reqjson.params).await {
|
|
|
|
Ok(ok) => result.result = ok,
|
|
|
|
Err(e) => result.error = Some(e),
|
|
|
|
}
|
2019-04-15 10:05:22 +08:00
|
|
|
|
2019-12-07 23:59:24 +06:00
|
|
|
Ok(HttpResponse::Ok()
|
|
|
|
.content_type("application/json")
|
|
|
|
.body(result.dump()))
|
2019-04-15 10:05:22 +08:00
|
|
|
}
|
|
|
|
|
2019-12-07 23:59:24 +06:00
|
|
|
async fn rpc_select(
|
2019-04-15 10:27:25 +08:00
|
|
|
app_state: &AppState,
|
|
|
|
method: &str,
|
|
|
|
params: Vec<Value>,
|
|
|
|
) -> Result<Value, convention::ErrorData> {
|
2019-04-15 10:05:22 +08:00
|
|
|
match method {
|
|
|
|
"ping" => {
|
|
|
|
let r = app_state.network.read().unwrap().ping();
|
|
|
|
Ok(Value::from(r))
|
|
|
|
}
|
2019-04-15 10:27:25 +08:00
|
|
|
"wait" => {
|
|
|
|
if params.len() != 1 || !params[0].is_u64() {
|
|
|
|
return Err(convention::ErrorData::std(-32602));
|
|
|
|
}
|
|
|
|
match app_state
|
|
|
|
.network
|
|
|
|
.read()
|
|
|
|
.unwrap()
|
|
|
|
.wait(params[0].as_u64().unwrap())
|
2019-12-07 23:59:24 +06:00
|
|
|
.await
|
2019-04-15 10:27:25 +08:00
|
|
|
{
|
|
|
|
Ok(ok) => Ok(Value::from(ok)),
|
|
|
|
Err(e) => Err(convention::ErrorData::new(500, &format!("{:?}", e)[..])),
|
|
|
|
}
|
|
|
|
}
|
2019-04-15 10:05:22 +08:00
|
|
|
"get" => {
|
|
|
|
let r = app_state.network.read().unwrap().get();
|
|
|
|
Ok(Value::from(r))
|
|
|
|
}
|
|
|
|
"inc" => {
|
|
|
|
app_state.network.write().unwrap().inc();
|
|
|
|
Ok(Value::Null)
|
|
|
|
}
|
|
|
|
_ => Err(convention::ErrorData::std(-32601)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait ImplNetwork {
|
|
|
|
fn ping(&self) -> String;
|
2019-09-05 00:04:57 +09:00
|
|
|
fn wait(
|
|
|
|
&self,
|
|
|
|
d: u64,
|
2019-12-07 23:59:24 +06:00
|
|
|
) -> Pin<Box<dyn Future<Output = Result<String, Box<dyn error::Error>>>>>;
|
2019-04-15 10:05:22 +08:00
|
|
|
|
|
|
|
fn get(&self) -> u32;
|
|
|
|
fn inc(&mut self);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct ObjNetwork {
|
|
|
|
c: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ObjNetwork {
|
|
|
|
fn new() -> Self {
|
|
|
|
Self { c: 0 }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ImplNetwork for ObjNetwork {
|
|
|
|
fn ping(&self) -> String {
|
|
|
|
String::from("pong")
|
|
|
|
}
|
|
|
|
|
2019-09-05 00:04:57 +09:00
|
|
|
fn wait(
|
|
|
|
&self,
|
|
|
|
d: u64,
|
2019-12-07 23:59:24 +06:00
|
|
|
) -> Pin<Box<dyn Future<Output = Result<String, Box<dyn error::Error>>>>> {
|
|
|
|
async move {
|
|
|
|
delay_for(Duration::from_secs(d)).await;
|
|
|
|
Ok(String::from("pong"))
|
|
|
|
}
|
2019-12-25 20:48:33 +04:00
|
|
|
.boxed_local()
|
2019-04-15 10:05:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn get(&self) -> u32 {
|
|
|
|
self.c
|
|
|
|
}
|
|
|
|
|
|
|
|
fn inc(&mut self) {
|
|
|
|
self.c += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct AppState {
|
2019-09-05 00:04:57 +09:00
|
|
|
network: Arc<RwLock<dyn ImplNetwork>>,
|
2019-04-15 10:05:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl AppState {
|
2019-09-05 00:04:57 +09:00
|
|
|
pub fn new(network: Arc<RwLock<dyn ImplNetwork>>) -> Self {
|
2019-04-15 10:05:22 +08:00
|
|
|
Self { network }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-07 23:59:24 +06:00
|
|
|
#[actix_rt::main]
|
|
|
|
async fn main() -> std::io::Result<()> {
|
2019-04-15 10:05:22 +08:00
|
|
|
std::env::set_var("RUST_LOG", "info");
|
|
|
|
env_logger::init();
|
|
|
|
|
|
|
|
let network = Arc::new(RwLock::new(ObjNetwork::new()));
|
|
|
|
|
|
|
|
HttpServer::new(move || {
|
|
|
|
let app_state = AppState::new(network.clone());
|
|
|
|
App::new()
|
|
|
|
.data(app_state)
|
|
|
|
.wrap(middleware::Logger::default())
|
2019-12-07 23:59:24 +06:00
|
|
|
.service(web::resource("/").route(web::post().to(rpc_handler)))
|
2019-04-15 10:05:22 +08:00
|
|
|
})
|
|
|
|
.bind("127.0.0.1:8080")
|
|
|
|
.unwrap()
|
2019-12-25 20:48:33 +04:00
|
|
|
.run()
|
2019-12-07 23:59:24 +06:00
|
|
|
.await
|
2019-04-15 10:05:22 +08:00
|
|
|
}
|