Commit Graph
93 Commits
Author SHA1 Message Date
Isaac Connor c533546f18 fix: always send the auth hash in stream command responses
ajax/stream.php only included `auth` in its reply when it differed from
the hash the request carried. That hash comes from auth_relay, while the
browser stamps stream <img> URLs from a separate auth_hash global, so once
the two drifted the condition held permanently and the stale copy was
never corrected.

Observed on a montage page: a reload minted a new connkey and baked the
drifted hash into the src, after which every native <img> reconnect got a
403 from zms for nearly five hours.

Send it unconditionally; it is 32 bytes on a response that already carries
auth_relay.
2026-08-09 10:29:34 -04:00
Isaac Connor 10359bc011 fix: address the review comments on the stream error classification refs #5038
Three points raised on #5038 after it was merged.

ajaxError() documents the reason field as included "only when set", but
tested it for truthiness, which would also drop '' and '0'. None of the
four STREAM_ERR_ constants are falsy so nothing changed behaviour, but
the check now matches the documented contract. The client already treats
an empty reason as fatal, so a caller that does pass one still gets the
old handling.

The case 0 branch called ajaxError() twice in sequence and relied on the
first one exiting to keep the second from running on a timeout. Made the
two paths mutually exclusive so it no longer depends on that.

The test's "every ajaxError call is classified" assertion compared the
number of call sites to the number of STREAM_ERR_ occurrences anywhere in
the file. The four define()s are part of that count, so up to four calls
could lose their classification and the test would still pass - verified
by dropping the argument from one call, which the old assertion accepted.
It now matches each call to the end of its statement and requires every
one to carry a constant.
2026-08-07 21:06:58 -04:00
Isaac ConnorandClaude Opus 5 ae8c7db488 fix: stop orphaning zms when a stream command fails refs #5029
getStreamCmdResponse() responded to every ajax/stream.php failure the same way:
mint a fresh connkey and reload the img src. ajaxError() returns HTTP 200 with
result=Error, so these arrive in jQuery's done() rather than fail(), and all
twelve error paths in stream.php took that branch.

Only one of them means zms is gone. For the rest the process is still running
and streaming, and replacing the connkey makes it unaddressable: CMD_STOP,
CMD_QUIT and mode=single all then go to the new key, so nothing can reach the
old process and only SIGPIPE can stop it, which we know is unreliable. That is
why the reports of lingering zms after switching monitors were unaffected by
changes to what the stop path sends.

The timeout path made this routine rather than rare. On select() expiry
ajaxError is commented out, so the script carries on to socket_recvfrom() on a
now non-blocking socket. That returns false, and false == 0 under switch's loose
comparison, so a merely slow zms was reported as 'No data to read from socket'
and torn down.

stream.php now classifies each failure as no_socket, timeout, transient or
invalid, and sends it as 'reason'. The client restarts the stream only for
no_socket. A missing reason is still treated as fatal, so a php that predates
this keeps the old behaviour.

Before replacing the connkey the client now sends CMD_QUIT to the old one, so
the process we are about to lose track of is asked to exit. That is deliberately
not routed through streamCommand(): it must name its target explicitly, since
this.connKey is about to change, and its response must not feed back into
getStreamCmdResponse(), or a QUIT that also failed would re-enter the error path
and loop.

ajaxError() takes the classification as a third argument, named $reason because
$code is already the HTTP status, and only includes it when set, so the other
131 callers are unaffected.

Tests: tests/js covers the fatal/non-fatal decision including the no-reason
fallback, tests/php pins the classification mapping and the switch(false)
semantics the timeout branch depends on. Both verified to fail when the
behaviour is reverted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 06:43:11 -04:00
copilot-swe-agent[bot]andconnortechnology 1be352c790 fix: add stopped state for CMD_STOP, fixing paused=true response bug
When CMD_STOP is sent via AJAX using ZMS MJPEG streaming, the response
was incorrectly returning paused=true instead of indicating a stopped
state (paused=false).

Changes:
- Add `stopped` boolean to StreamBase (zm_stream.h)
- MonitorStream: CMD_STOP now sets stopped=true, paused=false instead
  of paused=true; run loop skips frame sending when stopped
