mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Merge pull request #2831 from Subv/uds_auth
Services/UDS: Handle beacon frames and the basic AP connection sequence frames.
This commit is contained in:
		
						commit
						617b6974b9
					
				
					 7 changed files with 289 additions and 53 deletions
				
			
		|  | @ -145,6 +145,7 @@ set(SRCS | ||||||
|             hle/service/nwm/nwm_tst.cpp |             hle/service/nwm/nwm_tst.cpp | ||||||
|             hle/service/nwm/nwm_uds.cpp |             hle/service/nwm/nwm_uds.cpp | ||||||
|             hle/service/nwm/uds_beacon.cpp |             hle/service/nwm/uds_beacon.cpp | ||||||
|  |             hle/service/nwm/uds_connection.cpp | ||||||
|             hle/service/nwm/uds_data.cpp |             hle/service/nwm/uds_data.cpp | ||||||
|             hle/service/pm_app.cpp |             hle/service/pm_app.cpp | ||||||
|             hle/service/ptm/ptm.cpp |             hle/service/ptm/ptm.cpp | ||||||
|  | @ -344,6 +345,7 @@ set(HEADERS | ||||||
|             hle/service/nwm/nwm_tst.h |             hle/service/nwm/nwm_tst.h | ||||||
|             hle/service/nwm/nwm_uds.h |             hle/service/nwm/nwm_uds.h | ||||||
|             hle/service/nwm/uds_beacon.h |             hle/service/nwm/uds_beacon.h | ||||||
|  |             hle/service/nwm/uds_connection.h | ||||||
|             hle/service/nwm/uds_data.h |             hle/service/nwm/uds_data.h | ||||||
|             hle/service/pm_app.h |             hle/service/pm_app.h | ||||||
|             hle/service/ptm/ptm.h |             hle/service/ptm/ptm.h | ||||||
|  |  | ||||||
|  | @ -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,135 @@ 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(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Returns an available index in the nodes array for the | ||||||
|  |  * currently-hosted UDS network. | ||||||
|  |  */ | ||||||
|  | static u16 GetNextAvailableNodeId() { | ||||||
|  |     ASSERT_MSG(connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost), | ||||||
|  |                "Can not accept clients if we're not hosting a network"); | ||||||
|  | 
 | ||||||
|  |     for (u16 index = 0; index < connection_status.max_nodes; ++index) { | ||||||
|  |         if ((connection_status.node_bitmask & (1 << index)) == 0) | ||||||
|  |             return index; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Any connection attempts to an already full network should have been refused.
 | ||||||
|  |     ASSERT_MSG(false, "No available connection slots in the network"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Start a connection sequence with an UDS server. The sequence starts by sending an 802.11 | ||||||
|  |  * authentication frame with SEQ1. | ||||||
|  |  */ | ||||||
|  | void StartConnectionSequence(const MacAddress& server) { | ||||||
|  |     ASSERT(connection_status.status == static_cast<u32>(NetworkStatus::NotConnected)); | ||||||
|  | 
 | ||||||
|  |     // TODO(Subv): Handle timeout.
 | ||||||
|  | 
 | ||||||
|  |     // Send an authentication frame with SEQ1
 | ||||||
|  |     using Network::WifiPacket; | ||||||
|  |     WifiPacket auth_request; | ||||||
|  |     auth_request.channel = network_channel; | ||||||
|  |     auth_request.data = GenerateAuthenticationFrame(AuthenticationSeq::SEQ1); | ||||||
|  |     auth_request.destination_address = server; | ||||||
|  |     auth_request.type = WifiPacket::PacketType::Authentication; | ||||||
|  | 
 | ||||||
|  |     SendPacket(auth_request); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Sends an Association Response frame to the specified mac address
 | ||||||
|  | void SendAssociationResponseFrame(const MacAddress& address) { | ||||||
|  |     ASSERT_MSG(connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost)); | ||||||
|  | 
 | ||||||
|  |     using Network::WifiPacket; | ||||||
|  |     WifiPacket assoc_response; | ||||||
|  |     assoc_response.channel = network_channel; | ||||||
|  |     // TODO(Subv): This will cause multiple clients to end up with the same association id, but
 | ||||||
|  |     // we're not using that for anything.
 | ||||||
|  |     u16 association_id = 1; | ||||||
|  |     assoc_response.data = GenerateAssocResponseFrame(AssocStatus::Successful, association_id, | ||||||
|  |                                                      network_info.network_id); | ||||||
|  |     assoc_response.destination_address = address; | ||||||
|  |     assoc_response.type = WifiPacket::PacketType::AssociationResponse; | ||||||
|  | 
 | ||||||
|  |     SendPacket(assoc_response); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Handles the authentication request frame and sends the authentication response and association | ||||||
|  |  * response frames. Once an Authentication frame with SEQ1 is received by the server, it responds | ||||||
|  |  * with an Authentication frame containing SEQ2, and immediately sends an Association response frame | ||||||
|  |  * containing the details of the access point and the assigned association id for the new client. | ||||||
|  |  */ | ||||||
|  | void HandleAuthenticationFrame(const Network::WifiPacket& packet) { | ||||||
|  |     // Only the SEQ1 auth frame is handled here, the SEQ2 frame doesn't need any special behavior
 | ||||||
|  |     if (GetAuthenticationSeqNumber(packet.data) == AuthenticationSeq::SEQ1) { | ||||||
|  |         ASSERT_MSG(connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost)); | ||||||
|  | 
 | ||||||
|  |         // Respond with an authentication response frame with SEQ2
 | ||||||
|  |         using Network::WifiPacket; | ||||||
|  |         WifiPacket auth_request; | ||||||
|  |         auth_request.channel = network_channel; | ||||||
|  |         auth_request.data = GenerateAuthenticationFrame(AuthenticationSeq::SEQ2); | ||||||
|  |         auth_request.destination_address = packet.transmitter_address; | ||||||
|  |         auth_request.type = WifiPacket::PacketType::Authentication; | ||||||
|  | 
 | ||||||
|  |         SendPacket(auth_request); | ||||||
|  | 
 | ||||||
|  |         SendAssociationResponseFrame(packet.transmitter_address); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// 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; | ||||||
|  |     case Network::WifiPacket::PacketType::Authentication: | ||||||
|  |         HandleAuthenticationFrame(packet); | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * NWM_UDS::Shutdown service function |  * NWM_UDS::Shutdown service function | ||||||
|  *  Inputs: |  *  Inputs: | ||||||
|  | @ -111,8 +243,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 = |     auto beacons = GetReceivedBeacons(mac_address); | ||||||
|         GetReceivedPackets(WifiPacket::PacketType::Beacon, 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 +324,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,31 +744,22 @@ 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); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 |  | ||||||
|  * Returns an available index in the nodes array for the |  | ||||||
|  * currently-hosted UDS network. |  | ||||||
|  */ |  | ||||||
| static u32 GetNextAvailableNodeId() { |  | ||||||
|     ASSERT_MSG(connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost), |  | ||||||
|                "Can not accept clients if we're not hosting a network"); |  | ||||||
| 
 |  | ||||||
|     for (unsigned index = 0; index < connection_status.max_nodes; ++index) { |  | ||||||
|         if ((connection_status.node_bitmask & (1 << index)) == 0) |  | ||||||
|             return index; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Any connection attempts to an already full network should have been refused.
 |  | ||||||
|     ASSERT_MSG(false, "No available connection slots in the network"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /*
 | /*
 | ||||||
|  * Called when a client connects to an UDS network we're hosting, |  * Called when a client connects to an UDS network we're hosting, | ||||||
|  * updates the connection status and signals the update event. |  * updates the connection status and signals the update event. | ||||||
|  |  | ||||||
|  | @ -42,6 +42,7 @@ using NodeList = std::vector<NodeInfo>; | ||||||
| enum class NetworkStatus { | enum class NetworkStatus { | ||||||
|     NotConnected = 3, |     NotConnected = 3, | ||||||
|     ConnectedAsHost = 6, |     ConnectedAsHost = 6, | ||||||
|  |     Connecting = 7, | ||||||
|     ConnectedAsClient = 9, |     ConnectedAsClient = 9, | ||||||
|     ConnectedAsSpectator = 10, |     ConnectedAsSpectator = 10, | ||||||
| }; | }; | ||||||
|  | @ -85,6 +86,17 @@ static_assert(offsetof(NetworkInfo, oui_value) == 0xC, "oui_value is at the wron | ||||||
| static_assert(offsetof(NetworkInfo, wlan_comm_id) == 0x10, "wlancommid is at the wrong offset."); | static_assert(offsetof(NetworkInfo, wlan_comm_id) == 0x10, "wlancommid is at the wrong offset."); | ||||||
| static_assert(sizeof(NetworkInfo) == 0x108, "NetworkInfo has incorrect size."); | static_assert(sizeof(NetworkInfo) == 0x108, "NetworkInfo has incorrect size."); | ||||||
| 
 | 
 | ||||||
|  | /// Additional block tag ids in the Beacon and Association Response frames
 | ||||||
|  | enum class TagId : u8 { | ||||||
|  |     SSID = 0, | ||||||
|  |     SupportedRates = 1, | ||||||
|  |     DSParameterSet = 2, | ||||||
|  |     TrafficIndicationMap = 5, | ||||||
|  |     CountryInformation = 7, | ||||||
|  |     ERPInformation = 42, | ||||||
|  |     VendorSpecific = 221 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| class NWM_UDS final : public Interface { | class NWM_UDS final : public Interface { | ||||||
| public: | public: | ||||||
|     NWM_UDS(); |     NWM_UDS(); | ||||||
|  |  | ||||||
|  | @ -325,8 +325,5 @@ std::vector<u8> GenerateBeaconFrame(const NetworkInfo& network_info, const NodeL | ||||||
|     return buffer; |     return buffer; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::deque<WifiPacket> GetReceivedPackets(WifiPacket::PacketType type, const MacAddress& sender) { |  | ||||||
|     return {}; |  | ||||||
| } |  | ||||||
| } // namespace NWM
 | } // namespace NWM
 | ||||||
| } // namespace Service
 | } // namespace Service
 | ||||||
|  |  | ||||||
|  | @ -17,17 +17,6 @@ namespace NWM { | ||||||
| using MacAddress = std::array<u8, 6>; | using MacAddress = std::array<u8, 6>; | ||||||
| constexpr std::array<u8, 3> NintendoOUI = {0x00, 0x1F, 0x32}; | constexpr std::array<u8, 3> NintendoOUI = {0x00, 0x1F, 0x32}; | ||||||
| 
 | 
 | ||||||
| /// Additional block tag ids in the Beacon frames
 |  | ||||||
| enum class TagId : u8 { |  | ||||||
|     SSID = 0, |  | ||||||
|     SupportedRates = 1, |  | ||||||
|     DSParameterSet = 2, |  | ||||||
|     TrafficIndicationMap = 5, |  | ||||||
|     CountryInformation = 7, |  | ||||||
|     ERPInformation = 42, |  | ||||||
|     VendorSpecific = 221 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /**
 | /**
 | ||||||
|  * Internal vendor-specific tag ids as stored inside |  * Internal vendor-specific tag ids as stored inside | ||||||
|  * VendorSpecific blocks in the Beacon frames. |  * VendorSpecific blocks in the Beacon frames. | ||||||
|  | @ -135,20 +124,6 @@ struct BeaconData { | ||||||
| 
 | 
 | ||||||
| static_assert(sizeof(BeaconData) == 0x12, "BeaconData has incorrect size."); | static_assert(sizeof(BeaconData) == 0x12, "BeaconData has incorrect size."); | ||||||
| 
 | 
 | ||||||
| /// Information about a received WiFi packet.
 |  | ||||||
| /// Acts as our own 802.11 header.
 |  | ||||||
| struct WifiPacket { |  | ||||||
|     enum class PacketType { Beacon, Data }; |  | ||||||
| 
 |  | ||||||
|     PacketType type; ///< The type of 802.11 frame, Beacon / Data.
 |  | ||||||
| 
 |  | ||||||
|     /// Raw 802.11 frame data, starting at the management frame header for management frames.
 |  | ||||||
|     std::vector<u8> data; |  | ||||||
|     MacAddress transmitter_address; ///< Mac address of the transmitter.
 |  | ||||||
|     MacAddress destination_address; ///< Mac address of the receiver.
 |  | ||||||
|     u8 channel;                     ///< WiFi channel where this frame was transmitted.
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /**
 | /**
 | ||||||
|  * Decrypts the beacon data buffer for the network described by `network_info`. |  * Decrypts the beacon data buffer for the network described by `network_info`. | ||||||
|  */ |  */ | ||||||
|  | @ -161,10 +136,5 @@ void DecryptBeaconData(const NetworkInfo& network_info, std::vector<u8>& buffer) | ||||||
|  */ |  */ | ||||||
| std::vector<u8> GenerateBeaconFrame(const NetworkInfo& network_info, const NodeList& nodes); | std::vector<u8> GenerateBeaconFrame(const NetworkInfo& network_info, const NodeList& nodes); | ||||||
| 
 | 
 | ||||||
| /**
 |  | ||||||
|  * Returns a list of received 802.11 frames from the specified sender |  | ||||||
|  * matching the type since the last call. |  | ||||||
|  */ |  | ||||||
| std::deque<WifiPacket> GetReceivedPackets(WifiPacket::PacketType type, const MacAddress& sender); |  | ||||||
| } // namespace NWM
 | } // namespace NWM
 | ||||||
| } // namespace Service
 | } // namespace Service
 | ||||||
|  |  | ||||||
							
								
								
									
										79
									
								
								src/core/hle/service/nwm/uds_connection.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/core/hle/service/nwm/uds_connection.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,79 @@ | ||||||
|  | // Copyright 2017 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #include "core/hle/service/nwm/nwm_uds.h" | ||||||
|  | #include "core/hle/service/nwm/uds_connection.h" | ||||||
|  | #include "fmt/format.h" | ||||||
|  | 
 | ||||||
|  | namespace Service { | ||||||
|  | namespace NWM { | ||||||
|  | 
 | ||||||
|  | // Note: These values were taken from a packet capture of an o3DS XL
 | ||||||
|  | // broadcasting a Super Smash Bros. 4 lobby.
 | ||||||
|  | constexpr u16 DefaultExtraCapabilities = 0x0431; | ||||||
|  | 
 | ||||||
|  | std::vector<u8> GenerateAuthenticationFrame(AuthenticationSeq seq) { | ||||||
|  |     AuthenticationFrame frame{}; | ||||||
|  |     frame.auth_seq = static_cast<u16>(seq); | ||||||
|  | 
 | ||||||
|  |     std::vector<u8> data(sizeof(frame)); | ||||||
|  |     std::memcpy(data.data(), &frame, sizeof(frame)); | ||||||
|  | 
 | ||||||
|  |     return data; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | AuthenticationSeq GetAuthenticationSeqNumber(const std::vector<u8>& body) { | ||||||
|  |     AuthenticationFrame frame; | ||||||
|  |     std::memcpy(&frame, body.data(), sizeof(frame)); | ||||||
|  | 
 | ||||||
|  |     return static_cast<AuthenticationSeq>(frame.auth_seq); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Generates an SSID tag of an 802.11 Beacon frame with an 8-byte character representation of the | ||||||
|  |  * specified network id as the SSID value. | ||||||
|  |  * @param network_id The network id to use. | ||||||
|  |  * @returns A buffer with the SSID tag. | ||||||
|  |  */ | ||||||
|  | static std::vector<u8> GenerateSSIDTag(u32 network_id) { | ||||||
|  |     constexpr u8 SSIDSize = 8; | ||||||
|  | 
 | ||||||
|  |     struct { | ||||||
|  |         u8 id = static_cast<u8>(TagId::SSID); | ||||||
|  |         u8 size = SSIDSize; | ||||||
|  |     } tag_header; | ||||||
|  | 
 | ||||||
|  |     std::vector<u8> buffer(sizeof(tag_header) + SSIDSize); | ||||||
|  | 
 | ||||||
|  |     std::memcpy(buffer.data(), &tag_header, sizeof(tag_header)); | ||||||
|  | 
 | ||||||
|  |     std::string network_name = fmt::format("{0:08X}", network_id); | ||||||
|  | 
 | ||||||
|  |     std::memcpy(buffer.data() + sizeof(tag_header), network_name.c_str(), SSIDSize); | ||||||
|  | 
 | ||||||
|  |     return buffer; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::vector<u8> GenerateAssocResponseFrame(AssocStatus status, u16 association_id, u32 network_id) { | ||||||
|  |     AssociationResponseFrame frame{}; | ||||||
|  |     frame.capabilities = DefaultExtraCapabilities; | ||||||
|  |     frame.status_code = static_cast<u16>(status); | ||||||
|  |     // The association id is ORed with this magic value (0xC000)
 | ||||||
|  |     constexpr u16 AssociationIdMagic = 0xC000; | ||||||
|  |     frame.assoc_id = association_id | AssociationIdMagic; | ||||||
|  | 
 | ||||||
|  |     std::vector<u8> data(sizeof(frame)); | ||||||
|  |     std::memcpy(data.data(), &frame, sizeof(frame)); | ||||||
|  | 
 | ||||||
|  |     auto ssid_tag = GenerateSSIDTag(network_id); | ||||||
|  |     data.insert(data.end(), ssid_tag.begin(), ssid_tag.end()); | ||||||
|  | 
 | ||||||
|  |     // TODO(Subv): Add the SupportedRates tag.
 | ||||||
|  |     // TODO(Subv): Add the DSParameterSet tag.
 | ||||||
|  |     // TODO(Subv): Add the ERPInformation tag.
 | ||||||
|  |     return data; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace NWM
 | ||||||
|  | } // namespace Service
 | ||||||
							
								
								
									
										51
									
								
								src/core/hle/service/nwm/uds_connection.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/core/hle/service/nwm/uds_connection.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,51 @@ | ||||||
|  | // Copyright 2017 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <vector> | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "common/swap.h" | ||||||
|  | #include "core/hle/service/service.h" | ||||||
|  | 
 | ||||||
|  | namespace Service { | ||||||
|  | namespace NWM { | ||||||
|  | 
 | ||||||
|  | /// Sequence number of the 802.11 authentication frames.
 | ||||||
|  | enum class AuthenticationSeq : u16 { SEQ1 = 1, SEQ2 = 2 }; | ||||||
|  | 
 | ||||||
|  | enum class AuthAlgorithm : u16 { OpenSystem = 0 }; | ||||||
|  | 
 | ||||||
|  | enum class AuthStatus : u16 { Successful = 0 }; | ||||||
|  | 
 | ||||||
|  | enum class AssocStatus : u16 { Successful = 0 }; | ||||||
|  | 
 | ||||||
|  | struct AuthenticationFrame { | ||||||
|  |     u16_le auth_algorithm = static_cast<u16>(AuthAlgorithm::OpenSystem); | ||||||
|  |     u16_le auth_seq; | ||||||
|  |     u16_le status_code = static_cast<u16>(AuthStatus::Successful); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static_assert(sizeof(AuthenticationFrame) == 6, "AuthenticationFrame has wrong size"); | ||||||
|  | 
 | ||||||
|  | struct AssociationResponseFrame { | ||||||
|  |     u16_le capabilities; | ||||||
|  |     u16_le status_code; | ||||||
|  |     u16_le assoc_id; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static_assert(sizeof(AssociationResponseFrame) == 6, "AssociationResponseFrame has wrong size"); | ||||||
|  | 
 | ||||||
|  | /// Generates an 802.11 authentication frame, starting at the frame body.
 | ||||||
|  | std::vector<u8> GenerateAuthenticationFrame(AuthenticationSeq seq); | ||||||
|  | 
 | ||||||
|  | /// Returns the sequence number from the body of an Authentication frame.
 | ||||||
|  | AuthenticationSeq GetAuthenticationSeqNumber(const std::vector<u8>& body); | ||||||
|  | 
 | ||||||
|  | /// Generates an 802.11 association response frame with the specified status, association id and
 | ||||||
|  | /// network id, starting at the frame body.
 | ||||||
|  | std::vector<u8> GenerateAssocResponseFrame(AssocStatus status, u16 association_id, u32 network_id); | ||||||
|  | 
 | ||||||
|  | } // namespace NWM
 | ||||||
|  | } // namespace Service
 | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue