RyanHub – file viewer
filename: src/networking.cpp
branch: main
back to repo
#include "networking.h"
#include <WS2tcpip.h>
#include <iostream>

#include "constants.h"

#pragma comment(lib, "ws2_32.lib")

#define PORT 54000

SOCKET sock = INVALID_SOCKET;
SOCKET client_socket = INVALID_SOCKET;
int address_family = AF_INET;
int type = SOCK_STREAM;
int protocol = 0;

// packet definitions
GLfloat fail[IN_OUT_BUFF_SIZE] = { -1 };
GLfloat move[IN_OUT_BUFF_SIZE] = { 0 };
GLfloat shoot[IN_OUT_BUFF_SIZE] = { 1 };

string Network::printLocalIPAddress() {
    char host[NI_MAXHOST];
    if (gethostname(host, sizeof(host)) == SOCKET_ERROR) {
        cout << "Error getting hostname. Quitting" << endl;
        return "";
    }

    addrinfo hints = {};
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    addrinfo* info;
    if (getaddrinfo(host, nullptr, &hints, &info) != 0) {
        cout << "Error getting local IP. Quitting" << endl;
        return "";
    }

    string ipAddress;
    for (addrinfo* ptr = info; ptr != nullptr; ptr = ptr->ai_next) {
        sockaddr_in* ipv4 = (sockaddr_in*)ptr->ai_addr;
        char ipStr[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &ipv4->sin_addr, ipStr, INET_ADDRSTRLEN);
        cout << "Server IP: " << ipStr << endl;
        ipAddress = ipStr;
    }

    freeaddrinfo(info);

    return ipAddress;
}

SOCKET Network::serverSetup() {
    WSADATA wsData;
    WORD ver = MAKEWORD(2, 2);
    if (WSAStartup(ver, &wsData) != 0) {
        cout << "Winsock initialization failed!" << endl;
        return INVALID_SOCKET;
    }

    SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
    if (listening == INVALID_SOCKET) {
        cout << "Socket creation failed!" << endl;
        WSACleanup();
        return INVALID_SOCKET;
    }

    sockaddr_in hint = {};
    hint.sin_family = AF_INET;
    hint.sin_port = htons(PORT);
    hint.sin_addr.S_un.S_addr = INADDR_ANY;

    printLocalIPAddress();

    if (bind(listening, (sockaddr*)&hint, sizeof(hint)) == SOCKET_ERROR) {
        cout << "Binding failed!" << endl;
        closesocket(listening);
        WSACleanup();
        return INVALID_SOCKET;
    }

    listen(listening, SOMAXCONN);

    u_long mode = 1; // non blocking
    ioctlsocket(listening, FIONBIO, &mode);

    cout << "Waiting for a connection..." << endl;
    return listening; // not client socket
}
SOCKET Network::clientSetup(std::string serverIP) {
    WSADATA wsData;
    WORD ver = MAKEWORD(2, 2);
    if (WSAStartup(ver, &wsData) != 0) {
        cout << "Can't start Winsock! Quitting" << endl;
        return INVALID_SOCKET;
    }

    sock = socket(address_family, type, protocol);

    if (sock == INVALID_SOCKET) {
        cout << "Can't create socket, Err #" << WSAGetLastError() << endl;
        WSACleanup();
        return INVALID_SOCKET;
    }

    sockaddr_in hint = {};
    hint.sin_family = AF_INET;
    hint.sin_port = htons(PORT);
    inet_pton(AF_INET, serverIP.c_str(), &hint.sin_addr);

    if (connect(sock, (sockaddr*)&hint, sizeof(hint)) == SOCKET_ERROR) {
        cout << "Can't connect to server, Err #" << WSAGetLastError() << endl;
        closesocket(sock);
        WSACleanup();
        return INVALID_SOCKET;
    }
    cout << "Connected to server! Start chatting..." << endl;
    return sock;
}
bool Network::sendData(SOCKET sock, char* buff, size_t size) {
	int bytesSent = send(sock, buff, static_cast<int>(size), 0);
	if (bytesSent == SOCKET_ERROR) {
		std::cout << "send failed: " << WSAGetLastError() << std::endl;
		closesocket(sock);
		WSACleanup();
		return false;
	}
	return bytesSent == static_cast<int>(size);
}
bool Network::recvData(SOCKET sock, char* buff, size_t bufferSize, size_t& bytesReceived) {
    bytesReceived = recv(sock, buff, static_cast<int>(bufferSize), 0);
    if (bytesReceived == SOCKET_ERROR) {
        int err = WSAGetLastError();
        if (err == WSAEWOULDBLOCK) {
            // no data available now, but connection is still good
            bytesReceived = 0;
            return true;
        }
        std::cout << "recv failed: " << err << std::endl;
        return false;
    }
    if (bytesReceived == 0) {
        std::cout << "Connection closed by peer." << std::endl;
        return false;
    }
    return true;
}