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