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:
Subv 2017-07-17 09:51:03 -05:00
parent 2e9f544ecc
commit d088dbfbe1
1 changed files with 83 additions and 17 deletions

View File

@ -91,12 +91,95 @@ void HandleBeaconFrame(const Network::WifiPacket& packet) {
received_beacons.pop_front(); 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. /// Callback to parse and handle a received wifi packet.
void OnWifiPacketReceived(const Network::WifiPacket& packet) { void OnWifiPacketReceived(const Network::WifiPacket& packet) {
switch (packet.type) { switch (packet.type) {
case Network::WifiPacket::PacketType::Beacon: case Network::WifiPacket::PacketType::Beacon:
HandleBeaconFrame(packet); HandleBeaconFrame(packet);
break; 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); 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.