Files
libsst/Include/ZSimulation/ZNetworkService.hpp
2026-04-03 00:22:39 -05:00

181 lines
6.5 KiB
C++

/*
ZNetworkService.hpp
Author: Patrick Baggett <ptbaggett@762studios.com>, James Russell <jcrussell@762studios.com>
Created: 12/03/2013
Purpose:
Network functionality for ZSimulation. Operates a thread that handles sending and
receiving of network data. Can be initialized as a server instance of a client
instance, with the real difference being that client instances connect to a single
server and servers listen for connections from multiple clients and other server
instances.
License:
Copyright 2013, 762 Studios.
*/
#pragma once
#ifndef __ZNETWORKSERVICE_HPP
#define __ZNETWORKSERVICE_HPP
#include <enet/enet.h>
#include <ZUtil/ZUtil.hpp>
#include "ZRemotePeer.hpp"
#include "ZNetworkRequest.hpp"
#include "ZNetworkUpdateStream.hpp"
// forward decl
class ZSimulation;
// class decl
class ZNetworkService
{
public:
// c'tor
ZNetworkService(ZSimulation& sim);
/*
Initializes the network system as client or server. The name is for display
purposes for both client and server.
If initialized as a server, the maximum number of simultaneous connections must
be specified.
*/
bool InitAsClient(const char* name);
bool InitAsServer(uint32_t maxConnections, uint16_t listenPort, const char* name);
/*
As a client, initializes a connection to the provided remote host. As a server,
links to another server instance to share workload. Delete this when done.
*/
ZNetworkRequest* InitiateConnection(const char* remoteHost, uint16_t port);
/*
As a client, disconnects from the server (cID for server is always zero). As
a server, disconnects the given connection. This is a soft disconnect that
notifies the other side and waits for a response. Delete this when done.
*/
ZNetworkRequest* Disconnect(cID id);
/*
Generates the disconnection event immediately, but gives no notice to the other
side. Delete this when done.
*/
ZNetworkRequest* ResetConnection(cID id);
/*
Given a connection id, gets the associated remote peer object.
*/
ZRemotePeer* GetPeer(cID id);
/*
Given the network name, gets the associated id. Returns cID(-1) if not connected
to this simulation instance.
*/
cID GetId(const char* netname);
/*
Gets a list of node and host pairings on the network. If the pairing exists in both
directions, then the connection is between two servers.
*/
void GetTopography(ZArray<ZPair<ZString, ZString>>& mappings);
// thread control methods
void SignalAndWaitShutdown();
void ThreadMain();
private:
// spawns the network thread
void SpawnThread();
// main thread = these four functions, in a loop
void PollNetEvents();
void ProcessRequests();
void PushBufferUpdates(uint64_t dt);
void PushNetworkEvents(uint64_t dt);
// handlers for requests (return value indicates 'done')
bool HandleRequest(ZNetworkRequest* req);
bool HandleConnectRequest(ZNetworkRequest* req);
bool HandleDisconnectRequest(ZNetworkRequest* req);
bool HandleResetRequest(ZNetworkRequest* req);
bool HandleStopNetworkRequest(ZNetworkRequest* req);
// handlers for ENet Events
void HandleEvent(ENetEvent* ev);
// server side
void ServerHandleConnectEvent(ENetEvent* ev); // initial connection event from ENet
void ServerHandleDisconnectEvent(ENetEvent* ev); // disconnect event from ENet
void ServerHandleReceiveEvent(ENetEvent* ev); // data received (any channel)
void ServerReceiveJoinMessage(ZRemotePeer* client, const void* data, uint32_t len); // process client (or server) join message
void ServerReceiveSystemChannel(ZRemotePeer* client, const void* data, uint32_t len); // data received
void ServerReceiveUpdateChannel(ZRemotePeer* client, const void* data, uint32_t len); // data received on update channel
void ServerReceiveEventChannel(ZRemotePeer* client, const void* data, uint32_t len); // data received on event channel
// client side
void ClientHandleConnectEvent(ENetEvent* ev); // initial connect event from ENet
void ClientHandleDisconnectEvent(ENetEvent* ev); // disconnect event from ENet
void ClientHandleReceiveEvent(ENetEvent* ev); // data received (any channel)
void ClientRecieveJoinResponse(const void* data, uint32_t len); // process server response from join message
void ClientReceiveSystemChannel(const void* data, uint32_t len); // data received on system channel
void ClientReceiveUpdateChannel(const void* data, uint32_t len); // data received from server on update channel
void ClientReceiveEventChannel(const void* data, uint32_t len); // data received from server on event channel
// adds and removes a network node mapping
void AddNode(const ZString& node, const ZString& host);
void RemoveNode(const ZString& node);
enum Netstate {
UNINITIALIZED, // not yet initialized as client or server
DISCONNECTED, // initialized as client and disconnected
LISTEN, // initialized as server and listening for connections
CONNECTING, // initiating low-level connection
JOINING, // connected, but not yet ready to play
CONNECTED // connected and ready to SIMULATE
};
ZSimulation& Sim; // simulation reference
ZString Name; // network name
Netstate State; // state of this service
SST_Thread Thread; // thread running this service
bool bIsServer; // true if initialized as server
bool bIsConnected; // true if connected
volatile int iShouldShutdown; // shutdown flag
ENetHost* Host; // enet host service (server and client)
ENetPeer* RemoteServer; // as a client, this is the server (otherwise NULL)
uint32_t NrConnectionsMax; // max number of connections
ZRemotePeer* Connections; // all connections (as client, only a single remote peer, the server)
ZMutex NodesMutex; // mutex for locking access to nodes listing
ZArray<ZPair<ZString, ZString>> Nodes; // node name and host name pairing for all simulations on the network
void* PacketBuffer; // packet data buffer, used as local copy
size_t PacketBufferSize; // size of the buffer
ZMutex QueueMutex; // mutex for locking access to request queue
ZArray<ZNetworkRequest*> SharedRequestQueue; // network request queue
ZNetworkRequest* CurrentRequest; // network request currently being processed
uint32_t WaitTime; // value used to modify polling frequency
ZArray<ZNetworkRequest*> PendingRequests; // queue used to process a single tick worth of requests
NetworkUpdateQueue DelayedUpdates; // updates that are being delayed for artificial lag simulation
NetworkEventQueue DelayedEvents; // events that are being delayed for artificial lag simulation
};
#endif