Fawkes API  Fawkes Development Version
qa_socket_stream.cpp
00001 
00002 /***************************************************************************
00003  *  qa_socket_stream.cpp - Fawkes QA StreamSocket
00004  *
00005  *  Created: Fri Nov 11 14:38:10 2006 (on train back from Google, Hamburg)
00006  *  Copyright  2006  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 #include <core/threading/thread.h>
00027 #include <netcomm/socket/stream.h>
00028 #include <utils/system/signal.h>
00029 #include <utils/system/argparser.h>
00030 
00031 #include <cstdio>
00032 
00033 using namespace fawkes;
00034 
00035 class StreamServerThread : public Thread
00036 {
00037 public:
00038   StreamServerThread()
00039     : Thread("StreamServerThread", Thread::OPMODE_CONTINUOUS)
00040   {
00041     i = 0;
00042     s = new StreamSocket();
00043     s->bind(1910);
00044     s->listen();
00045     accepted = false;
00046     cs = NULL;
00047   }
00048 
00049   ~StreamServerThread()
00050   {
00051     printf("Closing server socket\n");
00052     s->close();
00053     if (cs) cs->close();
00054     printf("Closed server socket\n");
00055     delete s;
00056     delete cs;
00057   }
00058 
00059   virtual void loop()
00060   {
00061     if (! accepted) {
00062       try {
00063         cs = s->accept();
00064         accepted = true;
00065         printf("Server MTU: %u\n", cs->mtu());
00066       } catch (SocketException &e) {
00067         e.print_trace();
00068       }
00069     }
00070     if ( accepted ) {
00071       try {
00072         cs->write(&i, sizeof(i));
00073         unsigned int ri = 0;
00074         cs->read(&ri, sizeof(ri));
00075         if ( ri != i ) {
00076           printf("ERROR: sent %u but received %u\n", i, ri);
00077         } else {
00078           printf("OK: sent %u and received %u\n", i, ri);
00079         }
00080         ++i;
00081       } catch (SocketException &e) {
00082         e.print_trace();
00083         printf("Loop failed, disconnecting and waiting for new connection\n");
00084         delete cs;
00085         cs = NULL;
00086         accepted = false;
00087       }
00088     }
00089   }
00090 
00091  private:
00092   unsigned int i;
00093   StreamSocket *s;
00094   Socket *cs;
00095   bool accepted;
00096 };
00097 
00098 
00099 class StreamClientThread : public Thread
00100 {
00101 public:
00102   StreamClientThread(const char *host)
00103     : Thread("StreamClientThread", Thread::OPMODE_CONTINUOUS)
00104   {
00105     if ( host == NULL ) {
00106       this->host = "127.0.0.1";
00107     } else {
00108       this->host = host;
00109     }
00110 
00111     s = new StreamSocket();
00112     connected = false;
00113   }
00114 
00115   ~StreamClientThread()
00116   {
00117     printf("Closing client socket\n");
00118     s->close();
00119     printf("Closed client socket\n");
00120     delete s;
00121   }
00122 
00123   virtual void loop()
00124   {
00125     if (! connected) {
00126       try {
00127         s->connect(host, 1910);
00128         connected = true;
00129         printf("Client MTU: %u\n", s->mtu());
00130       } catch (SocketException &e) {
00131         e.print_trace();
00132       }
00133     }
00134     if ( connected ) {
00135       unsigned int i = 0;
00136       s->read(&i, sizeof(i));
00137       s->write(&i, sizeof(i));
00138     }
00139   }
00140 
00141  private:
00142   const char *host;
00143   StreamSocket *s;
00144   bool connected;
00145 };
00146 
00147 
00148 class StreamSocketQAMain : public SignalHandler
00149 {
00150  public:
00151   static const unsigned int MODE_STANDALONE = 1;
00152   static const unsigned int MODE_SERVER = 2;
00153   static const unsigned int MODE_CLIENT = 3;
00154 
00155   StreamSocketQAMain(unsigned int mode, const char *host = NULL)
00156   {
00157     s = NULL;
00158     c = NULL;
00159     if ( (mode == MODE_STANDALONE) ||
00160          (mode == MODE_SERVER) ) {
00161       s = new StreamServerThread();
00162     }
00163     if ( (mode == MODE_STANDALONE) ||
00164          (mode == MODE_CLIENT) ) {
00165       c = new StreamClientThread(host);
00166     }
00167   }
00168 
00169   ~StreamSocketQAMain()
00170   {
00171     delete s;
00172     delete c;
00173   }
00174 
00175 
00176   virtual void handle_signal(int signum)
00177   {
00178     printf("Signal received, cancelling threads\n");
00179     if (s)  s->cancel();
00180     if (c)  c->cancel();
00181     printf("Threads cancelled\n");
00182   }
00183 
00184   void run()
00185   {
00186     if (s)  s->start();
00187     if (c)  c->start();
00188     if (s)  s->join();
00189     if (c)  c->join();
00190   }
00191 
00192  private:
00193   StreamServerThread *s;
00194   StreamClientThread *c;
00195 
00196 };
00197 
00198 int
00199 main(int argc, char **argv)
00200 {
00201   StreamSocketQAMain *m;
00202   SignalManager::ignore(SIGPIPE);
00203 
00204   ArgumentParser argp(argc, argv, "sc:");
00205 
00206   if ( argp.has_arg("s") || argp.has_arg("c") ) {
00207     // Special mode
00208     if ( argp.has_arg("s") ) {
00209       // Only run Server
00210       m = new StreamSocketQAMain(StreamSocketQAMain::MODE_SERVER);
00211     } else {
00212       m = new StreamSocketQAMain(StreamSocketQAMain::MODE_CLIENT,
00213                                  argp.arg("c"));
00214     }
00215   } else {
00216     m = new StreamSocketQAMain(StreamSocketQAMain::MODE_STANDALONE);
00217   }
00218 
00219   SignalManager::register_handler(SIGINT, m);
00220 
00221   m->run();
00222   delete m;
00223 
00224   SignalManager::finalize();
00225 }
00226 
00227 /// @endcond