mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	Services/UDS: Handle the connection sequence packets.
There is currently no stage tracking, a client is considered "Connected" when it receives the EAPoL Logoff packet from the server, this is not yet implemented.
This commit is contained in:
		@@ -91,12 +91,95 @@ void HandleBeaconFrame(const Network::WifiPacket& packet) {
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -677,23 +760,6 @@ static void BeaconBroadcastCallback(u64 userdata, int cycles_late) {
 | 
			
		||||
                              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,
 | 
			
		||||
 * updates the connection status and signals the update event.
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user