#include "ANSONVIF.h" #include #include #include #include "bm\sys_inc.h" #include "bm\linked_list.h" #include "http\http.h" #include "http\http_parse.h" #include "onvif\onvif_probe.h" #include "onvif\onvif_event.h" #include "onvif\onvif_api.h" #include #include #include // Handle registry with refcount — prevents use-after-free when // ReleaseANSOnvifHandle is called while an operation is still running. static std::unordered_map& OnvifHandleRegistry() { static std::unordered_map s; return s; } static std::mutex& OnvifHandleRegistryMutex() { static std::mutex m; return m; } static std::condition_variable& OnvifHandleRegistryCV() { static std::condition_variable cv; return cv; } static void RegisterOnvifHandle(ANSCENTER::ANSOnvifClient* h) { std::lock_guard lk(OnvifHandleRegistryMutex()); OnvifHandleRegistry()[h] = 1; } static ANSCENTER::ANSOnvifClient* AcquireOnvifHandle(ANSCENTER::ANSOnvifClient* h) { std::lock_guard lk(OnvifHandleRegistryMutex()); auto it = OnvifHandleRegistry().find(h); if (it == OnvifHandleRegistry().end()) return nullptr; it->second++; return h; } static bool ReleaseOnvifHandleRef(ANSCENTER::ANSOnvifClient* h) { std::lock_guard lk(OnvifHandleRegistryMutex()); auto it = OnvifHandleRegistry().find(h); if (it == OnvifHandleRegistry().end()) return false; it->second--; if (it->second <= 0) { OnvifHandleRegistry().erase(it); OnvifHandleRegistryCV().notify_all(); return true; } return false; } static bool UnregisterOnvifHandle(ANSCENTER::ANSOnvifClient* h) { std::unique_lock lk(OnvifHandleRegistryMutex()); auto it = OnvifHandleRegistry().find(h); if (it == OnvifHandleRegistry().end()) return false; it->second--; bool ok = OnvifHandleRegistryCV().wait_for(lk, std::chrono::seconds(30), [&]() { auto it2 = OnvifHandleRegistry().find(h); return it2 == OnvifHandleRegistry().end() || it2->second <= 0; }); if (!ok) { OutputDebugStringA("WARNING: UnregisterOnvifHandle timed out waiting for in-flight operations\n"); } OnvifHandleRegistry().erase(h); return true; } // RAII guard — ensures ReleaseOnvifHandleRef is always called class OnvifHandleGuard { ANSCENTER::ANSOnvifClient* engine; public: explicit OnvifHandleGuard(ANSCENTER::ANSOnvifClient* e) : engine(e) {} ~OnvifHandleGuard() { if (engine) ReleaseOnvifHandleRef(engine); } ANSCENTER::ANSOnvifClient* get() const { return engine; } explicit operator bool() const { return engine != nullptr; } OnvifHandleGuard(const OnvifHandleGuard&) = delete; OnvifHandleGuard& operator=(const OnvifHandleGuard&) = delete; }; static bool ansonvifLicenceValid = false; // Global once_flag to protect license checking static std::once_flag ansonvifLicenseOnceFlag; namespace ANSCENTER { static void VerifyGlobalANSONVIFLicense(const std::string& licenseKey) { try { std::cout << "ANSOnvifClient::CheckLicense.", "Checking ONVIF license. Please wait...."; ansonvifLicenceValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(licenseKey, 1007, "ANSCV");// if (!ansonvifLicenceValid)ansonvifLicenceValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(licenseKey, 1003, "ANSVIS");//Default productId=1005 if (!ansonvifLicenceValid) std::cerr << "ANSOnvifClient::CheckLicense.", "Invalid ONVIF license. Please activate correct license."; else std::cout << "ANSOnvifClient::CheckLicense.", "Valid ONVIF license."; } catch (std::exception& e) { std::cerr << "ANSOnvifClient::CheckLicense()" << e.what(); ansonvifLicenceValid = false; } } //Private methods void ANSOnvifClient::GetDevInfo(ONVIF_DEVICE_EX* p_device) { char profileToken[ONVIF_TOKEN_LEN]; ONVIF_PROFILE* p_profile = nullptr; GetSystemDateAndTime(&p_device->onvif_device); GetCapabilities(&p_device->onvif_device); GetServices(&p_device->onvif_device); GetDeviceInformation(&p_device->onvif_device); GetVideoSources(&p_device->onvif_device); GetImagingSettings(&p_device->onvif_device); GetVideoSourceConfigurations(&p_device->onvif_device); GetVideoEncoderConfigurations(&p_device->onvif_device); if (GetAudioSources(&p_device->onvif_device)) { GetAudioSourceConfigurations(&p_device->onvif_device); GetAudioEncoderConfigurations(&p_device->onvif_device); } if (p_device->onvif_device.Capabilities.ptz.support) { GetNodes(&p_device->onvif_device); GetConfigurations(&p_device->onvif_device); } if (p_device->onvif_device.curProfile) { strcpy(profileToken, p_device->onvif_device.curProfile->token); } else { memset(profileToken, 0, sizeof(profileToken)); } if (profileToken[0] != '\0') { p_profile = onvif_find_profile(p_device->onvif_device.profiles, profileToken); } if (nullptr ==p_profile) { p_profile = p_device->onvif_device.profiles; } p_device->onvif_device.curProfile = p_profile; if (p_device->onvif_device.curProfile == nullptr) { p_device->thread_handler = 0; return ; } if (p_profile) { int len; uint8* p_buff; if (GetSnapshot(&p_device->onvif_device, p_profile->token, &p_buff, &len)) { if (p_device->snapshot) { FreeBuff(p_device->snapshot); p_device->snapshot = nullptr; p_device->snapshot_len = 0; } p_device->snapshot = p_buff; p_device->snapshot_len = len; } } if (p_device->onvif_device.Capabilities.events.support == 1 && p_device->onvif_device.events.subscribe == FALSE) { Subscribe(&p_device->onvif_device, pps_get_index(m_dev_ul, p_device)); } } ONVIF_DEVICE_EX* ANSOnvifClient::FindDevice(ONVIF_DEVICE_EX* pdevice) { ONVIF_DEVICE_EX* p_dev = static_cast(pps_lookup_start(m_dev_ul)); while (p_dev) { if (strcmp(p_dev->onvif_device.binfo.XAddr.host, pdevice->onvif_device.binfo.XAddr.host) == 0 && p_dev->onvif_device.binfo.XAddr.port == pdevice->onvif_device.binfo.XAddr.port) { break; } p_dev = static_cast(pps_lookup_next(m_dev_ul, p_dev)); } pps_lookup_end(m_dev_ul); return p_dev; } ONVIF_DEVICE_EX* ANSOnvifClient::FindDeviceByEndpointReference(char* p_EndpointReference) { ONVIF_DEVICE_EX* p_dev = static_cast(pps_lookup_start(m_dev_ul)); while (p_dev) { if (strcmp(p_dev->onvif_device.binfo.EndpointReference, p_EndpointReference) == 0) { break; } p_dev = static_cast(pps_lookup_next(m_dev_ul, p_dev)); } pps_lookup_end(m_dev_ul); return p_dev; } ONVIF_DEVICE_EX* ANSOnvifClient::AddDevice(ONVIF_DEVICE_EX* pdevice) { ONVIF_DEVICE_EX* p_dev = static_cast(pps_fl_pop(m_dev_fl)); if (p_dev) { memcpy(p_dev, pdevice, sizeof(ONVIF_DEVICE_EX)); p_dev->p_user = 0; p_dev->onvif_device.events.init_term_time = 60; onvif_SetAuthInfo(&p_dev->onvif_device, "admin", "admin"); onvif_SetAuthMethod(&p_dev->onvif_device, AuthMethod_UsernameToken); onvif_SetReqTimeout(&p_dev->onvif_device, 10000); pps_ctx_ul_add(m_dev_ul, p_dev); } return p_dev; } void ANSOnvifClient::UpdateDevice(ONVIF_DEVICE_EX* p_device) { if (nullptr ==p_device) { return; } if (p_device->thread_handler) { return; } BOOL need_update = FALSE; if (p_device->need_update) { need_update = TRUE; } if (!p_device->onvif_device.authFailed) { if (nullptr ==p_device->onvif_device.curProfile) { need_update = TRUE; } else if (p_device->onvif_device.curProfile->stream_uri[0] == '\0') { need_update = TRUE; } } if (need_update) { p_device->need_update = 0; GetDevInfo(p_device); } } void ANSOnvifClient::FreeDevice(ONVIF_DEVICE_EX* p_dev) { if (nullptr ==p_dev) { return; } while (p_dev->thread_handler) { usleep(1000); } onvif_free_device(&p_dev->onvif_device); if (p_dev->snapshot) { FreeBuff(p_dev->snapshot); p_dev->snapshot = nullptr; p_dev->snapshot_len = 0; } } void ANSOnvifClient::ClearDevices() { if (m_dev_ul != nullptr) { ONVIF_DEVICE_EX* next_dev; ONVIF_DEVICE_EX* dev = static_cast(pps_lookup_start(m_dev_ul)); int max_iterations = 100; // Set a reasonable limit for the maximum number of iterations int iteration_count = 0; while (dev && iteration_count < max_iterations) { next_dev = static_cast(pps_lookup_next(m_dev_ul, dev)); try { FreeDevice(dev); } catch (const std::exception& e) { // Log the exception or handle it as needed printf("Exception occurred while freeing device: %s\n", e.what()); } catch (...) { // Catch any other types of exceptions printf("Unknown exception occurred while freeing device.\n"); } dev = next_dev; iteration_count++; } if (iteration_count >= max_iterations) { printf("Warning: ClearDevices loop exceeded maximum iterations.\n"); } pps_lookup_end(m_dev_ul); } } void ANSOnvifClient::ProbeCallback(DEVICE_BINFO* p_res, int msgtype, void* p_data) { ONVIF_DEVICE_EX device; memset(&device, 0, sizeof(ONVIF_DEVICE_EX)); if (msgtype == PROBE_MSGTYPE_MATCH || msgtype == PROBE_MSGTYPE_HELLO) { memcpy(&device.onvif_device.binfo, p_res, sizeof(DEVICE_BINFO)); device.state = 1; std::string deviceURL = p_res->XAddr.url; if (deviceURL.find("/onvif/device_service") != std::string::npos) { OnvifDevice foundOnvifDevice; foundOnvifDevice.deviceIP = p_res->XAddr.host; foundOnvifDevice.devicePort = p_res->XAddr.port; // Check if the device is already in the list auto it = std::find_if(_deviceList.begin(), _deviceList.end(), [&foundOnvifDevice](const OnvifDevice& d) { return d.deviceIP == foundOnvifDevice.deviceIP && d.devicePort == foundOnvifDevice.devicePort; }); // If the device is not found, add it to the list if (it == _deviceList.end()) { printf("Found device. Ip : %s, port : %d\n", p_res->XAddr.host, p_res->XAddr.port); _deviceList.push_back(foundOnvifDevice); } } } else if (msgtype == PROBE_MSGTYPE_BYE) { printf("Exit onvif probe"); } } void ANSOnvifClient::ErrorHandler(ONVIF_DEVICE* p_device) { if (p_device->authFailed) // Authentication failed { std::cerr<<"ANSOnvifClient::ErrorHandler", "Authentication failed"; } switch (p_device->errCode) { case ONVIF_ERR_ConnFailure: // Connection failed std::cerr << "ANSOnvifClient::ErrorHandler", "Connect failed"; break; case ONVIF_ERR_MallocFailure: // Failed to allocate memory std::cerr << "ANSOnvifClient::ErrorHandler", "Memory malloc failed"; break; case ONVIF_ERR_NotSupportHttps: // The device requires an HTTPS connection, but the onvif client library does not support it (the HTTPS compilation macro is not enabled) std::cerr << "ANSOnvifClient::ErrorHandler", "Not support https"; break; case ONVIF_ERR_RecvTimeout: // Message receiving timeout std::cerr << "ANSOnvifClient::ErrorHandler", "Message receive timeout"; break; case ONVIF_ERR_InvalidContentType: // Device response message content is invalid std::cerr << "ANSOnvifClient::ErrorHandler", "Invalid content type"; break; case ONVIF_ERR_NullContent: // Device response message has no content std::cerr << "ANSOnvifClient::ErrorHandler", "Null content"; break; case ONVIF_ERR_ParseFailed: // Parsing the message failed std::cerr << "ANSOnvifClient::ErrorHandler", "Message parse failed"; break; case ONVIF_ERR_HandleFailed: // Message handling failed std::cerr << "ANSOnvifClient::ErrorHandler", "Message handle failed"; break; case ONVIF_ERR_HttpResponseError: // The device responded with an error message std::cerr << "ANSOnvifClient::ErrorHandler. Code="<< p_device->fault.Code; std::cerr << "ANSOnvifClient::ErrorHandler. Subcode="<< p_device->fault.Subcode; std::cerr << "ANSOnvifClient::ErrorHandler. Season="<< p_device->fault.Subcode; break; default: break; } } std::string ANSOnvifClient::DeviceListToJsonString(const std::vector& deviceList) { boost::property_tree::ptree root; boost::property_tree::ptree detectedObjects; for (int i = 0; i < deviceList.size(); i++) { boost::property_tree::ptree detectedNode; detectedNode.put("ip", deviceList[i].deviceIP); detectedNode.put("port", deviceList[i].devicePort); detectedObjects.push_back(std::make_pair("", detectedNode)); } root.add_child("results", detectedObjects); std::ostringstream stream; boost::property_tree::write_json(stream, root, false); std::string trackingResult = stream.str(); return trackingResult; } std::string ANSOnvifClient::DeviceProfileToJsonString(const std::vector& deviceProfileList) { boost::property_tree::ptree root; boost::property_tree::ptree detectedObjects; for (int i = 0; i < deviceProfileList.size(); i++) { boost::property_tree::ptree detectedNode; detectedNode.put("ip", deviceProfileList[i].deviceIP); detectedNode.put("name", deviceProfileList[i].deviceProfileName); detectedNode.put("uri", deviceProfileList[i].deviceProfileURI); detectedObjects.push_back(std::make_pair("", detectedNode)); } root.add_child("results", detectedObjects); std::ostringstream stream; boost::property_tree::write_json(stream, root, false); std::string trackingResult = stream.str(); return trackingResult; } void ANSOnvifClient::CheckLicense() { //try { // std::cout << "ANSOnvifClient::CheckLicense.", "Checking ONVIF license. Please wait...."; // _licenseValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(_licenseKey, 1007, "ANSCV");// // if(!_licenseValid)_licenseValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(_licenseKey, 1003, "ANSVIS");//Default productId=1005 // if(!_licenseValid) std::cerr << "ANSOnvifClient::CheckLicense.", "Invalid ONVIF license. Please activate correct license."; // else std::cout << "ANSOnvifClient::CheckLicense.", "Valid ONVIF license."; //} //catch (std::exception& e) { // std::cerr << "ANSOnvifClient::CheckLicense()"<< e.what(); //} try { // Check once globally std::call_once(ansonvifLicenseOnceFlag, [this]() { VerifyGlobalANSONVIFLicense(_licenseKey); }); // Update this instance's local license flag _licenseValid = ansonvifLicenceValid; } catch (const std::exception& e) { std::cerr << "ANSOnvifClient::CheckLicense()"<< e.what(); } } bool ANSOnvifClient::Init(const std::string& licenseKey) { CheckLicense(); if (!_licenseValid) { std::cerr << "ANSOnvifClient::Init", "Invalid license"; return false; } try { _deviceList.clear(); m_dev_fl = pps_ctx_fl_init(200, sizeof(ONVIF_DEVICE_EX), TRUE); m_dev_ul = pps_ctx_ul_init(m_dev_fl, TRUE); network_init(); sys_buf_init(200); http_msg_buf_init(200); onvif_event_init(nullptr, 30100, 10); set_probe_cb(ProbeCallback, 0); //StartDetectTask(); return true; } catch (std::exception& e) { std::cerr << "ANSOnvifClient::Init. Error"<< e.what(); return false; } catch (...) { std::cerr << "ANSOnvifClient::Init", "Unknown error"; return false; } } void ANSOnvifClient::Destroy() { ClearDevices(); onvif_event_deinit(); http_msg_buf_deinit(); sys_buf_deinit(); network_deinit(); if (m_dev_ul != nullptr) pps_ul_free(m_dev_ul); if (m_dev_fl != nullptr)pps_fl_free(m_dev_fl); _deviceList.clear(); std::cout << "ANSOnvifClient::Destroy.", "Clean-up ONVIF resource"; } ANSOnvifClient::~ANSOnvifClient() { Destroy(); } std::vectorANSOnvifClient::SearchForDevices(int sleepDuration) { if (sleepDuration <= 0)sleepDuration = 1; if (_licenseValid) { std::lock_guard lock(_mutex); start_probe(nullptr, 30); sleep(sleepDuration);//sleep for 15 seconds stop_probe(); return _deviceList; } else { std::cerr << "ANSOnvifClient::SearchForDevices.", "Invalid ONVIF license. Please activate correct license."; return _deviceList; } } std::vector ANSOnvifClient::SearchForDeviceProfile(const std::string& ip, int port, const std::string& username, const std::string& password) { std::lock_guard lock(_mutex); std::vector _deviceProfileList; _deviceProfileList.clear(); if (_licenseValid) { ONVIF_DEVICE g_device; memset(&g_device, 0, sizeof(g_device)); g_device.binfo.XAddr.https = 0; g_device.binfo.XAddr.port = port; strcpy(g_device.binfo.XAddr.host, ip.c_str()); strcpy(g_device.binfo.XAddr.url, "/onvif/device_service"); onvif_SetAuthInfo(&g_device, username.c_str(), password.c_str()); onvif_SetAuthMethod(&g_device, AuthMethod_UsernameToken); onvif_SetReqTimeout(&g_device, 5000); if (!GetSystemDateAndTime(&g_device)) { ErrorHandler(&g_device); std::cerr << "ANSOnvifClient::SearchForDeviceProfile. GetSystemDateAndTime failed."<< g_device.binfo.XAddr.host; } if (!GetCapabilities(&g_device)) { ErrorHandler(&g_device); std::cerr << "ANSOnvifClient::SearchForDeviceProfile. GetCapabilities failed."<< g_device.binfo.XAddr.host; } if (!GetServices(&g_device)) { ErrorHandler(&g_device); std::cerr << "ANSOnvifClient::SearchForDeviceProfile. GetServices failed."<< g_device.binfo.XAddr.host; } if (!GetDeviceInformation(&g_device)) { ErrorHandler(&g_device); std::cerr << "ANSOnvifClient::SearchForDeviceProfile. GetDeviceInformation failed." << g_device.binfo.XAddr.host; } if (!GetProfiles(&g_device)) { ErrorHandler(&g_device); std::cerr << "ANSOnvifClient::SearchForDeviceProfile. GetDeviceInformation failed."<< g_device.binfo.XAddr.host; } if (!GetStreamUris(&g_device, onvif_TransportProtocol::TransportProtocol_UDP)) { ErrorHandler(&g_device); std::cerr << "ANSOnvifClient::SearchForDeviceProfile. GetDeviceInformation failed."<< g_device.binfo.XAddr.host; } ONVIF_PROFILE* p_profile = g_device.profiles; bool foundProfile = false; while (p_profile) { OnvifDeviceProfile foundOnvifProfile; foundOnvifProfile.deviceIP = ip; foundOnvifProfile.deviceProfileName = p_profile->name; foundOnvifProfile.deviceProfileURI = p_profile->stream_uri; _deviceProfileList.push_back(foundOnvifProfile); foundProfile = true; p_profile = p_profile->next; } if (!foundProfile) { OnvifDeviceProfile foundOnvifProfile; foundOnvifProfile.deviceIP = g_device.binfo.XAddr.host; foundOnvifProfile.deviceProfileName = "Error"; foundOnvifProfile.deviceProfileURI = g_device.fault.Reason; _deviceProfileList.push_back(foundOnvifProfile); } onvif_free_device(&g_device); return _deviceProfileList; } else { std::cerr << "ANSOnvifClient::SearchForDeviceProfile.", "Invalid ONVIF license. Please activate correct license."; return _deviceProfileList; } } std::vector ANSOnvifClient::SearchForDeviceProfiles(const std::string& username, const std::string& password) { std::vector _deviceProfileList; _deviceProfileList.clear(); if (_licenseValid) { SearchForDevices(15); if (_deviceList.size() <= 0) return _deviceProfileList; for (int i = 0; i < _deviceList.size(); i++) { OnvifDevice currentOnvifDevice = _deviceList.at(i); std::vector _currentDeviceProfileList = SearchForDeviceProfile(currentOnvifDevice.deviceIP, currentOnvifDevice.devicePort, username, password); if (_currentDeviceProfileList.size() > 0) { for (int j = 0; j < _currentDeviceProfileList.size(); j++) { _deviceProfileList.push_back(_currentDeviceProfileList.at(j)); } } } return _deviceProfileList; } else { std::cerr << "ANSOnvifClient::SearchForDeviceProfiles.", "Invalid ONVIF license. Please activate correct license."; return _deviceProfileList; } } std::vector ANSOnvifClient::SearchForDeviceProfiles(const std::vector& usernameList, const std::vector& passwordList) { std::vector _deviceProfileList; _deviceProfileList.clear(); if (_licenseValid) { SearchForDevices(15); if (_deviceList.size() <= 0) return _deviceProfileList; if (usernameList.size() <= 0) return _deviceProfileList; if (usernameList.size() != passwordList.size())return _deviceProfileList; for (int i = 0; i < _deviceList.size(); i++) { OnvifDevice currentOnvifDevice = _deviceList.at(i); for (int j = 0; j < usernameList.size(); j++) { std::vector _currentDeviceProfileList = SearchForDeviceProfile(currentOnvifDevice.deviceIP, currentOnvifDevice.devicePort, usernameList.at(j).c_str(), passwordList.at(j).c_str()); if (_currentDeviceProfileList.size() > 0) { for (int k = 0; k < _currentDeviceProfileList.size(); k++) { _deviceProfileList.push_back(_currentDeviceProfileList.at(k)); } } } } return _deviceProfileList; } else { std::cerr << "ANSOnvifClient::SearchForDeviceProfiles.", "Invalid ONVIF license. Please activate correct license."; return _deviceProfileList; } } ANSOnvifClient::ANSOnvifClient() { _licenseValid = false; } void ANSOnvifClient::ClearDeviceList() { _deviceList.clear(); } } extern "C" __declspec(dllexport) int CreateANSOnvifHandle(ANSCENTER::ANSOnvifClient * *Handle, const char* licenseKey) { if (Handle == nullptr || licenseKey == nullptr) return 0; try { // Release existing handle if called twice (prevents leak from LabVIEW) if (*Handle) { if (UnregisterOnvifHandle(*Handle)) { delete *Handle; } *Handle = nullptr; } *Handle = new ANSCENTER::ANSOnvifClient(); if (*Handle == nullptr) return 0; if ((*Handle)->Init(licenseKey)) { RegisterOnvifHandle(*Handle); return 1; } delete *Handle; *Handle = nullptr; return 0; } catch (std::exception& e) { if (*Handle != nullptr) { delete *Handle; *Handle = nullptr; } return 0; } catch (...) { if (*Handle != nullptr) { delete *Handle; *Handle = nullptr; } return 0; } } static int ReleaseANSOnvifHandle_Impl(ANSCENTER::ANSOnvifClient** Handle) { try { if (!Handle || !*Handle) return 1; if (!UnregisterOnvifHandle(*Handle)) { *Handle = nullptr; return 1; } delete *Handle; *Handle = nullptr; return 1; } catch (...) { if (Handle) *Handle = nullptr; return 0; } } extern "C" __declspec(dllexport) int ReleaseANSOnvifHandle(ANSCENTER::ANSOnvifClient * *Handle) { __try { return ReleaseANSOnvifHandle_Impl(Handle); } __except (EXCEPTION_EXECUTE_HANDLER) { if (Handle) *Handle = nullptr; return 0; } } extern "C" __declspec(dllexport) int SearchANSOnvifDevices(ANSCENTER::ANSOnvifClient * *Handle, int sleepDuration, std::vector &deviceList) { if (Handle == nullptr || *Handle == nullptr) return 0; OnvifHandleGuard guard(AcquireOnvifHandle(*Handle)); if (!guard) return 0; try { deviceList.clear(); std::vector onvifDeviceList = guard.get()->SearchForDevices(sleepDuration); if (onvifDeviceList.size() <= 0)return 0; for (int i = 0; i < onvifDeviceList.size(); i++) { ANSCENTER::OnvifDevice currentDevice = onvifDeviceList.at(i); std::string currentDeviceStr = currentDevice.deviceIP + ":" + std::to_string(currentDevice.devicePort); deviceList.push_back(currentDeviceStr); } return 1; } catch (std::exception& e) { return 0; } catch (...) { return 0; } } extern "C" __declspec(dllexport) int SearchANSOnvifProfiles(ANSCENTER::ANSOnvifClient * *Handle, const char* username, const char* password, std::vector &profileList) { if (Handle == nullptr || *Handle == nullptr || username == nullptr || password == nullptr) return 0; OnvifHandleGuard guard(AcquireOnvifHandle(*Handle)); if (!guard) return 0; try { profileList.clear(); std::vector onvifDeviceProfileList = guard.get()->SearchForDeviceProfiles(username, password); if (onvifDeviceProfileList.size() <= 0)return 0; for (int i = 0; i < onvifDeviceProfileList.size(); i++) { ANSCENTER::OnvifDeviceProfile currentDevice = onvifDeviceProfileList.at(i); std::string currentDeviceStr = currentDevice.deviceProfileURI; profileList.push_back(currentDeviceStr); } return 1; } catch (std::exception& e) { return 0; } catch (...) { return 0; } } extern "C" __declspec(dllexport) int SearchANSOnvifSpecificProfiles(ANSCENTER::ANSOnvifClient * *Handle, const char* ip, int port, const char* username, const char* password, std::vector &profileList) { if (Handle == nullptr || *Handle == nullptr || ip == nullptr || username == nullptr || password == nullptr) return 0; OnvifHandleGuard guard(AcquireOnvifHandle(*Handle)); if (!guard) return 0; try { profileList.clear(); std::vector onvifDeviceProfileList = guard.get()->SearchForDeviceProfile(ip, port, username, password); if (onvifDeviceProfileList.size() <= 0)return 0; for (int i = 0; i < onvifDeviceProfileList.size(); i++) { ANSCENTER::OnvifDeviceProfile currentDevice = onvifDeviceProfileList.at(i); std::string currentDeviceStr = currentDevice.deviceProfileURI; profileList.push_back(currentDeviceStr); } return 1; } catch (std::exception& e) { return 0; } catch (...) { return 0; } } extern "C" __declspec(dllexport) int SearchANSOnvifDevices_LV(ANSCENTER::ANSOnvifClient * *Handle, int sleepDuration,LStrHandle deviceList) { if (Handle == nullptr || *Handle == nullptr || deviceList == nullptr) return 0; OnvifHandleGuard guard(AcquireOnvifHandle(*Handle)); if (!guard) return 0; try { std::vector onvifDeviceList = guard.get()->SearchForDevices(sleepDuration); std::string st = guard.get()->DeviceListToJsonString(onvifDeviceList); int size = static_cast(st.length()); if (size > 0) { MgErr error; error = DSSetHandleSize(deviceList, sizeof(int32) + size * sizeof(uChar)); if (error == noErr) { (*deviceList)->cnt = size; memcpy((*deviceList)->str, st.c_str(), size); return 1; } else return 0; } else return 0; } catch (std::exception& e) { return 0; } catch (...) { return 0; } } extern "C" __declspec(dllexport) int SearchANSOnvifProfiles_LV(ANSCENTER::ANSOnvifClient * *Handle, const char* username, const char* password, LStrHandle profileList) { if (Handle == nullptr || *Handle == nullptr || username == nullptr || password == nullptr || profileList == nullptr) return 0; OnvifHandleGuard guard(AcquireOnvifHandle(*Handle)); if (!guard) return 0; try { std::vector onvifDeviceProfileList = guard.get()->SearchForDeviceProfiles(username, password); std::string st = guard.get()->DeviceProfileToJsonString(onvifDeviceProfileList); int size = static_cast(st.length()); if (size > 0) { MgErr error; error = DSSetHandleSize(profileList, sizeof(int32) + size * sizeof(uChar)); if (error == noErr) { (*profileList)->cnt = size; memcpy((*profileList)->str, st.c_str(), size); return 1; } else return 0; } else return 0; } catch (std::exception& e) { return 0; } catch (...) { return 0; } } extern "C" __declspec(dllexport) int SearchANSOnvifSpecificProfiles_LV(ANSCENTER::ANSOnvifClient * *Handle, const char* ip, int port, const char* username, const char* password, LStrHandle profileList) { if (Handle == nullptr || *Handle == nullptr || ip == nullptr || username == nullptr || password == nullptr || profileList == nullptr) return 0; OnvifHandleGuard guard(AcquireOnvifHandle(*Handle)); if (!guard) return 0; try { std::vector onvifDeviceProfileList = guard.get()->SearchForDeviceProfile(ip, port, username, password); std::string st = guard.get()->DeviceProfileToJsonString(onvifDeviceProfileList); int size = static_cast(st.length()); if (size > 0) { MgErr error; error = DSSetHandleSize(profileList, sizeof(int32) + size * sizeof(uChar)); if (error == noErr) { (*profileList)->cnt = size; memcpy((*profileList)->str, st.c_str(), size); return 1; } else return 0; } else return 0; } catch (std::exception& e) { return 0; } catch (...) { return 0; } } // ============================================================================ // V2 entry points — accept uint64_t handleVal by value instead of Handle** // to eliminate LabVIEW buffer-reuse bug when concurrent calls share the same // Handle** buffer address. // ============================================================================ extern "C" __declspec(dllexport) int SearchANSOnvifDevices_LV_V2(uint64_t handleVal, int sleepDuration, LStrHandle deviceList) { auto* _v2h = reinterpret_cast(handleVal); if (!_v2h) return 0; if (deviceList == nullptr) return 0; OnvifHandleGuard guard(AcquireOnvifHandle(_v2h)); if (!guard) return 0; try { std::vector onvifDeviceList = guard.get()->SearchForDevices(sleepDuration); std::string st = guard.get()->DeviceListToJsonString(onvifDeviceList); int size = static_cast(st.length()); if (size > 0) { MgErr error; error = DSSetHandleSize(deviceList, sizeof(int32) + size * sizeof(uChar)); if (error == noErr) { (*deviceList)->cnt = size; memcpy((*deviceList)->str, st.c_str(), size); return 1; } else return 0; } else return 0; } catch (std::exception& e) { return 0; } catch (...) { return 0; } } extern "C" __declspec(dllexport) int SearchANSOnvifProfiles_LV_V2(uint64_t handleVal, const char* username, const char* password, LStrHandle profileList) { auto* _v2h = reinterpret_cast(handleVal); if (!_v2h) return 0; if (username == nullptr || password == nullptr || profileList == nullptr) return 0; OnvifHandleGuard guard(AcquireOnvifHandle(_v2h)); if (!guard) return 0; try { std::vector onvifDeviceProfileList = guard.get()->SearchForDeviceProfiles(username, password); std::string st = guard.get()->DeviceProfileToJsonString(onvifDeviceProfileList); int size = static_cast(st.length()); if (size > 0) { MgErr error; error = DSSetHandleSize(profileList, sizeof(int32) + size * sizeof(uChar)); if (error == noErr) { (*profileList)->cnt = size; memcpy((*profileList)->str, st.c_str(), size); return 1; } else return 0; } else return 0; } catch (std::exception& e) { return 0; } catch (...) { return 0; } } extern "C" __declspec(dllexport) int SearchANSOnvifSpecificProfiles_LV_V2(uint64_t handleVal, const char* ip, int port, const char* username, const char* password, LStrHandle profileList) { auto* _v2h = reinterpret_cast(handleVal); if (!_v2h) return 0; if (ip == nullptr || username == nullptr || password == nullptr || profileList == nullptr) return 0; OnvifHandleGuard guard(AcquireOnvifHandle(_v2h)); if (!guard) return 0; try { std::vector onvifDeviceProfileList = guard.get()->SearchForDeviceProfile(ip, port, username, password); std::string st = guard.get()->DeviceProfileToJsonString(onvifDeviceProfileList); int size = static_cast(st.length()); if (size > 0) { MgErr error; error = DSSetHandleSize(profileList, sizeof(int32) + size * sizeof(uChar)); if (error == noErr) { (*profileList)->cnt = size; memcpy((*profileList)->str, st.c_str(), size); return 1; } else return 0; } else return 0; } catch (std::exception& e) { return 0; } catch (...) { return 0; } }