diff --git a/.gitignore b/.gitignore index e827136..4b20cc7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ files/ -received/ \ No newline at end of file +received/ + +# Added by cargo + +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..af3045b --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,82 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "itransfer" +version = "0.1.0" +dependencies = [ + "bincode", + "byteorder", + "serde", +] + +[[package]] +name = "proc-macro2" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.163" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.163" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..7ed66c9 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "itransfer" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +bincode = "1.3.3" +serde = { version = "1.0.163", features = ["derive"] } +byteorder = "1.4.3" + diff --git a/client.py b/client.py index db94711..4a074ba 100644 --- a/client.py +++ b/client.py @@ -25,11 +25,11 @@ UDPClientSocket.sendto(str.encode(message), serverAddressPort) msgFromServer = UDPClientSocket.recvfrom(max_frame_payload)[0] -msg = struct.unpack(f'!LH{len(message)}s', msgFromServer) +msg = struct.unpack(f'!IHQ', msgFromServer) last_packet_size = msg[1] -if msg[2] != str.encode(message): +if msg[2] != sum(byte for byte in message.encode('utf-8')): print('Server error: wrong file name') exit() diff --git a/generate_data.py b/generate_data.py index 2281e1b..166acca 100644 --- a/generate_data.py +++ b/generate_data.py @@ -1,6 +1,6 @@ import secrets -rndsize = 488*50_000 +rndsize = 488*2 rndbytes = secrets.token_bytes(rndsize) diff --git a/server.py b/server.py index a0794e7..e3fda9f 100644 --- a/server.py +++ b/server.py @@ -24,8 +24,10 @@ while True: ready = select.select([UDPServerSocket], [], [], 0.1) if ready[0]: - - bytesAddressPair = UDPServerSocket.recvfrom(max_frame_payload) + try: + bytesAddressPair = UDPServerSocket.recvfrom(max_frame_payload) + except: + continue message = bytesAddressPair[0] @@ -70,23 +72,28 @@ while True: if last_packet_size == 0: last_packet_size = max_payload # if last packet is full, set size to max #print(max_payload,last_packet_size) + + filename_checksum = sum(message) - tosend = struct.pack(f'!LH{len(message.decode())}s', file_len, last_packet_size, message) + tosend = struct.pack(f'!IHQ', file_len, last_packet_size, filename_checksum) UDPServerSocket.sendto(tosend, address) sha512 = hashlib.sha512() - with open(filename, 'rb') as f: - for i in range(file_len): - fdata = f.read(max_payload) - sha512.update(fdata) - #if i == 5: #simulate lost packet - # continue - checksum = hashlib.sha3_512(fdata).digest()[:16] - data = struct.pack(f"{header}{max_payload}s", i, checksum, fdata) - #print("sending data",fdata) - UDPServerSocket.sendto(data, address) - print(f'{i+1}/{file_len}', end='\r') - UDPServerSocket.sendto(struct.pack("64s", sha512.digest()), address) + try: + with open(filename, 'rb') as f: + for i in range(file_len): + fdata = f.read(max_payload) + sha512.update(fdata) + #if i == 5: #simulate lost packet + # continue + checksum = hashlib.sha3_512(fdata).digest()[:16] + data = struct.pack(f"{header}{max_payload}s", i, checksum, fdata) + #print("sending data",fdata) + UDPServerSocket.sendto(data, address) + print(f'{i+1}/{file_len}', end='\r') + UDPServerSocket.sendto(struct.pack("64s", sha512.digest()), address) + except: + pass print(' '*100,end='\r') \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..fe94194 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,101 @@ +use bincode::{self, Error, options, Options}; +use std::net::{UdpSocket, SocketAddr}; +use serde::{Serialize, Deserialize}; + +const MAX_FRAME_PAYLOAD:u16=508; +const MAX_FRAME_PAYLOAD_U:usize=MAX_FRAME_PAYLOAD as usize; +const HEADER_SIZE:u16 = 20; +const MAX_PAYLOAD:u16 = MAX_FRAME_PAYLOAD - HEADER_SIZE; +const MAX_PAYLOAD_U:usize = MAX_PAYLOAD as usize; + +#[derive(Serialize, Deserialize)] +struct PacketInformation { + packet_numbers: u32, //4 bytes + last_packet_size: u16, //2 bytes + response_filename_checksum: u64, //8 bytes +} //14 bytes + +struct packet { + packet_number: u32, //4 bytes + payload_hash: u128, //16 bytes + payload: [u8; MAX_PAYLOAD_U], //508 bytes +} //512 bytes + +fn main() { + + let timeout = 1; + let server_ip = "213.47.107.152:1337"; + + let filename = "data.bin"; + + let local_addr: SocketAddr = "0.0.0.0:26000".parse().expect("Failed to parse address"); + let socket = UdpSocket::bind(local_addr).expect("Failed to bind socket"); + + socket.set_read_timeout(Some(std::time::Duration::new(timeout, 0))).expect("set_read_timeout call failed"); + //socket.set_nonblocking(true).expect("set_nonblocking call failed"); + + let server_addr: SocketAddr = server_ip.parse().expect("Failed to parse address"); + let message = filename; + let sum: u64 = filename.bytes().map(|b| b as u64).sum(); + socket.send_to(message.as_bytes(), server_addr).expect("Failed to send data"); + + // Receive data + let mut buffer = [0u8; MAX_FRAME_PAYLOAD_U]; + let (received_bytes, remote_addr) = socket.recv_from(&mut buffer).expect("Failed to receive data"); + + let filled_buffer = &buffer[..received_bytes]; + + //print the filled buffer + println!("Received data: {:?} {}", filled_buffer, filled_buffer.len()); + + if remote_addr != server_addr { + panic!("Received data from unknown address"); + } + + let options = options().with_big_endian().allow_trailing_bytes().with_fixint_encoding(); + + let packet_info_result: Result = options.deserialize(filled_buffer); + let packet_info: PacketInformation; + match packet_info_result { + Ok(packet) => { + println!("Packets to receive: {}", packet.packet_numbers); + println!("Last packet size: {}", packet.last_packet_size); + println!("Response filename checksum: {}", packet.response_filename_checksum); + //check checksum with sum + if packet.response_filename_checksum != sum { + panic!("Filename Checksums do not match, correct checksum: {}", sum); + } + + packet_info = packet; + } + Err(err) => { + panic!("Failed to deserialize data: {}", err); + } + } + + //create vector to store the packets + let mut packets: Vec = Vec::new(); + for _ in 0..packet_info.packet_numbers { + packets.push(0); + } + + let received_packets = 0; + + //receive the packets + while received_packets < packet_info.packet_numbers { + let mut buffer = [0u8; MAX_PAYLOAD_U]; + let (received_bytes, remote_addr) = socket.recv_from(&mut buffer).expect("Failed to receive data"); + + let filled_buffer = &buffer[..received_bytes]; + + //print the filled buffer + println!("Received data: {:?} {}", filled_buffer, filled_buffer.len()); + + if remote_addr != server_addr { + panic!("Received data from unknown address"); + } + + + } + +}