use bytes::Bytes; use getrandom::Error; use crate::NetworkEvent; use crate::P2PSharedData; use crate::cryptographic_signature::{CryptographicSignature, formatPubKey, sign_message}; use crate::message_handling::EventType; use crate::messages_channels::{Message, MultipleSenders}; use crate::messages_structure::construct_message; use crate::server_communication::generate_id; use crossbeam_channel::{Receiver, Sender}; use std::collections::HashMap; use std::net::SocketAddr; use std::net::UdpSocket; use std::str::FromStr; use std::sync::{Arc, Mutex}; /// /// sends the cryptographic signature to the server using a PUT request over the HTTP API. /// pub async fn register_with_the_server( crypto_pair: &Arc, server_uri: &String, ) -> Result<(), reqwest::Error> { let client = reqwest::Client::new(); let uri = format!("{0}/peers/{1}/key", server_uri, crypto_pair.username); let encoded_point = crypto_pair.pub_key.to_encoded_point(false); let pubkey_bytes = encoded_point.as_ref().to_vec(); let pubkey_bytes_minus = pubkey_bytes[1..].to_vec(); let res = client.put(uri).body(pubkey_bytes_minus).send().await?; let res = res.error_for_status()?; println!("register ip adresses"); Ok(()) } /// /// sends a get request to the server to get the socket address of the given peer /// pub async fn get_socket_address(username: String, ip: String) -> Result { let client = reqwest::Client::new(); let uri = format!("{}/peers/{}/addresses", ip, username); let res = client.get(uri).send().await?; if res.status().is_success() { println!("Successfully retreived the addresses."); } else { eprintln!( "Failed to get the peers addresses from the server. Status: {}", res.status() ); } let body: Bytes = res.bytes().await?; Ok(body) } pub fn parse_addresses(input: &String) -> Vec { let mut addrs = Vec::new(); for line in input.lines() { let s = line.trim(); if s.is_empty() { continue; } if let Ok(sock) = SocketAddr::from_str(s) { addrs.push(sock); } } addrs } /// /// registers the IP addresses by sending a Hello request to the server. /// pub async fn perform_handshake( sd: &P2PSharedData, username: String, ip: String, event_tx: Sender, is_server_handshake: bool, ) { println!("username: {}, ip: {}", username.clone(), ip.clone()); let crypto_pair = sd.cryptopair_ref(); let senders = sd.senders_ref(); let messages_list = sd.messages_list_ref(); let id = generate_id(); let server_addr_query = get_socket_address(username.clone(), ip.clone()); match server_addr_query.await { Ok(sockaddr_bytes) => { match String::from_utf8(sockaddr_bytes.to_vec()) { Ok(s) => { let addresses = parse_addresses(&s); if let Some(first) = addresses.first() { sd.set_servername(username); // first: &SocketAddr let mut payload = Vec::new(); payload.extend_from_slice(&0u32.to_be_bytes()); payload.extend_from_slice(&crypto_pair.username.clone().as_bytes()); let hello_handshake = construct_message(1, payload, id, crypto_pair); match hello_handshake { Some(handshake_message) => { senders.send_via( 0, handshake_message, first.to_string(), is_server_handshake, messages_list, ); } None => {} } //let res = event_tx // .send(NetworkEvent::()); } else { //let res = event_tx.send(NetworkEvent::Error()); let err_msg = format!("no valid socket addresses found in: {}", s).to_string(); let res = event_tx.send(NetworkEvent::Error(err_msg)); } } Err(e) => { //let res = event_tx.send(NetworkEvent::Error()); let err_msg = format!("invalid UTF-8 in socket address bytes: {}", e).to_string(); let res = event_tx.send(NetworkEvent::Error(err_msg)); } } } Err(e) => { let err_msg = format!("failed to retreive socket address: {}", e).to_string(); let res = event_tx.send(NetworkEvent::Error(err_msg)); } } /*let mut list = messages_list.lock().expect("Failed to lock messages_list"); match list.get(&id) { Some(_) => { list.remove(&id); } None => { list.insert(id, EventType::ServerHelloReply); } } println!("message sent: {}", &id);*/ // 3. Perform the insertion /*let mut buf = [0u8; 1024]; socket.recv_from(&mut buf).expect("receive failed"); let hello_handshake_received = UDPMessage::parse(buf.to_vec()); hello_handshake_received.display();*/ //TODO } #[cfg(test)] mod tests { // Note this useful idiom: importing names from outer (for mod tests) scope. use super::*; /*/// /// does the procedure to register with the server /// #[tokio::test] async fn registering_with_server() { let username = String::from("gameixtreize"); let server_uri = String::from("https://jch.irif.fr:8443"); let crypto_pair = CryptographicSignature::new(username); if let Err(e) = register_with_the_server(crypto_pair, server_uri).await { eprintln!("Error during registration: {}", e); } }*/ /*/// /// retreives the socket address of a given peer /// #[tokio::test] async fn retreive_socket_addr() { let username = String::from("ipjkndqfshjldfsjlbsdfjhhj"); match get_socket_address(username).await { Ok(body) => { println!("{:?}", body); } Err(e) => { eprintln!("Erreur HTTP: {}", e); } } }*/ }