@@ -86,16 +86,10 @@ ONVIF::~ONVIF() {
8686 _wsnt__UnsubscribeResponse wsnt__UnsubscribeResponse;
8787
8888 bool use_wsa = parent->soap_wsa_compl ;
89- const char *RequestMessageID = nullptr ;
9089
9190 if (use_wsa) {
92- RequestMessageID = soap_wsa_rand_uuid (soap);
93- if (soap_wsa_request (soap, RequestMessageID, response.SubscriptionReference .Address , " UnsubscribeRequest" ) == SOAP_OK) {
94- Debug (2 , " ONVIF: WS-Addressing headers set for Unsubscribe" );
91+ if (do_wsa_request (response.SubscriptionReference .Address , " UnsubscribeRequest" )) {
9592 proxyEvent.Unsubscribe (response.SubscriptionReference .Address , nullptr , &wsnt__Unsubscribe, wsnt__UnsubscribeResponse);
96- } else {
97- Error (" ONVIF: Couldn't set WS-Addressing headers for Unsubscribe. RequestMessageID=%s; TO=%s; Request=UnsubscribeRequest. Error %i %s, %s" ,
98- RequestMessageID, response.SubscriptionReference .Address , soap->error , soap_fault_string (soap), soap_fault_detail (soap));
9993 }
10094 } else {
10195 // No WS-Addressing, just unsubscribe
@@ -154,20 +148,14 @@ void ONVIF::start() {
154148 // Try to create subscription with digest authentication first
155149 set_credentials (soap);
156150
157- const char *RequestMessageID = nullptr ;
158151 bool use_wsa = parent->soap_wsa_compl ;
159152
160- if (use_wsa) {
161- RequestMessageID = soap_wsa_rand_uuid (soap);
162- if (soap_wsa_request (soap, RequestMessageID, proxyEvent.soap_endpoint , " CreatePullPointSubscriptionRequest" ) != SOAP_OK) {
163- Error (" ONVIF: Couldn't set WS-Addressing headers. RequestMessageID=%s; TO=%s; Request=CreatePullPointSubscriptionRequest. Error %i %s, %s" ,
164- RequestMessageID, proxyEvent.soap_endpoint , soap->error , soap_fault_string (soap), soap_fault_detail (soap));
165- soap_destroy (soap);
166- soap_end (soap);
167- soap_free (soap);
168- soap = nullptr ;
169- return ;
170- }
153+ if (use_wsa && !do_wsa_request (proxyEvent.soap_endpoint , " CreatePullPointSubscriptionRequest" )) {
154+ soap_destroy (soap);
155+ soap_end (soap);
156+ soap_free (soap);
157+ soap = nullptr ;
158+ return ;
171159 }
172160
173161 Debug (1 , " ONVIF: Creating PullPoint subscription at endpoint: %s" , proxyEvent.soap_endpoint );
@@ -198,15 +186,10 @@ void ONVIF::start() {
198186 // Set credentials with plain auth
199187 set_credentials (soap);
200188
201- if (use_wsa) {
202- RequestMessageID = soap_wsa_rand_uuid (soap);
203- if (soap_wsa_request (soap, RequestMessageID, proxyEvent.soap_endpoint , " CreatePullPointSubscriptionRequest" ) != SOAP_OK) {
204- Error (" ONVIF: Couldn't set WS-Addressing headers on retry. RequestMessageID=%s; TO=%s" ,
205- RequestMessageID, proxyEvent.soap_endpoint );
206- soap_free (soap);
207- soap = nullptr ;
208- return ;
209- }
189+ if (use_wsa && !do_wsa_request (proxyEvent.soap_endpoint , " CreatePullPointSubscriptionRequest" )) {
190+ soap_free (soap);
191+ soap = nullptr ;
192+ return ;
210193 }
211194
212195 rc = proxyEvent.CreatePullPointSubscription (&request, response);
@@ -287,15 +270,9 @@ void ONVIF::start() {
287270 // Empty the stored messages
288271 set_credentials (soap);
289272
290- if (use_wsa) {
291- RequestMessageID = soap_wsa_rand_uuid (soap);
292- if (soap_wsa_request (soap, RequestMessageID, response.SubscriptionReference .Address , " PullMessageRequest" ) != SOAP_OK) {
293- Error (" ONVIF: Couldn't set WS-Addressing headers for initial pull. RequestMessageID=%s; TO=%s; Request=PullMessageRequest. Error %i %s, %s" ,
294- RequestMessageID, response.SubscriptionReference .Address , soap->error , soap_fault_string (soap), soap_fault_detail (soap));
295- healthy = false ;
296- return ;
297- }
298- Debug (2 , " ONVIF: WS-Addressing headers set for initial pull" );
273+ if (use_wsa && !do_wsa_request (response.SubscriptionReference .Address , " PullMessageRequest" )) {
274+ healthy = false ;
275+ return ;
299276 }
300277
301278 if ((proxyEvent.PullMessages (response.SubscriptionReference .Address , nullptr , &tev__PullMessages, tev__PullMessagesResponse) != SOAP_OK) &&
@@ -308,36 +285,11 @@ void ONVIF::start() {
308285 healthy = true ;
309286 }
310287
311- // we renew the current subscription .........
312- if (use_wsa) {
313- set_credentials (soap);
314- RequestMessageID = soap_wsa_rand_uuid (soap);
315- if (soap_wsa_request (soap, RequestMessageID, response.SubscriptionReference .Address , " RenewRequest" ) == SOAP_OK) {
316- Debug (2 , " ONVIF: WS-Addressing headers set for Renew" );
317- if (proxyEvent.Renew (response.SubscriptionReference .Address , nullptr , &wsnt__Renew, wsnt__RenewResponse) != SOAP_OK) {
318- Error (" ONVIF: Couldn't do initial Renew ! Error %i %s, %s" , soap->error , soap_fault_string (soap), soap_fault_detail (soap));
319- if (soap->error ==12 ) {// ActionNotSupported
320- healthy = true ;
321- } else {
322- healthy = false ;
323- }
324- } else {
325- Debug (2 , " ONVIF: Good Initial Renew %i %s, %s" , soap->error , soap_fault_string (soap), soap_fault_detail (soap));
326- healthy = true ;
327- // Update renewal times from initial renew response
328- if (wsnt__RenewResponse.TerminationTime != 0 ) {
329- update_renewal_times (wsnt__RenewResponse.TerminationTime );
330- }
331- }
332- } else {
333- Error (" ONVIF: Couldn't set WS-Addressing headers for Renew. RequestMessageID=%s; TO=%s; Request=RenewRequest Error %i %s, %s" ,
334- RequestMessageID,
335- response.SubscriptionReference .Address ,
336- soap->error ,
337- soap_fault_string (soap),
338- soap_fault_detail (soap));
339- healthy = false ;
340- } // end renew
288+ // Perform initial renewal of the subscription
289+ if (use_wsa) { // Only if WS-Addressing is enabled
290+ if (!Renew ()) {
291+ Debug (1 , " ONVIF: Initial renewal failed, but continuing" );
292+ }
341293 }
342294 } // end else (success block)
343295#else
@@ -349,17 +301,12 @@ void ONVIF::WaitForMessage() {
349301#ifdef WITH_GSOAP
350302 set_credentials (soap);
351303
352- const char *RequestMessageID = nullptr ;
353304 bool use_wsa = parent->soap_wsa_compl ;
354305
355306 if (use_wsa) {
356- RequestMessageID = soap_wsa_rand_uuid (soap);
357- if (soap_wsa_request (soap, RequestMessageID, response.SubscriptionReference .Address , " PullMessageRequest" ) != SOAP_OK) {
358- Error (" ONVIF: Couldn't set WS-Addressing headers. RequestMessageID=%s; TO=%s; Request=PullMessageRequest. Error %i %s, %s" ,
359- RequestMessageID, response.SubscriptionReference .Address , soap->error , soap_fault_string (soap), soap_fault_detail (soap));
307+ if (!do_wsa_request (response.SubscriptionReference .Address , " PullMessageRequest" )) {
360308 return ;
361309 }
362- Debug (2 , " ONVIF: WS-Addressing headers set successfully" );
363310 } else {
364311 Debug (2 , " ONVIF: WS-Addressing disabled, not sending addressing headers" );
365312 }
@@ -567,77 +514,12 @@ void ONVIF::WaitForMessage() {
567514 } // end foreach msg
568515 } // end scope for lock
569516
570- // Check if renewal is needed (only renew 10 seconds before termination)
571- SystemTimePoint now = std::chrono::system_clock::now ();
572- bool renewal_needed = false ;
573-
574- // Check if we have valid renewal times set
575- if (!is_renewal_tracking_initialized ()) {
576- // No renewal tracking set up yet, always renew (backward compatibility)
577- Debug (2 , " ONVIF: No renewal tracking initialized, performing renewal" );
578- renewal_needed = true ;
579- } else if (now >= next_renewal_time) {
580- // Time to renew
581- auto seconds_overdue = std::chrono::duration_cast<std::chrono::seconds>(
582- now - next_renewal_time).count ();
583- Debug (2 , " ONVIF: Subscription renewal needed (overdue by %ld seconds)" , seconds_overdue);
584- renewal_needed = true ;
585- } else {
586- // Not yet time to renew
587- auto seconds_until_renewal = std::chrono::duration_cast<std::chrono::seconds>(
588- next_renewal_time - now).count ();
589- Debug (2 , " ONVIF: Subscription renewal not yet needed (renews in %ld seconds)" ,
590- seconds_until_renewal);
591- renewal_needed = false ;
592- }
593-
594- // Only renew if needed
595- if (renewal_needed) {
596- // we renew the current subscription .........
597- set_credentials (soap);
598- wsnt__Renew.TerminationTime = &subscription_timeout;
599- if (use_wsa) {
600- RequestMessageID = soap_wsa_rand_uuid (soap);
601- if (soap_wsa_request (soap, RequestMessageID, response.SubscriptionReference .Address , " RenewRequest" ) == SOAP_OK) {
602- Debug (2 , " ONVIF: WS-Addressing headers set for Renew" );
603- if (proxyEvent.Renew (response.SubscriptionReference .Address , nullptr , &wsnt__Renew, wsnt__RenewResponse) != SOAP_OK) {
604- Error (" ONVIF: Couldn't do Renew! Error %i %s, %s" , soap->error , soap_fault_string (soap), soap_fault_detail (soap));
605- if (soap->error ==12 ) {// ActionNotSupported
606- healthy = true ;
607- } else {
608- healthy = false ;
609- }
610- } else {
611- Debug (2 , " ONVIF: Good Renew %i %s, %s" , soap->error , soap_fault_string (soap), soap_fault_detail (soap));
612- healthy = true ;
613- // Update renewal times from renew response
614- if (wsnt__RenewResponse.TerminationTime != 0 ) {
615- update_renewal_times (wsnt__RenewResponse.TerminationTime );
616- }
617- }
618- } else {
619- Error (" ONVIF: Couldn't set WS-Addressing headers for Renew. RequestMessageID=%s; TO=%s; Request=RenewRequest. Error %i %s, %s" ,
620- RequestMessageID, response.SubscriptionReference .Address , soap->error , soap_fault_string (soap), soap_fault_detail (soap));
621- healthy = false ;
622- } // end renew
623- } else {
624- if (proxyEvent.Renew (response.SubscriptionReference .Address , nullptr , &wsnt__Renew, wsnt__RenewResponse) != SOAP_OK) {
625- Error (" ONVIF: Couldn't do Renew! Error %i %s, %s" , soap->error , soap_fault_string (soap), soap_fault_detail (soap));
626- if (soap->error ==12 ) {// ActionNotSupported
627- healthy = true ;
628- } else {
629- healthy = false ;
630- }
631- } else {
632- Debug (2 , " ONVIF: Good Renew %i %s, %s" , soap->error , soap_fault_string (soap), soap_fault_detail (soap));
633- healthy = true ;
634- // Update renewal times from renew response
635- if (wsnt__RenewResponse.TerminationTime != 0 ) {
636- update_renewal_times (wsnt__RenewResponse.TerminationTime );
637- }
638- }
517+ // Renew subscription if needed
518+ if (IsRenewalNeeded ()) {
519+ if (!Renew ()) {
520+ Warning (" ONVIF: Failed to renew subscription" );
639521 }
640- } // end if renewal_needed
522+ }
641523 } // end if SOAP OK/NOT OK
642524#endif
643525 return ;
@@ -812,6 +694,112 @@ bool ONVIF::is_renewal_tracking_initialized() const {
812694 return next_renewal_time.time_since_epoch ().count () != 0 ;
813695}
814696
697+ // Perform ONVIF subscription renewal
698+ // Returns true if renewal succeeded or is not supported, false on error
699+ bool ONVIF::Renew () {
700+ #ifdef WITH_GSOAP
701+ set_credentials (soap);
702+ wsnt__Renew.TerminationTime = &subscription_timeout;
703+
704+ bool use_wsa = parent->soap_wsa_compl ;
705+
706+ if (use_wsa && !do_wsa_request (response.SubscriptionReference .Address , " RenewRequest" )) {
707+ healthy = false ;
708+ return false ;
709+ }
710+
711+ if (proxyEvent.Renew (response.SubscriptionReference .Address , nullptr , &wsnt__Renew, wsnt__RenewResponse) != SOAP_OK) {
712+ Error (" ONVIF: Couldn't do Renew! Error %i %s, %s" , soap->error , soap_fault_string (soap), soap_fault_detail (soap));
713+ if (soap->error == 12 ) { // ActionNotSupported
714+ Debug (2 , " ONVIF: Renew not supported by device, continuing without renewal" );
715+ healthy = true ;
716+ return true ; // Not a fatal error
717+ } else {
718+ healthy = false ;
719+ return false ;
720+ }
721+ }
722+
723+ Debug (2 , " ONVIF: Subscription renewed successfully" );
724+ healthy = true ;
725+
726+ // Update renewal times from renew response
727+ if (wsnt__RenewResponse.TerminationTime != 0 ) {
728+ update_renewal_times (wsnt__RenewResponse.TerminationTime );
729+ }
730+
731+ return true ;
732+ #else
733+ return false ;
734+ #endif
735+ }
736+
737+ // Check if subscription renewal is needed
738+ // Returns true if renewal should be performed now, false if not yet needed
739+ bool ONVIF::IsRenewalNeeded () const {
740+ #ifdef WITH_GSOAP
741+ // Check if we have valid renewal times set
742+ if (!is_renewal_tracking_initialized ()) {
743+ // No renewal tracking set up yet, always renew (backward compatibility)
744+ Debug (2 , " ONVIF: No renewal tracking initialized, performing renewal" );
745+ return true ;
746+ }
747+
748+ SystemTimePoint now = std::chrono::system_clock::now ();
749+
750+ if (now >= next_renewal_time) {
751+ // Time to renew
752+ auto seconds_overdue = std::chrono::duration_cast<std::chrono::seconds>(
753+ now - next_renewal_time).count ();
754+ Debug (2 , " ONVIF: Subscription renewal needed (overdue by %ld seconds)" , seconds_overdue);
755+ return true ;
756+ }
757+
758+ // Not yet time to renew
759+ auto seconds_until_renewal = std::chrono::duration_cast<std::chrono::seconds>(
760+ next_renewal_time - now).count ();
761+ Debug (2 , " ONVIF: Subscription renewal not yet needed (renews in %ld seconds)" ,
762+ seconds_until_renewal);
763+ return false ;
764+ #else
765+ return false ;
766+ #endif
767+ }
768+
769+ // Setup WS-Addressing headers for SOAP request
770+ // This helper method encapsulates the common pattern of setting up WS-Addressing
771+ // headers for SOAP requests, eliminating code duplication across the class.
772+ //
773+ // Parameters:
774+ // address - The target endpoint address (TO header)
775+ // action - The SOAP action name for the request
776+ //
777+ // Returns:
778+ // true - WS-Addressing headers were successfully set
779+ // false - Failed to set headers (error logged), or invalid parameters
780+ //
781+ // Note: This method assumes the soap context is already initialized.
782+ bool ONVIF::do_wsa_request (const char * address, const char * action) {
783+ #ifdef WITH_GSOAP
784+ if (!soap || !address || !action) {
785+ Error (" ONVIF: Invalid parameters for WS-Addressing request" );
786+ return false ;
787+ }
788+
789+ const char * RequestMessageID = soap_wsa_rand_uuid (soap);
790+ if (soap_wsa_request (soap, RequestMessageID, address, action) != SOAP_OK) {
791+ Error (" ONVIF: Couldn't set WS-Addressing headers. RequestMessageID=%s; TO=%s; Request=%s. Error %i %s, %s" ,
792+ RequestMessageID, address, action, soap->error , soap_fault_string (soap), soap_fault_detail (soap));
793+ return false ;
794+ }
795+
796+ Debug (2 , " ONVIF: WS-Addressing headers set for %s" , action);
797+ return true ;
798+ #else
799+ return false ;
800+ #endif
801+ }
802+
815803// ONVIF Set Credentials
816804void ONVIF::set_credentials (struct soap *soap) {
817805 soap_wsse_delete_Security (soap);
0 commit comments