181 lines
6.5 KiB
C++
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 |