@@ -34,6 +34,19 @@ public final class OSCUDPServer {
3434 /// Network interface to restrict connections to.
3535 public private( set) var interface : String ?
3636
37+ /// Enable local UDP port reuse by other processes.
38+ /// This property must be set prior to calling ``start()`` in order to take effect.
39+ ///
40+ /// By default, only one socket can be bound to a given IP address & port combination at a time. To enable
41+ /// multiple processes to simultaneously bind to the same address & port, you need to enable
42+ /// this functionality in the socket. All processes that wish to use the address & port
43+ /// simultaneously must all enable reuse port on the socket bound to that port.
44+ ///
45+ /// Due to limitations of `SO_REUSEPORT` on Apple platforms, enabling this only permits receipt of broadcast
46+ /// or multicast messages for any additional sockets which bind to the same address and port. Unicast
47+ /// messages are only received by the first socket to bind.
48+ public var isPortReuseEnabled : Bool = false
49+
3750 /// Returns a boolean indicating whether the OSC server has been started.
3851 public private( set) var isStarted : Bool = false
3952
@@ -50,19 +63,22 @@ public final class OSCUDPServer {
5063 /// - port: Local port to listen on for inbound OSC packets.
5164 /// If `nil` or `0`, a random available port in the system will be chosen.
5265 /// - interface: Optionally specify a network interface for which to constrain communication.
66+ /// - isPortReuseEnabled: Enable local UDP port reuse by other processes to receive broadcast packets.
5367 /// - timeTagMode: OSC TimeTag mode. (Default is recommended.)
5468 /// - queue: Optionally supply a custom dispatch queue for receiving OSC packets and dispatching the
5569 /// handler callback closure. If `nil`, a dedicated internal background queue will be used.
5670 /// - receiveHandler: Handler to call when OSC bundles or messages are received.
5771 public init (
5872 port: UInt16 ? = 8000 ,
5973 interface: String ? = nil ,
74+ isPortReuseEnabled: Bool = false ,
6075 timeTagMode: OSCTimeTagMode = . ignore,
6176 queue: DispatchQueue ? = nil ,
6277 receiveHandler: OSCHandlerBlock ? = nil
6378 ) {
6479 _localPort = ( port == nil || port == 0 ) ? nil : port
6580 self . interface = interface
81+ self . isPortReuseEnabled = isPortReuseEnabled
6682 self . timeTagMode = timeTagMode
6783 let queue = queue ?? DispatchQueue ( label: " com.orchetect.OSCKit.OSCUDPServer.queue " )
6884 self . queue = queue
@@ -84,6 +100,7 @@ extension OSCUDPServer {
84100
85101 stop ( )
86102
103+ try udpSocket. enableReusePort ( isPortReuseEnabled)
87104 try udpSocket. bind (
88105 toPort: _localPort ?? 0 , // 0 causes system to assign random open port
89106 interface: interface
0 commit comments