Fawkes API
Fawkes Development Version
|
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