Skip to content

Commit

Permalink
feat(duplex): make oblivion full duplex
Browse files Browse the repository at this point in the history
  • Loading branch information
fu050409 committed Apr 21, 2024
1 parent abc5085 commit 7ff6de2
Show file tree
Hide file tree
Showing 12 changed files with 271 additions and 315 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "oblivion"
version = "1.3.0"
version = "2.0.0"
authors = ["苏向夜 <[email protected]>"]
description = "Rust High Concurrency Implementation of Oblivion, an End-to-End Encryption Protocol Based on ECDHE Encryption Algorithm"
edition = "2021"
Expand Down
26 changes: 10 additions & 16 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,29 @@ pub async fn request(
olps: &str,
data: Option<Value>,
file: Option<Vec<u8>>,
tfo: bool,
) -> Result<Response> {
let session = Session::new();
session
.request(method.to_string(), olps.to_string(), data, file, tfo)
.request(method.to_string(), olps.to_string(), data, file)
.await
}

/// GET method
pub async fn get(olps: &str, tfo: bool) -> Result<Response> {
request("get", olps, None, None, tfo).await
pub async fn get(olps: &str) -> Result<Response> {
request("get", olps, None, None).await
}

/// POST method
pub async fn post(olps: &str, data: Value, tfo: bool) -> Result<Response> {
request("post", olps, Some(data), None, tfo).await
pub async fn post(olps: &str, data: Value) -> Result<Response> {
request("post", olps, Some(data), None).await
}

/// PUT method
pub async fn put(olps: &str, data: Option<Value>, file: Vec<u8>, tfo: bool) -> Result<Response> {
request("put", olps, data, Some(file), tfo).await
pub async fn put(olps: &str, data: Option<Value>, file: Vec<u8>) -> Result<Response> {
request("put", olps, data, Some(file)).await
}

#[deprecated(since = "1.0.0", note = "FORWARD method may no longer supported.")]
pub async fn forward(
olps: &str,
data: Option<Value>,
file: Vec<u8>,
tfo: bool,
) -> Result<Response> {
request("forward", olps, data, Some(file), tfo).await
#[deprecated(since = "1.0.0", note = "FORWARD method is no longer supported.")]
pub async fn forward(olps: &str, data: Option<Value>, file: Vec<u8>) -> Result<Response> {
request("forward", olps, data, Some(file)).await
}
20 changes: 14 additions & 6 deletions src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ use oblivion::api::get;
use oblivion::models::render::{BaseResponse, Response};
use oblivion::models::router::{RoutePath, RouteType, Router};
use oblivion::models::server::Server;
use oblivion::models::session::Session;
use oblivion::path_route;
use oblivion::utils::parser::OblivionRequest;
use oblivion_codegen::async_route;
use serde_json::json;
use std::env::args;
use std::time::Instant;

#[async_route]
fn handler(mut _req: OblivionRequest) -> Response {
fn handler(_sess: &mut Session) -> Response {
Ok(BaseResponse::TextResponse(
"每一个人都应该拥有守护信息与获得真实信息的神圣权利, 任何与之对抗的都是我们的敌人"
.to_string(),
Expand All @@ -20,29 +20,37 @@ fn handler(mut _req: OblivionRequest) -> Response {
}

#[async_route]
fn welcome(mut req: OblivionRequest) -> Response {
fn welcome(_sess: &mut Session) -> Response {
Ok(BaseResponse::TextResponse(
format!("欢迎进入信息绝对安全区, 来自[{}]的朋友", req.get_ip()),
format!("欢迎进入信息绝对安全区, 来自[{}]的朋友", 1),
200,
))
}

#[async_route]
fn json(_req: OblivionRequest) -> Response {
fn json(_sess: &mut Session) -> Response {
Ok(BaseResponse::JsonResponse(
json!({"status": true, "msg": "只身堕入极暗之永夜, 以期再世涅槃之阳光"}),
200,
))
}

#[async_route]
async fn alive(mut _sess: Session) -> Response {
Ok(BaseResponse::JsonResponse(
json!({"status": true, "msg": "结束"}),
200,
))
}

#[tokio::main]
async fn main() -> Result<()> {
let args: Vec<String> = args().collect();
let is_server = if args.len() == 1 { true } else { false };
if !is_server {
loop {
let now = Instant::now();
get("127.0.0.1:7076/path", true).await.unwrap();
get("127.0.0.1:7076/path").await?;
println!("执行时间: {}", now.elapsed().as_millis());
}
} else {
Expand Down
145 changes: 41 additions & 104 deletions src/models/client.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//! # Oblivion Client
use crate::models::packet::{OED, OKE, OSC};
use crate::models::packet::{OED, OSC};

use crate::exceptions::OblivionException;
#[cfg(feature = "python")]
use crate::exceptions::PyOblivionException;

use crate::utils::gear::Socket;
use crate::utils::generator::generate_key_pair;
use crate::utils::parser::{length, Oblivion, OblivionPath};
use crate::utils::parser::{Oblivion, OblivionPath};

use anyhow::{Error, Result};
use p256::ecdh::EphemeralSecret;
Expand All @@ -17,11 +17,14 @@ use tokio::net::TcpStream;
#[cfg(feature = "python")]
use pyo3::prelude::*;
#[cfg(not(feature = "python"))]
use serde_json::{from_str, json, Value};
use serde_json::{from_str, Value};
#[cfg(feature = "python")]
use serde_json::{json, Value};

use super::session::Session;

#[cfg_attr(feature = "python", pyclass)]
#[derive(Debug, Default)]
pub struct Response {
#[cfg_attr(feature = "python", pyo3(get))]
pub header: String,
Expand Down Expand Up @@ -92,47 +95,29 @@ impl Response {
}
}

pub struct Request {
method: String,
pub struct Client {
olps: String,
path: OblivionPath,
data: Option<Value>,
file: Option<Vec<u8>>,
tfo: bool,
plain_text: String,
prepared: bool,
private_key: Option<EphemeralSecret>,
public_key: Option<PublicKey>,
aes_key: Option<Vec<u8>>,
tcp: Option<Socket>,
session: Option<Session>,
}

impl Request {
pub fn new(
method: String,
olps: String,
data: Option<Value>,
file: Option<Vec<u8>>,
tfo: bool,
) -> Result<Self> {
impl Client {
pub fn new(method: String, olps: String) -> Result<Self> {
let method = method.to_uppercase();
let path = OblivionPath::new(&olps)?;
let olps = path.get_olps();
let oblivion = Oblivion::new(&method, &olps);
let plain_text = oblivion.plain_text();
Ok(Self {
method,
olps,
path,
data,
file,
tfo,
plain_text,
prepared: false,
plain_text: plain_text.clone(),
private_key: None,
public_key: None,
aes_key: None,
tcp: None,
session: None,
})
}

Expand All @@ -150,96 +135,48 @@ impl Request {
}
Err(_) => return Err(Error::from(OblivionException::ConnectionRefusedError)),
};
self.tcp = Some(Socket::new(tcp));

if self.tfo {
// 在这里启用TCP Fast Open
};

self.send_header().await?;
self.session = Some(Session::new_with_header(
&self.plain_text,
Socket::new(tcp),
)?);

let mut oke = OKE::new(Some(&self.private_key.as_ref().unwrap()), self.public_key)?;
oke.from_stream_with_salt(self.tcp.as_mut().unwrap())
.await?;
self.aes_key = Some(oke.get_aes_key());
oke.to_stream(self.tcp.as_mut().unwrap()).await?;
let session = self.session.as_mut().unwrap();
session.handshake(0).await?;

self.prepared = true;
Ok(())
}

pub async fn send_header(&mut self) -> Result<()> {
let tcp = self.tcp.as_mut().unwrap();
let header = self.plain_text.as_bytes().to_vec();
tcp.send(&length(&header)?).await?;
tcp.send(&header).await?;
pub async fn send(&mut self, bytes: Vec<u8>) -> Result<()> {
let session = self.session.as_mut().unwrap();
let tcp = &mut session.socket;
let mut oed = OED::new(session.aes_key.clone());
oed.from_bytes(bytes)?;
oed.to_stream(tcp, 5).await?;
Ok(())
}

pub async fn send(&mut self) -> Result<()> {
if self.method == "GET" {
return Ok(());
};

let tcp = self.tcp.as_mut().unwrap();
let mut oed = if self.method == "POST" {
if self.data.is_none() {
let mut oed = OED::new(self.aes_key.clone());
oed.from_dict(json!({}))?;
oed
} else {
let mut oed = OED::new(self.aes_key.clone());
oed.from_dict(self.data.clone().unwrap())?;
oed
}
} else if self.method == "PUT" {
let mut oed = if self.data.is_none() {
let mut oed = OED::new(self.aes_key.clone());
oed.from_dict(json!({}))?;
oed
} else {
let mut oed = OED::new(self.aes_key.clone());
oed.from_dict(self.data.clone().unwrap())?;
oed
};
pub async fn recv(&mut self) -> Result<Response> {
let session = self.session.as_mut().unwrap();
let tcp = &mut session.socket;

oed.to_stream(tcp, 5).await?;
let flag = OSC::from_stream(tcp).await?;

let mut oed = OED::new(self.aes_key.clone());
oed.from_bytes(self.file.clone().unwrap())?;
oed
} else {
return Err(Error::from(OblivionException::UnsupportedMethod {
method: self.method.to_string(),
}));
};
let mut oed = OED::new(session.aes_key.clone());
oed.from_stream(tcp, 5).await?;

oed.to_stream(tcp, 5).await?;
Ok(())
}
let osc = OSC::from_stream(tcp).await?;

pub async fn recv(&mut self) -> Result<Response> {
let tcp = self.tcp.as_mut().unwrap();

if !self.prepared {
Err(Error::from(OblivionException::ErrorNotPrepared))
} else {
let mut oed = OED::new(self.aes_key.clone());
oed.from_stream(tcp, 5).await?;

let osc = OSC::from_stream(tcp).await?;

let response = Response::new(
self.plain_text.clone(),
oed.get_data(),
self.olps.clone(),
osc.status_code,
);
Ok(response)
}
}
let response = Response::new(
self.plain_text.clone(),
oed.get_data(),
self.olps.clone(),
osc.status_code,
);

pub fn is_prepared(&mut self) -> bool {
self.prepared
if flag.status_code == 1 {
tcp.close().await?;
}
Ok(response)
}
}
24 changes: 12 additions & 12 deletions src/models/handler.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
//! # Oblivion Default Handler
use super::{render::BaseResponse, render::Response};
use crate::utils::parser::OblivionRequest;
use oblivion_codegen::async_route;
use super::render::{BaseResponse, Response};
use super::session::Session;
use futures::FutureExt;

/// Not Found Handler
///
/// Handling a non-existent route request.
#[async_route]
pub fn not_found(mut request: OblivionRequest) -> Response {
Ok(BaseResponse::TextResponse(
format!(
"Path {} is not found, error with code 404.",
request.get_olps()
),
404,
))
pub fn not_found(session: &mut Session) -> Response {
let olps = session.request.as_mut().unwrap().get_ip();
async move {
Ok(BaseResponse::TextResponse(
format!("Path {} is not found, error with code 404.", olps),
404,
))
}
.boxed()
}
2 changes: 1 addition & 1 deletion src/models/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ pub mod packet;
pub mod render;
pub mod router;
pub mod server;
// pub mod session;
pub mod session;
Loading

0 comments on commit 7ff6de2

Please sign in to comment.