- EventStream: CMD_STOP sets stopped=true (was already setting
  paused=false); run loop skips frame sending when stopped
- All other play/pause commands reset stopped=false
- Both streams include stopped field in the status response struct
- stream.php unpacks the new stopped field from MSG_DATA_WATCH and
  MSG_DATA_EVENT responses
- MonitorStream.js handles stopped status in UI (shows 'Stopped' mode)
- EventStream.js tracks stopped state from server response

Fixes issue: CMD_STOP response paused=true should be paused=false

Agent-Logs-Url: https://github.com/ZoneMinder/zoneminder/sessions/ba9cb47a-a3e8-4e13-aec7-c9cd258e2a3d

Co-authored-by: connortechnology <925519+connortechnology@users.noreply.github.com>
2026-05-06 01:58:48 +00:00
Isaac ConnorandClaude Opus 4.6 4df2bf4f0b feat: add analysis_image field to stream status for client-side verification
Add a boolean analysis_image field to the CMD_QUERY status response that
reports whether zms is actually sending analysis images (with motion zone
overlays) or regular capture images. This lets MonitorStream.js detect
when the stream state is out of sync with what the client requested and
re-send the CMD_ANALYZE_ON/OFF command to correct it.

The field is true only when frame_type is FRAME_ANALYSIS, shared memory
is valid, and the monitor has analysis enabled — matching the same
condition used to select the image in the streaming loop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:44:49 -04:00
Isaac Connor 7250923e02 Comment out debug 2025-07-26 11:52:21 -04:00
Isaac Connor 02871576a5 Add fps to event status. Convert CmdTimer to Interval 2024-10-22 18:22:19 -04:00
Isaac Connor 4f03ce362d Add analysing to stream data 2024-10-01 17:01:17 -04:00
Isaac Connor 0780032149 Add score to monitorstream status 2024-10-01 16:28:56 -04:00
Isaac Connor b5f393d960 prevent fatal php crash when maxfps is '' but forcing it to 0 2024-09-18 09:10:43 -04:00
Isaac Connor 4107058000 FIx units on warning about timeout 2024-02-05 18:42:05 -05:00
Alejandro Criado-Pérez 6fd119157a Text corrections 2023-08-27 02:00:59 +02:00
Isaac Connor 01b886ef49 Add scale to status and fix cast on elapsed 2023-04-06 15:15:36 -04:00
Isaac Connor b8a97b0fb9 Don't report errors from mkdir, it normally exists 2022-10-27 17:01:00 -04:00
Isaac Connor fe0e4fcb8f handle lack of sysvsem support in php better. Turn errors back on, just don't display them. Proceed regardless of semaphore success but log an error. 2022-09-28 14:48:13 -04:00
Isaac Connor 63e4c81d9c Try out just using connkey as the semaphore key instead of ftok 2022-09-22 16:22:36 -04:00
Isaac Connor faa6b8c9e7 Add connkey and semaphore key to logging about failure to get semaphore. Add sem_release before every ajaxError call because ajaxError exits and so we never release the semaphore. 2022-09-22 11:30:59 -04:00
Isaac Connor 84f14a03b0 Set auto_relay as well as auth_hash. getNavBar uses it 2022-08-17 15:00:01 -04:00
Isaac Connor a41cba5c33 Quote and spacing 2022-08-15 17:59:17 -04:00
Doug Nazar 262c087800 Use old event unpack() on 32bit systems.
PHP unpack() 64bit formats aren't available on 32bit.
2022-07-24 04:28:37 -04:00
Isaac Connor 3299f5ed49 Handle php versions < 5.6.1 which don't have non-blocking semaphore support 2022-06-13 15:56:52 -04:00
Nic Boet f6fdcc2953 Fix semaphore_tries on systems without System V
This appears to be impacting systems without php System V semaphore support
have_semaphore is not a boolean

