Fawkes API  Fawkes Development Version
qa_socket_stream.cpp
1 
2 /***************************************************************************
3  * qa_socket_stream.cpp - Fawkes QA StreamSocket
4  *
5  * Created: Fri Nov 11 14:38:10 2006 (on train back from Google, Hamburg)
6  * Copyright 2006 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 #include <core/threading/thread.h>
27 #include <netcomm/socket/stream.h>
28 #include <utils/system/signal.h>
29 #include <utils/system/argparser.h>
30 
31 #include <cstdio>
32 
33 using namespace fawkes;
34 
35 class StreamServerThread : public Thread
36 {
37 public:
38  StreamServerThread()
39  : Thread("StreamServerThread", Thread::OPMODE_CONTINUOUS)
40  {
41  i = 0;
42  s = new StreamSocket();
43  s->bind(1910);
44  s->listen();
45  accepted = false;
46  cs = NULL;
47  }
48 
49  ~StreamServerThread()
50  {
51  printf("Closing server socket\n");
52  s->close();
53  if (cs) cs->close();
54  printf("Closed server socket\n");
55  delete s;
56  delete cs;
57  }
58 
59  virtual void loop()
60  {
61  if (! accepted) {
62  try {
63  cs = s->accept();
64  accepted = true;
65  printf("Server MTU: %u\n", cs->mtu());
66  } catch (SocketException &e) {
67  e.print_trace();
68  }
69  }
70  if ( accepted ) {
71  try {
72  cs->write(&i, sizeof(i));
73  unsigned int ri = 0;
74  cs->read(&ri, sizeof(ri));
75  if ( ri != i ) {
76  printf("ERROR: sent %u but received %u\n", i, ri);
77  } else {
78  printf("OK: sent %u and received %u\n", i, ri);
79  }
80  ++i;
81  } catch (SocketException &e) {
82  e.print_trace();
83  printf("Loop failed, disconnecting and waiting for new connection\n");
84  delete cs;
85  cs = NULL;
86  accepted = false;
87  }
88  }
89  }
90 
91  private:
92  unsigned int i;
93  StreamSocket *s;
94  Socket *cs;
95  bool accepted;
96 };
97 
98 
99 class StreamClientThread : public Thread
100 {
101 public:
102  StreamClientThread(const char *host)
103  : Thread("StreamClientThread", Thread::OPMODE_CONTINUOUS)
104  {
105  if ( host == NULL ) {
106  this->host = "127.0.0.1";
107  } else {
108  this->host = host;
109  }
110 
111  s = new StreamSocket();
112  connected = false;
113  }
114 
115  ~StreamClientThread()
116  {
117  printf("Closing client socket\n");
118  s->close();
119  printf("Closed client socket\n");
120  delete s;
121  }
122 
123  virtual void loop()
124  {
125  if (! connected) {
126  try {
127  s->connect(host, 1910);
128  connected = true;
129  printf("Client MTU: %u\n", s->mtu());
130  } catch (SocketException &e) {
131  e.print_trace();
132  }
133  }
134  if ( connected ) {
135  unsigned int i = 0;
136  s->read(&i, sizeof(i));
137  s->write(&i, sizeof(i));
138  }
139  }
140 
141  private:
142  const char *host;
143  StreamSocket *s;
144  bool connected;
145 };
146 
147 
148 class StreamSocketQAMain : public SignalHandler
149 {
150  public:
151  static const unsigned int MODE_STANDALONE = 1;
152  static const unsigned int MODE_SERVER = 2;
153  static const unsigned int MODE_CLIENT = 3;
154 
155  StreamSocketQAMain(unsigned int mode, const char *host = NULL)
156  {
157  s = NULL;
158  c = NULL;
159  if ( (mode == MODE_STANDALONE) ||
160  (mode == MODE_SERVER) ) {
161  s = new StreamServerThread();
162  }
163  if ( (mode == MODE_STANDALONE) ||
164  (mode == MODE_CLIENT) ) {
165  c = new StreamClientThread(host);
166  }
167  }
168 
169  ~StreamSocketQAMain()
170  {
171  delete s;
172  delete c;
173  }
174 
175 
176  virtual void handle_signal(int signum)
177  {
178  printf("Signal received, cancelling threads\n");
179  if (s) s->cancel();
180  if (c) c->cancel();
181  printf("Threads cancelled\n");
182  }
183 
184  void run()
185  {
186  if (s) s->start();
187  if (c) c->start();
188  if (s) s->join();
189  if (c) c->join();
190  }
191 
192  private:
193  StreamServerThread *s;
194  StreamClientThread *c;
195 
196 };
197 
198 int
199 main(int argc, char **argv)
200 {
201  StreamSocketQAMain *m;
202  SignalManager::ignore(SIGPIPE);
203 
204  ArgumentParser argp(argc, argv, "sc:");
205 
206  if ( argp.has_arg("s") || argp.has_arg("c") ) {
207  // Special mode
208  if ( argp.has_arg("s") ) {
209  // Only run Server
210  m = new StreamSocketQAMain(StreamSocketQAMain::MODE_SERVER);
211  } else {
212  m = new StreamSocketQAMain(StreamSocketQAMain::MODE_CLIENT,
213  argp.arg("c"));
214  }
215  } else {
216  m = new StreamSocketQAMain(StreamSocketQAMain::MODE_STANDALONE);
217  }
218 
220 
221  m->run();
222  delete m;
223 
225 }
226 
227 /// @endcond
static void finalize()
Finalize (and free) the SignalManager instance, this does NOT implicitly delete the signal handlers...
Definition: signal.cpp:98
Fawkes library namespace.
Interface for signal handling.
Definition: signal.h:35
Parse command line arguments.
Definition: argparser.h:66
Thread class encapsulation of pthreads.
Definition: thread.h:42
Socket base class.
Definition: socket.h:65
TCP stream socket over IP.
Definition: stream.h:31
static void ignore(int signum)
Ignore a signal.
Definition: signal.cpp:182
static SignalHandler * register_handler(int signum, SignalHandler *handler)
Register a SignalHandler for a signal.
Definition: signal.cpp:116
void print_trace()
Prints trace to stderr.
Definition: exception.cpp:619
Socket exception.
Definition: socket.h:58