1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#ifndef NET_PROTOCOL_H
#define NET_PROTOCOL_H
#include <atomic>
#include <string>
#include "BaseNetProtocol.h" // not used in here, but in all files including this one
#include "System/Threading/SpringThreading.h"
class ClientSetup;
class CDemoRecorder;
namespace netcode
{
class RawPacket;
class CConnection;
}
/**
* @brief Client interface for handling communication with the game server.
*
* Even when playing singleplayer, this is the way of communicating
* with the server. It keeps the connection alive,
* and is able to send and receive raw binary packets transparently
* over the network.
*/
class CNetProtocol
{
public:
CNetProtocol();
~CNetProtocol();
/**
* @brief Initialise in client mode (remote server)
*/
void InitClient(std::shared_ptr<ClientSetup> clientSetup, const std::string& clientVersion, const std::string& clientPlatform);
/**
* @brief Initialise in client mode (local server)
*/
void InitLocalClient();
/// Are we still connected (or did the connection time-out)?
bool CheckTimeout(int nsecs = 0, bool initial = false) const;
void AttemptReconnect(const std::string& myVersion, const std::string& myPlatform);
bool NeedsReconnect();
/// This checks if any data has been received yet
bool Connected() const;
std::string ConnectionStr() const;
/**
* @brief Take a look at the messages in the recieve buffer (read-only)
* @return A RawPacket holding the data, or 0 if no data
* @param ahead How many packets to look ahead. A typical usage would be:
* for (int ahead = 0; (packet = clientNet->Peek(ahead)) != NULL; ++ahead) {}
*/
std::shared_ptr<const netcode::RawPacket> Peek(unsigned ahead) const;
/**
* @brief Deletes a packet from the buffer
* @param index queue index number
* useful for messages that skips queuing and needs to be processed immediately
*/
void DeleteBufferPacketAt(unsigned index);
float GetPacketTime(int frameNum) const;
/**
* @brief Receive a single message (and remove it from the recieve buffer)
* @return The first data packet from the buffer, or 0 if there is no data
*
* Receives only one message at a time
* (even if there are more in the recieve buffer),
* so call this until you get a 0 in return.
* When a demo recorder is present it will be recorded.
*/
std::shared_ptr<const netcode::RawPacket> GetData(int framenum);
/**
* @brief Send a message to the server
*/
void Send(std::shared_ptr<const netcode::RawPacket> pkt);
/// @overload
void Send(const netcode::RawPacket* pkt);
/**
* Updates our network while the game loads to prevent timeouts.
* Runs until \a keepUpdating is false.
*/
void UpdateLoop();
/// Must be called to send / recieve packets
void Update();
void Close(bool flush = false);
void KeepUpdating(bool b) { keepUpdating = b; }
void SetDemoRecorder(CDemoRecorder&& r);
void ResetDemoRecorder();
netcode::CConnection* GetServerConnection() { return serverConnPtr; }
CDemoRecorder* GetDemoRecorder() { return demoRecordPtr; }
unsigned int GetNumWaitingServerPackets() const;
unsigned int GetNumWaitingPingPackets() const;
private:
std::atomic<bool> keepUpdating;
spring::spinlock serverConnMutex;
uint8_t serverConnMem[1024];
uint8_t demoRecordMem[ 512];
netcode::CConnection* serverConnPtr = nullptr;
CDemoRecorder* demoRecordPtr = nullptr;
std::string userName;
std::string userPasswd;
};
extern CNetProtocol* clientNet;
#endif // NET_PROTOCOL_H
|