initial commit - added jsonrpclient, session, rawclient

This commit is contained in:
Mahesh Bansod 2021-09-16 12:22:41 +05:30
commit 239ca2d1a7
14 changed files with 1465 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
target/

1145
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

6
Cargo.toml Normal file
View File

@ -0,0 +1,6 @@
[workspace]
members = [
"session",
"rawclient",
"jsonrpc2-client"
]

2
jsonrpc2-client/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
Cargo.lock

View File

@ -0,0 +1,12 @@
[package]
name = "jsonrpc2-client"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = {version = "1.11.0", features = ["full"]}
reqwest = {version = "0.11.4", features = ["json"]}
serde = { version = "1.0", features = ["derive"]}
serde_json = "1.0.67"

107
jsonrpc2-client/src/lib.rs Normal file
View File

@ -0,0 +1,107 @@
use serde::{Deserialize, Serialize};
pub struct Client {
client: reqwest::Client,
host_url: String,
}
pub fn new(host: &str) -> Client {
let client = reqwest::Client::new();
Client {
client,
host_url: host.to_string(),
}
}
impl Client {
pub async fn send_request<T: serde::de::DeserializeOwned + std::fmt::Debug>(
&self,
method: &str,
params: serde_json::Value,
) -> Result<T, RpcError> {
let request = RawRequest {
jsonrpc: "2.0".to_string(),
id: Some(generate_id()),
method: method.to_string(),
params: Some(params),
};
// println!(
// "Request: {}",
// serde_json::to_string_pretty(&request).unwrap()
// );
//TODO: maybe check the response better as well??
let resp = self
.client
.post(&self.host_url)
.json(&request)
.send()
.await?
.json::<RawResponse<T>>()
.await?;
resp.result()
}
}
#[derive(Debug, Serialize, Deserialize)]
struct RawRequest {
jsonrpc: String,
id: Option<String>,
method: String,
params: Option<serde_json::Value>,
}
#[derive(Debug, Serialize, Deserialize)]
struct RawResponse<T> {
jsonrpc: String,
result: Option<T>,
error: Option<RpcError>,
id: String,
}
impl<T> RawResponse<T> {
fn result(self) -> Result<T, RpcError> {
if let Some(res) = self.result {
return Ok(res);
}
if let Some(err) = self.error {
return Err(err);
}
Err(RpcError {
code: -1,
message: format!("Neither result nor error was found. ID = {:?}", self.id),
data: None,
})
}
}
fn generate_id() -> String {
"1".to_string()
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct RpcError {
code: i32,
message: String,
data: Option<serde_json::Value>,
}
impl std::convert::From<reqwest::Error> for RpcError {
fn from(error: reqwest::Error) -> Self {
RpcError {
code: -1,
message: format!("An error occurred: {}", error),
data: None,
}
}
}

2
rawclient/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
Cargo.lock

11
rawclient/Cargo.toml Normal file
View File

@ -0,0 +1,11 @@
[package]
name = "rawclient"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
jsonrpc2-client = {path = "../jsonrpc2-client"}
serde = { version = "1.0", features = ["derive"]}
serde_json = "1.0.67"

43
rawclient/src/error.rs Normal file
View File

@ -0,0 +1,43 @@
use jsonrpc2_client::RpcError;
use std::convert::From;
//TODO: IMPLEMENT THIS
type ErrorCode = i32;
#[derive(Debug)]
pub struct Error {
kind: ErrorKind,
code: ErrorCode,
description: Option<String>,
}
#[derive(Debug)]
pub enum ErrorKind {
ValidationError(ValidationError),
}
#[derive(Debug)]
enum ValidationError {
InvalidUsername,
InvalidPassword,
}
impl From<RpcError> for Error {
fn from(error: RpcError) -> Self {
let code = error.code();
let kind = get_error_kind(error.code());
let description = error.message();
Self {
code,
kind,
description,
}
}
}
impl std::convert::From<serde_json::Error> for Error {
fn from(_error: serde_json::Error) -> Self {
Self {}
}
}

42
rawclient/src/lib.rs Normal file
View File

@ -0,0 +1,42 @@
/// # Raw client for SocialVoid.
/// Makes a new client and makes JSONRPC requests. Also, useful in case we
/// want to switch the JSONRPC client crate used in the future.
mod error;
pub use error::Error;
const HOST: &str = "http://socialvoid.qlg1.com:5601/";
pub struct Client {
client: jsonrpc2_client::Client,
}
pub fn new() -> Client {
let host = get_host();
Client {
client: jsonrpc2_client::new(&host),
}
}
impl Client {
pub async fn send_request<T: serde::de::DeserializeOwned + std::fmt::Debug>(
&self,
method: &str,
params: serde_json::Value,
) -> Result<T, Error> {
let response = self.client.send_request::<T>(method, params).await?;
Ok(response)
}
}
fn get_host() -> String {
HOST.to_string()
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}

2
session/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
Cargo.lock

14
session/Cargo.toml Normal file
View File

@ -0,0 +1,14 @@
[package]
name = "session"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rawclient = {path = "../rawclient"}
serde = { version = "1.0", features = ["derive"]}
serde_json = "1.0.67"
sha256 = "1.0.2"
rand = "0.8.4"
tokio = {version = "1.11.0", features = ["full"]}

47
session/src/entities.rs Normal file
View File

@ -0,0 +1,47 @@
use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
pub struct SessionEstablished {
id: String,
challenge: String,
}
#[derive(Serialize)]
pub struct ClientInfo {
pub public_hash: String,
pub private_hash: String,
pub name: String,
pub platform: String,
pub version: String,
}
impl ClientInfo {
///Generates client information
pub fn generate() -> ClientInfo {
let public_hash = generate_random_hash();
let private_hash = generate_random_hash();
let platform = String::from("Linux"); //TODO: auto detect platform?
let name = String::from("Social Void rust");
let version = String::from("0.0.1"); //maybe have a better way to set this?
ClientInfo {
public_hash,
private_hash,
platform,
name,
version,
}
}
}
fn generate_random_hash() -> String {
//TODO: make it secure, more random idk
sha256::digest::<String>(
thread_rng()
.sample_iter(&Alphanumeric)
.take(30)
.map(char::from)
.collect(),
)
}

31
session/src/lib.rs Normal file
View File

@ -0,0 +1,31 @@
mod entities;
use entities::ClientInfo;
use entities::SessionEstablished;
use rawclient::Error;
pub async fn create(client: &rawclient::Client) -> Result<SessionEstablished, Error> {
let client_info = ClientInfo::generate();
client
.send_request("session.create", serde_json::value::to_value(client_info)?)
.await
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn it_should_establish_a_session() {
let client = rawclient::new();
let response = create(&client).await;
match response {
Ok(s_e) => {
println!("Result: {:?}", s_e);
}
Err(err) => {
println!("Error: {:?}", err);
unreachable!()
}
}
}
}