Fawkes API Fawkes Development Version
datagram_broadcast.cpp
1
2/***************************************************************************
3 * datagram_broadcast.cpp - Fawkes datagram broadcast socket (UDP)
4 *
5 * Created: Fri 02 Apr 2010 03:30:55 PM CEST
6 * Copyright 2006 Tim Niemueller [www.niemueller.de]
7 * Copyright 2010 Christoph Schwering
8 *
9 ****************************************************************************/
10
11/* This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version. A runtime exception applies to
15 * this software (see LICENSE.GPL_WRE file mentioned below for details).
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
21 *
22 * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
23 */
24
25#include <arpa/inet.h>
26#include <netcomm/socket/datagram_broadcast.h>
27#include <netinet/in.h>
28#include <sys/socket.h>
29
30#include <cerrno>
31#include <cstdlib>
32#include <cstring>
33
34namespace fawkes {
35
36/** @class BroadcastDatagramSocket netcomm/socket/datagram.h
37 * Broadcast datagram socket.
38 * An broadcast UDP socket on top of IPv4 (not available for IPv6).
39 *
40 * @ingroup NetComm
41 * @author Christoph Schwering
42 */
43
44/** Constructor.
45 * @param broadcast_addr_s textual representation of the broadcast IP address
46 * to use for broadcast communication. NOT a hostname!
47 * @param port port
48 * @param timeout timeout, if 0 all operationsare blocking, otherwise it
49 * is tried for timeout seconds.
50 */
52 unsigned short port,
53 float timeout)
54: Socket(IPv4, UDP, timeout)
55{
56 broadcast_addr = (struct ::sockaddr_in *)malloc(sizeof(struct ::sockaddr_in));
57
58 struct in_addr a;
59 if (inet_aton(broadcast_addr_s, &a) == -1) {
60 throw SocketException("Invalid address given");
61 }
62 broadcast_addr->sin_family = AF_INET;
63 broadcast_addr->sin_addr.s_addr = a.s_addr;
64 broadcast_addr->sin_port = htons(port);
65
66#if 0
67 //set_ttl(1);
68 set_loop(false);
69#endif
70}
71
72/** Destructor. */
74{
75 free(broadcast_addr);
76}
77
78/** Copy constructor.
79 * @param datagram_socket socket to copy.
80 */
82: Socket(datagram_socket)
83{
84 broadcast_addr = (struct ::sockaddr_in *)malloc(sizeof(struct ::sockaddr_in));
85 memcpy(broadcast_addr, datagram_socket.broadcast_addr, sizeof(struct ::sockaddr_in));
86}
87
88/** Assignment operator.
89 * @param s socket to copy from
90 * @return reference to this instance
91 */
94{
96 free(broadcast_addr);
97 broadcast_addr = (struct ::sockaddr_in *)malloc(sizeof(struct ::sockaddr_in));
98 memcpy(broadcast_addr, s.broadcast_addr, sizeof(struct ::sockaddr_in));
99 return *this;
100}
101
102/** Bind socket.
103 * This will make the socket listen for incoming traffic.
104 */
105void
107{
108 int broadcast = 1;
109 if (setsockopt(sock_fd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) == -1) {
110 throw SocketException(errno, "Could not set SO_BROADCAST");
111 }
112
113 int reuse = 1;
114 if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) {
115 throw SocketException(errno, "Could not set SO_REUSEADDR");
116 }
117
118 struct ::sockaddr_in local;
119 local.sin_family = AF_INET;
120 local.sin_addr.s_addr = INADDR_ANY;
121 local.sin_port = broadcast_addr->sin_port;
122
123 if (::bind(sock_fd, (struct ::sockaddr *)&local, sizeof(local)) < 0) {
124 throw SocketException(errno, "Could not bind to port");
125 }
126}
127
128void
129BroadcastDatagramSocket::bind(const unsigned short int port)
130{
131 broadcast_addr->sin_port = htons(port);
132
133 bind();
134}
135
136void
137BroadcastDatagramSocket::bind(const unsigned short int port, const char *hostname)
138{
139 free(broadcast_addr);
140 broadcast_addr = (struct ::sockaddr_in *)malloc(sizeof(struct ::sockaddr_in));
141
142 struct in_addr a;
143 if (inet_aton(hostname, &a) == -1) {
144 throw SocketException("Invalid address given");
145 }
146 broadcast_addr->sin_family = AF_INET;
147 broadcast_addr->sin_addr.s_addr = a.s_addr;
148 broadcast_addr->sin_port = htons(port);
149
150 bind();
151}
152
153/** Clone socket.
154 * @return a copied instance of BroadcastDatagramSocket.
155 */
156Socket *
158{
159 return new BroadcastDatagramSocket(*this);
160}
161
162/** Send data.
163 * This will send the given data to the broadcast address specified
164 * in the constructor.
165 * @param buf buffer to write
166 * @param buf_len length of buffer, number of bytes to write to stream
167 */
168void
169BroadcastDatagramSocket::send(void *buf, size_t buf_len)
170{
171 try {
172 Socket::send(buf, buf_len, (struct ::sockaddr *)broadcast_addr, sizeof(struct ::sockaddr_in));
173 } catch (SocketException &e) {
174 e.append("BroadcastDatagramSocket::send(void*, unsigned int) failed");
175 throw;
176 }
177}
178
179} // end namespace fawkes
Broadcast datagram socket.
BroadcastDatagramSocket & operator=(BroadcastDatagramSocket &s)
Assignment operator.
virtual Socket * clone()
Clone socket.
virtual ~BroadcastDatagramSocket()
Destructor.
virtual void send(void *buf, size_t buf_len)
Send data.
BroadcastDatagramSocket(const char *broadcast_addr_s, unsigned short port, float timeout=0.f)
Constructor.
virtual void bind()
Bind socket.
void append(const char *format,...) noexcept
Append messages to the message list.
Definition: exception.cpp:333
Socket exception.
Definition: socket.h:57
Socket base class.
Definition: socket.h:64
int sock_fd
Socket file descriptor.
Definition: socket.h:137
Socket & operator=(Socket &socket)
Copy constructor.
Definition: socket.cpp:250
virtual void send(void *buf, size_t buf_len)
Write to the socket.
Definition: socket.cpp:846
Fawkes library namespace.