LivoxProto1: Document UDP demuxer purpose & use cases

Also fix bug in transient resource transfer from continuation
to Device object.
This commit is contained in:
2025-10-24 03:09:17 -04:00
parent f7dcb7307d
commit 452d1966fc
3 changed files with 57 additions and 15 deletions
+11 -3
View File
@@ -1714,13 +1714,13 @@ private:
// Transfer ownership of the socket from temporary to main descriptor
if (tmpPcloudEnableFdDesc.is_open())
{
// Close the temporary descriptor (but don't close the fd)
int fd = tmpPcloudEnableFdDesc.native_handle();
tmpPcloudEnableFdDesc.release();
// Give the transient FD to the Device object.
device.pcloudDataSocketDesc =
std::make_unique<boost::asio::posix::stream_descriptor>(
device.componentThread->getIoService(), fd);
// Close the temporary descriptor (but don't close the fd)
tmpPcloudEnableFdDesc.release();
}
device.pcloudDataActive.store(true);
}
@@ -1888,6 +1888,14 @@ void Device::registerUdpCommandHandler(
const std::string& deviceIP
)
{
/** EXPLANATION:
* Register a UDP command handler for the given cmd_set and cmd_id.
* If the handler already exists for the given device IP, replace it.
* If the handler does not exist, add it to the temporary collection.
*
* Adding a handler to a cmd_set+cmd_id pair which already has a handler
* results in the new handler replacing the old one.
*/
auto key = std::make_pair(cmd_set, cmd_id);
udpCommandHandlers[key] = handler; // Don't move, we need to copy
+35 -12
View File
@@ -90,18 +90,6 @@ public:
uint8_t smoSubnetNbits;
uint16_t dataPort, cmdPort, imuPort;
// Static collection for devices being constructed (not yet in DeviceManager)
// Maps device IP to list of command-specific UDP handlers for that device
struct CommandHandler {
uint8_t cmd_set;
uint8_t cmd_id;
std::function<void(
const uint8_t* data, ssize_t bytesReceived,
const struct sockaddr_in& senderAddr)> handler;
};
static std::unordered_map<std::string, std::vector<CommandHandler>>
devicesUnderConstruction;
private:
// Heartbeat mechanism
void startHeartbeat();
@@ -182,12 +170,47 @@ private:
// Point cloud data setup
void cleanupPcloudDataSocket();
/** EXPLANATION:
* This is the "straightforward" map of command set and command id to
* handlers. This is useful for any commands which are guaranteed to be
* issued to the device *AFTER* the device has successfully been added
* to the DeviceManager's list of devices.
*
* I.e: it cannot be used for commands which are issued to the device before
* getOrCreateDevice() has added the device to the DeviceManager's list of
* devices.
*/
// Command handler map
std::unordered_map<
std::pair<uint8_t, uint8_t>,
std::function<void(
const uint8_t* data, ssize_t bytesReceived,
const struct sockaddr_in& senderAddr)>> udpCommandHandlers;
public:
/** EXPLANATION:
* This is the "temporary" map of command set and command id to
* handlers. This is useful for any commands which are issued to the device
* while it is being constructed.
*
* I.e: it shouldn't be used for cmds which are issued to the device after
* getOrCreateDevice() has added the device to the DeviceManager's list of
* devices. It will work for such commands, but we'd kind of prefer to use
* the "straightforward" map above for such commands.
*
* NOTE:
* There's a strong argument to be made for just getting rid of the
* "straightforward" map above and just using this one, tho.
*/
struct CommandHandler {
uint8_t cmd_set;
uint8_t cmd_id;
std::function<void(
const uint8_t* data, ssize_t bytesReceived,
const struct sockaddr_in& senderAddr)> handler;
};
static std::unordered_map<std::string, std::vector<CommandHandler>>
devicesUnderConstruction;
};
} // namespace livoxProto1
@@ -20,6 +20,17 @@ namespace comms {
* This class listens on the command port (65000) for incoming UDP datagrams
* from Livox devices and routes them to the appropriate Device based on
* the source IP address.
*
* The reason we need a whole class for this is because we use the same port
* numbers for all connected devices, so we have no way to distinguish between
* devices except based on the devices' IP addrs. Since all commands are sent
* over UDP, our sockets don't have built-in binding to a specific source IP.
*
* So we need to discriminate between source IPs manually, and demultiplex
* the dgrams received from different devices manually.
*
* We'll prolly also have to do the same thing for point cloud and IMU data, so
* we'll prolly end up renaming this class to UdpResponseDemuxer.
*/
class UdpCommandDemuxer
{