| |
| |
|
|
| #include <cstddef> |
| #include <cstring> |
| #include "common/logging/log.h" |
| #include "input_common/helpers/udp_protocol.h" |
|
|
| namespace InputCommon::CemuhookUDP { |
|
|
| static constexpr std::size_t GetSizeOfResponseType(Type t) { |
| switch (t) { |
| case Type::Version: |
| return sizeof(Response::Version); |
| case Type::PortInfo: |
| return sizeof(Response::PortInfo); |
| case Type::PadData: |
| return sizeof(Response::PadData); |
| } |
| return 0; |
| } |
|
|
| namespace Response { |
|
|
| |
| |
| |
| |
| |
| |
| std::optional<Type> Validate(u8* data, std::size_t size) { |
| if (size < sizeof(Header)) { |
| return std::nullopt; |
| } |
| Header header{}; |
| std::memcpy(&header, data, sizeof(Header)); |
| if (header.magic != SERVER_MAGIC) { |
| LOG_ERROR(Input, "UDP Packet has an unexpected magic value"); |
| return std::nullopt; |
| } |
| if (header.protocol_version != PROTOCOL_VERSION) { |
| LOG_ERROR(Input, "UDP Packet protocol mismatch"); |
| return std::nullopt; |
| } |
| if (header.type < Type::Version || header.type > Type::PadData) { |
| LOG_ERROR(Input, "UDP Packet is an unknown type"); |
| return std::nullopt; |
| } |
|
|
| |
| |
| |
| |
| const std::size_t data_len = GetSizeOfResponseType(header.type); |
| if (header.payload_length != data_len + sizeof(Type) || size < data_len + sizeof(Header)) { |
| LOG_ERROR( |
| Input, |
| "UDP Packet payload length doesn't match. Received: {} PayloadLength: {} Expected: {}", |
| size, header.payload_length, data_len + sizeof(Type)); |
| return std::nullopt; |
| } |
|
|
| const u32 crc32 = header.crc; |
| boost::crc_32_type result; |
| |
| std::memset(&data[offsetof(Header, crc)], 0, sizeof(u32_le)); |
|
|
| result.process_bytes(data, data_len + sizeof(Header)); |
| if (crc32 != result.checksum()) { |
| LOG_ERROR(Input, "UDP Packet CRC check failed. Offset: {}", offsetof(Header, crc)); |
| return std::nullopt; |
| } |
| return header.type; |
| } |
| } |
|
|
| } |
|
|