Signed-off-by: Nic Boet <nic@boet.cc>
2022-06-06 22:51:34 -05:00
Isaac Connor 47fae7a296 spacing, improve debug 2022-02-26 19:18:28 -05:00
Isaac Connor edbe726e86 Implement semaphore retry. Make not getting the semaphore an error 2021-12-17 09:41:45 -05:00
Isaac Connor 30e4d72c1d Implement CMD_MAXFPS 2021-12-16 16:36:12 -05:00
Isaac Connor 28a3868069 report both capture_fps and analysis_fps 2020-12-09 15:03:33 -05:00
Isaac Connor 130588eb8f fix typos 2020-11-04 18:22:50 -05:00
Isaac Connor 10c0a6617c Return Debug to a regular function to match other logging functions. Since we switched to using namespaces we no longer clash with cake_php. 2020-10-14 10:39:25 -04:00
Isaac Connor c28ff1f2b4 Include loading EndTime when loading Events data so that we can determine if an event is in-progress
Keep track of last_id which is the last frame id that we have info for. Use it instead of Frame Count to prevent
accessing non-existent frame records
close ffmpeg_input on event change
include duration in status messages because it may change when playing an in-progress event.
when we hit the end of our frame data if it is an in-progress event, reload the event data instead of moving to the next event.
Include X-Timestamp in http headers to match live stream behaviour
Only send time to next event when mode=ALL
Fix scale behaviour on event view
2020-10-08 09:06:56 -04:00
Isaac Connor d7429014b6 Convert progress to a double instead of int. 2020-10-06 16:36:56 -04:00
Isaac Connor 0e89d28c26 Send SEEK as two integers representing a float 2020-10-06 16:34:06 -04:00
Isaac Connor 7c21f065bd Checking AuthHashGeneratedAt is no good because it gets updated before we check it. Instead check the auth hash in session against the one in and sensd the update if they are different 2020-03-02 12:07:11 -05:00
Isaac Connor 1865df3fe0 remove some debug, add some parenthesis to ensure logic works as intended 2020-01-07 17:08:07 -05:00
Isaac Connor cfca67f663 spacing and quotes 2019-06-07 14:07:23 -04:00
Isaac Connor c02eb2cd46 spacing 2019-05-24 10:00:51 -04:00
Isaac Connor c3324ada18 Put back mkdir ZM_PATH_SOCKS 2019-03-20 14:26:03 -04:00
Isaac Connor 6b6e787e4e fix ajax stream code 2019-03-19 12:05:45 -04:00
Isaac Connor 418276ff1c cleanup/debug 2019-03-19 12:02:42 -04:00
Isaac Connor 95567e07a4 Merge branch 'storageareas' of github.com:/ConnorTechnology/ZoneMinder into storageareas 2019-02-26 11:43:07 -05:00
Isaac Connor fd310c0f0a Merge branch 'master' into storageareas 2019-02-22 11:33:47 -05:00
Isaac Connor 8dd8888975 Php namespace (#2537)
* experiment with namespaces on the Server class

* experiment with namespaces on the Server class

* Implement the ZM namespace on objects

* Implement the ZM namespace on objects

* Implement the ZM namespace on objects
2019-02-22 09:19:07 -05:00
Isaac Connor 7026ebafac Make ajax/stream wait longer for zms. On pi can take up to 3 seconds. Also for php < 5.6, we need to fake 64bit unpack support 2019-01-22 16:45:38 -05:00
Isaac Connor 94401b6765 create ZM_PATH_SOCKS if it doesn't exist 2018-08-11 13:35:57 -04:00
Isaac Connor 798d046d81 Remove some debugging lines 2018-06-06 11:39:41 -04:00
Isaac Connor 12d46e2377 change event_id in status_msg to 64bit when unpacking 2018-04-18 09:52:57 -04:00
Isaac Connor 0b0fbae1c5 Add output of paused image when paused 2018-04-12 18:43:57 -04:00
Isaac Connor 22f86da372 Have to use the .sock file instead of w.lock 2018-04-11 10:38:13 -04:00
Isaac Connor a610d564d1 tweak timeouts 2018-01-31 15:51:12 -05:00
Isaac Connor a76fcb331c Remove debugging. Treat can't get semaphore as a non-error 2018-01-29 08:25:46 -08:00
Isaac Connor b1b8b42f2b Fix getting stream status updates when # of files open is > 1024. 2018-01-29 07:21:31 -08:00