StreamSocket (next commit) is the first in-tree code to instantiate
zm::TcpUnixServer and zm::Pipe; three pre-existing defects surfaced:
- TcpUnixServer::listen() and accept() were declared but never defined,
failing at link time for any user of the class
- TcpUnixSocket/TcpInetSocket's (socket, newSd) constructors delegated to
TcpSocket only; Socket is a virtual base, so the descriptor-carrying
constructor was ignored and accepted sockets ended up with mSd == -1
(writes failed with EBADF)
- Pipe::setBlocking() only changed the write end; reads on the
supposedly non-blocking pipe blocked forever
Tests: covered indirectly by the StreamSocket suite added in the next
commit; full ctest suite (98 tests) passes at the branch head.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
InetSocket::bind creates its socket inside the getaddrinfo loop and
called ::bind without SO_REUSEADDR, so a connection lingering in
TIME_WAIT on the same port fails the bind with EADDRINUSE. Seen as
zm_comms test failures on macOS when the send/recv test runs before
the server bind tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1. Socket::getBlocking() returned inverted logic. When O_NONBLOCK flag
is set, the socket is non-blocking, so blocking should be false.
The code returned true when O_NONBLOCK was set.
2. Select::wait() checked the wrong fd_set for writers. It checked
&rfds (read fd_set) instead of &wfds (write fd_set), meaning
writeable sockets were never properly detected.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When using strncpy the NUL-termination can go missing if the string to be copied is longer than the buffer.
Make sure the last character in the buffer is NUL.
If this really happens, the error (non-existing path due to truncation) will be caught during bind-ing.
Fixes the following warning:
/home/peterke/DEV/zoneminder/src/zm_comms.cpp: In member function ‘bool ZM::SockAddrUnix::resolve(const char*, const char*)’:
/home/peterke/DEV/zoneminder/src/zm_comms.cpp:207:10: warning: ‘char* strncpy(char*, const char*, size_t)’ specified bound 108 equals destination size [-Wstringop-truncation]
207 | strncpy(mAddrUn.sun_path, path, sizeof(mAddrUn.sun_path));
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mLocalAddr is always nullptr and not used anywhere. So just use a local variable for
the time being.
The comms types will need an API rework since the current one is rather convoluted.
Postpone fixing this properly until then.
The Socket class collides with a class named the same way from liblive555. This confuses the linker and links the wrong object leading to a crash when connecting to the RTSP server.
With this commit a unified structure for includes is introduced.
The general rules:
* Only include what you need
* Include wherever possible in the cpp and forward-declare in the header
The includes are sorted in a local to global fashion. This means for the include order:
0. If cpp file: The corresponding h file and an empty line
1. Includes from the project sorted alphabetically
2. System/library includes sorted alphabetically
3. Conditional includes
Monitors with source type 'remote' can now be accessed over IPv6. This
code uses getaddrinfo(3) now instead of gethostbyname(3) - and changes a
lot of networking stuff which should be tested thoroughly.