Use separate network messages handling table

This commit is contained in:
Wojciech Figat
2022-09-13 16:25:48 +02:00
parent de1437102e
commit 9a19717556

View File

@@ -29,6 +29,8 @@ enum class NetworkMessageIDs : uint8
None = 0,
Handshake,
HandshakeReply,
MAX,
};
PACK_STRUCT(struct NetworkMessageHandshake
@@ -48,11 +50,76 @@ PACK_STRUCT(struct NetworkMessageHandshakeReply
int32 Result;
});
void OnNetworkMessageHandshake(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer)
{
// Read client connection data
NetworkMessageHandshake msgData;
event.Message.ReadStructure(msgData);
NetworkClientConnectionData connectionData;
connectionData.Client = client;
connectionData.Result = 0;
connectionData.Platform = (PlatformType)msgData.Platform;
connectionData.Architecture = (ArchitectureType)msgData.Architecture;
connectionData.PayloadData.Resize(msgData.PayloadDataSize);
event.Message.ReadBytes(connectionData.PayloadData.Get(), msgData.PayloadDataSize);
NetworkManager::ClientConnecting(connectionData); // Allow server to validate connection
// Reply to the handshake message with a result
NetworkMessageHandshakeReply replyData;
replyData.ID = NetworkMessageIDs::HandshakeReply;
replyData.Result = connectionData.Result;
NetworkMessage msgReply = peer->BeginSendMessage();
msgReply.WriteStructure(replyData);
peer->EndSendMessage(NetworkChannelType::ReliableOrdered, msgReply, event.Sender);
// Update client based on connection result
if (connectionData.Result != 0)
{
LOG(Info, "Connection blocked with result {0} from client id={1}.", connectionData.Result, event.Sender.ConnectionId);
client->State = NetworkConnectionState::Disconnecting;
peer->Disconnect(event.Sender);
client->State = NetworkConnectionState::Disconnected;
}
else
{
client->State = NetworkConnectionState::Connected;
LOG(Info, "Client id={0} connected", event.Sender.ConnectionId);
NetworkManager::ClientConnected(client);
}
}
void OnNetworkMessageHandshakeReply(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer)
{
ASSERT_LOW_LAYER(NetworkManager::IsClient());
NetworkMessageHandshakeReply msgData;
event.Message.ReadStructure(msgData);
if (msgData.Result != 0)
{
// Server failed to connect with client
// TODO: feed game with result from msgData.Result
NetworkManager::Stop();
return;
}
// Client got connected with server
NetworkManager::LocalClient->State = NetworkConnectionState::Connected;
NetworkManager::State = NetworkConnectionState::Connected;
NetworkManager::StateChanged();
}
namespace
{
NetworkPeer* Peer = nullptr;
uint32 GameProtocolVersion = 0;
double LastUpdateTime = 0;
// Network message handlers table
void (*MessageHandlers[(int32)NetworkMessageIDs::MAX])(NetworkEvent&, NetworkClient*, NetworkPeer*) =
{
nullptr,
OnNetworkMessageHandshake,
OnNetworkMessageHandshakeReply,
};
}
class NetworkManagerService : public EngineService
@@ -328,69 +395,13 @@ void NetworkManagerService::Update()
break;
}
uint8 id = *event.Message.Buffer;
switch ((NetworkMessageIDs)id)
if (id < (uint8)NetworkMessageIDs::MAX)
{
MessageHandlers[id](event, client, Peer);
}
else
{
case NetworkMessageIDs::Handshake:
{
// Read client connection data
NetworkMessageHandshake msgData;
event.Message.ReadStructure(msgData);
NetworkClientConnectionData connectionData;
connectionData.Client = client;
connectionData.Result = 0;
connectionData.Platform = (PlatformType)msgData.Platform;
connectionData.Architecture = (ArchitectureType)msgData.Architecture;
connectionData.PayloadData.Resize(msgData.PayloadDataSize);
event.Message.ReadBytes(connectionData.PayloadData.Get(), msgData.PayloadDataSize);
NetworkManager::ClientConnecting(connectionData); // Allow server to validate connection
// Reply to the handshake message with a result
NetworkMessageHandshakeReply replyData;
replyData.ID = NetworkMessageIDs::HandshakeReply;
replyData.Result = connectionData.Result;
NetworkMessage msgReply = Peer->BeginSendMessage();
msgReply.WriteStructure(replyData);
Peer->EndSendMessage(NetworkChannelType::ReliableOrdered, msgReply, event.Sender);
// Update client based on connection result
if (connectionData.Result != 0)
{
LOG(Info, "Connection blocked with result {0} from client id={1}.", connectionData.Result, event.Sender.ConnectionId);
client->State = NetworkConnectionState::Disconnecting;
Peer->Disconnect(event.Sender);
client->State = NetworkConnectionState::Disconnected;
}
else
{
client->State = NetworkConnectionState::Connected;
LOG(Info, "Client id={0} connected", event.Sender.ConnectionId);
NetworkManager::ClientConnected(client);
}
break;
}
case NetworkMessageIDs::HandshakeReply:
{
ASSERT_LOW_LAYER(NetworkManager::IsClient());
NetworkMessageHandshakeReply msgData;
event.Message.ReadStructure(msgData);
if (msgData.Result != 0)
{
// Server failed to connect with client
// TODO: feed game with result from msgData.Result
NetworkManager::Stop();
return;
}
// Client got connected with server
NetworkManager::LocalClient->State = NetworkConnectionState::Connected;
NetworkManager::State = NetworkConnectionState::Connected;
NetworkManager::StateChanged();
break;
}
#if !BUILD_RELEASE
default:
LOG(Warning, "Unknown message id={0} from connection {1}", id, event.Sender.ConnectionId);
#endif
}
}
Peer->RecycleMessage(event.Message);