portability/udp_sockets.hpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
#ifndef STLPLUS_UDP_SOCKET
#define STLPLUS_UDP_SOCKET
////////////////////////////////////////////////////////////////////////////////
 
// Author:    Andy Rushton
// Copyright: (c) Southampton University 1999-2004
//            (c) Andy Rushton           2004 onwards
// License:   BSD License, see ../docs/license.html
 
// A platform-independent (Unix and Windows anyway) interface to UDP sockets
 
////////////////////////////////////////////////////////////////////////////////
 
#include "portability_fixes.hpp"
#include "ip_sockets.hpp"
#include <string>
 
namespace stlplus
{
 
  //////////////////////////////////////////////////////////////////////////////
  // UDP client - creates a connectioned socket
 
  class UDP_client : protected IP_socket
  {
  public:
 
    // create an uninitialised socket
    UDP_client(void);
 
    // Send/Receive datagram packets to/from the given address/remote port on the local port.
    // - remote_address: IP name or number of remote host
    // - remote_port: port number of remote host
    // - local_port: port number to receive on - 0 to get an ephemeral port.
    UDP_client(const std::string& remote_address, unsigned short remote_port, unsigned short local_port=0);
 
    // Send/Receive datagram packets to/from the given address/remote port on the given local port
    // Enables default send to remote address/port
    // - remote_address: IP address of remote host - pre-looked-up using ip_lookup
    // - remote_port: port number of remote host
    // - local_port: port number to receive on - 0 to get an ephemeral port.
    UDP_client(unsigned long remote_address, unsigned short remote_port, unsigned short local_port=0);
 
    ////////////////////////////////////////////////////////////////////////////
    // initialisation, connection
 
    // function for performing IP lookup (i.e. gethostbyname)
    // could be standalone but making it a member means that it can use the socket's error handler
    // i.e. if this fails, the sockets error code will be set - clear it to use the socket again
    // - remote_address: IP name (stlplus.sourceforge.net) or dotted number (216.34.181.96)
    // - returns the IP address as a long integer - zero if there's an error
    // unsigned long ip_lookup(const std::string& remote_address);
    using IP_socket::ip_lookup;
 
    // Send/Receive datagram packets to/from the given address/remote port on the local port.
    // Enables default send to remote address/port
    // - remote_address: IP name or number of remote host
    // - remote_port: port number of remote host
    // - local_port: port number to receive on - 0 to get an ephemeral port.
    // - returns a success flag
    bool initialise(const std::string& remote_address, unsigned short remote_port, unsigned short local_port=0);
 
    // Send/Receive datagram packets to/from the given address/remote port on the given local port
    // Enables default send to remote address/port
    // - remote_address: IP address of remote host - pre-looked-up using ip_lookup
    // - remote_port: port number of remote host
    // - local_port: port number to receive on - 0 to get an ephemeral port.
    // - returns a success flag
    bool initialise(unsigned long remote_address, unsigned short remote_port, unsigned short local_port=0);
 
    // test whether this is an initialised socket
    // - returns whether this is initialised
    // bool initialised(void) const;
    using IP_socket::initialised;
 
    // close, i.e. disconnect the socket
    // - returns a success flag
    // bool close(void);
    using IP_socket::close;
 
    ////////////////////////////////////////////////////////////////////////////
    // sending/receiving
 
    // test whether a socket is connected and ready to send data, returns if ready or on timeout
    // - timeout: how long to wait in microseconds if not connected yet (blocking)
    // - returns status
    // bool send_ready(unsigned timeout = 0);
    using IP_socket::send_ready;
 
    // send to the remote address/port setup in initialise, from the local port also setup in initialise.
    // send data through the socket as a single datagram
    // - packet: string containing data to be sent - if data is successfully sent it is removed
    // - returns success flag
    bool send(std::string& packet);
 
    // test whether a socket is connected and ready to receive data, returns if ready or on timeout
    // - timeout: how long to wait in microseconds if not connected yet (blocking)
    // - returns status
    // bool receive_ready(unsigned timeout = 0);
    using IP_socket::receive_ready;
 
    // datagram receive
    // - packet: string to receive data from datagram - if data is successfully sent it is appended
    // - returns success flag - i.e. packet successfully received
    bool receive(std::string& packet);
 
    ////////////////////////////////////////////////////////////////////////////
    // informational
 
    // the local port number of the connection
    // returns the port number, 0 if not bound to a port
    // unsigned short local_port(void) const;
    using IP_socket::local_port;
 
    // the remote address of the connection
    // returns the address, 0 if ANY address
    // unsigned long remote_address(void) const;
    using IP_socket::remote_address;
 
    // the remote port number of the connection
    // returns the port number, 0 if not bound to a port
    // unsigned short remote_port(void) const;
    using IP_socket::remote_port;
 
    ////////////////////////////////////////////////////////////////////////////
    // error handling
    // errors are set internally
    // an error code of 0 is the test for no error, don't rely on the message being an empty string
    // an error code != 0 means an error, then there will be a message explaining the error
 
