Fawkes API Fawkes Development Version
qa_socket_datagram_broadcast.cpp
1
2/***************************************************************************
3 * qa_socket_datagram_broadcast.cpp - Fawkes QA BroadcastDatagramSocket
4 *
5 * Created: Fri 02 Apr 2010 03:15:49 PM CEST
6 * Copyright 2006-2007 Tim Niemueller [www.niemueller.de]
7 * Copyright 2010 Christoph Schwering (copied from Tim's
8 * qa_socket_datagram_multicast.cpp)
9 *
10 ****************************************************************************/
11
12/* This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version. A runtime exception applies to
16 * this software (see LICENSE.GPL_WRE file mentioned below for details).
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Library General Public License for more details.
22 *
23 * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
24 */
25
26/// @cond QA
27
28/* NOTE:
29 * This program does not do any error correction, if a number is not received
30 * by the reflector, this may stall. On wireless networks this is usually
31 * the case for an i << 100, often even i < 10. If you use a cable connection
32 * this problem does not occur. Meaning that the connection stalls is not an
33 * indicator for a broken implementation, as long as you can do this with a
34 * reliable connection like a cabled LAN for a long time (stopped my tests
35 * at i ~ 1000).
36 */
37
38#include <core/threading/thread.h>
39#include <netcomm/socket/datagram_broadcast.h>
40#include <netinet/in.h>
41#include <utils/system/argparser.h>
42#include <utils/system/signal.h>
43
44#include <cstdio>
45#include <cstring>
46#include <netdb.h>
47
48#define BROADCAST_IP "172.16.35.255"
49
50using namespace fawkes;
51
52class BroadcastDatagramServerThread : public Thread
53{
54public:
55 BroadcastDatagramServerThread(unsigned short int port)
56 : Thread("BroadcastDatagramServerThread", Thread::OPMODE_CONTINUOUS)
57 {
58 i = 0;
59 try {
60 s = new BroadcastDatagramSocket(BROADCAST_IP, port);
61 s->bind();
62 } catch (Exception &e) {
63 e.print_trace();
64 throw;
65 }
66 }
67
68 ~BroadcastDatagramServerThread()
69 {
70 printf("Closing server socket\n");
71 s->close();
72 printf("Closed server socket\n");
73 delete s;
74 }
75
76 virtual void
77 loop()
78 {
79 try {
80 printf("Sending %u\n", i);
81 s->send(&i, sizeof(i));
82 printf("Sent %u\n", i);
83 unsigned int ri = 0;
84 from_len = sizeof(from);
85 printf("Receiving\n");
86 s->recv(&ri, sizeof(ri), (struct sockaddr *)&from, &from_len);
87 if (ri != i) {
88 printf("ERROR: sent %u but received %u\n", i, ri);
89 } else {
90 printf("OK: sent %u and received %u\n", i, ri);
91 }
92 ++i;
93 } catch (Exception &e) {
94 printf("Loop failed\n");
95 e.print_trace();
96 throw;
97 }
98 }
99
100private:
101 unsigned int i;
103 struct sockaddr_in from;
104 unsigned int from_len;
105};
106
107class BroadcastDatagramReflectorThread : public Thread
108{
109public:
110 BroadcastDatagramReflectorThread(unsigned short int port)
111 : Thread("BroadcastDatagramReflectorThread", Thread::OPMODE_CONTINUOUS)
112 {
113 try {
114 s = new BroadcastDatagramSocket("224.16.0.1", port);
115 s->bind();
116 } catch (Exception &e) {
117 e.print_trace();
118 throw;
119 }
120 from_len = sizeof(from);
121 }
122
123 ~BroadcastDatagramReflectorThread()
124 {
125 printf("Closing reflector socket\n");
126 s->close();
127 printf("Closed reflector socket\n");
128 delete s;
129 }
130
131 virtual void
132 loop()
133 {
134 unsigned int i = 0;
135 printf("Waiting for data to reflect\n");
136 s->recv(&i, sizeof(i), (struct sockaddr *)&from, &from_len);
137 printf("Received %u, reflecting\n", i);
138 s->send(&i, sizeof(i));
139 }
140
141private:
143 struct sockaddr_in from;
144 unsigned int from_len;
145};
146
147class BroadcastDatagramSocketQAMain : public SignalHandler
148{
149public:
150 BroadcastDatagramSocketQAMain(ArgumentParser &argp)
151 {
152 s = NULL;
153 r = NULL;
154 if (argp.has_arg("r")) {
155 printf("Going to be a reflector\n");
156 r = new BroadcastDatagramReflectorThread(1910);
157 } else {
158 s = new BroadcastDatagramServerThread(1910);
159 }
160 }
161
162 ~BroadcastDatagramSocketQAMain()
163 {
164 delete s;
165 delete r;
166 }
167
168 virtual void
169 handle_signal(int signum)
170 {
171 printf("Signal received, cancelling threads\n");
172 if (s != NULL)
173 s->cancel();
174 if (r != NULL)
175 r->cancel();
176 printf("Threads cancelled\n");
177 }
178
179 void
180 run()
181 {
182 if (s != NULL) {
183 s->start();
184 s->join();
185 }
186 if (r != NULL) {
187 r->start();
188 r->join();
189 }
190 }
191
192private:
193 BroadcastDatagramServerThread * s;
194 BroadcastDatagramReflectorThread *r;
195};
196
197int
198main(int argc, char **argv)
199{
200 printf("Going to broadcast to " BROADCAST_IP "\n");
201 ArgumentParser argp(argc, argv, "r");
202 BroadcastDatagramSocketQAMain m(argp);
203 SignalManager::register_handler(SIGINT, &m);
204 SignalManager::ignore(SIGPIPE);
205
206 m.run();
207 return 0;
208}
209
210/// @endcond
Parse command line arguments.
Definition: argparser.h:64
bool has_arg(const char *argn)
Check if argument has been supplied.
Definition: argparser.cpp:165
Broadcast datagram socket.
Base class for exceptions in Fawkes.
Definition: exception.h:36
void print_trace() noexcept
Prints trace to stderr.
Definition: exception.cpp:601
Interface for signal handling.
Definition: signal.h:36
Thread class encapsulation of pthreads.
Definition: thread.h:46
Fawkes library namespace.