LivoxProto1: Document UDP demuxer purpose & use cases
Also fix bug in transient resource transfer from continuation to Device object.
This commit is contained in:
@@ -1714,13 +1714,13 @@ private:
|
|||||||
// Transfer ownership of the socket from temporary to main descriptor
|
// Transfer ownership of the socket from temporary to main descriptor
|
||||||
if (tmpPcloudEnableFdDesc.is_open())
|
if (tmpPcloudEnableFdDesc.is_open())
|
||||||
{
|
{
|
||||||
|
// Close the temporary descriptor (but don't close the fd)
|
||||||
int fd = tmpPcloudEnableFdDesc.native_handle();
|
int fd = tmpPcloudEnableFdDesc.native_handle();
|
||||||
|
tmpPcloudEnableFdDesc.release();
|
||||||
|
// Give the transient FD to the Device object.
|
||||||
device.pcloudDataSocketDesc =
|
device.pcloudDataSocketDesc =
|
||||||
std::make_unique<boost::asio::posix::stream_descriptor>(
|
std::make_unique<boost::asio::posix::stream_descriptor>(
|
||||||
device.componentThread->getIoService(), fd);
|
device.componentThread->getIoService(), fd);
|
||||||
|
|
||||||
// Close the temporary descriptor (but don't close the fd)
|
|
||||||
tmpPcloudEnableFdDesc.release();
|
|
||||||
}
|
}
|
||||||
device.pcloudDataActive.store(true);
|
device.pcloudDataActive.store(true);
|
||||||
}
|
}
|
||||||
@@ -1888,6 +1888,14 @@ void Device::registerUdpCommandHandler(
|
|||||||
const std::string& deviceIP
|
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);
|
auto key = std::make_pair(cmd_set, cmd_id);
|
||||||
udpCommandHandlers[key] = handler; // Don't move, we need to copy
|
udpCommandHandlers[key] = handler; // Don't move, we need to copy
|
||||||
|
|
||||||
|
|||||||
@@ -90,18 +90,6 @@ public:
|
|||||||
uint8_t smoSubnetNbits;
|
uint8_t smoSubnetNbits;
|
||||||
uint16_t dataPort, cmdPort, imuPort;
|
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:
|
private:
|
||||||
// Heartbeat mechanism
|
// Heartbeat mechanism
|
||||||
void startHeartbeat();
|
void startHeartbeat();
|
||||||
@@ -182,12 +170,47 @@ private:
|
|||||||
// Point cloud data setup
|
// Point cloud data setup
|
||||||
void cleanupPcloudDataSocket();
|
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
|
// Command handler map
|
||||||
std::unordered_map<
|
std::unordered_map<
|
||||||
std::pair<uint8_t, uint8_t>,
|
std::pair<uint8_t, uint8_t>,
|
||||||
std::function<void(
|
std::function<void(
|
||||||
const uint8_t* data, ssize_t bytesReceived,
|
const uint8_t* data, ssize_t bytesReceived,
|
||||||
const struct sockaddr_in& senderAddr)>> udpCommandHandlers;
|
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
|
} // namespace livoxProto1
|
||||||
|
|||||||
@@ -20,6 +20,17 @@ namespace comms {
|
|||||||
* This class listens on the command port (65000) for incoming UDP datagrams
|
* This class listens on the command port (65000) for incoming UDP datagrams
|
||||||
* from Livox devices and routes them to the appropriate Device based on
|
* from Livox devices and routes them to the appropriate Device based on
|
||||||
* the source IP address.
|
* 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
|
class UdpCommandDemuxer
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user