Fawkes API Fawkes Development Version

qa_socket_datagram_multicast.cpp

00001 
00002 /***************************************************************************
00003  *  qa_socket_datagram_multicast.cpp - Fawkes QA MulticastDatagramSocket
00004  *
00005  *  Created: Sat Jan 13 23:51:23 2007
00006  *  Copyright  2006-2007  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 /// @cond QA
00025 
00026 /* NOTE:
00027  * This program does not do any error correction, if a number is not received
00028  * by the reflector, this may stall. On wireless networks this is usually
00029  * the case for an i << 100, often even i < 10. If you use a cable connection
00030  * this problem does not occur. Meaning that the connection stalls is not an
00031  * indicator for a broken implementation, as long as you can do this with a
00032  * reliable connection like a cabled LAN for a long time (stopped my tests
00033  * at i ~ 1000).
00034  */
00035 
00036 
00037 #include <core/threading/thread.h>
00038 #include <netcomm/socket/datagram_multicast.h>
00039 #include <utils/system/signal.h>
00040 #include <utils/system/argparser.h>
00041 
00042 #include <netdb.h>
00043 #include <cstdio>
00044 #include <cstring>
00045 #include <netinet/in.h>
00046 
00047 using namespace fawkes;
00048 
00049 class MulticastDatagramServerThread : public Thread
00050 {
00051 public:
00052   MulticastDatagramServerThread(unsigned short int port, bool looping)
00053     : Thread("MulticastDatagramServerThread", Thread::OPMODE_CONTINUOUS)
00054   {
00055     i = 0;
00056     try {
00057       s = new MulticastDatagramSocket("224.16.0.1", port);
00058       s->bind();
00059       s->set_loop(looping);
00060     } catch (Exception &e) {
00061       e.print_trace();
00062       throw;
00063     }
00064   }
00065 
00066   ~MulticastDatagramServerThread()
00067   {
00068     printf("Closing server socket\n");
00069     s->close();
00070     printf("Closed server socket\n");
00071     delete s;
00072   }
00073 
00074   virtual void loop()
00075   {
00076     try {
00077       printf("Sending %u\n", i);
00078       s->send(&i, sizeof(i));
00079       printf("Sent %u\n", i);
00080       unsigned int ri = 0;
00081       from_len = sizeof(from);
00082       printf("Receiving\n");
00083       s->recv(&ri, sizeof(ri), (struct sockaddr *)&from, &from_len);
00084       if ( ri != i ) {
00085         printf("ERROR: sent %u but received %u\n", i, ri);
00086       } else {
00087         printf("OK: sent %u and received %u\n", i, ri);
00088       }
00089       ++i;
00090     } catch (Exception &e) {
00091       printf("Loop failed\n");
00092       e.print_trace();
00093       throw;
00094     }
00095   }
00096 
00097  private:
00098   unsigned int i;
00099   MulticastDatagramSocket *s;
00100   struct sockaddr_in from;
00101   unsigned int from_len;
00102 };
00103 
00104 class MulticastDatagramReflectorThread : public Thread
00105 {
00106 public:
00107   MulticastDatagramReflectorThread(unsigned short int port)
00108     : Thread("MulticastDatagramReflectorThread", Thread::OPMODE_CONTINUOUS)
00109   {
00110     try {
00111       s = new MulticastDatagramSocket("224.16.0.1", port);
00112       s->bind();
00113     } catch (Exception &e) {
00114       e.print_trace();
00115       throw;
00116     }
00117     from_len = sizeof(from);
00118   }
00119 
00120   ~MulticastDatagramReflectorThread()
00121   {
00122     printf("Closing reflector socket\n");
00123     s->close();
00124     printf("Closed reflector socket\n");
00125     delete s;
00126   }
00127 
00128   virtual void loop()
00129   {
00130     unsigned int i = 0;
00131     printf("Waiting for data to reflect\n");
00132     s->recv(&i, sizeof(i), (struct sockaddr *)&from, &from_len);
00133     printf("Received %u, reflecting\n", i);
00134     s->send(&i, sizeof(i));
00135   }
00136 
00137  private:
00138   MulticastDatagramSocket *s;
00139   struct sockaddr_in from;
00140   unsigned int from_len;
00141 };
00142 
00143 
00144 class MulticastDatagramSocketQAMain : public SignalHandler
00145 {
00146  public:
00147   MulticastDatagramSocketQAMain(ArgumentParser *argp)
00148   {
00149     s = NULL;
00150     r = NULL;
00151     this->argp = argp;
00152     if ( argp->has_arg("r") ) {
00153       printf("Going to be a reflector\n");
00154       r = new MulticastDatagramReflectorThread(1910);
00155     } else {
00156       bool looping = argp->has_arg("l");
00157       if ( looping ) {
00158         printf("Enabling local loop (we receive own traffic)\n");
00159       }
00160       s = new MulticastDatagramServerThread(1910, looping);
00161     }
00162   }
00163 
00164   ~MulticastDatagramSocketQAMain()
00165   {
00166     delete s;
00167     delete r;
00168   }
00169 
00170 
00171   virtual void handle_signal(int signum)
00172   {
00173     printf("Signal received, cancelling threads\n");
00174     if ( s != NULL )  s->cancel();
00175     if ( r != NULL )  r->cancel();
00176     printf("Threads cancelled\n");
00177   }
00178 
00179   void run()
00180   {
00181     if ( s != NULL ) {
00182       s->start();
00183       s->join();
00184     }
00185     if ( r != NULL ) {
00186       r->start();
00187       r->join();
00188     }
00189   }
00190 
00191  private:
00192   ArgumentParser *argp;
00193   MulticastDatagramServerThread *s;
00194   MulticastDatagramReflectorThread *r;
00195 
00196 };
00197 
00198 int
00199 main(int argc, char **argv)
00200 {
00201   ArgumentParser *argp = new ArgumentParser(argc, argv, "rl");
00202 
00203   MulticastDatagramSocketQAMain m(argp);
00204   SignalManager::register_handler(SIGINT, &m);
00205   SignalManager::ignore(SIGPIPE);
00206 
00207   m.run();
00208 
00209   delete argp;
00210   return 0;
00211 }
00212 
00213 /// @endcond
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends