Browse Source

Services/UDS: Store the received beacon frames until RecvBeaconBroadcastData is called, up to 15 beacons at the same time, removing any older beacon frames when the limit is exceeded.

Subv 9 years ago
parent
commit
2e9f544ecc
1 changed files with 62 additions and 3 deletions
  1. 62 3
      src/core/hle/service/nwm/nwm_uds.cpp

+ 62 - 3
src/core/hle/service/nwm/nwm_uds.cpp

@@ -4,6 +4,7 @@
 
 
 #include <array>
 #include <array>
 #include <cstring>
 #include <cstring>
+#include <mutex>
 #include <unordered_map>
 #include <unordered_map>
 #include <vector>
 #include <vector>
 #include "common/common_types.h"
 #include "common/common_types.h"
@@ -15,8 +16,10 @@
 #include "core/hle/result.h"
 #include "core/hle/result.h"
 #include "core/hle/service/nwm/nwm_uds.h"
 #include "core/hle/service/nwm/nwm_uds.h"
 #include "core/hle/service/nwm/uds_beacon.h"
 #include "core/hle/service/nwm/uds_beacon.h"
+#include "core/hle/service/nwm/uds_connection.h"
 #include "core/hle/service/nwm/uds_data.h"
 #include "core/hle/service/nwm/uds_data.h"
 #include "core/memory.h"
 #include "core/memory.h"
+#include "network/network.h"
 
 
 namespace Service {
 namespace Service {
 namespace NWM {
 namespace NWM {
@@ -51,6 +54,52 @@ static NetworkInfo network_info;
 // Event that will generate and send the 802.11 beacon frames.
 // Event that will generate and send the 802.11 beacon frames.
 static int beacon_broadcast_event;
 static int beacon_broadcast_event;
 
 
+// Mutex to synchronize access to the list of received beacons between the emulation thread and the
+// network thread.
+static std::mutex beacon_mutex;
+
+// Number of beacons to store before we start dropping the old ones.
+// TODO(Subv): Find a more accurate value for this limit.
+constexpr size_t MaxBeaconFrames = 15;
+
+// List of the last <MaxBeaconFrames> beacons received from the network.
+static std::deque<Network::WifiPacket> received_beacons;
+
+/**
+ * Returns a list of received 802.11 beacon frames from the specified sender since the last call.
+ */
+std::deque<Network::WifiPacket> GetReceivedBeacons(const MacAddress& sender) {
+    std::lock_guard<std::mutex> lock(beacon_mutex);
+    // TODO(Subv): Filter by sender.
+    return std::move(received_beacons);
+}
+
+/// Sends a WifiPacket to the room we're currently connected to.
+void SendPacket(Network::WifiPacket& packet) {
+    // TODO(Subv): Implement.
+}
+
+// Inserts the received beacon frame in the beacon queue and removes any older beacons if the size
+// limit is exceeded.
+void HandleBeaconFrame(const Network::WifiPacket& packet) {
+    std::lock_guard<std::mutex> lock(beacon_mutex);
+
+    received_beacons.emplace_back(packet);
+
+    // Discard old beacons if the buffer is full.
+    if (received_beacons.size() > MaxBeaconFrames)
+        received_beacons.pop_front();
+}
+
+/// Callback to parse and handle a received wifi packet.
+void OnWifiPacketReceived(const Network::WifiPacket& packet) {
+    switch (packet.type) {
+    case Network::WifiPacket::PacketType::Beacon:
+        HandleBeaconFrame(packet);
+        break;
+    }
+}
+
 /**
 /**
  * NWM_UDS::Shutdown service function
  * NWM_UDS::Shutdown service function
  *  Inputs:
  *  Inputs:
@@ -111,8 +160,7 @@ static void RecvBeaconBroadcastData(Interface* self) {
     u32 total_size = sizeof(BeaconDataReplyHeader);
     u32 total_size = sizeof(BeaconDataReplyHeader);
 
 
     // Retrieve all beacon frames that were received from the desired mac address.
     // Retrieve all beacon frames that were received from the desired mac address.
-    std::deque<WifiPacket> beacons =
-        GetReceivedPackets(WifiPacket::PacketType::Beacon, mac_address);
+    auto beacons = GetReceivedBeacons(mac_address);
 
 
     BeaconDataReplyHeader data_reply_header{};
     BeaconDataReplyHeader data_reply_header{};
     data_reply_header.total_entries = beacons.size();
     data_reply_header.total_entries = beacons.size();
@@ -193,6 +241,9 @@ static void InitializeWithVersion(Interface* self) {
     rb.Push(RESULT_SUCCESS);
     rb.Push(RESULT_SUCCESS);
     rb.PushCopyHandles(Kernel::g_handle_table.Create(connection_status_event).Unwrap());
     rb.PushCopyHandles(Kernel::g_handle_table.Create(connection_status_event).Unwrap());
 
 
+    // TODO(Subv): Connect the OnWifiPacketReceived function to the wifi packet received callback of
+    // the room we're currently in.
+
     LOG_DEBUG(Service_NWM, "called sharedmem_size=0x%08X, version=0x%08X, sharedmem_handle=0x%08X",
     LOG_DEBUG(Service_NWM, "called sharedmem_size=0x%08X, version=0x%08X, sharedmem_handle=0x%08X",
               sharedmem_size, version, sharedmem_handle);
               sharedmem_size, version, sharedmem_handle);
 }
 }
@@ -610,9 +661,17 @@ static void BeaconBroadcastCallback(u64 userdata, int cycles_late) {
     if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost))
     if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost))
         return;
         return;
 
 
-    // TODO(Subv): Actually send the beacon.
     std::vector<u8> frame = GenerateBeaconFrame(network_info, node_info);
     std::vector<u8> frame = GenerateBeaconFrame(network_info, node_info);
 
 
+    using Network::WifiPacket;
+    WifiPacket packet;
+    packet.type = WifiPacket::PacketType::Beacon;
+    packet.data = std::move(frame);
+    packet.destination_address = Network::BroadcastMac;
+    packet.channel = network_channel;
+
+    SendPacket(packet);
+
     // Start broadcasting the network, send a beacon frame every 102.4ms.
     // Start broadcasting the network, send a beacon frame every 102.4ms.
     CoreTiming::ScheduleEvent(msToCycles(DefaultBeaconInterval * MillisecondsPerTU) - cycles_late,
     CoreTiming::ScheduleEvent(msToCycles(DefaultBeaconInterval * MillisecondsPerTU) - cycles_late,
                               beacon_broadcast_event, 0);
                               beacon_broadcast_event, 0);