diff --git a/client.cpp b/client.cpp index 232d3c0..30b8143 100644 --- a/client.cpp +++ b/client.cpp @@ -10,7 +10,7 @@ #include #include -#define DIRECTORY_PATH "/Users/rajkumar/Desktop/Snap-Sync/tmp/" +#define DIRECTORY_PATH "test_data/" using namespace std; @@ -31,174 +31,190 @@ class Client { int client_socket; struct sockaddr_in server_addr; - public: - Client(const string& ip_address, int port) { - create_socket(); - setup_server_address(ip_address, port); - connect_to_server(); +public: + Client(const string& ip_address, int port) { + create_socket(); + setup_server_address(ip_address, port); + connect_to_server(); + } + + ~Client() { + close(client_socket); + } + + void run() { + authenticate(); + send_files_in_directory(DIRECTORY_PATH); + } + +private: + void create_socket() { + if ((client_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + perror("Error creating socket"); + exit(EXIT_FAILURE); } + } - ~Client() { + void setup_server_address(const string& ip_address, int port) { + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(port); + if (inet_pton(AF_INET, ip_address.c_str(), &server_addr.sin_addr) <= 0) { + perror("Invalid address/ Address not supported"); close(client_socket); + exit(EXIT_FAILURE); } + } - void run() { - authenticate(); - send_files_in_directory(DIRECTORY_PATH); + void connect_to_server() { + if (connect(client_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { + perror("Error connecting to server"); + close(client_socket); + exit(EXIT_FAILURE); } + } - private: - void create_socket() { - if ((client_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) { - perror("Error creating socket"); - exit(EXIT_FAILURE); - } + void authenticate() { + char token[1024]; + if (recv(client_socket, token, sizeof(token), 0) == -1) { + perror("Error receiving token from server"); + exit(EXIT_FAILURE); } - void setup_server_address(const string& ip_address, int port) { - server_addr.sin_family = AF_INET; - server_addr.sin_port = htons(port); - if (inet_pton(AF_INET, ip_address.c_str(), &server_addr.sin_addr) <= 0) { - perror("Invalid address/ Address not supported"); - close(client_socket); - exit(EXIT_FAILURE); - } - } + cout << "\nToken received from the server: " << token << endl; - void connect_to_server() { - if (connect(client_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { - perror("Error connecting to server"); - close(client_socket); - exit(EXIT_FAILURE); - } - } + string token_string(token); + string token_hash = to_string(fnv1a_hash(token_string)); - void authenticate() { - char token[1024]; - if (recv(client_socket, token, sizeof(token), 0) == -1) { - perror("Error receiving token from server"); - exit(EXIT_FAILURE); - } + if (send(client_socket, token_hash.c_str(), token_hash.size() + 1, 0) == -1) { // include null terminator + perror("Error sending hash to server"); + exit(EXIT_FAILURE); + } - cout << "\nToken received from the server: " << token << endl; + cout << "\nHash sent to the server\n"; + cout << "\nWaiting for the server to authenticate...\n"; - string token_string(token); - string token_hash = to_string(fnv1a_hash(token_string)); + char auth_status[1024] = {0}; + if (recv(client_socket, auth_status, sizeof(auth_status), 0) == -1) { + perror("Error receiving authentication status from server"); + exit(EXIT_FAILURE); + } - if (send(client_socket, token_hash.c_str(), token_hash.size() + 1, 0) == -1) { // include null terminator - perror("Error sending hash to server"); - exit(EXIT_FAILURE); - } + cout << auth_status << endl; - cout << "\nHash sent to the server\n"; - cout << "\nWaiting for the server to authenticate...\n"; + char signal[1024] = {0}; + if (recv(client_socket, signal, sizeof(signal), 0) == -1) { + perror("Error receiving start signal from server"); + exit(EXIT_FAILURE); + } - char auth_status[1024] = {0}; - if (recv(client_socket, auth_status, sizeof(auth_status), 0) == -1) { - perror("Error receiving authentication status from server"); - exit(EXIT_FAILURE); - } + cout << "Server signal: " << signal << endl; + } - cout << auth_status << endl; + bool send_file(const string& filepath) { + ifstream file(filepath, ios::binary); + if (!file) { + perror("Error opening file"); + return false; + } - char signal[1024] = {0}; - if (recv(client_socket, signal, sizeof(signal), 0) == -1) { - perror("Error receiving start signal from server"); - exit(EXIT_FAILURE); - } + // Get the file size + file.seekg(0, ios::end); + size_t filesize = file.tellg(); + file.seekg(0, ios::beg); - cout << "Server signal: " << signal << endl; + // Send the filename + string filename = filepath.substr(filepath.find_last_of("/") + 1); + if (filename.empty()) { + cerr << "Error: Empty filename, skipping file: " << filepath << endl; + return false; } - bool send_file(const string& filepath) { - ifstream file(filepath, ios::binary); - if (!file) { - perror("Error opening file"); - return false; - } + if (send(client_socket, filename.c_str(), filename.size() + 1, 0) == -1) { // include null terminator + perror("Error sending filename to server"); + file.close(); + return false; + } - // Get the file size - file.seekg(0, ios::end); - size_t filesize = file.tellg(); - file.seekg(0, ios::beg); + // Send the file size + if (send(client_socket, &filesize, sizeof(filesize), 0) == -1) { + perror("Error sending file size to server"); + file.close(); + return false; + } - // Send the filename - string filename = filepath.substr(filepath.find_last_of("/") + 1); - if (send(client_socket, filename.c_str(), filename.size() + 1, 0) == -1) { // include null terminator - perror("Error sending filename to server"); + // Send the file data + char buffer[1024]; + while (file.read(buffer, sizeof(buffer))) { + if (send(client_socket, buffer, sizeof(buffer), 0) == -1) { + perror("Error sending file data to server"); file.close(); return false; } - - // Send the file size - if (send(client_socket, &filesize, sizeof(filesize), 0) == -1) { - perror("Error sending file size to server"); + } + if (file.gcount() > 0) { + if (send(client_socket, buffer, file.gcount(), 0) == -1) { + perror("Error sending remaining file data to server"); file.close(); return false; } + } - // Send the file data - char buffer[1024]; - while (file.read(buffer, sizeof(buffer))) { - if (send(client_socket, buffer, sizeof(buffer), 0) == -1) { - perror("Error sending file data to server"); - file.close(); - return false; - } - } - if (file.gcount() > 0) { - if (send(client_socket, buffer, file.gcount(), 0) == -1) { - perror("Error sending remaining file data to server"); - file.close(); - return false; - } - } + file.close(); + return true; + } - file.close(); - return true; + void send_files_in_directory(const string& directory_path) { + DIR* dir; + struct dirent* ent; + if ((dir = opendir(directory_path.c_str())) == NULL) { + perror("Error opening directory"); + send_end_signal(); + exit(EXIT_FAILURE); } - void send_files_in_directory(const string& directory_path) { - DIR* dir; - struct dirent* ent; - if ((dir = opendir(directory_path.c_str())) == NULL) { - perror("Error opening directory"); - exit(EXIT_FAILURE); + bool files_sent = false; + while ((ent = readdir(dir)) != NULL) { + if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { + continue; } - while ((ent = readdir(dir)) != NULL) { - if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { - continue; - } - - string filepath = directory_path + string(ent->d_name); - if (!send_file(filepath)) { - closedir(dir); - exit(EXIT_FAILURE); - } - - cout << "\nFile sent to the server: " << filepath << endl; - - // Wait for confirmation from the server before sending the next file - char confirmation[1024]; - if (recv(client_socket, confirmation, sizeof(confirmation), 0) == -1) { - perror("Error receiving confirmation from server"); - closedir(dir); - exit(EXIT_FAILURE); - } - cout << "Server confirmation: " << confirmation << endl; + string filepath = directory_path + string(ent->d_name); + if (!send_file(filepath)) { + closedir(dir); + send_end_signal(); + exit(EXIT_FAILURE); } - // Send end signal to indicate all files have been sent - string end_signal = "end_of_files"; - if (send(client_socket, end_signal.c_str(), end_signal.size() + 1, 0) == -1) { // include null terminator - perror("Error sending end signal to server"); + cout << "\nFile sent to the server: " << filepath << endl; + + // Wait for confirmation from the server before sending the next file + char confirmation[1024]; + if (recv(client_socket, confirmation, sizeof(confirmation), 0) == -1) { + perror("Error receiving confirmation from server"); + closedir(dir); + send_end_signal(); exit(EXIT_FAILURE); } - cout << "\nAll files sent to the server\n"; + cout << "Server confirmation: " << confirmation << endl; + files_sent = true; + } + + closedir(dir); + if (!files_sent) { + cout << "No files to send.\n"; + } - closedir(dir); + send_end_signal(); + cout << "\nAll files sent to the server\n"; + } + + void send_end_signal() { + string end_signal = "end_of_files"; + if (send(client_socket, end_signal.c_str(), end_signal.size() + 1, 0) == -1) { // include null terminator + perror("Error sending end signal to server"); + exit(EXIT_FAILURE); } + } }; int main() { diff --git a/server.cpp b/server.cpp index c7f0af6..806e742 100644 --- a/server.cpp +++ b/server.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #define TOKEN_LENGTH 256 @@ -23,237 +24,244 @@ class Server { struct sockaddr_in address; int address_length; - public: - Server(int port = 6969) : PORT(port) { - create_socket(); - setup_address(); - bind_socket(); - listen_for_connections(); - register_signal_handler(); +public: + Server(int port = 6969) : PORT(port) { + create_socket(); + setup_address(); + bind_socket(); + listen_for_connections(); + register_signal_handler(); + } + + ~Server() { + close(server_socket); + } + + void run() { + while (true) { + accept_connection(); + handle_client(); } + } - ~Server() { - close(server_socket); +private: + void create_socket() { + if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == 0) { + perror("[ERROR] : Socket creation failed"); + exit(EXIT_FAILURE); } - - void run() { - while (true) { - accept_connection(); - handle_client(); - } + cout << "[LOG] : Socket created successfully.\n"; + } + + void setup_address() { + address.sin_family = AF_INET; + address.sin_addr.s_addr = INADDR_ANY; + address.sin_port = htons(PORT); + address_length = sizeof(address); + } + + void bind_socket() { + if (bind(server_socket, (struct sockaddr *)&address, sizeof(address)) < 0) { + perror("[ERROR] : Bind failed"); + exit(EXIT_FAILURE); } + cout << "[LOG] : Bind successful.\n"; + } - private: - void create_socket() { - if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == 0) { - perror("[ERROR] : Socket creation failed"); - exit(EXIT_FAILURE); - } - cout << "[LOG] : Socket created successfully.\n"; + void listen_for_connections() { + if (listen(server_socket, 3) < 0) { + perror("[ERROR] : Listen failed"); + exit(EXIT_FAILURE); } + cout << "[LOG] : Listening for connections (Max queue: 3)\n"; + } - void setup_address() { - address.sin_family = AF_INET; - address.sin_addr.s_addr = INADDR_ANY; - address.sin_port = htons(PORT); - address_length = sizeof(address); + void accept_connection() { + if ((client_socket = accept(server_socket, (struct sockaddr *)&address, (socklen_t*)&address_length)) < 0) { + perror("[ERROR] : Accept failed"); + exit(EXIT_FAILURE); } + cout << "[LOG] : Connection accepted from client.\n"; + } - void bind_socket() { - if (bind(server_socket, (struct sockaddr *)&address, sizeof(address)) < 0) { - perror("[ERROR] : Bind failed"); - exit(EXIT_FAILURE); - } - cout << "[LOG] : Bind successful.\n"; - } + void handle_client() { + flush_socket_buffer(client_socket); - void listen_for_connections() { - if (listen(server_socket, 3) < 0) { - perror("[ERROR] : Listen failed"); - exit(EXIT_FAILURE); - } - cout << "[LOG] : Listening for connections (Max queue: 3)\n"; - } + string token = generate_random_string(TOKEN_LENGTH); + cout << "Token: " << token << '\n'; - void accept_connection() { - if ((client_socket = accept(server_socket, (struct sockaddr *)&address, (socklen_t*)&address_length)) < 0) { - perror("[ERROR] : Accept failed"); - exit(EXIT_FAILURE); - } - cout << "[LOG] : Connection accepted from client.\n"; + if (send(client_socket, token.c_str(), token.size() + 1, 0) == -1) { // include null terminator + perror("[ERROR] : Sending token to client failed"); + close(client_socket); + return; } + cout << "[LOG] : Token sent to client. Waiting for hash...\n"; - void handle_client() { - flush_socket_buffer(client_socket); - - string token = generate_random_string(TOKEN_LENGTH); - cout << "Token: " << token << '\n'; - - if (send(client_socket, token.c_str(), token.size() + 1, 0) == -1) { - perror("[ERROR] : Sending token to client failed"); - close(client_socket); - return; - } - cout << "[LOG] : Token sent to client. Waiting for hash...\n"; - - flush_socket_buffer(client_socket); + flush_socket_buffer(client_socket); - string expected_hash = to_string(fnv1a_hash(token)); - char received_hash[1024] = {0}; - if (recv(client_socket, received_hash, sizeof(received_hash), 0) == -1) { - perror("[ERROR] : Receiving hash from client failed"); - close(client_socket); - return; - } - cout << "[LOG] : Hash received from client. Checking hash...\n"; + string expected_hash = to_string(fnv1a_hash(token)); + char received_hash[1024] = {0}; + if (recv(client_socket, received_hash, sizeof(received_hash), 0) == -1) { + perror("[ERROR] : Receiving hash from client failed"); + close(client_socket); + return; + } + cout << "[LOG] : Hash received from client. Checking hash...\n"; - if (authenticate_client(string(received_hash), expected_hash)) { - cout << "[LOG] : Hash verified!\n"; - send_message("Authentication successful\n"); + if (authenticate_client(string(received_hash), expected_hash)) { + cout << "[LOG] : Hash verified!\n"; + send_message("Authentication successful\n"); - string folder_name = create_timestamped_folder(); - if (!folder_name.empty()) { - cout << "[LOG] : Folder created successfully.\n"; - send_message("start"); + string folder_name = create_timestamped_folder(); + if (!folder_name.empty()) { + cout << "[LOG] : Folder created successfully.\n"; + send_message("start"); - receive_files(folder_name); - } else { - cout << "[ERROR] : Folder creation failed.\n"; - } + receive_files(folder_name); } else { - cout << "[LOG] : Hash verification failed!\n"; + cout << "[ERROR] : Folder creation failed.\n"; } - - close(client_socket); + } else { + cout << "[LOG] : Hash verification failed!\n"; } - void flush_socket_buffer(int socket) { - char buffer[1024]; - int bytes_available = 0; + close(client_socket); + } - if (ioctl(socket, FIONREAD, &bytes_available) == -1) { - perror("[ERROR] : Checking socket buffer failed"); - return; - } + void flush_socket_buffer(int socket) { + char buffer[1024]; + int bytes_available = 0; - while (bytes_available > 0) { - ssize_t bytes_received = recv(socket, buffer, sizeof(buffer), 0); - if (bytes_received <= 0) { - break; - } - bytes_available -= bytes_received; + if (ioctl(socket, FIONREAD, &bytes_available) == -1) { + perror("[ERROR] : Checking socket buffer failed"); + return; + } + + while (bytes_available > 0) { + ssize_t bytes_received = recv(socket, buffer, sizeof(buffer), 0); + if (bytes_received <= 0) { + break; } + bytes_available -= bytes_received; } + } - string generate_random_string(size_t length) { - const string characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_=+[]{}|;:',.<>?/~`"; - random_device rd; - mt19937 generator(rd()); - uniform_int_distribution<> distribution(0, characters.size() - 1); + string generate_random_string(size_t length) { + const string characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_=+[]{}|;:',.<>?/~`"; + random_device rd; + mt19937 generator(rd()); + uniform_int_distribution<> distribution(0, characters.size() - 1); - string random_string; - for (size_t i = 0; i < length; ++i) { - random_string += characters[distribution(generator)]; - } - return random_string; + string random_string; + for (size_t i = 0; i < length; ++i) { + random_string += characters[distribution(generator)]; } + return random_string; + } - size_t fnv1a_hash(const string& str) { - const size_t FNV_offset_basis = 14695981039346656037ULL; - const size_t FNV_prime = 1099511628211ULL; + size_t fnv1a_hash(const string& str) { + const size_t FNV_offset_basis = 14695981039346656037ULL; + const size_t FNV_prime = 1099511628211ULL; - size_t hash = FNV_offset_basis; - for (char c : str) { - hash ^= static_cast(c); - hash *= FNV_prime; - } - return hash; + size_t hash = FNV_offset_basis; + for (char c : str) { + hash ^= static_cast(c); + hash *= FNV_prime; } + return hash; + } + + bool authenticate_client(const string& received_hash, const string& expected_hash) { + return received_hash == expected_hash; + } - bool authenticate_client(const string& received_hash, const string& expected_hash) { - return received_hash == expected_hash; + bool create_folder(const string& folder_name) { + if (mkdir(folder_name.c_str(), 0755) == -1) { + perror("[ERROR] : Creating folder failed"); + return false; } + return true; + } + + string create_timestamped_folder() { + time_t now = time(0); + tm *ltm = localtime(&now); + string folder_name = to_string(1900 + ltm->tm_year) + "-" + + to_string(1 + ltm->tm_mon) + "-" + + to_string(ltm->tm_mday) + "_" + + to_string(ltm->tm_hour) + "-" + + to_string(ltm->tm_min) + "-" + + to_string(ltm->tm_sec); + return create_folder(folder_name) ? folder_name : ""; + } + + void receive_files(const string& folder_name) { + while (true) { + flush_socket_buffer(client_socket); - bool create_folder(const string& folder_name) { - if (mkdir(folder_name.c_str(), 0755) == -1) { - perror("[ERROR] : Creating folder failed"); - return false; + char filename[1024] = {0}; + if (recv(client_socket, filename, sizeof(filename), 0) == -1) { + perror("[ERROR] : Receiving filename from client failed"); + return; } - return true; - } - string create_timestamped_folder() { - time_t now = time(0); - tm *ltm = localtime(&now); - string folder_name = to_string(1900 + ltm->tm_year) + "-" + - to_string(1 + ltm->tm_mon) + "-" + - to_string(ltm->tm_mday) + "_" + - to_string(ltm->tm_hour) + "-" + - to_string(ltm->tm_min) + "-" + - to_string(ltm->tm_sec); - return create_folder(folder_name) ? folder_name : ""; - } + // Check if filename is empty + if (strlen(filename) == 0) { + cerr << "[ERROR] : Received empty filename, skipping.\n"; + continue; + } - void receive_files(const string& folder_name) { - while (true) { - flush_socket_buffer(client_socket); + if (strcmp(filename, "end_of_files") == 0) { + break; + } + cout << "[LOG] : Receiving file: " << filename << endl; - char filename[1024] = {0}; - if (recv(client_socket, filename, sizeof(filename), 0) == -1) { - perror("[ERROR] : Receiving filename from client failed"); - return; - } - if (strcmp(filename, "end_of_files") == 0) { - break; - } - cout << "[LOG] : Receiving file: " << filename << endl; + size_t filesize; + if (recv(client_socket, &filesize, sizeof(filesize), 0) == -1) { + perror("[ERROR] : Receiving file size from client failed"); + return; + } + cout << "[LOG] : File size: " << filesize << " bytes\n"; - size_t filesize; - if (recv(client_socket, &filesize, sizeof(filesize), 0) == -1) { - perror("[ERROR] : Receiving file size from client failed"); - return; - } - cout << "[LOG] : File size: " << filesize << " bytes\n"; + string filepath = folder_name + "/" + string(filename); + ofstream file(filepath, ios::binary); + if (!file) { + perror("[ERROR] : Opening file for writing failed"); + return; + } - string filepath = folder_name + "/" + string(filename); - ofstream file(filepath, ios::binary); - if (!file) { - perror("[ERROR] : Opening file for writing failed"); + char buffer[1024]; + size_t bytes_received = 0; + while (bytes_received < filesize) { + ssize_t n = recv(client_socket, buffer, min(sizeof(buffer), filesize - bytes_received), 0); + if (n == -1) { + perror("[ERROR] : Receiving file data from client failed"); return; } - - char buffer[1024]; - size_t bytes_received = 0; - while (bytes_received < filesize) { - ssize_t n = recv(client_socket, buffer, min(sizeof(buffer), filesize - bytes_received), 0); - if (n == -1) { - perror("[ERROR] : Receiving file data from client failed"); - return; - } - file.write(buffer, n); - bytes_received += n; - } - - cout << "[LOG] : File received and saved to " << filepath << endl; - send_message("File received: " + string(filename)); + file.write(buffer, n); + bytes_received += n; } - cout << "[LOG] : All files received.\n"; - } - void send_message(const string& message) { - if (send(client_socket, message.c_str(), message.size() + 1, 0) == -1) { - perror("[ERROR] : Sending message to client failed"); - } + cout << "[LOG] : File received and saved to " << filepath << endl; + send_message("File received: " + string(filename)); } + cout << "[LOG] : All files received.\n"; + } - static void signal_handler(int signum) { - cout << "\nInterrupt signal (" << signum << ") received. Shutting down...\n"; - exit(signum); + void send_message(const string& message) { + if (send(client_socket, message.c_str(), message.size() + 1, 0) == -1) { // include null terminator + perror("[ERROR] : Sending message to client failed"); } + } - void register_signal_handler() { - signal(SIGINT, signal_handler); - } + static void signal_handler(int signum) { + cout << "\nInterrupt signal (" << signum << ") received. Shutting down...\n"; + exit(signum); + } + + void register_signal_handler() { + signal(SIGINT, signal_handler); + } }; int main() {