246 lines
4.9 KiB
C++
246 lines
4.9 KiB
C++
#ifndef NETWORK_HPP
|
|
#define NETWORK_HPP
|
|
|
|
#include <exception>
|
|
|
|
#include <glm/vec3.hpp>
|
|
|
|
#include "../Platform.hpp"
|
|
#include "../platform/PreprocUtils.hpp"
|
|
#include "../crypto/DiffieHellman.hpp"
|
|
#include "../io/MemoryStream.hpp"
|
|
|
|
namespace Diggler {
|
|
namespace Net {
|
|
|
|
bool Init();
|
|
void DeInit();
|
|
std::string GetNetworkLibVersion();
|
|
|
|
enum class Tfer {
|
|
Rel,
|
|
Unrel,
|
|
Unseq
|
|
};
|
|
|
|
enum class Channels : uint8 {
|
|
Base = 0,
|
|
ConnectionMeta,
|
|
ConnectionMetaPlain,
|
|
Chat,
|
|
Life,
|
|
Movement,
|
|
PlayerInfo,
|
|
PlayerInteract,
|
|
MapUpdate,
|
|
MapTransfer,
|
|
MAX
|
|
};
|
|
|
|
enum class MessageType : uint8 {
|
|
Null = 0,
|
|
|
|
ServerInfo = 220,
|
|
|
|
ConnectionParam = 200,
|
|
|
|
PlayerJoin = 1,
|
|
PlayerUpdate,
|
|
PlayerQuit,
|
|
ChunkTransfer,
|
|
BlockUpdate,
|
|
Chat,
|
|
|
|
NetConnect = 240,
|
|
NetDisconnect
|
|
};
|
|
|
|
enum QuitReason : uint8 {
|
|
Quit,
|
|
Timeout,
|
|
Kicked,
|
|
Banned,
|
|
ServerShutdown,
|
|
UsernameAlreadyUsed
|
|
};
|
|
|
|
using EventType = uint32;
|
|
|
|
class Message : public virtual MemoryStream {
|
|
protected:
|
|
friend class Host;
|
|
MessageType m_type;
|
|
uint8 m_subtype;
|
|
|
|
Message() {}
|
|
Message(MessageType, uint8);
|
|
Message(const Message&) = delete;
|
|
Message& operator=(Message&) = delete;
|
|
Message& operator=(const Message&) = delete;
|
|
|
|
public:
|
|
static constexpr uint HeaderSize = 2;
|
|
|
|
virtual ~Message() {}
|
|
|
|
inline MessageType getType() const { return m_type; }
|
|
inline uint8 getSubtype() const { return m_subtype; }
|
|
|
|
inline SizeT remaining() const {
|
|
return length() - tell();
|
|
}
|
|
};
|
|
|
|
class InMessage : public Message, public InMemoryStream {
|
|
protected:
|
|
friend class Host;
|
|
Channels m_chan;
|
|
void setType(MessageType type);
|
|
void fromData(const void *data, SizeT, Channels);
|
|
void free();
|
|
|
|
public:
|
|
InMessage();
|
|
~InMessage();
|
|
|
|
inline const void* getCursorPtr(uint advanceCursor = 0) {
|
|
m_cursor += advanceCursor;
|
|
return &(m_data[m_cursor-advanceCursor]);
|
|
}
|
|
inline const void* getCursorPtr() const {
|
|
return &(m_data[m_cursor]);
|
|
}
|
|
|
|
glm::vec3 readVec3();
|
|
glm::ivec3 readIVec3();
|
|
|
|
Channels getChannel() const;
|
|
};
|
|
|
|
class OutMessage : public Message, public OutMemoryStream {
|
|
protected:
|
|
friend class Host;
|
|
mutable uint8 *m_actualData;
|
|
void fit(SizeT) override;
|
|
|
|
public:
|
|
OutMessage(MessageType t = MessageType::Null, uint8 subtype = 255);
|
|
~OutMessage();
|
|
|
|
inline void setType(MessageType t) { m_type = t; }
|
|
template<typename T>
|
|
inline void setSubtype(T t) { m_subtype = static_cast<uint8>(t); }
|
|
template<typename T>
|
|
inline void setType(MessageType t, T st) { setType(t); setSubtype(st); }
|
|
|
|
inline void writeVec3(float x, float y, float z) {
|
|
writeFloat(x);
|
|
writeFloat(y);
|
|
writeFloat(z);
|
|
}
|
|
inline void writeVec3(const glm::vec3 &vec) {
|
|
writeFloat(vec.x);
|
|
writeFloat(vec.y);
|
|
writeFloat(vec.z);
|
|
}
|
|
inline void writeIVec3(int x, int y, int z) {
|
|
writeI32(x);
|
|
writeI32(y);
|
|
writeI32(z);
|
|
}
|
|
inline void writeIVec3(const glm::ivec3 &vec) {
|
|
writeI32(vec.x);
|
|
writeI32(vec.y);
|
|
writeI32(vec.z);
|
|
}
|
|
|
|
// msgpack::packer compatibility
|
|
inline void write(const char *buf, size_t len) {
|
|
writeData(buf, len);
|
|
}
|
|
};
|
|
|
|
class Exception : public std::exception {
|
|
};
|
|
|
|
using Port = uint16;
|
|
|
|
class Host;
|
|
|
|
struct Peer {
|
|
Crypto::DiffieHellman::SecretKey connectionSk;
|
|
Crypto::DiffieHellman::PublicKey connectionPk;
|
|
|
|
Crypto::DiffieHellman::PublicKey remotePk;
|
|
Crypto::DiffieHellman::SharedSecret sharedSecret;
|
|
|
|
Host &host;
|
|
void *const peer;
|
|
|
|
Peer(Host&, void*);
|
|
nocopy(Peer);
|
|
nomove(Peer);
|
|
|
|
bool operator==(const Peer&) const;
|
|
bool operator!=(const Peer&) const;
|
|
|
|
/**
|
|
* @brief Disconnects the peer.
|
|
* @param data
|
|
* Adds the peer for pending disconnection. A NetDisconnect event will be generated once the
|
|
* peer has successfully disconnected, and the current Peer object will be deallocated as per
|
|
* Host::recv's rules.
|
|
*/
|
|
void disconnect(uint32 data = 0);
|
|
std::string peerHost();
|
|
std::string peerIP();
|
|
Port peerPort();
|
|
};
|
|
|
|
class Host {
|
|
private:
|
|
std::vector<Peer*> m_peersToDelete;
|
|
void processPeersToDelete();
|
|
|
|
void *host;
|
|
uint64 rxBytes, txBytes;
|
|
|
|
Host(const Host&) = delete;
|
|
Host& operator=(Host&) = delete;
|
|
Host& operator=(const Host&) = delete;
|
|
|
|
void sendKeyExchange(Peer&);
|
|
|
|
public:
|
|
using Timeout = uint32;
|
|
|
|
public:
|
|
Host();
|
|
~Host();
|
|
void create(Port port = 0, uint maxconn = 64);
|
|
Peer& connect(const std::string &hostAddr, Port port, Timeout timeout);
|
|
|
|
void send(Peer &peer, const OutMessage &msg, Tfer mode = Tfer::Rel, Channels chan = Channels::Base);
|
|
|
|
// Returns true if a message is available, and put it in msg.
|
|
// msg may be modified even if recv returns false.
|
|
// If the msg is a NetDisconnect, returned peer object is put on a deletion list and will be
|
|
// freed upon the next call to recv.
|
|
bool recv(InMessage &msg, Peer **peer, Timeout timeout);
|
|
inline bool recv(InMessage &msg, Timeout timeout) {
|
|
return recv(msg, nullptr, timeout);
|
|
}
|
|
|
|
inline uint64 getRxBytes() const {
|
|
return rxBytes;
|
|
}
|
|
inline uint64 getTxBytes() const {
|
|
return txBytes;
|
|
}
|
|
};
|
|
|
|
}
|
|
}
|
|
|
|
#endif
|