summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/service/nwm/nwm_uds.cpp100
1 files changed, 83 insertions, 17 deletions
diff --git a/src/core/hle/service/nwm/nwm_uds.cpp b/src/core/hle/service/nwm/nwm_uds.cpp
index 8fdf160ff..893bbb1e7 100644
--- a/src/core/hle/service/nwm/nwm_uds.cpp
+++ b/src/core/hle/service/nwm/nwm_uds.cpp
@@ -91,12 +91,95 @@ void HandleBeaconFrame(const Network::WifiPacket& packet) {
91 received_beacons.pop_front(); 91 received_beacons.pop_front();
92} 92}
93 93
94/*
95 * Returns an available index in the nodes array for the
96 * currently-hosted UDS network.
97 */
98static u16 GetNextAvailableNodeId() {
99 ASSERT_MSG(connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost),
100 "Can not accept clients if we're not hosting a network");
101
102 for (u16 index = 0; index < connection_status.max_nodes; ++index) {
103 if ((connection_status.node_bitmask & (1 << index)) == 0)
104 return index;
105 }
106
107 // Any connection attempts to an already full network should have been refused.
108 ASSERT_MSG(false, "No available connection slots in the network");
109}
110
111/*
112 * Start a connection sequence with an UDS server. The sequence starts by sending an 802.11
113 * authentication frame with SEQ1.
114 */
115void StartConnectionSequence(const MacAddress& server) {
116 ASSERT(connection_status.status == static_cast<u32>(NetworkStatus::NotConnected));
117
118 // TODO(Subv): Handle timeout.
119
120 // Send an authentication frame with SEQ1
121 using Network::WifiPacket;
122 WifiPacket auth_request;
123 auth_request.channel = network_channel;
124 auth_request.data = GenerateAuthenticationFrame(AuthenticationSeq::SEQ1);
125 auth_request.destination_address = server;
126 auth_request.type = WifiPacket::PacketType::Authentication;
127
128 SendPacket(auth_request);
129}
130
131/// Sends an Association Response frame to the specified mac address
132void SendAssociationResponseFrame(const MacAddress& address) {
133 ASSERT_MSG(connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost));
134
135 using Network::WifiPacket;
136 WifiPacket assoc_response;
137 assoc_response.channel = network_channel;
138 // TODO(Subv): This will cause multiple clients to end up with the same association id, but
139 // we're not using that for anything.
140 u16 association_id = 1;
141 assoc_response.data = GenerateAssocResponseFrame(AssocStatus::Successful, association_id,
142 network_info.network_id);
143 assoc_response.destination_address = address;
144 assoc_response.type = WifiPacket::PacketType::AssociationResponse;
145
146 SendPacket(assoc_response);
147}
148
149/*
150 * Handles the authentication request frame and sends the authentication response and association
151 * response frames. Once an Authentication frame with SEQ1 is received by the server, it responds
152 * with an Authentication frame containing SEQ2, and immediately sends an Association response frame
153 * containing the details of the access point and the assigned association id for the new client.
154 */
155void HandleAuthenticationFrame(const Network::WifiPacket& packet) {
156 // Only the SEQ1 auth frame is handled here, the SEQ2 frame doesn't need any special behavior
157 if (GetAuthenticationSeqNumber(packet.data) == AuthenticationSeq::SEQ1) {
158 ASSERT_MSG(connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost));
159
160 // Respond with an authentication response frame with SEQ2
161 using Network::WifiPacket;
162 WifiPacket auth_request;
163 auth_request.channel = network_channel;
164 auth_request.data = GenerateAuthenticationFrame(AuthenticationSeq::SEQ2);
165 auth_request.destination_address = packet.transmitter_address;
166 auth_request.type = WifiPacket::PacketType::Authentication;
167
168 SendPacket(auth_request);
169
170 SendAssociationResponseFrame(packet.transmitter_address);
171 }
172}
173
94/// Callback to parse and handle a received wifi packet. 174/// Callback to parse and handle a received wifi packet.
95void OnWifiPacketReceived(const Network::WifiPacket& packet) { 175void OnWifiPacketReceived(const Network::WifiPacket& packet) {
96 switch (packet.type) { 176 switch (packet.type) {
97 case Network::WifiPacket::PacketType::Beacon: 177 case Network::WifiPacket::PacketType::Beacon:
98 HandleBeaconFrame(packet); 178 HandleBeaconFrame(packet);
99 break; 179 break;
180 case Network::WifiPacket::PacketType::Authentication:
181 HandleAuthenticationFrame(packet);
182 break;
100 } 183 }
101} 184}
102 185
@@ -678,23 +761,6 @@ static void BeaconBroadcastCallback(u64 userdata, int cycles_late) {
678} 761}
679 762
680/* 763/*
681 * Returns an available index in the nodes array for the
682 * currently-hosted UDS network.
683 */
684static u32 GetNextAvailableNodeId() {
685 ASSERT_MSG(connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost),
686 "Can not accept clients if we're not hosting a network");
687
688 for (unsigned index = 0; index < connection_status.max_nodes; ++index) {
689 if ((connection_status.node_bitmask & (1 << index)) == 0)
690 return index;
691 }
692
693 // Any connection attempts to an already full network should have been refused.
694 ASSERT_MSG(false, "No available connection slots in the network");
695}
696
697/*
698 * Called when a client connects to an UDS network we're hosting, 764 * Called when a client connects to an UDS network we're hosting,
699 * updates the connection status and signals the update event. 765 * updates the connection status and signals the update event.
700 * @param network_node_id Network Node Id of the connecting client. 766 * @param network_node_id Network Node Id of the connecting client.