Fawkes API  Fawkes Development Version
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
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 IP.
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(PF_INET, SOCK_DGRAM, IPPROTO_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("Could not set SO_BROADCAST", errno);
100  }
101 
102  int reuse = 1;
103  if ( setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) {
104  throw SocketException("Could not set SO_REUSEADDR", errno);
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("Could not bind to port", errno);
114  }
115 }
116 
117 
118 /** Clone socket.
119  * @return a copied instance of BroadcastDatagramSocket.
120  */
121 Socket *
123 {
124  return new BroadcastDatagramSocket(*this);
125 }
126 
127 
128 /** Send data.
129  * This will send the given data to the broadcast address specified
130  * in the constructor.
131  * @param buf buffer to write
132  * @param buf_len length of buffer, number of bytes to write to stream
133  */
134 void
135 BroadcastDatagramSocket::send(void *buf, unsigned int buf_len)
136 {
137  try {
138  Socket::send(buf, buf_len, (struct ::sockaddr *)broadcast_addr, sizeof(struct ::sockaddr_in));
139  } catch (SocketException &e) {
140  e.append("BroadcastDatagramSocket::send(void*, unsigned int) failed");
141  throw;
142  }
143 }
144 
145 } // end namespace fawkes
BroadcastDatagramSocket(const char *broadcast_addr_s, unsigned short port, float timeout=0.f)
Constructor.
virtual void send(void *buf, unsigned int buf_len)
Send data.
virtual ~BroadcastDatagramSocket()
Destructor.
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:125
virtual void send(void *buf, size_t buf_len)
Write to the socket.
Definition: socket.cpp:608
void append(const char *format,...)
Append messages to the message list.
Definition: exception.cpp:341
Socket exception.
Definition: socket.h:58