From f5e635addaef59159bf6bc529b17954eda3684a1 Mon Sep 17 00:00:00 2001 From: FearlessTobi Date: Sun, 31 Jul 2022 04:46:26 +0200 Subject: ldn: Initial implementation --- src/network/room.cpp | 63 +++++++++++++++++++++++++++++++++++++++++++++ src/network/room.h | 1 + src/network/room_member.cpp | 57 ++++++++++++++++++++++++++++++++++++++++ src/network/room_member.h | 35 ++++++++++++++++++++++++- 4 files changed, 155 insertions(+), 1 deletion(-) (limited to 'src/network') diff --git a/src/network/room.cpp b/src/network/room.cpp index 8c63b255b..dc5dbce7f 100644 --- a/src/network/room.cpp +++ b/src/network/room.cpp @@ -211,6 +211,12 @@ public: */ void HandleProxyPacket(const ENetEvent* event); + /** + * Broadcasts this packet to all members except the sender. + * @param event The ENet event containing the data + */ + void HandleLdnPacket(const ENetEvent* event); + /** * Extracts a chat entry from a received ENet packet and adds it to the chat queue. * @param event The ENet event that was received. @@ -247,6 +253,9 @@ void Room::RoomImpl::ServerLoop() { case IdProxyPacket: HandleProxyPacket(&event); break; + case IdLdnPacket: + HandleLdnPacket(&event); + break; case IdChatMessage: HandleChatPacket(&event); break; @@ -861,6 +870,60 @@ void Room::RoomImpl::HandleProxyPacket(const ENetEvent* event) { enet_host_flush(server); } +void Room::RoomImpl::HandleLdnPacket(const ENetEvent* event) { + Packet in_packet; + in_packet.Append(event->packet->data, event->packet->dataLength); + + in_packet.IgnoreBytes(sizeof(u8)); // Message type + + in_packet.IgnoreBytes(sizeof(u8)); // LAN packet type + in_packet.IgnoreBytes(sizeof(IPv4Address)); // Local IP + + IPv4Address remote_ip; + in_packet.Read(remote_ip); // Remote IP + + bool broadcast; + in_packet.Read(broadcast); // Broadcast + + Packet out_packet; + out_packet.Append(event->packet->data, event->packet->dataLength); + ENetPacket* enet_packet = enet_packet_create(out_packet.GetData(), out_packet.GetDataSize(), + ENET_PACKET_FLAG_RELIABLE); + + const auto& destination_address = remote_ip; + if (broadcast) { // Send the data to everyone except the sender + std::lock_guard lock(member_mutex); + bool sent_packet = false; + for (const auto& member : members) { + if (member.peer != event->peer) { + sent_packet = true; + enet_peer_send(member.peer, 0, enet_packet); + } + } + + if (!sent_packet) { + enet_packet_destroy(enet_packet); + } + } else { + std::lock_guard lock(member_mutex); + auto member = std::find_if(members.begin(), members.end(), + [destination_address](const Member& member_entry) -> bool { + return member_entry.fake_ip == destination_address; + }); + if (member != members.end()) { + enet_peer_send(member->peer, 0, enet_packet); + } else { + LOG_ERROR(Network, + "Attempting to send to unknown IP address: " + "{}.{}.{}.{}", + destination_address[0], destination_address[1], destination_address[2], + destination_address[3]); + enet_packet_destroy(enet_packet); + } + } + enet_host_flush(server); +} + void Room::RoomImpl::HandleChatPacket(const ENetEvent* event) { Packet in_packet; in_packet.Append(event->packet->data, event->packet->dataLength); diff --git a/src/network/room.h b/src/network/room.h index c2a4b1a70..edbd3ecfb 100644 --- a/src/network/room.h +++ b/src/network/room.h @@ -40,6 +40,7 @@ enum RoomMessageTypes : u8 { IdRoomInformation, IdSetGameInfo, IdProxyPacket, + IdLdnPacket, IdChatMessage, IdNameCollision, IdIpCollision, diff --git a/src/network/room_member.cpp b/src/network/room_member.cpp index 06818af78..572e55a5b 100644 --- a/src/network/room_member.cpp +++ b/src/network/room_member.cpp @@ -58,6 +58,7 @@ public: private: CallbackSet callback_set_proxy_packet; + CallbackSet callback_set_ldn_packet; CallbackSet callback_set_chat_messages; CallbackSet callback_set_status_messages; CallbackSet callback_set_room_information; @@ -107,6 +108,12 @@ public: */ void HandleProxyPackets(const ENetEvent* event); + /** + * Extracts an LdnPacket from a received ENet packet. + * @param event The ENet event that was received. + */ + void HandleLdnPackets(const ENetEvent* event); + /** * Extracts a chat entry from a received ENet packet and adds it to the chat queue. * @param event The ENet event that was received. @@ -166,6 +173,9 @@ void RoomMember::RoomMemberImpl::MemberLoop() { case IdProxyPacket: HandleProxyPackets(&event); break; + case IdLdnPacket: + HandleLdnPackets(&event); + break; case IdChatMessage: HandleChatPacket(&event); break; @@ -372,6 +382,27 @@ void RoomMember::RoomMemberImpl::HandleProxyPackets(const ENetEvent* event) { Invoke(proxy_packet); } +void RoomMember::RoomMemberImpl::HandleLdnPackets(const ENetEvent* event) { + LDNPacket ldn_packet{}; + Packet packet; + packet.Append(event->packet->data, event->packet->dataLength); + + // Ignore the first byte, which is the message id. + packet.IgnoreBytes(sizeof(u8)); // Ignore the message type + + u8 packet_type; + packet.Read(packet_type); + ldn_packet.type = static_cast(packet_type); + + packet.Read(ldn_packet.local_ip); + packet.Read(ldn_packet.remote_ip); + packet.Read(ldn_packet.broadcast); + + packet.Read(ldn_packet.data); + + Invoke(ldn_packet); +} + void RoomMember::RoomMemberImpl::HandleChatPacket(const ENetEvent* event) { Packet packet; packet.Append(event->packet->data, event->packet->dataLength); @@ -449,6 +480,11 @@ RoomMember::RoomMemberImpl::CallbackSet& RoomMember::RoomMemberImpl return callback_set_proxy_packet; } +template <> +RoomMember::RoomMemberImpl::CallbackSet& RoomMember::RoomMemberImpl::Callbacks::Get() { + return callback_set_ldn_packet; +} + template <> RoomMember::RoomMemberImpl::CallbackSet& RoomMember::RoomMemberImpl::Callbacks::Get() { @@ -607,6 +643,21 @@ void RoomMember::SendProxyPacket(const ProxyPacket& proxy_packet) { room_member_impl->Send(std::move(packet)); } +void RoomMember::SendLdnPacket(const LDNPacket& ldn_packet) { + Packet packet; + packet.Write(static_cast(IdLdnPacket)); + + packet.Write(static_cast(ldn_packet.type)); + + packet.Write(ldn_packet.local_ip); + packet.Write(ldn_packet.remote_ip); + packet.Write(ldn_packet.broadcast); + + packet.Write(ldn_packet.data); + + room_member_impl->Send(std::move(packet)); +} + void RoomMember::SendChatMessage(const std::string& message) { Packet packet; packet.Write(static_cast(IdChatMessage)); @@ -663,6 +714,11 @@ RoomMember::CallbackHandle RoomMember::BindOnProxyPacketReceived( return room_member_impl->Bind(callback); } +RoomMember::CallbackHandle RoomMember::BindOnLdnPacketReceived( + std::function callback) { + return room_member_impl->Bind(callback); +} + RoomMember::CallbackHandle RoomMember::BindOnRoomInformationChanged( std::function callback) { return room_member_impl->Bind(callback); @@ -699,6 +755,7 @@ void RoomMember::Leave() { } template void RoomMember::Unbind(CallbackHandle); +template void RoomMember::Unbind(CallbackHandle); template void RoomMember::Unbind(CallbackHandle); template void RoomMember::Unbind(CallbackHandle); template void RoomMember::Unbind(CallbackHandle); diff --git a/src/network/room_member.h b/src/network/room_member.h index f578f7f6a..0d6417294 100644 --- a/src/network/room_member.h +++ b/src/network/room_member.h @@ -17,7 +17,24 @@ namespace Network { using AnnounceMultiplayerRoom::GameInfo; using AnnounceMultiplayerRoom::RoomInformation; -/// Information about the received WiFi packets. +enum class LDNPacketType : u8 { + Scan, + ScanResp, + Connect, + SyncNetwork, + Disconnect, + DestroyNetwork, +}; + +struct LDNPacket { + LDNPacketType type; + IPv4Address local_ip; + IPv4Address remote_ip; + bool broadcast; + std::vector data; +}; + +/// Information about the received proxy packets. struct ProxyPacket { SockAddrIn local_endpoint; SockAddrIn remote_endpoint; @@ -151,6 +168,12 @@ public: */ void SendProxyPacket(const ProxyPacket& packet); + /** + * Sends an LDN packet to the room. + * @param packet The WiFi packet to send. + */ + void SendLdnPacket(const LDNPacket& packet); + /** * Sends a chat message to the room. * @param message The contents of the message. @@ -204,6 +227,16 @@ public: CallbackHandle BindOnProxyPacketReceived( std::function callback); + /** + * Binds a function to an event that will be triggered every time an LDNPacket is received. + * The function wil be called everytime the event is triggered. + * The callback function must not bind or unbind a function. Doing so will cause a deadlock + * @param callback The function to call + * @return A handle used for removing the function from the registered list + */ + CallbackHandle BindOnLdnPacketReceived( + std::function callback); + /** * Binds a function to an event that will be triggered every time the RoomInformation changes. * The function wil be called every time the event is triggered. -- cgit v1.2.3