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