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