Untitled

 avatar
unknown
plain_text
a month ago
8.3 kB
3
Indexable
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <thread>
#include <filesystem>
#include <cstring>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <ifaddrs.h>

#define PORT 4444
#define BUFFER_SIZE 1024

using namespace std;
using namespace filesystem;

// Function declarations
string getIPAddress();
void sendFile(int clientSocket, const string &filename);
int receiveFile(int peerSocket, const string &filename);
int handleFiles(int clientSocket);
vector<string> getFileList(const string &path);
int startServer();

int main()
{
    string IPADDRESS = getIPAddress();
    vector<string> filesNameList = getFileList("../files");
    string serverIP;

    cout << "Enter server IP: ";
    cin >> serverIP;

    // Start a local server thread
    thread serverThread(startServer);
    serverThread.detach();

    // Create a socket
    int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (clientSocket == -1)
    {
        cerr << "Failed to create socket.\n";
        return -1;
    }

    // Configure server address
    sockaddr_in serverAddr{};
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(PORT);
    inet_pton(AF_INET, serverIP.c_str(), &serverAddr.sin_addr);

    // Connect to the server
    if (connect(clientSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1)
    {
        cerr << "Failed to connect to the server.\n";
        close(clientSocket);
        return -1;
    }

    // Send filenames and IP address to the server
    string fileData;
    for (const auto &file : filesNameList)
    {
        fileData += file + ' ' + IPADDRESS + ':';
    }

    send(clientSocket, fileData.c_str(), fileData.length(), 0);

    // Handle file requests
    while (true)
    {
        if (handleFiles(clientSocket))
        {
            break;
        }
    }

    // Send exit command and close socket
    string exitCommand = "exit";
    send(clientSocket, exitCommand.c_str(), exitCommand.size(), 0);
    close(clientSocket);
    return 0;
}

void sendFile(int clientSocket, const string &filename)
{
    ifstream file("../files/" + filename, ios::binary);
    if (!file.is_open())
    {
        cerr << "Error: Could not open file " << filename << "\n";
        string errorMsg = "Error: File not found";
        send(clientSocket, errorMsg.c_str(), errorMsg.size(), 0);
        return;
    }

    char buffer[BUFFER_SIZE];
    while (!file.eof())
    {
        file.read(buffer, BUFFER_SIZE);
        streamsize bytesRead = file.gcount();
        if (bytesRead > 0)
        {
            send(clientSocket, buffer, bytesRead, 0);
        }
    }

    file.close();
    cout << "File " << filename << " sent successfully.\n";
}

int receiveFile(int peerSocket, const string &filename)
{
    ofstream outFile("../files/" + filename, ios::binary);
    if (!outFile.is_open())
    {
        cerr << "Error: Could not create file " << filename << "\n";
        return -1;
    }

    char buffer[BUFFER_SIZE];
    int bytesRead;

    struct timeval timeout;
    timeout.tv_sec = 1; // Set timeout to 1 seconds
    timeout.tv_usec = 0;

    // Set the timeout option for the socket
    setsockopt(peerSocket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout));

    while ((bytesRead = recv(peerSocket, buffer, BUFFER_SIZE, 0)) > 0)
    {
        outFile.write(buffer, bytesRead);
    }

    if (bytesRead < 0)
    {
        cerr << "Error: Failed to receive file data.\n";
        outFile.close();
        return -1;
    }

    outFile.close();
    cout << "File " << filename << " received successfully.\n";
    return 0;
}

int handleFiles(int clientSocket)
{
    string input;
    cout << "Enter filenames to request (separated by spaces, or 'exit' to quit): ";
    getline(cin >> ws, input);

    if (input == "exit")
    {
        return 1;
    }

    vector<string> filenames;
    size_t pos = 0, found;

    while ((found = input.find(' ', pos)) != string::npos)
    {
        filenames.push_back(input.substr(pos, found - pos));
        pos = found + 1;
    }

    filenames.push_back(input.substr(pos));

    for (const auto &filename : filenames)
    {
        string command = "Send " + filename;
        send(clientSocket, command.c_str(), command.size(), 0);

        char response[BUFFER_SIZE] = {0};
        int bytesRead = read(clientSocket, response, BUFFER_SIZE);

        if (bytesRead <= 0 || string(response).find("File not found") != string::npos)
        {
            cerr << "Error: File not found on server: " << filename << "\n";
            continue;
        }

        int peerSocket = socket(AF_INET, SOCK_STREAM, 0);
        if (peerSocket == -1)
        {
            cerr << "Failed to create server socket.\n";
            return -1;
        }

        string ip_addr_of_recipient = string(response);
        sockaddr_in peerServerAddr;
        memset(&peerServerAddr, 0, sizeof(peerServerAddr));
        peerServerAddr.sin_family = AF_INET;
        peerServerAddr.sin_port = htons(5555);
        inet_pton(AF_INET, string(response).c_str(), &peerServerAddr.sin_addr);

        if (connect(peerSocket, (struct sockaddr *)&peerServerAddr, sizeof(peerServerAddr)) == -1)
        {
            cout << "Peer socket connection failed" << endl;
            continue;
        }

        command = "Send " + filename;
        send(peerSocket, command.c_str(), command.size(), 0);

        receiveFile(peerSocket, filename);
    }

    return 0;
}

vector<string> getFileList(const string &path)
{
    vector<string> fileList;
    for (const auto &entry : directory_iterator(path))
    {
        fileList.push_back(entry.path().filename().string());
    }
    return fileList;
}

int startServer()
{
    int serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSocket == -1)
    {
        cerr << "Failed to create server socket.\n";
        return -1;
    }

    sockaddr_in serverAddr{};
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(5555);
    serverAddr.sin_addr.s_addr = INADDR_ANY;

    if (bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1)
    {
        cerr << "Failed to bind socket.\n";
        close(serverSocket);
        return -1;
    }

    if (listen(serverSocket, 5) == -1)
    {
        cerr << "Failed to listen on socket.\n";
        close(serverSocket);
        return -1;
    }

    cout << "Server is listening on port " << 5555 << "...\n";
    while (true)
    {
        sockaddr_in clientAddr{};
        socklen_t clientLen = sizeof(clientAddr);
        int clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddr, &clientLen);

        if (clientSocket == -1)
        {
            cerr << "Failed to accept connection.\n";
            continue;
        }

        char buffer[2048] = {0};
        read(clientSocket, buffer, sizeof(buffer));
        string response = string(buffer);

        if (response.rfind("Send ", 0) != string::npos)
        {
            sendFile(clientSocket, response.substr(5));
        }
    }
}

string getIPAddress()
{
    struct ifaddrs *interfaces = nullptr;
    struct ifaddrs *temp_addr = nullptr;
    std::string ipAddress = "Unable to get IP Address";

    // Retrieve the list of network interfaces
    if (getifaddrs(&interfaces) == 0)
    {
        temp_addr = interfaces;
        while (temp_addr != nullptr)
        {
            if (temp_addr->ifa_addr && temp_addr->ifa_addr->sa_family == AF_INET)
            {
                // Check if it's an IPv4 address and not the loopback interface
                if (strcmp(temp_addr->ifa_name, "lo") != 0)
                {
                    ipAddress = inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr);
                    break;
                }
            }
            temp_addr = temp_addr->ifa_next;
        }

        // Free the memory allocated by getifaddrs()
        freeifaddrs(interfaces);
    }

    return ipAddress;
}
Editor is loading...
Leave a Comment