rob@76
|
1 /*
|
rob@76
|
2 oscpack -- Open Sound Control (OSC) packet manipulation library
|
rob@76
|
3 http://www.rossbencina.com/code/oscpack
|
rob@76
|
4
|
rob@76
|
5 Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
rob@76
|
6
|
rob@76
|
7 Permission is hereby granted, free of charge, to any person obtaining
|
rob@76
|
8 a copy of this software and associated documentation files
|
rob@76
|
9 (the "Software"), to deal in the Software without restriction,
|
rob@76
|
10 including without limitation the rights to use, copy, modify, merge,
|
rob@76
|
11 publish, distribute, sublicense, and/or sell copies of the Software,
|
rob@76
|
12 and to permit persons to whom the Software is furnished to do so,
|
rob@76
|
13 subject to the following conditions:
|
rob@76
|
14
|
rob@76
|
15 The above copyright notice and this permission notice shall be
|
rob@76
|
16 included in all copies or substantial portions of the Software.
|
rob@76
|
17
|
rob@76
|
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
rob@76
|
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
rob@76
|
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
rob@76
|
21 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
rob@76
|
22 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
rob@76
|
23 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
rob@76
|
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
rob@76
|
25 */
|
rob@76
|
26
|
rob@76
|
27 /*
|
rob@76
|
28 The text above constitutes the entire oscpack license; however,
|
rob@76
|
29 the oscpack developer(s) also make the following non-binding requests:
|
rob@76
|
30
|
rob@76
|
31 Any person wishing to distribute modifications to the Software is
|
rob@76
|
32 requested to send the modifications to the original developer so that
|
rob@76
|
33 they can be incorporated into the canonical version. It is also
|
rob@76
|
34 requested that these non-binding requests be included whenever the
|
rob@76
|
35 above license is reproduced.
|
rob@76
|
36 */
|
rob@76
|
37 #ifndef INCLUDED_OSCPACK_UDPSOCKET_H
|
rob@76
|
38 #define INCLUDED_OSCPACK_UDPSOCKET_H
|
rob@76
|
39
|
rob@76
|
40 #include <cstring> // size_t
|
rob@76
|
41
|
rob@76
|
42 #include "NetworkingUtils.h"
|
rob@76
|
43 #include "IpEndpointName.h"
|
rob@76
|
44
|
rob@76
|
45
|
rob@76
|
46 class PacketListener;
|
rob@76
|
47 class TimerListener;
|
rob@76
|
48
|
rob@76
|
49 class UdpSocket;
|
rob@76
|
50
|
rob@76
|
51 class SocketReceiveMultiplexer{
|
rob@76
|
52 class Implementation;
|
rob@76
|
53 Implementation *impl_;
|
rob@76
|
54
|
rob@76
|
55 friend class UdpSocket;
|
rob@76
|
56
|
rob@76
|
57 public:
|
rob@76
|
58 SocketReceiveMultiplexer();
|
rob@76
|
59 ~SocketReceiveMultiplexer();
|
rob@76
|
60
|
rob@76
|
61 // only call the attach/detach methods _before_ calling Run
|
rob@76
|
62
|
rob@76
|
63 // only one listener per socket, each socket at most once
|
rob@76
|
64 void AttachSocketListener( UdpSocket *socket, PacketListener *listener );
|
rob@76
|
65 void DetachSocketListener( UdpSocket *socket, PacketListener *listener );
|
rob@76
|
66
|
rob@76
|
67 void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener );
|
rob@76
|
68 void AttachPeriodicTimerListener(
|
rob@76
|
69 int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener );
|
rob@76
|
70 void DetachPeriodicTimerListener( TimerListener *listener );
|
rob@76
|
71
|
rob@76
|
72 void Run(); // loop and block processing messages indefinitely
|
rob@76
|
73 void RunUntilSigInt();
|
rob@76
|
74 void Break(); // call this from a listener to exit once the listener returns
|
rob@76
|
75 void AsynchronousBreak(); // call this from another thread or signal handler to exit the Run() state
|
rob@76
|
76 };
|
rob@76
|
77
|
rob@76
|
78
|
rob@76
|
79 class UdpSocket{
|
rob@76
|
80 class Implementation;
|
rob@76
|
81 Implementation *impl_;
|
rob@76
|
82
|
rob@76
|
83 friend class SocketReceiveMultiplexer::Implementation;
|
rob@76
|
84
|
rob@76
|
85 public:
|
rob@76
|
86
|
rob@76
|
87 // Ctor throws std::runtime_error if there's a problem
|
rob@76
|
88 // initializing the socket.
|
rob@76
|
89 UdpSocket();
|
rob@76
|
90 virtual ~UdpSocket();
|
rob@76
|
91
|
rob@76
|
92 // Enable broadcast addresses (e.g. x.x.x.255)
|
rob@76
|
93 // Sets SO_BROADCAST socket option.
|
rob@76
|
94 void SetEnableBroadcast( bool enableBroadcast );
|
rob@76
|
95
|
rob@76
|
96 // Enable multiple listeners for a single port on same
|
rob@76
|
97 // network interface*
|
rob@76
|
98 // Sets SO_REUSEADDR (also SO_REUSEPORT on OS X).
|
rob@76
|
99 // [*] The exact behavior of SO_REUSEADDR and
|
rob@76
|
100 // SO_REUSEPORT is undefined for some common cases
|
rob@76
|
101 // and may have drastically different behavior on different
|
rob@76
|
102 // operating systems.
|
rob@76
|
103 void SetAllowReuse( bool allowReuse );
|
rob@76
|
104
|
rob@76
|
105
|
rob@76
|
106 // The socket is created in an unbound, unconnected state
|
rob@76
|
107 // such a socket can only be used to send to an arbitrary
|
rob@76
|
108 // address using SendTo(). To use Send() you need to first
|
rob@76
|
109 // connect to a remote endpoint using Connect(). To use
|
rob@76
|
110 // ReceiveFrom you need to first bind to a local endpoint
|
rob@76
|
111 // using Bind().
|
rob@76
|
112
|
rob@76
|
113 // Retrieve the local endpoint name when sending to 'to'
|
rob@76
|
114 IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const;
|
rob@76
|
115
|
rob@76
|
116 // Connect to a remote endpoint which is used as the target
|
rob@76
|
117 // for calls to Send()
|
rob@76
|
118 void Connect( const IpEndpointName& remoteEndpoint );
|
rob@76
|
119 void Send( const char *data, std::size_t size );
|
rob@76
|
120 void SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size );
|
rob@76
|
121
|
rob@76
|
122
|
rob@76
|
123 // Bind a local endpoint to receive incoming data. Endpoint
|
rob@76
|
124 // can be 'any' for the system to choose an endpoint
|
rob@76
|
125 void Bind( const IpEndpointName& localEndpoint );
|
rob@76
|
126 bool IsBound() const;
|
rob@76
|
127
|
rob@76
|
128 std::size_t ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size );
|
rob@76
|
129 };
|
rob@76
|
130
|
rob@76
|
131
|
rob@76
|
132 // convenience classes for transmitting and receiving
|
rob@76
|
133 // they just call Connect and/or Bind in the ctor.
|
rob@76
|
134 // note that you can still use a receive socket
|
rob@76
|
135 // for transmitting etc
|
rob@76
|
136
|
rob@76
|
137 class UdpTransmitSocket : public UdpSocket{
|
rob@76
|
138 public:
|
rob@76
|
139 UdpTransmitSocket( const IpEndpointName& remoteEndpoint )
|
rob@76
|
140 { Connect( remoteEndpoint ); }
|
rob@76
|
141 };
|
rob@76
|
142
|
rob@76
|
143
|
rob@76
|
144 class UdpReceiveSocket : public UdpSocket{
|
rob@76
|
145 public:
|
rob@76
|
146 UdpReceiveSocket( const IpEndpointName& localEndpoint )
|
rob@76
|
147 { Bind( localEndpoint ); }
|
rob@76
|
148 };
|
rob@76
|
149
|
rob@76
|
150
|
rob@76
|
151 // UdpListeningReceiveSocket provides a simple way to bind one listener
|
rob@76
|
152 // to a single socket without having to manually set up a SocketReceiveMultiplexer
|
rob@76
|
153
|
rob@76
|
154 class UdpListeningReceiveSocket : public UdpSocket{
|
rob@76
|
155 SocketReceiveMultiplexer mux_;
|
rob@76
|
156 PacketListener *listener_;
|
rob@76
|
157 public:
|
rob@76
|
158 UdpListeningReceiveSocket( const IpEndpointName& localEndpoint, PacketListener *listener )
|
rob@76
|
159 : listener_( listener )
|
rob@76
|
160 {
|
rob@76
|
161 Bind( localEndpoint );
|
rob@76
|
162 mux_.AttachSocketListener( this, listener_ );
|
rob@76
|
163 }
|
rob@76
|
164
|
rob@76
|
165 ~UdpListeningReceiveSocket()
|
rob@76
|
166 { mux_.DetachSocketListener( this, listener_ ); }
|
rob@76
|
167
|
rob@76
|
168 // see SocketReceiveMultiplexer above for the behaviour of these methods...
|
rob@76
|
169 void Run() { mux_.Run(); }
|
rob@76
|
170 void RunUntilSigInt() { mux_.RunUntilSigInt(); }
|
rob@76
|
171 void Break() { mux_.Break(); }
|
rob@76
|
172 void AsynchronousBreak() { mux_.AsynchronousBreak(); }
|
rob@76
|
173 };
|
rob@76
|
174
|
rob@76
|
175
|
rob@76
|
176 #endif /* INCLUDED_OSCPACK_UDPSOCKET_H */
|