Merge branch 'channel-structure' of https://github.com/mitch161/rust-chat-server into channel-structure
This commit is contained in:
commit
d34c9580bd
|
|
@ -15,6 +15,7 @@ crossbeam-utils = "0.7"
|
||||||
crossbeam-queue = "0.2"
|
crossbeam-queue = "0.2"
|
||||||
dashmap = "3.11.4"
|
dashmap = "3.11.4"
|
||||||
async-std = "1.6.2"
|
async-std = "1.6.2"
|
||||||
|
lazy_static = "1.4.0"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
opt-level = 0
|
opt-level = 0
|
||||||
|
|
|
||||||
25
src/main.rs
25
src/main.rs
|
|
@ -1,18 +1,23 @@
|
||||||
|
#[macro_use]
|
||||||
|
extern crate lazy_static;
|
||||||
|
|
||||||
mod server;
|
mod server;
|
||||||
// mod server_v2;
|
|
||||||
|
|
||||||
use crate::server::client::client_profile::Client;
|
|
||||||
use crate::server::server_profile::Server;
|
use crate::server::server_profile::Server;
|
||||||
use std::net::{TcpStream, TcpListener};
|
|
||||||
use rust_chat_server::ThreadPool;
|
|
||||||
use std::sync::{Arc, Barrier, Mutex};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
fn main(){
|
fn main(){
|
||||||
|
lazy_static!{
|
||||||
|
static ref server_name: &'static str = "Server-01";
|
||||||
|
static ref server_address: &'static str = "0.0.0.0:6000";
|
||||||
|
static ref server_author: &'static str = "noreply@email.com";
|
||||||
|
static ref SERVER: Server<'static> = Server::new(&server_name, &server_address, &server_author);
|
||||||
|
}
|
||||||
|
/*
|
||||||
let server_name = String::from("Server-01");
|
let server_name = String::from("Server-01");
|
||||||
let server_address = String::from("0.0.0.0:6000");
|
let server_address = String::from("0.0.0.0:6000");
|
||||||
let server_owner = String::from("noreply@email.com");
|
let server_author = String::from("noreply@email.com");
|
||||||
|
*/
|
||||||
|
|
||||||
let server = Server::new(&server_name, &server_address, &server_owner);
|
//let server = Server::new(server_name, server_address, server_author);
|
||||||
server.start();
|
SERVER.start();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,28 +6,27 @@ use crate::server::commands::{Commands};
|
||||||
use std::net::{Shutdown, TcpStream};
|
use std::net::{Shutdown, TcpStream};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use parking_lot::FairMutex;
|
use parking_lot::FairMutex;
|
||||||
use std::collections::HashMap;
|
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use crossbeam::{channel, Sender, Receiver, TryRecvError};
|
use crossbeam::{Sender, Receiver, TryRecvError};
|
||||||
use crossbeam_channel::unbounded;
|
use crossbeam_channel::unbounded;
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Client<'client_lifetime> {
|
pub struct Client<'a> {
|
||||||
connected: bool,
|
connected: bool,
|
||||||
stream: Arc<TcpStream>,
|
stream: Arc<TcpStream>,
|
||||||
uuid: String,
|
uuid: String,
|
||||||
username: String,
|
username: String,
|
||||||
address: String,
|
address: String,
|
||||||
server: &'client_lifetime Server<'client_lifetime>,
|
server: &'a Server<'a>,
|
||||||
tx_channel: Sender<Commands>,
|
tx_channel: Sender<Commands>,
|
||||||
rx_channel: Receiver<Commands>,
|
rx_channel: Receiver<Commands>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Client<'a> {
|
impl<'a> Client<'a> {
|
||||||
pub fn new(server: &'a Server<'a>, stream: Arc<TcpStream>, uuid: &String, username: &String, address: &String) -> Client<'a>{
|
pub fn new(server: &'a Server<'static>, stream: Arc<TcpStream>, uuid: &String, username: &String, address: &String) -> Self{
|
||||||
let (tx_channel, rx_channel): (Sender<Commands>, Receiver<Commands>) = unbounded();
|
let (tx_channel, rx_channel): (Sender<Commands>, Receiver<Commands>) = unbounded();
|
||||||
|
|
||||||
Client {
|
Client {
|
||||||
|
|
@ -84,7 +83,7 @@ impl<'a> Client<'a> {
|
||||||
Commands::Client(Some(params)) => {
|
Commands::Client(Some(params)) => {
|
||||||
self.transmit_data(a.to_string().as_str());
|
self.transmit_data(a.to_string().as_str());
|
||||||
|
|
||||||
let command = Commands::from(&buffer);
|
/*let command = Commands::from(&buffer);
|
||||||
match command{
|
match command{
|
||||||
Commands::Success(None) => {
|
Commands::Success(None) => {
|
||||||
println!("sucess confirmed");
|
println!("sucess confirmed");
|
||||||
|
|
@ -94,6 +93,7 @@ impl<'a> Client<'a> {
|
||||||
self.transmit_data(error.to_string().as_str());
|
self.transmit_data(error.to_string().as_str());
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
},
|
},
|
||||||
Commands::Success(data) => {},
|
Commands::Success(data) => {},
|
||||||
_ => {},
|
_ => {},
|
||||||
|
|
@ -113,7 +113,8 @@ impl<'a> Client<'a> {
|
||||||
let command = Commands::from(incoming_message.clone());
|
let command = Commands::from(incoming_message.clone());
|
||||||
|
|
||||||
println!("Request: {}", &incoming_message);
|
println!("Request: {}", &incoming_message);
|
||||||
|
|
||||||
|
/*command behaviour*/
|
||||||
match command {
|
match command {
|
||||||
Commands::Connect(Some(params)) => todo!(),
|
Commands::Connect(Some(params)) => todo!(),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::server::client::client_profile::Client;
|
/*use crate::server::client::client_profile::Client;
|
||||||
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
@ -26,4 +26,4 @@ pub fn get_client_data(clients_ref: &Arc<Mutex<HashMap<String, Client>>>, data:
|
||||||
},
|
},
|
||||||
None => String::from("client not online"),
|
None => String::from("client not online"),
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::server::client::client_profile::Client;
|
/*use crate::server::client::client_profile::Client;
|
||||||
|
|
||||||
pub fn format_client_data(uuid: &String, client: &Client) -> String{
|
pub fn format_client_data(uuid: &String, client: &Client) -> String{
|
||||||
["!client: username:",client.get_username(), " uuid:", uuid, " host:\"", client.get_address(), "\""].concat()
|
["!client: username:",client.get_username(), " uuid:", uuid, " host:\"", client.get_address(), "\""].concat()
|
||||||
}
|
}*/
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::server::client::client_profile::Client;
|
/*use crate::server::client::client_profile::Client;
|
||||||
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
@ -10,3 +10,4 @@ pub fn add_client(clients_ref: &Arc<Mutex<HashMap<String, Client>>>, client: &Cl
|
||||||
let uuid = client.get_uuid().to_string();
|
let uuid = client.get_uuid().to_string();
|
||||||
//clients_hashmap.insert(uuid, client.clone());
|
//clients_hashmap.insert(uuid, client.clone());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::server::client::client_profile::Client;
|
/*use crate::server::client::client_profile::Client;
|
||||||
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
@ -7,4 +7,4 @@ use std::collections::HashMap;
|
||||||
pub fn remove_client(clients_ref: &Arc<Mutex<HashMap<String, Client>>>, client: &Client){
|
pub fn remove_client(clients_ref: &Arc<Mutex<HashMap<String, Client>>>, client: &Client){
|
||||||
let mut clients_hashmap = clients_ref.lock().unwrap();
|
let mut clients_hashmap = clients_ref.lock().unwrap();
|
||||||
clients_hashmap.remove(client.get_uuid()).unwrap();
|
clients_hashmap.remove(client.get_uuid()).unwrap();
|
||||||
}
|
}*/
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,7 @@ mod client;
|
||||||
mod test;
|
mod test;
|
||||||
mod message;
|
mod message;
|
||||||
|
|
||||||
use crate::server::client::client_profile::Client;
|
|
||||||
use crate::server::server_profile::Server;
|
|
||||||
|
|
||||||
use std::string::ToString;
|
use std::string::ToString;
|
||||||
|
|
||||||
use parking_lot::FairMutex;
|
|
||||||
use std::sync::Mutex;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
|
|
@ -136,11 +129,13 @@ impl ToString for Commands {
|
||||||
let mut out_string = String::new();
|
let mut out_string = String::new();
|
||||||
|
|
||||||
let (command, parameters) = match self {
|
let (command, parameters) = match self {
|
||||||
|
Commands::Request(arguments) => { ("!request:", arguments) },
|
||||||
Commands::Info(arguments) => { ("!info:", arguments) },
|
Commands::Info(arguments) => { ("!info:", arguments) },
|
||||||
Commands::Connect(arguments) => { ("!connect:", arguments) },
|
Commands::Connect(arguments) => { ("!connect:", arguments) },
|
||||||
Commands::Disconnect(arguments) => { ("!disconnect:", arguments) },
|
Commands::Disconnect(arguments) => { ("!disconnect:", arguments) },
|
||||||
Commands::ClientUpdate(arguments) => { ("!clientUpdate:", arguments) },
|
Commands::ClientUpdate(arguments) => { ("!clientUpdate:", arguments) },
|
||||||
Commands::ClientInfo(arguments) => { ("!clientInfo:", arguments) },
|
Commands::ClientInfo(arguments) => { ("!clientInfo:", arguments) },
|
||||||
|
Commands::Client(arguments) => { ("!client:", arguments) },
|
||||||
Commands::Error(arguments) => { ("!error:", arguments) },
|
Commands::Error(arguments) => { ("!error:", arguments) },
|
||||||
_ => { ("!error:", &None) }
|
_ => { ("!error:", &None) }
|
||||||
};
|
};
|
||||||
|
|
@ -236,4 +231,4 @@ mod test_commands_v2 {
|
||||||
|
|
||||||
println!("{:?}", command.to_string())
|
println!("{:?}", command.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,41 +4,40 @@ use crate::server::client::client_profile::Client;
|
||||||
use crate::server::commands::{Commands};
|
use crate::server::commands::{Commands};
|
||||||
|
|
||||||
use rust_chat_server::ThreadPool;
|
use rust_chat_server::ThreadPool;
|
||||||
use std::collections::VecDeque;
|
|
||||||
use std::net::{TcpStream, TcpListener};
|
use std::net::{TcpStream, TcpListener};
|
||||||
use std::sync::{Arc, Barrier, Mutex };
|
use std::sync::{Arc, Mutex};
|
||||||
use crossbeam_channel::{unbounded, Sender, Receiver};
|
use crossbeam_channel::Sender;
|
||||||
use parking_lot::FairMutex;
|
use parking_lot::FairMutex;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
pub struct Server<'server_lifetime> {
|
pub struct Server<'z> {
|
||||||
name: String,
|
name: &'z str,
|
||||||
address: String,
|
address: &'z str,
|
||||||
author: String,
|
author: &'z str,
|
||||||
connected_clients: Arc<Mutex<HashMap<String,&'server_lifetime Client<'server_lifetime>>>>,
|
connected_clients: Arc<Mutex<HashMap<String, Sender<Commands>>>>,
|
||||||
thread_pool: ThreadPool,
|
thread_pool: ThreadPool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - server implemetation
|
// MARK: - server implemetation
|
||||||
impl<'server_lifetime> Server<'server_lifetime> {
|
impl<'z> Server<'z> {
|
||||||
pub fn new(name: &String, address: &String, author: &String) -> Server<'server_lifetime> {
|
pub fn new(name: &'z str, address: &'z str, author: &'z str) -> Self {
|
||||||
Server{
|
Self {
|
||||||
name: name.to_string(),
|
name: name,
|
||||||
address: address.to_string(),
|
address: address,
|
||||||
author: author.to_string(),
|
author: author,
|
||||||
connected_clients: Arc::new(Mutex::new(HashMap::new())),
|
connected_clients: Arc::new(Mutex::new(HashMap::new())),
|
||||||
thread_pool: ThreadPool::new(16)
|
thread_pool: ThreadPool::new(16),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_address(&self) -> &String{
|
pub fn get_address(&self) -> String{
|
||||||
&self.address
|
self.address.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(&'server_lifetime self) {
|
pub fn start(&'static self) {
|
||||||
let listener = TcpListener::bind(self.get_address()).unwrap();
|
let listener = TcpListener::bind(self.get_address()).unwrap();
|
||||||
let mut buffer = [0; 1024];
|
let mut buffer = [0; 1024];
|
||||||
|
|
||||||
|
|
@ -47,8 +46,8 @@ impl<'server_lifetime> Server<'server_lifetime> {
|
||||||
println!("Server: new connection, {}", addr);
|
println!("Server: new connection, {}", addr);
|
||||||
|
|
||||||
let request = Commands::Request(None);
|
let request = Commands::Request(None);
|
||||||
request.to_string();
|
//request.to_string();
|
||||||
self.transmit_data(&stream, &*request.to_string().as_str());
|
self.transmit_data(&stream, &request.to_string().as_str());
|
||||||
|
|
||||||
stream.read(&mut buffer).unwrap();
|
stream.read(&mut buffer).unwrap();
|
||||||
|
|
||||||
|
|
@ -64,22 +63,22 @@ impl<'server_lifetime> Server<'server_lifetime> {
|
||||||
let mut client = Client::new(self, stream, &uuid, &username, &address);
|
let mut client = Client::new(self, stream, &uuid, &username, &address);
|
||||||
|
|
||||||
let mut clients_hashmap = self.connected_clients.lock().unwrap();
|
let mut clients_hashmap = self.connected_clients.lock().unwrap();
|
||||||
|
clients_hashmap.insert(uuid.to_string(), client.get_transmitter().clone());
|
||||||
clients_hashmap.insert(uuid.to_string(), &client);
|
std::mem::drop(clients_hashmap);
|
||||||
|
|
||||||
self.thread_pool.execute(move || {
|
self.thread_pool.execute(move || {
|
||||||
client.handle_connection();
|
client.handle_connection();
|
||||||
});
|
});
|
||||||
|
|
||||||
let params: HashMap<String, String> = [(String::from("name"), username.clone()), (String::from("host"), address.clone()), (String::from("uuid"), uuid.clone())];
|
let params: HashMap<String, String> = [(String::from("name"), username.clone()), (String::from("host"), address.clone()), (String::from("uuid"), uuid.clone())].iter().cloned().collect();
|
||||||
let new_client = Commands::Client(Some(params));
|
let new_client = Commands::Client(Some(params));
|
||||||
|
|
||||||
self.update_all_clients(new_client);
|
self.update_all_clients(new_client);
|
||||||
},
|
},
|
||||||
Commands::Info(None) => {
|
Commands::Info(None) => {
|
||||||
let mut params: HashMap<String, String> = HashMap::new();
|
let mut params: HashMap<String, String> = HashMap::new();
|
||||||
params.insert(String::from("name"), self.name.clone());
|
params.insert(String::from("name"), self.name.to_string().clone());
|
||||||
params.insert(String::from("owner"), self.author.clone());
|
params.insert(String::from("owner"), self.author.to_string().clone());
|
||||||
|
|
||||||
let command = Commands::Info(Some(params));
|
let command = Commands::Info(Some(params));
|
||||||
|
|
||||||
|
|
@ -90,14 +89,14 @@ impl<'server_lifetime> Server<'server_lifetime> {
|
||||||
self.transmit_data(&stream, Commands::Error(None).to_string().as_str());
|
self.transmit_data(&stream, Commands::Error(None).to_string().as_str());
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_info(&self, tx: Sender<Commands>) {
|
pub fn get_info(&self, tx: Sender<Commands>) {
|
||||||
let mut params: HashMap<String, String> = HashMap::new();
|
let mut params: HashMap<String, String> = HashMap::new();
|
||||||
params.insert(String::from("name"), self.name.clone());
|
params.insert(String::from("name"), self.name.to_string().clone());
|
||||||
params.insert(String::from("owner"), self.author.clone());
|
params.insert(String::from("owner"), self.author.to_string().clone());
|
||||||
|
|
||||||
let command = Commands::Info(Some(params));
|
let command = Commands::Info(Some(params));
|
||||||
tx.send(command).unwrap();
|
tx.send(command).unwrap();
|
||||||
|
|
@ -105,8 +104,7 @@ impl<'server_lifetime> Server<'server_lifetime> {
|
||||||
|
|
||||||
pub fn update_all_clients(&self, command: Commands){
|
pub fn update_all_clients(&self, command: Commands){
|
||||||
let clients = self.connected_clients.lock().unwrap();
|
let clients = self.connected_clients.lock().unwrap();
|
||||||
for client in clients.values(){
|
for tx in clients.values(){
|
||||||
let tx = client.get_transmitter();
|
|
||||||
tx.send(command.clone()).unwrap();
|
tx.send(command.clone()).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -115,6 +113,11 @@ impl<'server_lifetime> Server<'server_lifetime> {
|
||||||
println!("Transmitting...");
|
println!("Transmitting...");
|
||||||
println!("data: {}",data);
|
println!("data: {}",data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This will throw an error and crash any thread, including the main thread, if
|
||||||
|
* the connection is lost before transmitting. Maybe change to handle any exceptions
|
||||||
|
* that may occur.
|
||||||
|
*/
|
||||||
stream.write(data.to_string().as_bytes()).unwrap();
|
stream.write(data.to_string().as_bytes()).unwrap();
|
||||||
stream.flush().unwrap();
|
stream.flush().unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue