Files
zoneminder/tests/zm_onvif_poll_wait.cpp
T
Isaac ConnorandClaude Opus 5.5 d7238f745a fix: stop busy-polling ONVIF cameras that don't hold PullMessages refs #5180 (#5182)
ZM asks the camera to hold each PullMessages for up to pull_timeout
seconds (default 1). The Beward camera from #5165 answers in 10-30ms with
no messages, which gSOAP reports as SOAP_EOF, and Run() issued the next
request at once: ~2,500 PullMessages in 74 seconds of the reporter's log
(~34/s), each with a fresh UsernameToken digest.

Time each PullMessages. When it comes back with no messages (SOAP_EOF, or
a SOAP_OK response with no NotificationMessage) before the Timeout,
WaitForMessage() now waits out the remainder in 100ms steps, staying
responsive to terminate_ and zm_terminate. A camera that ignores the
long-poll is then polled at most once per pull_timeout; one that holds it
is polled again immediately as before. Events raised during the wait stay
queued in the camera's pull point and arrive with the next request, so
the added latency is at most pull_timeout.

ONVIFEarlyPollWait() computes the remainder and is tested for an
immediate answer, a full hold, a partial hold and sub-millisecond
elapsed times.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:03:24 -04:00

47 lines
1.8 KiB
C++

/*
* This file is part of the ZoneMinder Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "zm_catch2.h"
#include "zm_monitor_onvif.h"
#ifdef WITH_GSOAP
using std::chrono::milliseconds;
TEST_CASE("ONVIFEarlyPollWait", "[onvif]") {
SECTION("Camera that answers at once is held to one poll per Timeout") {
// The #5180 Beward answered a 1s PullMessages in 10-30ms, ~34 polls a second.
REQUIRE(ONVIFEarlyPollWait(milliseconds(10), 1) == milliseconds(990));
REQUIRE(ONVIFEarlyPollWait(milliseconds(0), 5) == milliseconds(5000));
}
SECTION("Camera that holds the long-poll for the full Timeout is polled again at once") {
REQUIRE(ONVIFEarlyPollWait(milliseconds(1000), 1) == milliseconds(0));
REQUIRE(ONVIFEarlyPollWait(milliseconds(1003), 1) == milliseconds(0));
}
SECTION("Partial hold waits only for the rest of the Timeout") {
REQUIRE(ONVIFEarlyPollWait(milliseconds(400), 1) == milliseconds(600));
}
SECTION("Sub-millisecond elapsed time is not rounded into a longer wait") {
REQUIRE(ONVIFEarlyPollWait(std::chrono::microseconds(10500), 1) == milliseconds(989));
}
}
#endif // WITH_GSOAP