gbe_fork/dll/dll/network.h
2024-05-03 03:33:46 +03:00

173 lines
5.7 KiB
C++

/* Copyright (C) 2019 Mr Goldberg
This file is part of the Goldberg Emulator
The Goldberg Emulator is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
The Goldberg Emulator is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the Goldberg Emulator; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef NETWORK_INCLUDE
#define NETWORK_INCLUDE
#include "base.h"
#include <curl/curl.h>
#define DEFAULT_PORT 47584
#if defined(STEAM_WIN32)
typedef unsigned int sock_t;
#else
typedef int sock_t;
#endif
static inline bool protobuf_message_equal(
const google::protobuf::MessageLite& msg_a,
const google::protobuf::MessageLite& msg_b)
{
return (msg_a.GetTypeName() == msg_b.GetTypeName()) &&
(msg_a.SerializeAsString() == msg_b.SerializeAsString());
}
struct IP_PORT {
uint32 ip{};
uint16 port{};
bool operator <(const IP_PORT& other) const
{
return (ip < other.ip) || (ip == other.ip && port < other.port);
}
};
struct Network_Callback {
void (*message_callback)(void *object, Common_Message *msg) = nullptr;
void *object{};
CSteamID steam_id{};
};
enum Callback_Ids {
CALLBACK_ID_USER_STATUS,
CALLBACK_ID_LOBBY,
CALLBACK_ID_NETWORKING,
CALLBACK_ID_GAMESERVER,
CALLBACK_ID_FRIEND,
CALLBACK_ID_AUTH_TICKET,
CALLBACK_ID_FRIEND_MESSAGES,
CALLBACK_ID_NETWORKING_SOCKETS,
CALLBACK_ID_STEAM_MESSAGES,
CALLBACK_ID_NETWORKING_MESSAGES,
CALLBACK_ID_GAMESERVER_STATS,
CALLBACK_ID_LEADERBOARDS_STATS,
CALLBACK_IDS_MAX
};
struct Network_Callback_Container {
std::vector<struct Network_Callback> callbacks{};
};
struct TCP_Socket {
sock_t sock = static_cast<sock_t>(~0);
bool received_data = false;
std::vector<char> recv_buffer{};
std::vector<char> send_buffer{};
std::chrono::high_resolution_clock::time_point last_heartbeat_sent{}, last_heartbeat_received{};
};
struct Connection {
struct TCP_Socket tcp_socket_outgoing{}, tcp_socket_incoming{};
bool connected = false;
IP_PORT udp_ip_port{};
bool udp_pinged = false;
IP_PORT tcp_ip_port{};
std::vector<CSteamID> ids{};
uint32 appid{};
std::chrono::high_resolution_clock::time_point last_received{};
};
class Networking
{
bool enabled = false;
bool query_alive{};
std::chrono::high_resolution_clock::time_point last_run{};
sock_t query_socket, udp_socket{}, tcp_socket{};
uint16 udp_port{}, tcp_port{};
uint32 own_ip{};
std::vector<struct Connection> connections{};
std::vector<CSteamID> ids;
uint32 appid;
std::chrono::high_resolution_clock::time_point last_broadcast;
std::vector<IP_PORT> custom_broadcasts;
std::vector<struct TCP_Socket> accepted;
std::recursive_mutex mutex;
struct Network_Callback_Container callbacks[CALLBACK_IDS_MAX];
std::vector<Common_Message> local_send;
struct Connection *find_connection(CSteamID id, uint32 appid = 0);
struct Connection *new_connection(CSteamID id, uint32 appid);
bool handle_announce(Common_Message *msg, IP_PORT ip_port);
bool handle_low_level_udp(Common_Message *msg, IP_PORT ip_port);
bool handle_tcp(Common_Message *msg, struct TCP_Socket &socket);
void send_announce_broadcasts();
bool add_id_connection(struct Connection *connection, CSteamID steam_id);
void run_callbacks(Callback_Ids id, Common_Message *msg);
void run_callback_user(CSteamID steam_id, bool online, uint32 appid);
void do_callbacks_message(Common_Message *msg);
Common_Message create_announce(bool request);
public:
Networking(CSteamID id, uint32 appid, uint16 port, std::set<IP_PORT> *custom_broadcasts, bool disable_sockets);
~Networking();
//NOTE: for all functions ips/ports are passed/returned in host byte order
//ex: 127.0.0.1 should be passed as 0x7F000001
static std::set<IP_PORT> resolve_ip(std::string dns);
void addListenId(CSteamID id);
void setAppID(uint32 appid);
void Run();
// send to a specific user, set_dest_id() must be called
bool sendTo(Common_Message *msg, bool reliable, Connection *conn = NULL);
// send to all users whose account type is Individual, no need to call set_dest_id(), this is done automatically
bool sendToAllIndividuals(Common_Message *msg, bool reliable);
// send to all users whose account type is GameServer, no need to call set_dest_id(), this is done automatically
bool sendToAllGameservers(Common_Message *msg, bool reliable);
// send to all active/current connections, no need to call set_dest_id(), this is done automatically
bool sendToAll(Common_Message *msg, bool reliable);
// send to active/current connections with specific ip/port, no need to call set_dest_id(), this is done automatically
//TODO: actually send to ip/port
bool sendToIPPort(Common_Message *msg, uint32 ip, uint16 port, bool reliable);
bool setCallback(Callback_Ids id, CSteamID steam_id, void (*message_callback)(void *object, Common_Message *msg), void *object);
void rmCallback(Callback_Ids id, CSteamID steam_id, void (*message_callback)(void *object, Common_Message *msg), void *object);
uint32 getIP(CSteamID id);
uint32 getOwnIP();
void startQuery(IP_PORT ip_port);
void shutDownQuery();
bool isQueryAlive();
};
#endif // NETWORK_INCLUDE_H