You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
2.5 KiB

#pragma once
#include <algorithm>
#include <array>
#include <atomic>
#include <cstdint>
#include <deque>
#include <exception>
#include <map>
#include <set>
#include <string>
#include "dvlnet/frame_queue.h"
namespace devilution {
namespace net {
class protocol_exception : public std::exception {
public:
const char *what() const throw() override
{
return "Protocol error";
}
};
class protocol_zt {
public:
class endpoint {
public:
std::array<unsigned char, 16> addr = {};
explicit operator bool() const
{
auto empty = std::array<unsigned char, 16> {};
return (addr != empty);
}
bool operator==(const endpoint &rhs) const
{
return addr == rhs.addr;
}
bool operator!=(const endpoint &rhs) const
{
return !(*this == rhs);
}
bool operator<(const endpoint &rhs) const
{
return addr < rhs.addr;
}
buffer_t serialize() const
{
return buffer_t(addr.begin(), addr.end());
}
void unserialize(const buffer_t &buf)
{
if (buf.size() != 16)
throw protocol_exception();
std::copy(buf.begin(), buf.end(), addr.begin());
}
void from_string(const std::string &str);
};
protocol_zt();
~protocol_zt();
void disconnect(const endpoint &peer);
bool send(const endpoint &peer, const buffer_t &data);
bool send_oob(const endpoint &peer, const buffer_t &data) const;
bool send_oob_mc(const buffer_t &data) const;
bool recv(endpoint &peer, buffer_t &data);
bool get_disconnected(endpoint &peer);
bool network_online();
bool is_peer_connected(endpoint &peer);
bool is_peer_relayed(const endpoint &peer) const;
static std::string make_default_gamename();
private:
static constexpr uint32_t PKTBUF_LEN = 65536;
static constexpr uint16_t default_port = 6112;
struct peer_state {
int fd = -1;
std::deque<buffer_t> send_queue;
frame_queue recv_queue;
};
std::deque<std::pair<endpoint, buffer_t>> oob_recv_queue;
std::deque<endpoint> disconnect_queue;
std::map<endpoint, peer_state> peer_list;
int fd_tcp = -1;
int fd_udp = -1;
static uint64_t current_ms();
void close_all();
static void set_nonblock(int fd);
static void set_nodelay(int fd);
static void set_reuseaddr(int fd);
bool send_queued_peer(const endpoint &peer);
bool recv_peer(const endpoint &peer);
bool send_queued_all();
bool recv_from_peers();
bool recv_from_udp();
bool accept_all();
};
} // namespace net
} // namespace devilution