use crate::types::{Callback, Metadata};
use std::collections::HashMap;
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::net::{TcpListener, TcpStream};
use std::str;
use std::sync::mpsc::{self, channel, Sender};
use std::sync::Arc;
use std::sync::RwLock;
use std::thread;
pub struct TcpServer<'a> {
metadata: &'a Arc<RwLock<Vec<Metadata>>>,
waiting_list: HashMap<String, String>,
}
impl<'a> TcpServer<'a> {
pub fn new(metadata: &'a Arc<RwLock<Vec<Metadata>>>) -> TcpServer<'a> {
TcpServer {
metadata,
waiting_list: HashMap::new(),
}
}
pub fn listen(&mut self, tx: Sender<Metadata>) -> Result<(), std::io::Error> {
println!("TCP Listening...");
let listener = TcpListener::bind("0.0.0.0:7878").unwrap();
for stream in listener.incoming() {
let mut op = [0 as u8; 1];
let mut stream = stream.unwrap();
stream.read(&mut op).unwrap();
match op[0] {
0u8 => {
self.handle_metadata(&mut stream);
}
1u8 => {
let tx_pipe = mpsc::Sender::clone(&tx);
thread::spawn(move || {
let meta = TcpServer::handle_file(&mut stream);
match tx_pipe.send(meta) {
Ok(_) => println!("Received"),
Err(err) => println!("Erro: {}", err),
}
});
}
_ => println!("No op setted in the packet"),
}
}
Ok(())
}
fn handle_metadata(&mut self, stream: &mut TcpStream) {
let mut buf = [0 as u8; 1024];
stream.read(&mut buf).unwrap();
let eos = buf.iter().position(|&r| r == 0).unwrap();
let json = String::from_utf8_lossy(&buf[..eos]);
let incoming_metadata: Vec<Metadata> = serde_json::from_str(&json).unwrap();
let requested_files = self.pick_files(&incoming_metadata);
stream.write(requested_files.as_bytes()).unwrap();
stream.flush().unwrap();
}
fn pick_files(&mut self, incoming_metadata: &Vec<Metadata>) -> String {
let mut requested_files: Vec<&Metadata> = Vec::new();
let metadata = self.metadata.read().unwrap();
println!("META SNAPSHOT: {:?}", metadata);
match metadata.len() {
0 => {
println!("The metada file is empty");
serde_json::to_string(&incoming_metadata).unwrap()
}
_ => {
for incoming_file in incoming_metadata {
let mut found = false;
for meta in metadata.iter() {
println!("Files to pick: {:?}, {:?}", incoming_file.hash, meta.hash);
if incoming_file.hash == meta.hash {
found = true;
}
}
if !found {
self.waiting_list.insert(
incoming_file.hash.to_owned(),
incoming_file.name_extension.to_owned(),
);
requested_files.push(incoming_file);
}
}
serde_json::to_string(&requested_files).unwrap()
}
}
}
fn handle_file(stream: &mut TcpStream) -> Metadata {
let meta_offset = 72;
let mut buf = [0 as u8; 72];
stream.read(&mut buf).unwrap();
let metabuf = &buf[0..meta_offset];
let metadata = TcpServer::get_metadata(&metabuf);
let mut file = File::create(&metadata.name_extension).unwrap();
println!("Writing the file to the disk");
io::copy(stream, &mut file).unwrap();
metadata
}
fn get_metadata(metabuf: &[u8]) -> Metadata {
let eoh = metabuf.iter().position(|&r| r == 0).unwrap();
let name = String::from_utf8_lossy(&metabuf[..eoh]);
let split = name.split(":");
let data: Vec<&str> = split.collect();
let hash = data[0].to_string();
let name = data[1].to_string();
let extension = data[2].to_string();
let name_extension = format!("{}.{}", name, extension);
Metadata {
name,
extension,
name_extension,
size: 0,
hash,
}
}
fn check_hash() {}
}