Skip to content

Fix UDP socket binding on reconnection (Fixes #25) - #27

Merged
Skeyelab merged 1 commit into
mainfrom
fix-udp
Oct 24, 2025
Merged

Skeyelab merged 1 commit into
mainfrom
fix-udp

Conversation

@Skeyelab

Copy link
Copy Markdown
Member

Summary

This PR fixes the UDP socket binding issue described in #25 where connection attempts would fail with "Failed to create UDP sockets" on retry.

Problem

The original issue was that closeUdpSockets() only called shutdown() on socket objects but didn't recreate them. JUCE's DatagramSocket objects remain bound to their ports after shutdown(), preventing subsequent bindToPort() calls from succeeding.

Flow of the bug:

  1. First connection attempt fails at TCP handshake
  2. closeUdpSockets() is called, which only shuts down sockets
  3. Second attempt calls createUdpSockets() which tries to bind to same ports
  4. Binding fails because sockets are still bound from previous attempt

Solution

1. Fix Socket Cleanup (Primary Fix)

  • Modified closeUdpSockets() to recreate socket objects using std::make_unique<juce::DatagramSocket>() after shutdown
  • This ensures ports are properly released and new sockets can bind to them

2. Add Socket State Validation (Defensive)

  • Added defensive validation in createUdpSockets() to ensure socket objects exist before binding
  • Added comprehensive logging to track socket lifecycle and binding attempts

3. Enhanced Debugging & Monitoring

  • Added detailed logging throughout the connection flow
  • Fixed logging output to use juce::Logger::writeToLog() instead of undefined DBG macro
  • Added RTSP request/response debugging

4. Test Coverage

  • Added unit tests to verify socket reconnection behavior
  • Tests verify multiple connection cycles work correctly

Files Modified

  • Source/AirPlay/RaopClient.cpp - Main socket management fixes
  • Source/AirPlay/RaopClient.h - Made socket methods public for testing
  • Source/AirPlay/AirPlayManager.cpp - Added connection debugging
  • Source/PluginEditor.cpp - Added UI connection debugging
  • Source/Discovery/DeviceDiscoveryMac.mm - Added device discovery debugging
  • Tests/RaopClientTests.cpp - Added socket reconnection tests

Testing

✅ Verified Working:

  • UDP socket binding now works on retry attempts
  • No more "Failed to create UDP sockets" error
  • Device discovery working correctly (finds 5 AirPlay devices)
  • TCP connection establishment working
  • RTSP request sending working

Current Status

The original UDP socket binding issue is completely resolved. The connection now proceeds to RTSP handshake, but there's a separate issue where AirPlay devices are not responding to RTSP requests (this will be addressed in a separate issue).

Related Issues

Fixes #25

- Modify closeUdpSockets() to recreate socket objects after shutdown
- Add defensive validation in createUdpSockets() to ensure clean state
- Add comprehensive logging for debugging connection flow
- Add unit tests to verify socket reconnection behavior
- Fix RTSP connection timeout by removing unnecessary socket readiness check
- Fix logging output to use juce::Logger::writeToLog

This resolves the 'Failed to create UDP sockets' error on retry attempts
by ensuring socket objects are properly recreated after shutdown.
@Skeyelab
Skeyelab merged commit 945586b into main Oct 24, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Connection fails on first attempt, UDP socket error on retry

2 participants