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 
34 namespace 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  */
105 void
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 
128 void
129 BroadcastDatagramSocket::bind(const unsigned short int port)
130 {
131  broadcast_addr->sin_port = htons(port);
132 
133  bind();
134 }
135 
136 void
137 BroadcastDatagramSocket::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  */
156 Socket *
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  */
168 void
169 BroadcastDatagramSocket::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
BroadcastDatagramSocket(const char *broadcast_addr_s, unsigned short port, float timeout=0.f)
Constructor.
virtual ~BroadcastDatagramSocket()
Destructor.
Fawkes library namespace.
BroadcastDatagramSocket & operator=(BroadcastDatagramSocket &s)
Assignment operator.
Socket base class.
Definition: socket.h:63
Broadcast datagram socket.
virtual void bind()
Bind socket.
virtual Socket * clone()
Clone socket.
Socket & operator=(Socket &socket)
Copy constructor.
Definition: socket.cpp:250
int sock_fd
Socket file descriptor.
Definition: socket.h:137
virtual void send(void *buf, size_t buf_len)
Write to the socket.
Definition: socket.cpp:846
virtual void send(void *buf, size_t buf_len)
Send data.
void append(const char *format,...)
Append messages to the message list.
Definition: exception.cpp:333
Socket exception.
Definition: socket.h:56