Skip to content

Commit

Permalink
Standardize
Browse files Browse the repository at this point in the history
  • Loading branch information
WKHAllen committed Aug 17, 2022
1 parent e8df1c9 commit 857a6dc
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 102 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
[package]
name = "rustdtp"
version = "0.3.1"
version = "0.3.2"
authors = ["WKHAllen <[email protected]>"]
license = "MIT"
description = "Asynchronous cross-platform networking interfaces for Rust."
repository = "https://github.com/WKHAllen/rustdtp"
homepage = "https://wkhallen.com/dtp/"
keywords = ["socket", "networking"]
include = ["src/**/*", "LICENSE", "README.md"]
edition = "2021"
Expand Down
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

Asynchronous cross-platform networking interfaces for Rust.

The two fundamental network objects this crate provides are the server and client. When starting a server or connecting via a client, the task will not block while it performs network operations in the background. Upon instantiation, both the server and client return handles that provide a mechanism for communicating with the background task, and instructing it to provide status information or halt network operations.
## Data Transfer Protocol

The Data Transfer Protocol (DTP) is a larger project to make ergonomic network programming available in any language.
See the full project [here](https://wkhallen.com/dtp/).

## Creating a server

Expand All @@ -21,18 +24,18 @@ async fn main() {
match event {
ServerEvent::Connect { client_id } => {
println!("Client with ID {} connected", client_id);
},
}
ServerEvent::Disconnect { client_id } => {
println!("Client with ID {} disconnected", client_id);
},
}
ServerEvent::Receive { client_id, data } => {
// Send back the length of the string
server.send(client_id, data.len()).await.unwrap();
},
}
ServerEvent::Stop => {
// No more events will be sent, and the loop will end
println!("Server closed");
},
}
}
}
}
Expand Down Expand Up @@ -60,11 +63,11 @@ async fn main() {
// Validate the response
println!("Received response from server: {}", data);
assert_eq!(data, msg.len());
},
}
event => {
// Unexpected response
panic!("expected to receive a response from the server, instead got {:?}", event);
},
}
}
}
```
Expand All @@ -75,4 +78,5 @@ Note that in order to iterate over events, the `EventStreamExt` extension trait

## Security

Information security comes included. Every message sent over a network interface is encrypted with AES-256. Key exchanges are performed using a 2048-bit RSA key-pair.
Information security comes included. Every message sent over a network interface is encrypted with AES-256. Key
exchanges are performed using a 2048-bit RSA key-pair.
62 changes: 32 additions & 30 deletions src/client.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
//! The client network interface.
use crate::command_channel::*;
use crate::crypto::*;
use crate::event_stream::*;
use crate::util::*;
use rsa::pkcs8::DecodePublicKey;
use rsa::RsaPublicKey;
use serde::{de::DeserializeOwned, ser::Serialize};
use std::io;
use std::marker::PhantomData;
use std::net::SocketAddr;

use rsa::pkcs8::DecodePublicKey;
use rsa::RsaPublicKey;
use serde::{de::DeserializeOwned, ser::Serialize};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::{TcpStream, ToSocketAddrs};
use tokio::sync::mpsc::channel;
use tokio::task::JoinHandle;

use crate::command_channel::*;
use crate::crypto::*;
use crate::event_stream::*;
use crate::util::*;

/// A command sent from the client handle to the background client task.
pub enum ClientCommand<S>
where
S: Serialize + Send + 'static,
where
S: Serialize + Send + 'static,
{
Disconnect,
Send { data: S },
Expand Down Expand Up @@ -49,36 +51,36 @@ pub enum ClientCommandReturn {
/// match event {
/// ClientEvent::Receive { data } => {
/// println!("Server sent: {}", data);
/// },
/// }
/// ClientEvent::Disconnect => {
/// // No more events will be sent, and the loop will end
/// println!("Client disconnected");
/// },
/// }
/// }
/// }
/// }
/// ```
#[derive(Debug)]
pub enum ClientEvent<R>
where
R: DeserializeOwned + Send + 'static,
where
R: DeserializeOwned + Send + 'static,
{
Receive { data: R },
Disconnect,
}

/// A handle to the client.
pub struct ClientHandle<S>
where
S: Serialize + Send + 'static,
where
S: Serialize + Send + 'static,
{
client_command_sender: CommandChannelSender<ClientCommand<S>, ClientCommandReturn>,
client_task_handle: JoinHandle<io::Result<()>>,
}

