1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-16 03:23:15 +01:00

refactor NetworkConnection and NetworkPacket

This commit is contained in:
Ted John
2016-05-28 17:54:45 +01:00
parent 46ecd53a99
commit 31ac6e7fdf
8 changed files with 587 additions and 403 deletions

View File

@@ -62,32 +62,6 @@ extern "C" {
Network gNetwork;
NetworkActions gNetworkActions;
enum {
NETWORK_READPACKET_SUCCESS,
NETWORK_READPACKET_NO_DATA,
NETWORK_READPACKET_MORE_DATA,
NETWORK_READPACKET_DISCONNECTED
};
enum {
NETWORK_COMMAND_AUTH,
NETWORK_COMMAND_MAP,
NETWORK_COMMAND_CHAT,
NETWORK_COMMAND_GAMECMD,
NETWORK_COMMAND_TICK,
NETWORK_COMMAND_PLAYERLIST,
NETWORK_COMMAND_PING,
NETWORK_COMMAND_PINGLIST,
NETWORK_COMMAND_SETDISCONNECTMSG,
NETWORK_COMMAND_GAMEINFO,
NETWORK_COMMAND_SHOWERROR,
NETWORK_COMMAND_GROUPLIST,
NETWORK_COMMAND_EVENT,
NETWORK_COMMAND_TOKEN,
NETWORK_COMMAND_MAX,
NETWORK_COMMAND_INVALID = -1
};
enum {
ADVERTISE_STATUS_DISABLED,
ADVERTISE_STATUS_UNREGISTERED,
@@ -115,94 +89,6 @@ static void network_get_private_key_path(utf8 *buffer, size_t bufferSize, const
static void network_get_public_key_path(utf8 *buffer, size_t bufferSize, const utf8 * playerName, const utf8 * hash);
static void network_get_keymap_path(utf8 *buffer, size_t bufferSize);
NetworkPacket::NetworkPacket()
{
transferred = 0;
read = 0;
size = 0;
data = std::make_shared<std::vector<uint8>>();
}
std::unique_ptr<NetworkPacket> NetworkPacket::Allocate()
{
return std::unique_ptr<NetworkPacket>(new NetworkPacket); // change to make_unique in c++14
}
std::unique_ptr<NetworkPacket> NetworkPacket::Duplicate(NetworkPacket& packet)
{
return std::unique_ptr<NetworkPacket>(new NetworkPacket(packet)); // change to make_unique in c++14
}
uint8* NetworkPacket::GetData()
{
return &(*data)[0];
}
uint32 NetworkPacket::GetCommand()
{
if (data->size() >= sizeof(uint32)) {
return ByteSwapBE(*(uint32*)(&(*data)[0]));
} else {
return NETWORK_COMMAND_INVALID;
}
}
void NetworkPacket::Write(const uint8* bytes, unsigned int size)
{
data->insert(data->end(), bytes, bytes + size);
}
void NetworkPacket::WriteString(const char* string)
{
Write((uint8*)string, strlen(string) + 1);
}
const uint8* NetworkPacket::Read(unsigned int size)
{
if (read + size > NetworkPacket::size) {
return 0;
} else {
uint8* data = &GetData()[read];
read += size;
return data;
}
}
const char* NetworkPacket::ReadString()
{
char* str = (char*)&GetData()[read];
char* strend = str;
while (read < size && *strend != 0) {
read++;
strend++;
}
if (*strend != 0) {
return nullptr;
}
read++;
return str;
}
void NetworkPacket::Clear()
{
transferred = 0;
read = 0;
data->clear();
}
bool NetworkPacket::CommandRequiresAuth()
{
switch (GetCommand()) {
case NETWORK_COMMAND_PING:
case NETWORK_COMMAND_AUTH:
case NETWORK_COMMAND_TOKEN:
case NETWORK_COMMAND_GAMEINFO:
return false;
default:
return true;
}
}
void NetworkPlayer::Read(NetworkPacket& packet)
{
const char* name = packet.ReadString();
@@ -371,172 +257,6 @@ void NetworkGroup::SetName(std::string name)
NetworkGroup::name = name;
}
NetworkConnection::NetworkConnection()
{
authstatus = NETWORK_AUTH_NONE;
player = 0;
socket = INVALID_SOCKET;
ResetLastPacketTime();
last_disconnect_reason = NULL;
}
NetworkConnection::~NetworkConnection()
{
if (socket != INVALID_SOCKET) {
closesocket(socket);
}
if (last_disconnect_reason) {
delete[] last_disconnect_reason;
}
}
int NetworkConnection::ReadPacket()
{
if (inboundpacket.transferred < sizeof(inboundpacket.size)) {
// read packet size
int readBytes = recv(socket, &((char*)&inboundpacket.size)[inboundpacket.transferred], sizeof(inboundpacket.size) - inboundpacket.transferred, 0);
if (readBytes == SOCKET_ERROR || readBytes == 0) {
if (LAST_SOCKET_ERROR() != EWOULDBLOCK && LAST_SOCKET_ERROR() != EAGAIN) {
return NETWORK_READPACKET_DISCONNECTED;
} else {
return NETWORK_READPACKET_NO_DATA;
}
}
inboundpacket.transferred += readBytes;
if (inboundpacket.transferred == sizeof(inboundpacket.size)) {
inboundpacket.size = ntohs(inboundpacket.size);
if(inboundpacket.size == 0){ // Can't have a size 0 packet
return NETWORK_READPACKET_DISCONNECTED;
}
inboundpacket.data->resize(inboundpacket.size);
}
} else {
// read packet data
if (inboundpacket.data->capacity() > 0) {
int readBytes = recv(socket, (char*)&inboundpacket.GetData()[inboundpacket.transferred - sizeof(inboundpacket.size)],
sizeof(inboundpacket.size) + inboundpacket.size - inboundpacket.transferred, 0);
if (readBytes == SOCKET_ERROR || readBytes == 0) {
if (LAST_SOCKET_ERROR() != EWOULDBLOCK && LAST_SOCKET_ERROR() != EAGAIN) {
return NETWORK_READPACKET_DISCONNECTED;
} else {
return NETWORK_READPACKET_NO_DATA;
}
}
inboundpacket.transferred += readBytes;
}
if (inboundpacket.transferred == sizeof(inboundpacket.size) + inboundpacket.size) {
last_packet_time = SDL_GetTicks();
return NETWORK_READPACKET_SUCCESS;
}
}
return NETWORK_READPACKET_MORE_DATA;
}
bool NetworkConnection::SendPacket(NetworkPacket& packet)
{
uint16 sizen = htons(packet.size);
std::vector<uint8> tosend;
tosend.reserve(sizeof(sizen) + packet.size);
tosend.insert(tosend.end(), (uint8*)&sizen, (uint8*)&sizen + sizeof(sizen));
tosend.insert(tosend.end(), packet.data->begin(), packet.data->end());
while (1) {
int sentBytes = send(socket, (const char*)&tosend[packet.transferred], tosend.size() - packet.transferred, FLAG_NO_PIPE);
if (sentBytes == SOCKET_ERROR) {
return false;
}
packet.transferred += sentBytes;
if (packet.transferred == tosend.size()) {
return true;
}
}
return false;
}
void NetworkConnection::QueuePacket(std::unique_ptr<NetworkPacket> packet, bool front)
{
if (authstatus == NETWORK_AUTH_OK || !packet->CommandRequiresAuth()) {
packet->size = (uint16)packet->data->size();
if (front) {
outboundpackets.push_front(std::move(packet));
} else {
outboundpackets.push_back(std::move(packet));
}
}
}
void NetworkConnection::SendQueuedPackets()
{
while (outboundpackets.size() > 0 && SendPacket(*(outboundpackets.front()).get())) {
outboundpackets.remove(outboundpackets.front());
}
}
bool NetworkConnection::SetTCPNoDelay(bool on)
{
return setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (const char*)&on, sizeof(on)) == 0;
}
bool NetworkConnection::SetNonBlocking(bool on)
{
return SetNonBlocking(socket, on);
}
bool NetworkConnection::SetNonBlocking(SOCKET socket, bool on)
{
#ifdef __WINDOWS__
u_long nonblocking = on;
return ioctlsocket(socket, FIONBIO, &nonblocking) == 0;
#else
int flags = fcntl(socket, F_GETFL, 0);
return fcntl(socket, F_SETFL, on ? (flags | O_NONBLOCK) : (flags & ~O_NONBLOCK)) == 0;
#endif
}
void NetworkConnection::ResetLastPacketTime()
{
last_packet_time = SDL_GetTicks();
}
bool NetworkConnection::ReceivedPacketRecently()
{
#ifndef DEBUG
if (SDL_TICKS_PASSED(SDL_GetTicks(), last_packet_time + 7000)) {
return false;
}
#endif
return true;
}
const char* NetworkConnection::getLastDisconnectReason() const
{
return this->last_disconnect_reason;
}
void NetworkConnection::setLastDisconnectReason(const char *src)
{
if (src == nullptr) {
if (last_disconnect_reason) {
delete[] last_disconnect_reason;
last_disconnect_reason = NULL;
}
return;
}
if (!last_disconnect_reason) {
last_disconnect_reason = new char[NETWORK_DISCONNECT_REASON_BUFFER_SIZE];
}
strncpy(last_disconnect_reason, src, NETWORK_DISCONNECT_REASON_BUFFER_SIZE - 1);
}
void NetworkConnection::setLastDisconnectReason(const rct_string_id string_id, void *args)
{
char buffer[NETWORK_DISCONNECT_REASON_BUFFER_SIZE];
format_string(buffer, string_id, args);
setLastDisconnectReason(buffer);
}
Network::Network()
{
wsa_initialized = false;