Files
zoneminder/tests
Isaac ConnorandClaude Opus 5.5 82901ac1fb fix: schedule ONVIF subscription renewal for short and unreported lifetimes (#5181)
* fix: schedule ONVIF subscription renewal for short and unreported lifetimes refs #5179

The Beward camera from #5165 grants a 60 second subscription and its
RenewResponse carries no TerminationTime. Three things combined so that
ZM renewed after every PullMessages that returned messages (61 renewals
in 74 seconds of the reporter's log):

- The renewal was scheduled a fixed ONVIF_RENEWAL_ADVANCE_SECONDS (60)
  before termination, which for a 60 second subscription is its creation
  time. ONVIFNextRenewalTime() now uses the smaller of that advance and
  half the remaining lifetime.
- Renew() only logged a missing TerminationTime and left
  next_renewal_time in the past. assume_renewal_times() now schedules
  from the lifetime we asked for, capped at what the camera last granted
  (ONVIFAssumedLifetime()), so this camera renews every 30 seconds.
- IsRenewalNeeded() was only checked after a response carrying messages,
  so a camera quiet for longer than its subscription was never renewed.
  It is now also checked after an empty (SOAP_EOF) poll.

Since renewal is now checked after every poll, a camera that answers
Renew with ActionNotSupported has renewal disabled rather than being
asked again on each poll, matching the existing handling of unusable
TerminationTimes.

Tests cover the renewal time for long, short and very short
subscriptions, and the assumed lifetime with no, smaller and larger
previously granted lifetimes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: only disable ONVIF renewal for ActionNotSupported, keep sub-second grants refs #5179

Review follow-ups on the renewal scheduling change:

- Renew() treated soap->error == 12 as ActionNotSupported, but 12 is
  gSOAP's generic SOAP_FAULT. With renewal now disabled on that path, a
  NotAuthorized or InvalidArgVal fault from Renew would have stopped
  renewal for good while marking the subscription healthy.
  ONVIFIsActionNotSupported() checks the fault subcode and string for
  ActionNotSupported (wsa: or ter:); any other fault now takes the
  existing cleanup and re-subscribe path.
- granted_lifetime truncated the remaining time to whole seconds. A
  termination less than a second away stored 0, which reads as "never
  reported", so the next Renew without a TerminationTime assumed the full
  requested 300 seconds. ONVIFGrantedLifetime() rounds up instead.

Tests cover ActionNotSupported subcodes and strings against other faults
and non-fault results, and the granted lifetime for whole, fractional and
sub-second remainders.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: count an assumed ONVIF renewal lifetime from the request, not the response refs #5179

When a RenewResponse has no TerminationTime, assume_renewal_times()
started the assumed lifetime when the response arrived, but the camera
counts it from when it received the request. A slow response pushed the
deadline and the next renewal later by the response time: with
subscription_timeout=10 and a 6 second response, the camera's deadline
was request+10 but the renewal was scheduled for request+11. In absolute
renewal mode it also ignored the exact deadline that was sent.

Renew() now records the time just before building the request and the
deadline it asks for: request time plus subscription_timeout, or the
absolute whole-second time it sends. ONVIFAssumedTermination() replaces
ONVIFAssumedLifetime() and returns that deadline, capped at request time
plus the lifetime the camera last granted. The renewal is scheduled from
the request time; if the response arrived after it, it is already due and
the next poll renews.

Tests cover no, smaller and larger previous grants, an absolute deadline
kept exactly, and the slow-response case from review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 12:33:00 -04:00
..
2024-05-08 14:16:05 -04:00
2021-05-30 22:56:21 +02:00