impl<S> ClientHandle<S>
where
S: Serialize + Send + 'static,
where
S: Serialize + Send + 'static,
{
/// Disconnect from the server.
///
Expand All @@ -101,8 +103,8 @@ where
/// client.disconnect().await.unwrap();
/// break;
/// }
/// },
/// _ => {}, // Do nothing for other events
/// }
/// _ => {} // Do nothing for other events
/// }
/// }
/// }
Expand Down Expand Up @@ -220,27 +222,27 @@ where
/// // Validate the response
/// println!("Received response from server: {}", data);
/// assert_eq!(data, msg.len());
/// },
/// }
/// event => {
/// // Unexpected response
/// panic!("expected to receive a response from the server, instead got {:?}", event);
/// },
/// }
/// }
/// }
/// ```
pub struct Client<S, R>
where
S: Serialize + Send + 'static,
R: DeserializeOwned + Send + 'static,
where
S: Serialize + Send + 'static,
R: DeserializeOwned + Send + 'static,
{
phantom_send: PhantomData<S>,
phantom_receive: PhantomData<R>,
}

impl<S, R> Client<S, R>
where
S: Serialize + Send + 'static,
R: DeserializeOwned + Send + 'static,
where
S: Serialize + Send + 'static,
R: DeserializeOwned + Send + 'static,
{
/// Connect to a socket server.
///
Expand All @@ -257,8 +259,8 @@ where
/// }
/// ```
pub async fn connect<A>(addr: A) -> io::Result<(ClientHandle<S>, EventStream<ClientEvent<R>>)>
where
A: ToSocketAddrs,
where
A: ToSocketAddrs,
{
// Client TCP stream
let mut stream = TcpStream::connect(addr).await?;
Expand Down Expand Up @@ -489,7 +491,7 @@ where
// Send a disconnect event, ignoring send errors
if let Err(_e) = client_event_sender.send(ClientEvent::Disconnect).await {}

io::Result::Ok(())
Ok(())
};

// Return client loop result
Expand Down
1 change: 1 addition & 0 deletions src/command_channel.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::io;

use tokio::sync::mpsc::{channel, error::SendError, Receiver, Sender};

/// An error associated with a command channel.
Expand Down
2 changes: 1 addition & 1 deletion src/crypto.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use aes_gcm::aead::{Aead, NewAead};
use aes_gcm::{Aes256Gcm, Key, Nonce};
use aes_gcm::aead::{Aead, NewAead};
use rsa::{PaddingScheme, PublicKey, RsaPrivateKey, RsaPublicKey};

/// Generate a pair of RSA keys.
Expand Down
1 change: 1 addition & 0 deletions src/event_stream.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::pin::Pin;
use std::task::{Context, Poll};

use tokio::sync::mpsc::Receiver;
use tokio_stream::Stream;

Expand Down
33 changes: 19 additions & 14 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@
//! match event {
//! ServerEvent::Connect { client_id } => {
//! println!("Client with ID {} connected", client_id);
//! },
//! }
//! ServerEvent::Disconnect { client_id } => {
//! println!("Client with ID {} disconnected", client_id);
//! },
//! }
//! ServerEvent::Receive { client_id, data } => {
//! // Send back the length of the string
//! server.send(client_id, data.len()).await.unwrap();
//! },
//! }
//! ServerEvent::Stop => {
//! // No more events will be sent, and the loop will end
//! println!("Server closed");
//! },
//! }
//! }
//! }
//! }
Expand Down Expand Up @@ -60,11 +60,11 @@
//! // Validate the response
//! println!("Received response from server: {}", data);
//! assert_eq!(data, msg.len());
//! },
//! }
//! event => {
//! // Unexpected response
//! panic!("expected to receive a response from the server, instead got {:?}", event);
//! },
//! }
//! }
//! }
//! ```
Expand All @@ -80,28 +80,33 @@
#![crate_type = "lib"]
#![crate_name = "rustdtp"]

/// Types re-exported from the crate.
pub use tokio_stream::StreamExt as EventStreamExt;

/// Types exported from the crate.
pub use client::{Client, ClientEvent, ClientHandle};
pub use event_stream::EventStream;
pub use server::{Server, ServerEvent, ServerHandle};

mod client;
mod command_channel;
mod crypto;
mod event_stream;
mod server;
mod util;

/// Types exported from the crate.
pub use client::{Client, ClientEvent, ClientHandle};
pub use event_stream::EventStream;
pub use server::{Server, ServerEvent, ServerHandle};
pub use tokio_stream::StreamExt as EventStreamExt;

/// Crate tests.
#[cfg(test)]
mod tests {
use super::*;
use rand;
use std::thread;
use std::time::Duration;

use rand;

use util::*;

use super::*;

/// Default amount of time to sleep, in milliseconds.
const SLEEP_TIME: u64 = 100;
/// Default server address.
Expand Down
Loading

0 comments on commit 857a6dc

Please sign in to comment.