Skip to content

Commit

Permalink
feat: added server support
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaskowicz1 committed Jan 1, 2024
1 parent d888ea8 commit fa8482d
Show file tree
Hide file tree
Showing 7 changed files with 409 additions and 17 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ Rcon++ is a modern Source RCON library for C++, allowing people to easily use RC

- Support for Valve and non-Valve games.
- Callbacks, allowing non-blocking calls.
- Support for hosting an RCON server.

#### To-do

- Support for hosting an RCON server.
- Support for multiple response packets.

#### Library Usage
Expand Down
122 changes: 121 additions & 1 deletion include/rconpp/server.h
Original file line number Diff line number Diff line change
@@ -1 +1,121 @@
#pragma once
#pragma once

#ifdef _WIN32
#include <winsock2.h>
#include <WS2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
#else
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
#include <fcntl.h>
#include <string>
#include <functional>
#include <vector>
#include <iostream>
#include <cstring>
#include <thread>
#include "utilities.h"

namespace rconpp {

struct connected_client {
struct sockaddr_in sock_info{};
int socket{0};
bool connected{false};

bool authenticated{false};
};

struct server_info {
std::string address{};
int port{0};
std::string password{};
};

struct client_command {
connected_client client;
std::string command{};
};

class RCONPP_EXPORT rcon_server {
server_info serv_info{};

#ifdef _WIN32
SOCKET sock{INVALID_SOCKET};
#else
int sock{0};
#endif

std::thread accept_connections_runner;

public:
bool online{false};

std::function<std::string(const client_command& command)> on_command;

/**
* @brief A map of connected clients. The key is their socket to talk to.
*/
std::unordered_map<int, connected_client> connected_clients{};

std::unordered_map<int, std::thread> request_handlers{};

/**
* @brief rcon_server constuctor. Initiates a connection to an RCON server with the parameters given.
*
* @param addr The IP Address (NOT domain) to connect to.
* @param _port The port to connect to.
* @param pass The password for the RCON server you are connecting to.
*
* @note This is a blocking call (done on purpose). It needs to wait to connect to the RCON server before anything else happens.
* It will timeout after 4 seconds if it can't connect.
*/
rcon_server(const std::string_view addr, const int port, const std::string_view pass);

~rcon_server();

/**
* @brief Disconnect a client from the server.
*
* @param client_socket The socket of the client to disconnect.
*/
void disconnect_client(const int client_socket);

private:

/**
* @brief Connects to RCON using `address`, `port`, and `password`.
* Those values are pre-filled when constructing this class.
*
* @warning This should only ever be called by the constructor.
* The constructor calls this function once it has filled in the required data and proceeds to login.
*/
bool startup_server();

/**
* @brief Ask to receive information from the server for a specified ID.
*
* @param id The ID that we should except the server to return, alongside information.
* @param type The type of packet that we should expect.
*
* @return Data given by the server.
*/
response receive_information(int32_t id, data_type type);

/**
* @brief Gathers all the packet's content (based on the length returned by `read_packet_length`)
*/
void read_packet(rconpp::connected_client client);

/**
* @brief Reads the first 4 bytes of a packet to get the packet size (not to be mistaken with length).
*
* @return The size (not length) of the packet.
*/
int read_packet_size(const rconpp::connected_client client);
};

} // namespace rconpp
9 changes: 9 additions & 0 deletions include/rconpp/utilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ RCONPP_EXPORT packet form_packet(const std::string_view data, int32_t id, int32_
*/
RCONPP_EXPORT int bit32_to_int(const std::vector<char>& buffer);

/**
* @brief Turn the second lot of 4 bytes (bytes 4-7) of a buffer (which ideally a 32 bit int) into an integer.
*
* @param buffer The bytes to turn into an integer.
*
* @return The value of the 4 bytes.
*/
RCONPP_EXPORT int type_to_int(const std::vector<char>& buffer);

/**
* @brief Reports the recent socket error.
*/
Expand Down
6 changes: 3 additions & 3 deletions src/rconpp/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ rconpp::rcon_client::rcon_client(const std::string_view addr, const int _port, c
std::cout << "Attempting connection to RCON server..." << "\n";

if (!connect_to_server()) {
std::cout << "RCON is aborting as it failed to initiate." << "\n";
std::cout << "RCON is aborting as it failed to initiate client." << "\n";
return;
}

Expand Down Expand Up @@ -56,7 +56,7 @@ rconpp::rcon_client::~rcon_client() {

#ifdef _WIN32
closesocket(sock);
WSACleanup();
WSACleanup();
#else
close(sock);
#endif
Expand Down Expand Up @@ -129,7 +129,7 @@ bool rconpp::rcon_client::connect_to_server() {

#ifdef _WIN32
int corrected_timeout = DEFAULT_TIMEOUT * 1000;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&corrected_timeout, sizeof(corrected_timeout));
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&corrected_timeout, sizeof(corrected_timeout));
#else
// Set a timeout of 4 seconds.
struct timeval tv {};
Expand Down

0 comments on commit fa8482d

Please sign in to comment.