blob: c0b287d7ba9dac1f7b0268aa31311e1f786195ba [file] [log] [blame]
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001// Copyright (C) 1999-2005 Open Source Telecom Corporation.
2// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
3//
4// This program is free software; you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation; either version 2 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17//
18// As a special exception, you may use this file as part of a free software
19// library without restriction. Specifically, if other files instantiate
20// templates or use macros or inline functions from this file, or you compile
21// this file and link it with other files to produce an executable, this
22// file does not by itself cause the resulting executable to be covered by
23// the GNU General Public License. This exception does not however
24// invalidate any other reasons why the executable file might be covered by
25// the GNU General Public License.
26//
27// This exception applies only to the code released under the name GNU
28// Common C++. If you copy code from other releases into a copy of GNU
29// Common C++, as the General Public License permits, the exception does
30// not apply to the code that you add in this way. To avoid misleading
31// anyone as to the status of such modified files, you must delete
32// this exception notice from them.
33//
34// If you write modifications of your own for GNU Common C++, it is your choice
35// whether to permit this exception to apply to your modifications.
36// If you do not wish that, delete this exception notice.
37//
38
39/**
40 * @file commoncpp/udp.h
41 * @short udp derived socket classes.
42 **/
43
44#ifndef COMMONCPP_UDP_H_
45#define COMMONCPP_UDP_H_
46
47#include <cstdio>
48
49#ifndef COMMONCPP_CONFIG_H_
50#include <commoncpp/config.h>
51#endif
52
53#ifndef COMMONCPP_STRING_H_
54#include <commoncpp/string.h>
55#endif
56
57#ifndef COMMONCPP_ADDRESS_H_
58#include <commoncpp/address.h>
59#endif
60
61#ifndef COMMONCPP_SOCKET_H_
62#include <commoncpp/socket.h>
63#endif
64
65NAMESPACE_COMMONCPP
66
67/**
68 * UDP sockets implement the TCP SOCK_DGRAM UDP protocol. They can be
69 * used to pass unverified messages between hosts, or to broadcast a
70 * specific message to an entire subnet. Please note that Streaming of
71 * realtime data commonly use UDPDuplex related classes rather than
72 * UDPSocket.
73 *
74 * In addition to connected TCP sessions, Common C++ supports UDP sockets and
75 * these also cover a range of functionality. Like a TCPSocket, A UDPSocket
76 * can be created bound to a specific network interface and/or port address,
77 * though this is not required. UDP sockets also are usually either
78 * connected or otherwise "associated" with a specific "peer" UDP socket.
79 * Since UDP sockets operate through discreet packets, there are no streaming
80 * operators used with UDP sockets.
81 *
82 * In addition to the UDP "socket" class, there is a "UDPBroadcast" class.
83 * The UDPBroadcast is a socket that is set to send messages to a subnet as a
84 * whole rather than to an individual peer socket that it may be associated
85 * with.
86 *
87 * UDP sockets are often used for building "realtime" media streaming
88 * protocols and full duplex messaging services. When used in this manner,
89 * typically a pair of UDP sockets are used together; one socket is used to
90 * send and the other to receive data with an associated pair of UDP sockets
91 * on a "peer" host. This concept is represented through the Common C++
92 * UDPDuplex object, which is a pair of sockets that communicate with another
93 * UDPDuplex pair.
94 *
95 *
96 * @author David Sugar <dyfet@ostel.com>
97 * @short Unreliable Datagram Protocol sockets.
98 */
99class __EXPORT UDPSocket : public Socket
100{
101private:
102 inline Error setKeepAlive(bool enable)
103 {return Socket::setKeepAlive(enable);};
104
105protected:
106#ifdef CCXX_IPV6
107 union {
108 struct sockaddr_in6 ipv6;
109 struct sockaddr_in ipv4;
110 } peer;
111#else
112 union {
113 struct sockaddr_in ipv4;
114 } peer;
115#endif
116
117 Family family;
118
119public:
120 /**
121 * Create an unbound UDP socket, mostly for internal use.
122 */
123 UDPSocket(Family family = IPV4);
124
125 /**
126 * Create a UDP socket bound by a service name.
127 */
128 UDPSocket(const char *name, Family family = IPV4);
129
130 /**
131 * Create a UDP socket and bind it to a specific interface
132 * and port address so that other UDP sockets on remote
133 * machines (or the same host) may find and send UDP messages
134 * to it. On failure to bind, an exception is thrown.
135 *
136 * @param bind address to bind this socket to.
137 * @param port number to bind this socket to.
138 */
139 UDPSocket(const IPV4Address &bind, tpport_t port);
140#ifdef CCXX_IPV6
141 UDPSocket(const IPV6Address &bind, tpport_t port);
142#endif
143
144 /**
145 * Destroy a UDP socket as a socket.
146 */
147 virtual ~UDPSocket();
148
149 /**
150 * Set the loopback.
151 */
152 inline Error setLoopback(bool enable)
153 {return Socket::setLoopbackByFamily(enable, family);}
154
155 /**
156 * Set the multicast.
157 */
158 inline Error setMulticast(bool enable)
159 {return Socket::setMulticastByFamily(enable, family);}
160
161 /**
162 * Set time to live.
163 */
164 inline Error setTimeToLive(char ttl)
165 {return Socket::setTimeToLiveByFamily(ttl, family);}
166
167 /**
168 * set the peer address to send message packets to. This can be
169 * set before every send() call if nessisary.
170 *
171 * @param host address to send packets to.
172 * @param port number to deliver packets to.
173 */
174 void setPeer(const IPV4Host &host, tpport_t port);
175 void connect(const IPV4Host &host, tpport_t port);
176#ifdef CCXX_IPV6
177 void setPeer(const IPV6Host &host, tpport_t port);
178 void connect(const IPV6Host &host, tpport_t port);
179#endif
180
181 /**
182 * get the interface index for a named network device
183 *
184 * @param ethX is device name, like "eth0" or "eth1"
185 * @param InterfaceIndex is the index value returned by os
186 * @todo Win32 and ipv6 specific implementation.
187 */
188 Socket::Error getInterfaceIndex(const char *ethX,int& InterfaceIndex);
189
190 /**
191 * join a multicast group on a particular interface
192 *
193 * @param ia is the multicast address to use
194 * @param InterfaceIndex is the index value returned by
195 * getInterfaceIndex
196 * @todo Win32 and ipv6 specific implementation.
197 */
198 Socket::Error join(const IPV4Multicast &ia,int InterfaceIndex);
199
200 /**
201 * Send a message packet to a peer host.
202 *
203 * @param buf pointer to packet buffer to send.
204 * @param len of packet buffer to send.
205 * @return number of bytes sent.
206 */
207 ssize_t send(const void *buf, size_t len);
208
209 /**
210 * Receive a message from any host.
211 *
212 * @param buf pointer to packet buffer to receive.
213 * @param len of packet buffer to receive.
214 * @param reply save sender address for reply if true.
215 * @return number of bytes received.
216 */
217 ssize_t receive(void *buf, size_t len, bool reply = false);
218
219 /**
220 * Examine address of sender of next waiting packet. This also
221 * sets "peer" address to the sender so that the next "send"
222 * message acts as a "reply". This additional behavior overides
223 * the standard socket getSender behavior.
224 *
225 * @param port pointer to hold port number.
226 */
227 IPV4Host getIPV4Peer(tpport_t *port = NULL) const;
228 inline IPV4Host getPeer(tpport_t *port = NULL) const
229 {return getIPV4Peer(port);}
230
231#ifdef CCXX_IPV6
232 IPV6Host getIPV6Peer(tpport_t *port = NULL) const;
233#endif
234
235 /**
236 * Examine contents of next waiting packet.
237 *
238 * @param buf pointer to packet buffer for contents.
239 * @param len of packet buffer.
240 * @return number of bytes examined.
241 */
242 inline ssize_t peek(void *buf, size_t len)
243 {return ::recv(so, (char *)buf, len, MSG_PEEK);};
244
245 /**
246 * Associate socket with a named connection
247 */
248 void setPeer(const char *service);
249 void connect(const char *service);
250
251 /**
252 * Disassociate this socket from any host connection. No data
253 * should be read or written until a connection is established.
254 */
255 Error disconnect(void);
256};
257
258/**
259 * Representing a UDP socket used for subnet broadcasts, this class
260 * provides an alternate binding and setPeer() capability for UDP
261 * sockets.
262 *
263 * @author David Sugar <dyfet@ostel.com>
264 * @short Unreliable Datagram for subnet broadcasts.
265 */
266class __EXPORT UDPBroadcast : public UDPSocket
267{
268private:
269 void setPeer(const IPV4Host &ia, tpport_t port);
270
271 Error setBroadcast(bool enable)
272 {return Socket::setBroadcast(enable);};
273
274public:
275 /**
276 * Create and bind a subnet broadcast socket.
277 *
278 * @param ia address to bind socket under locally.
279 * @param port to bind socket under locally.
280 */
281 UDPBroadcast(const IPV4Address &ia, tpport_t port);
282
283 /**
284 * Set peer by subnet rather than specific host.
285 *
286 * @param subnet of peer hosts to send to.
287 * @param port number to use.
288 */
289 void setPeer(const IPV4Broadcast &subnet, tpport_t port);
290};
291
292/**
293 * Representing half of a two-way UDP connection, the UDP transmitter
294 * can broadcast data to another selected peer host or to an entire
295 * subnet.
296 *
297 * @author David Sugar <dyfet@ostel.com>
298 * @short Unreliable Datagram Peer Associations.
299 */
300class __EXPORT UDPTransmit : protected UDPSocket
301{
302private:
303 /**
304 * Common code for diferent flavours of Connect (host, broadcast,
305 * multicast).
306 *
307 * @param ia network address to associate with
308 * @param port port number to associate with
309 */
310 Error cConnect(const IPV4Address &ia, tpport_t port);
311
312protected:
313 /**
314 * Create a UDP transmitter.
315 */
316 UDPTransmit(Family family = IPV4);
317
318 /**
319 * Create a UDP transmitter, bind it to a specific interface
320 * and port address so that other UDP sockets on remote
321 * machines (or the same host) may find and send UDP messages
322 * to it, and associate it with a given port on a peer host.
323 * On failure to bind, an exception is thrown. This class is
324 * only used to build the UDP Duplex.
325 *
326 * @param bind address to bind this socket to.
327 * @param port number to bind this socket to.
328 */
329 UDPTransmit(const IPV4Address &bind, tpport_t port = 5005);
330#ifdef CCXX_IPV6
331 UDPTransmit(const IPV6Address &bind, tpport_t port = 5005);
332#endif
333
334 /**
335 * Associate this socket with a specified peer host. The port
336 * number from the constructor will be used. All UDP packets
337 * will be sent to and received from the specified host.
338 *
339 * @return 0 on success, -1 on error.
340 * @param host address to connect socket to.
341 * @param port to connect socket to.
342 */
343 Error connect(const IPV4Host &host, tpport_t port);
344#ifdef CCXX_IPV6
345 Error connect(const IPV6Address &host, tpport_t port);
346#endif
347
348 /**
349 * Associate this socket with a subnet of peer hosts for
350 * subnet broadcasting. The server must be able to assert
351 * broadcast permission for the socket.
352 *
353 * @return 0 on success, -1 on error.
354 * @param subnet subnet address to broadcast into.
355 * @param port transport port to broadcast into.
356 */
357 Error connect(const IPV4Broadcast &subnet, tpport_t port);
358
359 /**
360 * Associate this socket with a multicast group.
361 *
362 * @return 0 on success, -1 on error.
363 * @param mgroup address of the multicast group to send to.
364 * @param port port number
365 */
366 Error connect(const IPV4Multicast &mgroup, tpport_t port);
367#ifdef CCXX_IPV6
368 Error connect(const IPV6Multicast &mgroup, tpport_t port);
369#endif
370
371 /**
372 * Transmit "send" to use "connected" send rather than sendto.
373 *
374 * @return number of bytes sent.
375 * @param buf address of buffer to send.
376 * @param len of bytes to send.
377 */
378 inline ssize_t send(const void *buf, size_t len)
379 {return ::send(so, (const char *)buf, len, MSG_NOSIGNAL);}
380
381 /**
382 * Stop transmitter.
383 */
384 inline void endTransmitter(void)
385 {Socket::endSocket();}
386
387 /*
388 * Get transmitter socket.
389 *
390 * @return transmitter.
391 */
392 inline SOCKET getTransmitter(void)
393 {return so;};
394
395 inline Error setMulticast(bool enable)
396 {return Socket::setMulticastByFamily(enable, family);}
397
398 inline Error setTimeToLive(unsigned char ttl)
399 {return Socket::setTimeToLiveByFamily(ttl, family);};
400
401public:
402 /**
403 * Transmit "send" to use "connected" send rather than sendto.
404 *
405 * @note Windows does not support MSG_DONTWAIT, so it is defined
406 * as 0 on that platform.
407 * @return number of bytes sent.
408 * @param buffer address of buffer to send.
409 * @param len of bytes to send.
410 */
411 inline ssize_t transmit(const char *buffer, size_t len)
412 {return ::send(so, buffer, len, MSG_DONTWAIT|MSG_NOSIGNAL);}
413
414 /**
415 * See if output queue is empty for sending more packets.
416 *
417 * @return true if output available.
418 * @param timeout in milliseconds to wait.
419 */
420 inline bool isOutputReady(unsigned long timeout = 0l)
421 {return Socket::isPending(Socket::pendingOutput, timeout);};
422
423
424 inline Error setRouting(bool enable)
425 {return Socket::setRouting(enable);};
426
427 inline Error setTypeOfService(Tos tos)
428 {return Socket::setTypeOfService(tos);};
429
430 inline Error setBroadcast(bool enable)
431 {return Socket::setBroadcast(enable);};
432};
433
434/**
435 * Representing half of a two-way UDP connection, the UDP receiver
436 * can receive data from another peer host or subnet. This class is
437 * used exclusivily to derive the UDPDuplex.
438 *
439 * @author David Sugar <dyfet@ostel.com>
440 * @short Unreliable Datagram Peer Associations.
441 */
442class __EXPORT UDPReceive : protected UDPSocket
443{
444protected:
445 /**
446 * Create a UDP receiver, bind it to a specific interface
447 * and port address so that other UDP sockets on remote
448 * machines (or the same host) may find and send UDP messages
449 * to it, and associate it with a given port on a peer host.
450 * On failure to bind, an exception is thrown.
451 *
452 * @param bind address to bind this socket to.
453 * @param port number to bind this socket to.
454 */
455 UDPReceive(const IPV4Address &bind, tpport_t port);
456#ifdef CCXX_IPV6
457 UDPReceive(const IPV6Address &bind, tpport_t port);
458#endif
459
460 /**
461 * Associate this socket with a specified peer host. The port
462 * number from the constructor will be used. All UDP packets
463 * will be sent received from the specified host.
464 *
465 * @return 0 on success, -1 on error.
466 * @param host host network address to connect socket to.
467 * @param port host transport port to connect socket to.
468 */
469 Error connect(const IPV4Host &host, tpport_t port);
470#ifdef CCXX_IPV6
471 Error connect(const IPV6Host &host, tpport_t port);
472#endif
473
474 /**
475 * Check for pending data.
476 *
477 * @return true if data is waiting.
478 * @param timeout in milliseconds.
479 */
480 bool isPendingReceive(timeout_t timeout)
481 {return Socket::isPending(Socket::pendingInput, timeout);};
482
483 /**
484 * End receiver.
485 */
486 inline void endReceiver(void)
487 {Socket::endSocket();}
488
489 inline SOCKET getReceiver(void) const
490 {return so;};
491
492 inline Error setRouting(bool enable)
493 {return Socket::setRouting(enable);}
494
495 inline Error setMulticast(bool enable)
496 {return Socket::setMulticastByFamily(enable, family);}
497
498 inline Error join(const IPV4Multicast &ia)
499 {return Socket::join(ia);}
500
501#ifdef CCXX_IPV6
502 inline Error join(const IPV6Multicast &ia)
503 {return Socket::join(ia);}
504#endif
505
506 inline Error drop(const IPV4Multicast &ia)
507 {return Socket::drop(ia);}
508
509#ifdef CCXX_IPV6
510 inline Error drop(const IPV6Multicast &ia)
511 {return Socket::drop(ia);}
512#endif
513
514public:
515 /**
516 * Receive a data packet from the connected peer host.
517 *
518 * @return num of bytes actually received.
519 * @param buf address of data receive buffer.
520 * @param len size of data receive buffer.
521 */
522 inline ssize_t receive(void *buf, size_t len)
523 {return ::recv(so, (char *)buf, len, 0);};
524
525 /**
526 * See if input queue has data packets available.
527 *
528 * @return true if data packets available.
529 * @param timeout in milliseconds.
530 */
531 inline bool isInputReady(timeout_t timeout = TIMEOUT_INF)
532 {return Socket::isPending(Socket::pendingInput, timeout);};
533};
534
535/**
536 * UDP duplex connections impliment a bi-directional point-to-point UDP
537 * session between two peer hosts. Two UDP sockets are typically used
538 * on alternating port addresses to assure that sender and receiver
539 * data does not collide or echo back. A UDP Duplex is commonly used
540 * for full duplex real-time streaming of UDP data between hosts.
541 *
542 * @author David Sugar <dyfet@ostel.com>
543 * @short Unreliable Datagram Peer Associations.
544 */
545class __EXPORT UDPDuplex : public UDPTransmit, public UDPReceive
546{
547public:
548 /**
549 * Create a UDP duplex as a pair of UDP simplex objects
550 * bound to alternating and interconnected port addresses.
551 *
552 * @param bind address to bind this socket to.
553 * @param port number to bind sender.
554 */
555 UDPDuplex(const IPV4Address &bind, tpport_t port);
556#ifdef CCXX_IPV6
557 UDPDuplex(const IPV6Address &bind, tpport_t port);
558#endif
559
560 /**
561 * Associate the duplex with a specified peer host. Both
562 * the sender and receiver will be interconnected with
563 * the remote host.
564 *
565 * @return 0 on success, error code on error.
566 * @param host address to connect socket to.
567 * @param port number to connect socket to.
568 */
569 Error connect(const IPV4Host &host, tpport_t port);
570#ifdef CCXX_IPV6
571 Error connect(const IPV6Host &host, tpport_t port);
572#endif
573
574 /**
575 * Disassociate this duplex from any host connection. No data
576 * should be read or written until a connection is established.
577 *
578 * @return 0 on success, error code on error.
579 */
580 Error disconnect(void);
581};
582
583END_NAMESPACE
584
585#endif