diff --git a/commonLibs/livoxProto1/device.cpp b/commonLibs/livoxProto1/device.cpp index d50539f..e2788b4 100644 --- a/commonLibs/livoxProto1/device.cpp +++ b/commonLibs/livoxProto1/device.cpp @@ -1370,6 +1370,9 @@ public: // The timeout timer. boost::asio::deadline_timer timeoutTimer; + // Temporary point cloud data socket descriptor (for enable operations) + boost::asio::posix::stream_descriptor tmpPcloudEnableFdDesc; + // Received data storage uint8_t responseBuffer[1024]{}; ssize_t bytesReceived = -1; @@ -1382,7 +1385,8 @@ protected: smo::Callback cb) : smo::NonPostedAsynchronousContinuation(std::move(cb)), device(dev), - timeoutTimer(device.componentThread->getIoService()) + timeoutTimer(device.componentThread->getIoService()), + tmpPcloudEnableFdDesc(device.componentThread->getIoService()) {} public: @@ -1556,6 +1560,10 @@ protected: void cleanup() { timeoutTimer.cancel(); + if (tmpPcloudEnableFdDesc.is_open()) { + tmpPcloudEnableFdDesc.cancel(); + tmpPcloudEnableFdDesc.close(); + } } // Pure virtual methods that derived classes must implement @@ -1563,6 +1571,61 @@ protected: virtual const char* getCommandName() const = 0; virtual void setPcloudDataActiveState() = 0; + // Method to set up temporary point cloud data socket + bool setupTmpPcloudDataSocket() + { + // RAII class to manage socket file descriptor + struct SocketRAII + { + int fd; + SocketRAII(int socketFd) : fd(socketFd) {} + ~SocketRAII() { if (fd >= 0) close(fd); } + void release() { fd = -1; } // Release ownership, prevent close + int getFd() const { return fd; } + bool isValid() const { return fd >= 0; } + }; + + // Create UDP socket for point cloud data reception + SocketRAII socketGuard(socket(AF_INET, SOCK_DGRAM, 0)); + if (!socketGuard.isValid()) + { + std::cerr << __func__ << ": Failed to create socket: " + << strerror(errno) << std::endl; + return false; + } + + // Set socket to non-blocking mode + int flags = fcntl(socketGuard.getFd(), F_GETFL, 0); + if (flags < 0 || + fcntl(socketGuard.getFd(), F_SETFL, flags | O_NONBLOCK) < 0) + { + std::cerr << __func__ << ": Failed to set non-blocking mode: " + << strerror(errno) << std::endl; + return false; + } + + // Bind to the data port (65001) + struct sockaddr_in localAddr; + memset(&localAddr, 0, sizeof(localAddr)); + localAddr.sin_family = AF_INET; + localAddr.sin_addr.s_addr = INADDR_ANY; + localAddr.sin_port = htons(65001); // Data port + + if (bind( + socketGuard.getFd(), (struct sockaddr *)&localAddr, + sizeof(localAddr)) < 0) + { + std::cerr << __func__ << ": Failed to bind to data port: " + << strerror(errno) << std::endl; + return false; + } + + // Assign the file descriptor to the stream descriptor + tmpPcloudEnableFdDesc.assign(socketGuard.getFd()); + socketGuard.release(); + return true; + } + // Common sendCommand implementation bool sendCommand() { @@ -1648,6 +1711,17 @@ private: void setPcloudDataActiveState() override { + // Transfer ownership of the socket from temporary to main descriptor + if (tmpPcloudEnableFdDesc.is_open()) + { + int fd = tmpPcloudEnableFdDesc.native_handle(); + device.pcloudDataSocketDesc = + std::make_unique( + device.componentThread->getIoService(), fd); + + // Close the temporary descriptor (but don't close the fd) + tmpPcloudEnableFdDesc.release(); + } device.pcloudDataActive.store(true); } }; @@ -1662,7 +1736,8 @@ public: DisablePcloudDataReq( Device& dev, smo::Callback cb) - : EnDisablePcloudDataReq(dev, std::move(cb)) + : EnDisablePcloudDataReq( + dev, std::move(cb)) {} ~DisablePcloudDataReq() @@ -1703,10 +1778,10 @@ void Device::enablePcloudDataReq( return; } - // Set up the point cloud data socket for actual data reception - if (!setupPcloudDataSocket()) + // Set up the temporary point cloud data socket for actual data reception + if (!request->setupTmpPcloudDataSocket()) { - std::cerr << __func__ << ": Failed to set up point cloud data socket" + std::cerr << __func__ << ": Failed to set up transient pcloud data FD." << std::endl; request->callOriginalCallbackWithFailure(); return; @@ -1756,63 +1831,6 @@ void Device::disablePcloudDataReq( request->setupAsyncCallbacks(request); } -bool Device::setupPcloudDataSocket() -{ - // RAII class to manage socket file descriptor - struct SocketRAII - { - int fd; - SocketRAII(int socketFd) : fd(socketFd) {} - ~SocketRAII() { if (fd >= 0) close(fd); } - void release() { fd = -1; } // Release ownership, prevent close - int getFd() const { return fd; } - bool isValid() const { return fd >= 0; } - }; - - // Create UDP socket for point cloud data reception - SocketRAII socketGuard(socket(AF_INET, SOCK_DGRAM, 0)); - if (!socketGuard.isValid()) - { - std::cerr << __func__ << ": Failed to create socket: " - << strerror(errno) << std::endl; - return false; - } - - // Set socket to non-blocking mode - int flags = fcntl(socketGuard.getFd(), F_GETFL, 0); - if (flags < 0 || - fcntl(socketGuard.getFd(), F_SETFL, flags | O_NONBLOCK) < 0) - { - std::cerr << __func__ << ": Failed to set non-blocking mode: " - << strerror(errno) << std::endl; - return false; - } - - // Bind to the data port (65001) - struct sockaddr_in localAddr; - memset(&localAddr, 0, sizeof(localAddr)); - localAddr.sin_family = AF_INET; - localAddr.sin_addr.s_addr = INADDR_ANY; - localAddr.sin_port = htons(65001); // Data port - - if (bind( - socketGuard.getFd(), (struct sockaddr *)&localAddr, - sizeof(localAddr)) < 0) - { - std::cerr << __func__ << ": Failed to bind to data port: " - << strerror(errno) << std::endl; - return false; - } - - // Create boost wrapper for async operations - pcloudDataSocketDesc = - std::make_unique( - componentThread->getIoService(), socketGuard.getFd()); - - socketGuard.release(); - return true; -} - void Device::cleanupPcloudDataSocket() { if (pcloudDataSocketDesc) { diff --git a/commonLibs/livoxProto1/device.h b/commonLibs/livoxProto1/device.h index 923825b..c3adeb4 100644 --- a/commonLibs/livoxProto1/device.h +++ b/commonLibs/livoxProto1/device.h @@ -180,7 +180,6 @@ public: private: // Point cloud data setup - bool setupPcloudDataSocket(); void cleanupPcloudDataSocket(); // Command handler map