CNA-BUG-162: The phone notification channel and sender never initialise Winsock or link ws2_32, so on Windows they work only if something else did
Evidence basis: source-verified at the pinned commit; inferred from the source (the behaviour was not run). Claims on this page were checked by reading the CNA source at commit 3b43bd86; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.
modules/phone calls no WSAStartup and its library names no Winsock import library, so on Windows Open and SendAsync work only after another component initialised Winsock. Its INVALID_SOCKET checks were fixed on 2026-10-22.
- Identifier
CNA-BUG-162- Category
- Bug
- Subsystem
- Networking & gamer services
- Status
- Narrowed (partially fixed; describes only what survives)
- Verified against
- CNA
3b43bd86(3b43bd8687ed46523d873f9bec4b32bd8481dcb5) - Severity
- Medium (a triage suggestion, not a project priority)
- Evidence basis
- Inferred (strong): follows from the code, but the behaviour was not run
- Tests touching this area
- None
- Affected contract
- HttpNotificationChannel::Open() and RawPushNotificationMessage / ToastPushNotificationMessage::SendAsync on Windows
Expected behaviour
CNA builds the notification path for Windows on purpose: cmake/UnitTests.cmake (WINNATIVE-0014) says “The channel ITSELF is built on Windows ... this excludes the test's POSIX listener, not the feature”, and CNA's native-Windows plan records two compile fixes in these files. Winsock requires WSAStartup before socket or getaddrinfo; CNA's own Inspector socket layer calls it for exactly that reason.
Actual behaviour at TARGET
No file under modules/phone calls WSAStartup; among CNA's own sources only the Inspector's InternalSocket.cpp does (besides the vendored ENet's initialisation). In a process where neither ran, socket() fails with WSANOTINITIALISED: Open queues a ChannelOpenFailed error, logs that it could not create a listening socket and returns with no URI, and SendAsync fails at getaddrinfo and returns false. modules/phone/CMakeLists.txt links cna_phone to no ws2_32; the only phone target that names it is the MinGW build of the lifecycle test, which also calls WSAStartup itself.
Source locations
modules/phone/src/HttpNotificationChannel.cpp— Open and Listen (InvalidNativeSocket checks); no WSAStartupmodules/phone/src/PushNotificationSender.cpp— Post (getaddrinfo, socket check); no WSAStartupmodules/phone/CMakeLists.txt— cna_phone links no Winsock import librarymodules/inspector/src/InternalSocket.cpp— the one WSAStartup among CNA library sources, for comparisoncmake/UnitTests.cmake— WINNATIVE-0014 exclusion of HttpNotificationChannelTests.cpp under WIN32; CnaNotificationLifecycleTests links ws2_32 only for MinGWtools/phone/notification_lifecycle_test.cpp— calls WSAStartup itself before opening a channel
Evidence
Checked by reading the two phone sources, the module's CMake file and cmake/UnitTests.cmake at 3b43bd86, and by searching CNA's sources and CMake files for WSAStartup and ws2_32. Not executed: no Windows host was used. The start-up failure rests on Winsock's documented initialisation rule. Whether an executable that links CNA::Phone without the Inspector or ENet links at all on Windows was not established.
Narrowed at c6dec91f: 20fe6efd2 (MUSEUM-PHONE-001, 2026-10-22) replaced the < 0 comparisons in Open and Listen with a check against static_cast<socket_t>(-1), which equals INVALID_SOCKET, and Post in PushNotificationSender.cpp uses the same check, so a failed socket or accept is now detected. The missing initialisation and import library are unchanged.
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
HttpNotificationChannelTests.cpp, which holds both the channel and the sender suites, is still removed from the test sources under WIN32 because its test client uses POSIX socket headers. notification_lifecycle_test.cpp is also built for 64-bit MinGW, but it calls WSAStartup before opening a channel, so no test exercises a process that has not initialised Winsock.
Regression test
A Windows test that opens a channel in a process that has not initialised Winsock and posts to it. The fix is a reference-counted WSAStartup/WSACleanup inside the module, as InternalSocket.cpp does, with an explicit ws2_32 link on cna_phone.
Blast radius
Windows builds (native, and MinGW under Wine) of phone ports that use push notifications. PhoneApplicationService and POSIX hosts are unaffected. A process that already initialised Winsock (CNA networking started, the Inspector enabled, or host code) avoids the failure.
Workaround
Call WSAStartup(MAKEWORD(2, 2), &data) in the host before opening a channel or sending, and link ws2_32 explicitly.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- User guide
- Platform Support: Windows
- Known issues
- Bug index