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 <netcomm/socket/datagram_broadcast.h>
26 
27 #include <sys/socket.h>
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
30 #include <cstdlib>
31 #include <cstring>
32 #include <cerrno>
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 
73 /** Destructor. */
75 {
76  free(broadcast_addr);
77 }
78 
79 
80 /** Copy constructor.
81  * @param datagram_socket socket to copy.
82  */
84  : Socket(datagram_socket)
85 {
86  broadcast_addr = (struct ::sockaddr_in *)malloc(sizeof(struct ::sockaddr_in));
87  memcpy(broadcast_addr, datagram_socket.broadcast_addr, sizeof(struct ::sockaddr_in));
88 }
89 
90 
91 /** Bind socket.
92  * This will make the socket listen for incoming traffic.
93  */
94 void
96 {
97  int broadcast = 1;
98  if ( setsockopt(sock_fd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) == -1) {
99  throw SocketException(errno, "Could not set SO_BROADCAST");
100  }
101 
102  int reuse = 1;
103  if ( setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) {
104  throw SocketException(errno, "Could not set SO_REUSEADDR");
105  }
106 
107  struct ::sockaddr_in local;
108  local.sin_family = AF_INET;
109  local.sin_addr.s_addr = INADDR_ANY;
110  local.sin_port = broadcast_addr->sin_port;
111 
112  if (::bind(sock_fd, (struct ::sockaddr *) &local, sizeof(local)) < 0) {
113  throw SocketException(errno, "Could not bind to port");
114  }
115 }
116 
117 void
118 BroadcastDatagramSocket::bind(const unsigned short int port)
119 {
120  broadcast_addr->sin_port = htons(port);
121 
122  bind();
123 }
124 
125 void
126 BroadcastDatagramSocket::bind(const unsigned short int port, const char *hostname)
127 {
128  free(broadcast_addr);
129  broadcast_addr = (struct ::sockaddr_in *)malloc(sizeof(struct ::sockaddr_in));
130 
131  struct in_addr a;
132  if ( inet_aton(hostname, &a) == -1 ) {
133  throw SocketException("Invalid address given");
134  }
135  broadcast_addr->sin_family = AF_INET;
136  broadcast_addr->sin_addr.s_addr = a.s_addr;
137  broadcast_addr->sin_port = htons(port);
138 
139  bind();
140 }
141 
142 /** Clone socket.
143  * @return a copied instance of BroadcastDatagramSocket.
144  */
145 Socket *
147 {
148  return new BroadcastDatagramSocket(*this);
149 }
150 
151 
152 /** Send data.
153  * This will send the given data to the broadcast address specified
154  * in the constructor.
155  * @param buf buffer to write
156  * @param buf_len length of buffer, number of bytes to write to stream
157  */
158 void
159 BroadcastDatagramSocket::send(void *buf, size_t buf_len)
160 {
161  try {
162  Socket::send(buf, buf_len, (struct ::sockaddr *)broadcast_addr, sizeof(struct ::sockaddr_in));
163  } catch (SocketException &e) {
164  e.append("BroadcastDatagramSocket::send(void*, unsigned int) failed");
165  throw;
166  }
167 }
168 
169 } // end namespace fawkes
BroadcastDatagramSocket(const char *broadcast_addr_s, unsigned short port, float timeout=0.f)
Constructor.
virtual ~BroadcastDatagramSocket()
Destructor.
Fawkes library namespace.
Socket base class.
Definition: socket.h:65
Broadcast datagram socket.
virtual void bind()
Bind socket.
virtual Socket * clone()
Clone socket.
int sock_fd
Socket file descriptor.
Definition: socket.h:140
virtual void send(void *buf, size_t buf_len)
Write to the socket.
Definition: socket.cpp:816
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:341
Socket exception.
Definition: socket.h:58