rob@76: /* rob@76: oscpack -- Open Sound Control (OSC) packet manipulation library rob@76: http://www.rossbencina.com/code/oscpack rob@76: rob@76: Copyright (c) 2004-2013 Ross Bencina rob@76: rob@76: Permission is hereby granted, free of charge, to any person obtaining rob@76: a copy of this software and associated documentation files rob@76: (the "Software"), to deal in the Software without restriction, rob@76: including without limitation the rights to use, copy, modify, merge, rob@76: publish, distribute, sublicense, and/or sell copies of the Software, rob@76: and to permit persons to whom the Software is furnished to do so, rob@76: subject to the following conditions: rob@76: rob@76: The above copyright notice and this permission notice shall be rob@76: included in all copies or substantial portions of the Software. rob@76: rob@76: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, rob@76: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF rob@76: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. rob@76: IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR rob@76: ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF rob@76: CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION rob@76: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rob@76: */ rob@76: rob@76: /* rob@76: The text above constitutes the entire oscpack license; however, rob@76: the oscpack developer(s) also make the following non-binding requests: rob@76: rob@76: Any person wishing to distribute modifications to the Software is rob@76: requested to send the modifications to the original developer so that rob@76: they can be incorporated into the canonical version. It is also rob@76: requested that these non-binding requests be included whenever the rob@76: above license is reproduced. rob@76: */ rob@76: #ifndef INCLUDED_OSCPACK_UDPSOCKET_H rob@76: #define INCLUDED_OSCPACK_UDPSOCKET_H rob@76: rob@76: #include // size_t rob@76: rob@76: #include "NetworkingUtils.h" rob@76: #include "IpEndpointName.h" rob@76: rob@76: rob@76: class PacketListener; rob@76: class TimerListener; rob@76: rob@76: class UdpSocket; rob@76: rob@76: class SocketReceiveMultiplexer{ rob@76: class Implementation; rob@76: Implementation *impl_; rob@76: rob@76: friend class UdpSocket; rob@76: rob@76: public: rob@76: SocketReceiveMultiplexer(); rob@76: ~SocketReceiveMultiplexer(); rob@76: rob@76: // only call the attach/detach methods _before_ calling Run rob@76: rob@76: // only one listener per socket, each socket at most once rob@76: void AttachSocketListener( UdpSocket *socket, PacketListener *listener ); rob@76: void DetachSocketListener( UdpSocket *socket, PacketListener *listener ); rob@76: rob@76: void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener ); rob@76: void AttachPeriodicTimerListener( rob@76: int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener ); rob@76: void DetachPeriodicTimerListener( TimerListener *listener ); rob@76: rob@76: void Run(); // loop and block processing messages indefinitely rob@76: void RunUntilSigInt(); rob@76: void Break(); // call this from a listener to exit once the listener returns rob@76: void AsynchronousBreak(); // call this from another thread or signal handler to exit the Run() state rob@76: }; rob@76: rob@76: rob@76: class UdpSocket{ rob@76: class Implementation; rob@76: Implementation *impl_; rob@76: rob@76: friend class SocketReceiveMultiplexer::Implementation; rob@76: rob@76: public: rob@76: rob@76: // Ctor throws std::runtime_error if there's a problem rob@76: // initializing the socket. rob@76: UdpSocket(); rob@76: virtual ~UdpSocket(); rob@76: rob@76: // Enable broadcast addresses (e.g. x.x.x.255) rob@76: // Sets SO_BROADCAST socket option. rob@76: void SetEnableBroadcast( bool enableBroadcast ); rob@76: rob@76: // Enable multiple listeners for a single port on same rob@76: // network interface* rob@76: // Sets SO_REUSEADDR (also SO_REUSEPORT on OS X). rob@76: // [*] The exact behavior of SO_REUSEADDR and rob@76: // SO_REUSEPORT is undefined for some common cases rob@76: // and may have drastically different behavior on different rob@76: // operating systems. rob@76: void SetAllowReuse( bool allowReuse ); rob@76: rob@76: rob@76: // The socket is created in an unbound, unconnected state rob@76: // such a socket can only be used to send to an arbitrary rob@76: // address using SendTo(). To use Send() you need to first rob@76: // connect to a remote endpoint using Connect(). To use rob@76: // ReceiveFrom you need to first bind to a local endpoint rob@76: // using Bind(). rob@76: rob@76: // Retrieve the local endpoint name when sending to 'to' rob@76: IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const; rob@76: rob@76: // Connect to a remote endpoint which is used as the target rob@76: // for calls to Send() rob@76: void Connect( const IpEndpointName& remoteEndpoint ); rob@76: void Send( const char *data, std::size_t size ); rob@76: void SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size ); rob@76: rob@76: rob@76: // Bind a local endpoint to receive incoming data. Endpoint rob@76: // can be 'any' for the system to choose an endpoint rob@76: void Bind( const IpEndpointName& localEndpoint ); rob@76: bool IsBound() const; rob@76: rob@76: std::size_t ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size ); rob@76: }; rob@76: rob@76: rob@76: // convenience classes for transmitting and receiving rob@76: // they just call Connect and/or Bind in the ctor. rob@76: // note that you can still use a receive socket rob@76: // for transmitting etc rob@76: rob@76: class UdpTransmitSocket : public UdpSocket{ rob@76: public: rob@76: UdpTransmitSocket( const IpEndpointName& remoteEndpoint ) rob@76: { Connect( remoteEndpoint ); } rob@76: }; rob@76: rob@76: rob@76: class UdpReceiveSocket : public UdpSocket{ rob@76: public: rob@76: UdpReceiveSocket( const IpEndpointName& localEndpoint ) rob@76: { Bind( localEndpoint ); } rob@76: }; rob@76: rob@76: rob@76: // UdpListeningReceiveSocket provides a simple way to bind one listener rob@76: // to a single socket without having to manually set up a SocketReceiveMultiplexer rob@76: rob@76: class UdpListeningReceiveSocket : public UdpSocket{ rob@76: SocketReceiveMultiplexer mux_; rob@76: PacketListener *listener_; rob@76: public: rob@76: UdpListeningReceiveSocket( const IpEndpointName& localEndpoint, PacketListener *listener ) rob@76: : listener_( listener ) rob@76: { rob@76: Bind( localEndpoint ); rob@76: mux_.AttachSocketListener( this, listener_ ); rob@76: } rob@76: rob@76: ~UdpListeningReceiveSocket() rob@76: { mux_.DetachSocketListener( this, listener_ ); } rob@76: rob@76: // see SocketReceiveMultiplexer above for the behaviour of these methods... rob@76: void Run() { mux_.Run(); } rob@76: void RunUntilSigInt() { mux_.RunUntilSigInt(); } rob@76: void Break() { mux_.Break(); } rob@76: void AsynchronousBreak() { mux_.AsynchronousBreak(); } rob@76: }; rob@76: rob@76: rob@76: #endif /* INCLUDED_OSCPACK_UDPSOCKET_H */