    // if an error is set it stays set - so you must clear it before further operations
    // void clear_error (void);
    using IP_socket::clear_error ;
 
    // get the error code of the last error
    // int error(void) const;
    using IP_socket::error;
 
    // get the explanatory message of the last error
    // std::string message(void) const;
    using IP_socket::message;
 
    ////////////////////////////////////////////////////////////////////////////
 
  private:
    IP_socket m_socket;
  };
 
  ////////////////////////////////////////////////////////////////////////////////
  // UDP server - creates a connectionless (multicast) listener socket
 
  class UDP_server : protected IP_socket
  {
  public:
 
    // create an uninitialised socket
    UDP_server(void);
 
    // Initialise socket.
    // Receive datagram packets from any address on provided local receiving port.
    // - local_port: port number to receive on - 0 to get an ephemeral port.
    UDP_server(unsigned short local_port);
 
    ////////////////////////////////////////////////////////////////////////////
    // initialisation, connection
 
    // function for performing IP lookup (i.e. gethostbyname)
    // could be standalone but making it a member means that it can use the socket's error handler
    // i.e. if this fails, the sockets error code will be set - clear it to use the socket again
    // - remote_address: IP name (stlplus.sourceforge.net) or dotted number (216.34.181.96)
    // - returns the IP address as a long integer - zero if there's an error
    // unsigned long ip_lookup(const std::string& remote_address);
    using IP_socket::ip_lookup;
 
    // Initialise socket.
    // Receive datagram packets from any address on provided local receiving port.
    // - local_port: port number to receive on - 0 to get an ephemeral port.
    // - returns a success flag
    bool initialise(unsigned short local_port);
 
    // test whether this is an initialised socket
    // - returns whether this is initialised
    // bool initialised(void) const;
    using IP_socket::initialised;
 
    // close, i.e. disconnect the socket
    // - returns a success flag
    // bool close(void);
    using IP_socket::close;
 
    ////////////////////////////////////////////////////////////////////////////
    // sending/receiving
 
    // test whether a socket is connected and ready to send data, returns if ready or on timeout
    // - timeout: how long to wait in microseconds if not connected yet (blocking)
    // - returns status
    // bool send_ready(unsigned timeout = 0);
    using IP_socket::send_ready;
 
    // send to the address/port given here, from the local port setup in initialise.
    // send data through the socket as a single datagram
    // - packet: string containing data to be sent - if data is successfully sent it is removed
    // - remote_address: IP name (stlplus.sourceforge.net) or dotted number (216.34.181.96)
    // - remote_port: port number of remote host
    // - returns success flag
    bool send(std::string& packet, const std::string& remote_address, unsigned short remote_port);
 
    // send to the address/port given here, from the local port setup in initialise.
    // send data through the socket as a single datagram
    // - packet: string containing data to be sent - if data is successfully sent it is removed
    // - remote_address: pre-looked-up IP address of remote host
    // - remote_port: port number of remote host
    // - returns success flag
    bool send(std::string& packet, unsigned long remote_address, unsigned short remote_port);
 
    // test whether a socket is connected and ready to receive data, returns if ready or on timeout
    // - timeout: how long to wait in microseconds if not connected yet (blocking)
    // - returns status
    // bool receive_ready(unsigned timeout = 0);
    using IP_socket::receive_ready;
 
    // datagram receive
    // - packet: string to receive data from datagram - if data is successfully sent it is appended
    // - remote_address: the address of the client that sent the packet, can then be used to reply
    // - remote_port: the port of the client that sent the packet, can then be used to reply
    // - returns success flag - i.e. packet successfully received
    bool receive(std::string& packet, unsigned long& remote_address, unsigned short& remote_port);
 
    ////////////////////////////////////////////////////////////////////////////
    // informational
 
    // the local port number of the connection
    // returns the port number, 0 if not bound to a port
    // unsigned short local_port(void) const;
    using IP_socket::local_port;
 
    ////////////////////////////////////////////////////////////////////////////
    // error handling
    // errors are set internally
    // an error code of 0 is the test for no error, don't rely on the message being an empty string
    // an error code != 0 means an error, then there will be a message explaining the error
 
    // if an error is set it stays set - so you must clear it before further operations
    // void clear_error(void);
    using IP_socket::clear_error;
 
    // get the error code of the last error
    // int error(void) const;
    using IP_socket::error;
 
    // get the explanatory message of the last error
    // std::string message(void) const;
    using IP_socket::message;
 
    ////////////////////////////////////////////////////////////////////////////
  };
 
  /////////////////////////////////////////////////////////////////////////////
  // fire and forget UDP client packet send function
 
  bool UDP_send(const std::string& packet,
                const std::string& remote_address, unsigned short remote_port, unsigned short local_port = 0);
 
  ////////////////////////////////////////////////////////////////////////////////
 
} // end namespace stlplus
 
#endif