feisty meow concerns codebase 2.140
test_cromp_server.cpp
Go to the documentation of this file.
1/*****************************************************************************\
2* *
3* Name : test_cromp_server *
4* Author : Chris Koeritz *
5* *
6*******************************************************************************
7* Copyright (c) 2002-$now By Author. This program is free software; you can *
8* redistribute it and/or modify it under the terms of the GNU General Public *
9* License as published by the Free Software Foundation; either version 2 of *
10* the License or (at your option) any later version. This is online at: *
11* http://www.fsf.org/copyleft/gpl.html *
12* Please send any updates to: fred@gruntose.com *
13\*****************************************************************************/
14
15#include "crompish_pax.h"
16
20#include <basis/astring.h>
21#include <basis/byte_array.h>
22#include <basis/functions.h>
23#include <cromp/cromp_server.h>
25#include <loggers/file_logger.h>
27#include <octopus/tentacle.h>
29#include <sockets/machine_uid.h>
30#include <sockets/tcpip_stack.h>
32#include <timely/time_control.h>
33#include <timely/time_stamp.h>
34#include <unit_test/unit_base.h>
35
36using namespace application;
37using namespace basis;
38using namespace configuration;
39using namespace cromp;
40using namespace mathematics;
41using namespace filesystem;
42using namespace loggers;
43using namespace octopi;
44using namespace processes;
45using namespace sockets;
46using namespace structures;
47using namespace textual;
48using namespace timely;
49using namespace unit_test;
50
51#define LOG(a) CLASS_EMERGENCY_LOG(program_wide_logger::get(), a)
52
53const int REPORTING_INTERVAL = 28 * SECOND_ms; // how often to squawk.
54
55//const int ACCEPTING_THREADS = 5;
56const int ACCEPTING_THREADS = 1;
57
58// specifies whether to support lazy evaluation by tentacles.
59//const bool SUPPORT_BACKGROUNDING = true;
60const bool SUPPORT_BACKGROUNDING = false;
61
62// determines whether the octopus will do immediate evaluation or not.
63//const bool IMMEDIATE_EVALUATION = true;
64const bool IMMEDIATE_EVALUATION = false;
65
67
68// forward.
69class cromp_server_tester;
70
71class our_cromp_server : public cromp_server
72{
73public:
74 our_cromp_server(cromp_server_tester &parent, const internet_address &addr)
76 _parent(parent) {}
77
78 ~our_cromp_server() {}
79
80 DEFINE_CLASS_NAME("our_cromp_server");
81
82private:
83 cromp_server_tester &_parent;
84};
85
87
88class cromp_server_tester : virtual public unit_base, virtual public application_shell
89{
90public:
91 bool _saw_clients; // true if we ever got a connection.
92
93 cromp_server_tester();
94 ~cromp_server_tester();
95
96 virtual int execute();
97
98 DEFINE_CLASS_NAME("cromp_server_tester");
99
100private:
101 our_cromp_server *_uplink;
102 // provides the connection and transmission services.
103 bool _leave_when_no_clients; // true if we should just do one run.
104 bool _encryption; // true if we should do an encrypted connection.
105 internet_address c_address;
106};
107
109
110class real_bubbles_tentacle : public bubbles_tentacle
111{
112public:
113 real_bubbles_tentacle(cromp_server_tester &parent, bool backgrounding)
114 : bubbles_tentacle(backgrounding), _parent(parent) {}
115
116 virtual outcome consume(infoton &to_chow, const octopus_request_id &item_id,
117 byte_array &transformed)
118 {
119 transformed.reset();
120 _parent._saw_clients = true; // we saw someone.
121//LOG("got to our cromp's bubble tentacle.");
122 bubble *inf = dynamic_cast<bubble *>(&to_chow);
123 if (!inf) return NO_HANDLER;
124//LOG("caching product! success getting unpacked etc.");
125 bubble *junk = dynamic_cast<bubble *>(inf->clone());
126 store_product(junk, item_id);
127 return OKAY;
128 }
129
130private:
131 cromp_server_tester &_parent;
132};
133
135
136cromp_server_tester::cromp_server_tester()
139 _saw_clients(false),
140 _uplink(NULL_POINTER),
141 _leave_when_no_clients(false),
142 _encryption(false)
143{
144 FUNCDEF("constructor");
146 LOG("");
147 LOG("");
148
150 // check for a port on the command line.
151 astring port_text;
152 int port = 5678;
153 if (args.get_value("port", port_text, false)) {
154 LOG(astring("using port: ") + port_text);
155 port = port_text.convert(5678);
156 }
157 int posn = 0;
158 if (args.find("exit", posn)) {
159 LOG("seeing the 'exit without clients' flag set.");
160 _leave_when_no_clients = true;
161 }
162
163//hmmm:normalize host so this can take either name or IP.
164
165 // check for a hostname on the command line.
166 astring hostname("local");
167 astring host_temp;
168 if (args.get_value("host", host_temp, false)) {
169 LOG(astring("using host: ") + host_temp);
170 hostname = host_temp;
171 }
172 strcpy(c_address.hostname, hostname.s());
173
174//LOG(astring("here's the command line:") + parser_bits::platform_eol_to_chars() + args.text_form());
175
176 int indy = 0;
177 if (args.find("encrypt", indy) || (args.find('e', indy)) ) {
178 // they're saying that we should encrypt the communication.
179 LOG("turning on encryption.");
180 _encryption = true;
181 }
182
183// tcpip_stack stack;
184// machine_uid host = stack.this_host(machine_uid::TCPIP_LOCATION);
185 c_address.port = port;
186// host.native().stuff(internet_address::ADDRESS_SIZE, c_address.ip_address);
187 LOG("starting cromp_server");
188 _uplink = new our_cromp_server(*this, c_address);
189 _uplink->add_tentacle(new real_bubbles_tentacle(*this, SUPPORT_BACKGROUNDING));
190 _uplink->enable_servers(_encryption);
191}
192
193cromp_server_tester::~cromp_server_tester()
194{
195 WHACK(_uplink);
196}
197
198int cromp_server_tester::execute()
199{
200 FUNCDEF("execute");
201
202 time_stamp next_report(REPORTING_INTERVAL);
203
204 while (true) {
205 // make sure we didn't see our exit condition.
206 if (!_uplink->clients() && _leave_when_no_clients && _saw_clients) {
207 LOG("exiting now");
208 break;
209 }
210
211 if (time_stamp() > next_report) {
212 int client_count = _uplink->clients();
213 const char *verb = "are";
214 if (client_count == 1) verb = "is";
215 const char *ending = "s";
216 if (client_count == 1) ending = "";
217 LOG(a_sprintf("There %s %d client%s.", verb, client_count, ending));
218 next_report.reset(REPORTING_INTERVAL);
219 }
220
221// new test case; rip out server while still possibly connected.
222if (randomizer().inclusive(1, 200) == 32) {
223LOG("tearing down entire server and re-creating.");
224WHACK(_uplink);
225_uplink = new our_cromp_server(*this, c_address);
226_uplink->add_tentacle(new real_bubbles_tentacle(*this, SUPPORT_BACKGROUNDING));
227_uplink->enable_servers(_encryption);
228}
229
231 }
232 return 0;
233}
234
236
237HOOPLE_MAIN(cromp_server_tester, )
238
The application_shell is a base object for console programs.
virtual int execute()=0
< retrieves the command line from the /proc hierarchy on linux.
a_sprintf is a specialization of astring that provides printf style support.
Definition astring.h:440
void reset(int number=0, const contents *initial_contents=NULL_POINTER)
Resizes this array and sets the contents from an array of contents.
Definition array.h:349
Provides a dynamically resizable ASCII character string.
Definition astring.h:35
int convert(int default_value) const
Converts the string into a corresponding integer.
Definition astring.cpp:760
A very common template for a dynamic array of bytes.
Definition byte_array.h:36
Outcomes describe the state of completion for an operation.
Definition outcome.h:31
virtual clonable * clone() const
must be provided to allow creation of a copy of this object.
An infoton is an individual request parcel with accompanying information.
Definition infoton.h:32
Identifies requests made on an octopus by users.
virtual basis::outcome consume(infoton &formal(to_chow), const octopus_request_id &formal(item_id), basis::byte_array &transformed)
consume is not really provided here. remember to implement for servers!
bool backgrounding() const
reports on whether this tentacle supports background operation or not.
Definition tentacle.h:58
@ NO_HANDLER
no handler for that type of infoton.
Definition tentacle.h:73
bool store_product(infoton *product, const octopus_request_id &original_id)
used by tentacles to store the objects they produce from infotons.
Definition tentacle.cpp:118
this type of address describes a destination out on the internet.
static void sleep_ms(basis::un_int msec)
a system independent name for a forced snooze measured in milliseconds.
Represents a point in time relative to the operating system startup time.
Definition time_stamp.h:38
#define NULL_POINTER
The value representing a pointer to nothing.
Definition definitions.h:32
#define DEFINE_CLASS_NAME(objname)
Defines the name of a class by providing a couple standard methods.
Definition enhance_cpp.h:42
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition enhance_cpp.h:54
Provides macros that implement the 'main' program of an application.
#define HOOPLE_MAIN(obj_name, obj_args)
options that should work for most unix and linux apps.
Definition hoople_main.h:61
Implements an application lock to ensure only one is running at once.
char ** _global_argv
The guards collection helps in testing preconditions and reporting errors.
Definition array.h:30
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
Definition functions.h:121
const int SECOND_ms
Number of milliseconds in a second.
A platform independent way to obtain the timestamp of a file.
A logger that sends to the console screen using the standard output device.
An extension to floating point primitives providing approximate equality.
Definition averager.h:21
Provides access to the operating system's socket methods.
A dynamic container class that holds any kind of object via pointers.
Definition amorph.h:55
#include <time.h>
Useful support functions for unit testing, especially within hoople.
Definition unit_base.cpp:35
#define randomizer()
const bool SUPPORT_BACKGROUNDING
#define LOG(a)
const bool IMMEDIATE_EVALUATION
const int REPORTING_INTERVAL
const int ACCEPTING_THREADS