#define HOOPLE_MAIN(obj_name, obj_args) \
HOOPLE_STARTUP_CODE; \
int main(int argc, char *argv[]) { \
- SETUP_COMBO_LOGGER; \
SET_ARGC_ARGV(argc, argv); \
+ SETUP_COMBO_LOGGER; \
obj_name to_run_obj obj_args; \
return to_run_obj.execute_application(); \
}
#define STRICT
#endif
// winsock support...
- #undef FD_SETSIZE
- #define FD_SETSIZE 1000
+// #undef FD_SETSIZE
+// #define FD_SETSIZE 1000
// if you don't set this, you can only select on a default of 64 sockets.
#include <winsock2.h>
// windows headers...
#ifdef _MSC_VER
#define _WINSOCKAPI_ // make windows.h happy about winsock.
// winsock support...
- #undef FD_SETSIZE
- #define FD_SETSIZE 1000
+// #undef FD_SETSIZE
+// #define FD_SETSIZE 1000
// if you don't set this, you can only select on a default of 64 sockets.
#include <winsock2.h>
#include <windows.h>
#ifdef __WIN32__
#define _WINSOCKAPI_ // make windows.h happy about winsock.
// winsock support...
- #undef FD_SETSIZE
- #define FD_SETSIZE 1000
+// #undef FD_SETSIZE
+// #define FD_SETSIZE 1000
// if you don't set this, you can only select on a default of 64 sockets.
#include <winsock2.h>
#include <windows.h>
#include <basis/byte_array.h>
#include <basis/contracts.h>
-#include <openssl/rsa.h>
-
// forward.
//struct RSA;
+typedef struct rsa_st RSA;
namespace crypto {
#ifndef MAX_ABS_PATH
#ifdef __WIN32__
// winsock support...
- #undef FD_SETSIZE
- #define FD_SETSIZE 1000
+// #undef FD_SETSIZE
+// #define FD_SETSIZE 1000
// if you don't set this, you can only select on a default of 64 sockets.
#include <winsock2.h>
#include <windows.h>
#ifndef _MANAGED
#define _WINSOCKAPI_ // the dance of the windows headers.
// winsock support...
- #undef FD_SETSIZE
- #define FD_SETSIZE 1000
+// #undef FD_SETSIZE
+// #define FD_SETSIZE 1000
// if you don't set this, you can only select on a default of 64 sockets.
#include <winsock2.h>
#include <windows.h>
#include <basis/environment.h>
#include <basis/mutex.h>
+#include <loggers/program_wide_logger.h>
#include <stdlib.h>
#ifdef __WIN32__
#define _WINSOCKAPI_ // make windows.h happy about winsock.
-// #include <windows.h>
#include <winsock2.h> // timeval.
#endif
+//#define DEBUG_TIME_STAMP
+
+#ifdef DEBUG_TIME_STAMP
+ #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
+ using namespace loggers;
+#endif
+
using namespace basis;
namespace timely {
return double(__rollovers) * __rollover_point + double(ticks_up);
}
-timeval time_stamp::fill_timeval_ms(int duration)
+void time_stamp::fill_timeval_ms(struct timeval &time_out, int duration)
{
- timeval time_out; // timeval has tv_sec=seconds, tv_usec=microseconds.
+ FUNCDEF("fill_timeval_ms");
+ // timeval has tv_sec=seconds, tv_usec=microseconds.
if (!duration) {
// duration is immediate for the check; just a quick poll.
time_out.tv_sec = 0;
time_out.tv_usec = 0;
-#ifdef DEBUG_PORTABLE
-// LOG("no duration specified");
+#ifdef DEBUG_TIME_STAMP
+ LOG("no duration specified");
#endif
} else {
// a non-zero duration means we need to compute secs and usecs.
// now take out the chunk we've already recorded as seconds.
time_out.tv_usec = duration * 1000;
// set the number of microseconds from the remaining milliseconds.
-#ifdef DEBUG_PORTABLE
-// LOG(isprintf("duration of %d ms went to %d sec and %d usec.", duration,
-// time_out.tv_sec, time_out.tv_usec));
+#ifdef DEBUG_TIME_STAMP
+ LOG(a_sprintf("duration of %d ms went to %d sec and %d usec.", duration,
+ time_out.tv_sec, time_out.tv_usec));
#endif
}
- return time_out;
}
} //namespace.
class time_stamp : public virtual basis::orderable
{
public:
+ DEFINE_CLASS_NAME("time_stamp");
+
typedef double time_representation;
//!< the representation of time for this universe, measured in milliseconds.
// helper functions for using the OS's time support.
- static timeval fill_timeval_ms(int milliseconds);
+ static void fill_timeval_ms(timeval &time_point, int milliseconds);
//!< returns a timeval system object that represents the "milliseconds".
/*!< if "milliseconds" is zero, then the returned timeval will
represent zero time passing (rather than infinite duration as some
fd_set_wrapper &read_list, fd_set_wrapper &write_list,
fd_set_wrapper &exceptions) const
{
-#ifdef DEBUG_RAW_SOCKET
FUNCDEF("inner_select");
-#endif
// setup the file descriptor sets for the select. we check readability,
// writability and exception status.
+LOG("select A");
FD_ZERO(&read_list); FD_SET(socket, &read_list);
+LOG("select B");
FD_ZERO(&write_list); FD_SET(socket, &write_list);
+LOG("select C");
FD_ZERO(&exceptions); FD_SET(socket, &exceptions);
-
- timeval time_out = time_stamp::fill_timeval_ms(timeout);
+LOG("select D");
+timeval *farkle = new timeval;
+LOG("select D.1");
+time_stamp *t = new time_stamp();
+LOG("select D.2");
+
+ timeval time_out;
+ time_stamp::fill_timeval_ms(time_out, timeout);
// timeval has tv_sec=seconds, tv_usec=microseconds.
+LOG("select E");
// select will tell us about the socket.
int ret = ::select(socket + 1,
(mode & SELECTING_JUST_WRITE)? NIL : &read_list,
(mode & SELECTING_JUST_READ)? NIL : &write_list,
&exceptions, &time_out);
+LOG("select F");
int error = critical_events::system_error();
+LOG("select G");
if (!ret) return 0; // nothing to report.
if (ret == SOCKET_ERROR) {
+LOG("select H");
switch (error) {
// all real errors fall out to the error handling stuff.
case SOCK_EFAULT: // intentional fall-through.
#endif
return 0; // not really an error.
}
+LOG("select I");
#ifdef DEBUG_RAW_SOCKET
LOG(a_sprintf("socket %u had error %d in select: %s.",
socket, error, _stack->tcpip_error_name(error).s()));
return SI_ERRONEOUS;
}
+LOG("select J");
// if we got to here, then there are some things to report...
return SI_BASELINE;
}
FD_SET(sock, &write_list);
}
- timeval time_out = time_stamp::fill_timeval_ms(timeout);
+ timeval time_out;
+ time_stamp::fill_timeval_ms(time_out, timeout);
// timeval has tv_sec=seconds, tv_usec=microseconds.
// select will tell us about the socket.
namespace sockets {
-//#define DEBUG_SPOCKET
+#define DEBUG_SPOCKET
// uncomment for noisy version.
#undef LOG
// ensure that the socket is in a good state.
#define ENSURE_HEALTH(retval) \
- if (!_was_connected) return retval; /* never has been. */ \
+ if (!was_connected()) return retval; /* never has been. */ \
if (!_socket) { RECOGNIZE_DISCO; return retval; /* not set. */ }
#define CHECK_BOGUS(retval) \
spocket::~spocket()
{
-#ifdef DEBUG_SPOCKET
FUNCDEF("destructor");
+#ifdef DEBUG_SPOCKET
LOG(a_sprintf("closing spocket: ") + text_form());
#endif
disconnect();
// ints and since _where currently does not get destroyed.
astring spocket::text_form()
{
- a_sprintf sock_string("socket=%d", _socket);
- if (is_root_server())
- sock_string += a_sprintf("root-socket=%d", _server_socket);
-
- return a_sprintf("%s spocket: %s, %s, %s",
- (is_client()? "client" :
- (is_root_server()? "root-server" : "server") ),
- (connected()? "connected" :
- (was_connected()? "unconnected (was once)" : "never-connected") ),
- sock_string.s(),
- _where->text_form().s());
+ FUNCDEF("text_form");
+LOG("INTO TEXT_FORM A");
+ astring to_return = is_client()? "client" :
+ (is_root_server()? "root-server" : "server");
+LOG("INTO TEXT_FORM B");
+ to_return += " spocket: ";
+LOG("INTO TEXT_FORM C");
+ if (connected()) {
+LOG("INTO TEXT_FORM C.1");
+ to_return += "connected, ";
+ } else {
+LOG("INTO TEXT_FORM C.2");
+ if (was_connected()) to_return += "unconnected (was once), ";
+ else to_return += "never-connected, ";
+LOG("INTO TEXT_FORM C.3");
+ }
+LOG("INTO TEXT_FORM D");
+ to_return += a_sprintf("socket=%u, ", _socket);
+LOG("INTO TEXT_FORM E");
+ if (is_root_server()) {
+LOG("INTO TEXT_FORM F");
+ to_return += a_sprintf("root-socket=%u, ", _server_socket);
+LOG("INTO TEXT_FORM G");
+ }
+LOG("INTO TEXT_FORM H");
+ to_return += _where->text_form().s();
+LOG("INTO TEXT_FORM X");
+ return to_return;
}
void spocket::bind_client(const internet_address &addr)
outcome spocket::disconnect()
{
-#ifdef DEBUG_SPOCKET
FUNCDEF("disconnect");
-#endif
RECOGNIZE_DISCO;
if (_socket) {
#ifdef DEBUG_SPOCKET
bool spocket::connected()
{
-#ifdef DEBUG_SPOCKET
FUNCDEF("connected");
-#endif
ENSURE_HEALTH(false);
- if (_type != CONNECTED) return _was_connected;
+ if (_type != CONNECTED) return was_connected();
+
+ if (!_socket) return false;
+
+LOG("conn check, _sock not null");
// do examination on spocket.
int sel_mode = 0;
GRAB_LOCK;
- int ret = _socks->select(_socket, sel_mode);
+LOG(a_sprintf("lock was grabbed, socks is %x", _socks));
- if (ret == 0) {
- return true; // we are happy.
- }
- if ( (ret & SI_DISCONNECTED) || (ret & SI_ERRONEOUS) ) {
- RECOGNIZE_DISCO;
+ try {
+ int ret = _socks->select(_socket, sel_mode);
+
+LOG("after select");
+
+ if (ret == 0) {
+ return true; // we are happy.
+ }
+ if ( (ret & SI_DISCONNECTED) || (ret & SI_ERRONEOUS) ) {
+ RECOGNIZE_DISCO;
+ return false;
+ }
+ return true;
+ } catch (...) {
+LOG("caught exception thrown from select, returning false.");
return false;
}
- return true;
}
outcome spocket::await_readable(int timeout)
{
-#ifdef DEBUG_SPOCKET
FUNCDEF("await_readable");
-#endif
CHECK_BOGUS(NO_CONNECTION);
ENSURE_HEALTH(NO_CONNECTION);
GRAB_LOCK;
outcome spocket::await_writable(int timeout)
{
-#ifdef DEBUG_SPOCKET
FUNCDEF("await_writable");
-#endif
CHECK_BOGUS(NO_CONNECTION);
ENSURE_HEALTH(NO_CONNECTION);
GRAB_LOCK;
CHECK_BOGUS(NO_CONNECTION);
{
GRAB_LOCK; // short lock.
- if ( (_was_connected && !_client) || _server_socket) {
+ if ( (was_connected() && !_client) || _server_socket) {
#ifdef DEBUG_SPOCKET
LOG("this object was already opened as a server!");
#endif
}
_socket = int(::socket(AF_INET, sock_type, proto));
if ( (_socket == basis::un_int(INVALID_SOCKET)) || !_socket) {
- _socket = NIL;
+ _socket = 0;
LOG("Failed to open the client's connecting spocket.");
return ACCESS_DENIED;
}
+LOG(a_sprintf("hola, socket value received is: %d", _socket));
// mark the spocket for _blocking_ I/O. we want connect to sit there
// until it's connected or returns with an error.
_socks->set_non_blocking(_socket, false);
+LOG(a_sprintf("set nonblock false on : %d", _socket));
+
if (_type == BROADCAST) {
if (!_socks->set_broadcast(_socket)) return ACCESS_DENIED;
// mark the socket for broadcast capability.
if (!_socks->set_reuse_address(_socket)) return ACCESS_DENIED;
// mark the socket so we don't get bind errors on in-use conditions.
+LOG(a_sprintf("set reuse addr : %d", _socket));
}
if (_type == CONNECTED) {
_server_socket = int(::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
#ifdef DEBUG_SPOCKET
LOG(a_sprintf("srv sock is %d", _server_socket));
-#endif
-
-#ifdef DEBUG_SPOCKET
LOG(astring("creating server socket now for ") + _where->text_form());
#endif
// now try accepting a connection on the spocket.
sockaddr new_sock;
socklen_t sock_len = sizeof(new_sock);
- int accepted = int(::accept(_server_socket, &new_sock, &sock_len));
+ basis::un_int accepted = int(::accept(_server_socket, &new_sock, &sock_len));
int error = critical_events::system_error();
- if (accepted == INVALID_SOCKET) {
+ if (!accepted || (accepted == INVALID_SOCKET)) {
if (error == SOCK_EWOULDBLOCK) return NO_CONNECTION;
#ifdef DEBUG_SPOCKET
LOG(astring("Accept got no client, with an error of ")
return ACCESS_DENIED;
}
+LOG(a_sprintf("accepted socket number is %d", accepted));
+
// mark the new spocket for non-blocking I/O.
_socks->set_non_blocking(accepted, true);
+LOG("after set nonblockheading");
+
//move to socks object!
int sock_hop = 1;
if (setsockopt(accepted, SOL_SOCKET, SO_KEEPALIVE, (char *)&sock_hop,
#endif
}
- // create the spocket address that we will connect to.
#ifdef DEBUG_SPOCKET
- LOG(astring("accepted a client socket for ") + _where->text_form());
+ LOG(astring("accepted a client on our socket: ") + _where->text_form());
#endif
// NOTE: normally, our network code sets the spocket to be kept alive (using
// keep alives), but we are trying to have a minimal spocket usage and
// a minimal network load for this test scenario.
+ // create the spocket address that we will connect to.
sock = new spocket(*_where);
+LOG("preview new spock A:"); LOG(sock->text_form());
*sock->_remote = _stack->convert(new_sock);
+LOG("preview new spock B:"); LOG(sock->text_form());
sock->_socket = accepted;
+LOG("preview new spock C:"); LOG(sock->text_form());
sock->_server_socket = 0; // reset to avoid whacking.
+LOG("preview new spock D:"); LOG(sock->text_form());
sock->_was_connected = true;
+LOG("about to return this spocket as new spock:");
+LOG(sock->text_form());
return OKAY;
}
outcome spocket::send(const abyte *buffer, int size, int &len_sent)
{
-#ifdef DEBUG_SPOCKET
FUNCDEF("send");
-#endif
CHECK_BOGUS(OKAY);
if (_type != CONNECTED) return BAD_INPUT;
GRAB_LOCK;
outcome spocket::receive(byte_array &buffer, int &size)
{
-#ifdef DEBUG_SPOCKET
FUNCDEF("receive");
-#endif
CHECK_BOGUS(NONE_READY);
if (_type != CONNECTED) return BAD_INPUT;
if (size <= 0) return BAD_INPUT;
outcome spocket::receive(abyte *buffer, int &size)
{
-#ifdef DEBUG_SPOCKET
FUNCDEF("receive");
-#endif
+LOG("RECV A");
CHECK_BOGUS(NONE_READY);
+LOG("RECV B");
if (_type != CONNECTED) return BAD_INPUT;
ENSURE_HEALTH(NO_CONNECTION);
+LOG("RECV C");
int expected = size;
size = 0;
if (expected <= 0) return BAD_INPUT;
+LOG("RECV D");
GRAB_LOCK;
+LOG("RECV E");
int len = recv(_socket, (char *)buffer, expected, 0);
+LOG("RECV F");
if (!len) {
+LOG("RECV F.1");
// check to make sure we're not disconnected.
int ret = _socks->select(_socket, raw_socket::SELECTING_JUST_READ);
+LOG("RECV F.2");
if (ret & SI_DISCONNECTED) {
RECOGNIZE_DISCO;
return NO_CONNECTION;
}
+LOG("RECV F.3");
// seems like more normal absence of data.
return NONE_READY;
} else if (len < 0) {
+LOG("RECV F.4");
if (critical_events::system_error() == SOCK_EWOULDBLOCK) return NONE_READY;
#ifdef DEBUG_SPOCKET
LOG(astring("The receive failed with an error ")
+ critical_events::system_error_text(critical_events::system_error()));
#endif
+LOG("RECV F.5");
if (!connected()) return NO_CONNECTION;
+LOG("RECV F.6");
return ACCESS_DENIED;
}
+LOG("RECV G");
size = len;
return OKAY;
}
outcome spocket::receive_from(byte_array &buffer, int &size,
internet_address &where_from)
{
-#ifdef DEBUG_SPOCKET
FUNCDEF("receive_from");
-#endif
where_from = internet_address();
CHECK_BOGUS(NONE_READY);
if (_type == CONNECTED) return BAD_INPUT;
outcome spocket::receive_from(abyte *buffer, int &size,
internet_address &where_from)
{
-#ifdef DEBUG_SPOCKET
FUNCDEF("receive_from");
-#endif
where_from = internet_address();
CHECK_BOGUS(NONE_READY);
if (_type == CONNECTED) return BAD_INPUT;
#include <errno.h>
-//using namespace application;
using namespace basis;
-//using namespace filesystem;
using namespace loggers;
using namespace mathematics;
using namespace sockets;
using namespace structures;
-//using namespace textual;
using namespace timely;
using namespace unit_test;
static abyte receive_buffer[MAXIMUM_WINSOCK_MTU + 1];
// used for dumping received data into.
-//#define DEBUG_SPOCKET_TESTER
+#define DEBUG_SPOCKET_TESTER
// uncomment for noisy version.
broadcast_spocket_tester::broadcast_spocket_tester
#include <errno.h>
-//using namespace application;
using namespace basis;
-//using namespace filesystem;
using namespace loggers;
using namespace mathematics;
using namespace sockets;
using namespace structures;
using namespace textual;
using namespace timely;
-//using namespace unit_test;
#define LOG(to_print) EMERGENCY_LOG(program_wide_logger().get(), astring(to_print))
const int PAUSE_TIME = 200;
// the snooze interval when we encounter socket underflow or overflow.
-//#define DEBUG_SPOCKET_TESTER
+#define DEBUG_SPOCKET_TESTER
// uncomment for noisy version.
spocket_tester::spocket_tester(const internet_address &where)
bool spocket_tester::connect()
{
if (!_socket) {
+LOG("creating new client socket");
_socket = new spocket(*_where);
}
+LOG(astring("connect socket info: ") + _socket->text_form());
outcome ret = spocket::NO_CONNECTION;
while (true) {
ret = _socket->connect();
bool spocket_tester::accept(bool wait)
{
if (!_root_server) {
+LOG("hey creating new root server socket");
_root_server = new spocket(*_where);
+LOG("got past creating the root server socket");
+LOG(astring("accept root server socket info: ") + _root_server->text_form());
}
if (_socket) {
LOG("already have a socket for accept!");
return true;
}
outcome ret = spocket::NO_CONNECTION;
+LOG("int accepting loop on root server");
while (true) {
ret = _root_server->accept(_socket, false);
if (ret == spocket::OKAY) break;
if (ret != spocket::NO_CONNECTION) break;
- if (!wait) return true; // we accepted at least once.
- time_control::sleep_ms(100);
+ if (!wait) return true; // we tried to accept at least once.
+ time_control::sleep_ms(100); // snooze to avoid slamming with accepts.
}
+
+if (_socket != NIL) {
+LOG(astring("accepted! socket info: ") + _socket->text_form());
+}
return ret == spocket::OKAY;
}
#endif
time_stamp when_to_leave(MAXIMUM_TRANSFER_WAIT);
+LOG("FARP 1");
int full_length = 0;
while ( (full_length < size_expected) && (time_stamp() < when_to_leave) ) {
+LOG("FARP 2");
time_stamp start_of_receive;
int len = MAXIMUM_WINSOCK_MTU;
+LOG("FARP 3");
+if (!_socket) {
+ LOG("WHAT? SOCKET IS NULL!!!");
+}
+////time_control::sleep_ms(PAUSE_TIME);
+LOG("FARP 3.1");
+LOG(astring("socket info: ") + _socket->text_form());
+LOG("FARP 3.2");
outcome ret = _socket->receive(receive_buffer, len);
+LOG("FARP 4");
if (ret != spocket::OKAY) {
if (ret == spocket::NONE_READY) {
if (len != 0) LOG(a_sprintf("supposedly nothing was received (%d bytes)", len));
#define LOG(to_print) EMERGENCY_LOG(program_wide_logger().get(), astring(to_print))
-const int INITIAL_DELAY = 1; // number of seconds before starting sends.
+const int INITIAL_DELAY = 2; // number of seconds before starting sends.
typedef abyte ip_address_holder[4];
int test_spocket::execute()
{
FUNCDEF("execute");
+LOG("OY POINT A");
ip_address_holder ip_address; // accumulates the source address.
int rcv_port = 0;
bool is_client = false;
int send_count = 0;
const char *DEFAULT_HOST = "127.0.0.1";
- const int DEFAULT_PORT = 12342;
+ const int DEFAULT_PORT = 12348;
const int DEFAULT_SEND_SIZE = 1008;
const int DEFAULT_SEND_COUNT = 10;
+LOG("OY POINT B");
+
if (_global_argc < 6) {
if (_global_argc > 1) {
LOG("\
}
}
+LOG("OY POINT C");
+
// only parse the parameters if we got enough from the user; otherwise we accept our
// defaults to do a simple test run.
if (_global_argc >= 6) {
+LOG("OY POINT D");
if (!parse_address(_global_argv[1], ip_address)) {
LOG("failed to parse source address.");
return 9283;
}
+LOG("OY POINT E");
LOG(a_sprintf("\tParsed a source of: \"%d.%d.%d.%d\".",
(int)ip_address[0], (int)ip_address[1], (int)ip_address[2],
(int)ip_address[3]));
LOG(a_sprintf("\tGot a send count of %d.", send_count));
}
+LOG("OY POINT Q");
+
// package our parameters in a form the tester likes.
internet_address to_pass(byte_array(4, ip_address), "", rcv_port);
// now, construct our tester object.
- spocket_tester tester(to_pass);
+ spocket_tester *tester = new spocket_tester(to_pass);
// choose the appropriate action based on our role.
bool outcome;
- if (is_client)
- outcome = tester.connect();
- else
- outcome = tester.accept(_global_argc != 1);
+ if (is_client) {
+LOG("client side is connecting");
+ outcome = tester->connect();
+ } else {
+LOG("server side is accepting");
+ outcome = tester->accept(_global_argc != 1);
+ }
if (!outcome) {
const char *action = is_client? "connect" : "accept";
LOG(astring("Failed to ") + action + " on the tester.");
return 10;
}
+LOG("success after conn/accept");
+
+LOG("OY POINT T");
if (_global_argc == 1) {
// launch a paired duplicate of our test so we can chat.
+ a_sprintf("%d", DEFAULT_SEND_SIZE) + " " + a_sprintf("%d", DEFAULT_SEND_COUNT),
launch_process::RETURN_IMMEDIATELY, kidnum);
ASSERT_EQUAL(result, 0, "launching paired process should start successfully");
+LOG("OY POINT U.1");
- // now we try again accepting from our client.
- outcome = tester.accept();
+ // now we try again accepting from our client side.
+ outcome = tester->accept();
//hmmm: redundant below.
+LOG("OY POINT U.2");
if (!outcome) {
const char *action = is_client? "connect" : "accept";
+LOG("OY POINT U.3");
LOG(astring("Failed to ") + action + " on the tester.");
return 10;
}
}
+LOG("OY POINT V");
// so, we're connected. try sending the test packages out.
testing_statistics stats; // to be filled by the tester.
- outcome = tester.perform_test(send_size, send_count * 2, stats);
+LOG("OY POINT V.1");
+ outcome = tester->perform_test(send_size, send_count * 2, stats);
// multiply send_count since we count each side as one.
+LOG("OY POINT V.2");
if (!outcome) {
LOG("Failed out of send_data; maybe other side terminated.");
}
+LOG("OY POINT V.3");
stats.total_runs /= 2; // cut down to the real number of tests.
+LOG("OY POINT V.4");
if (!stats.total_runs)
stats.total_runs = 1;
+LOG("OY POINT W");
+
// now report on the stats that we get from the data sending.
LOG(a_sprintf("Report for %d completed test cycles.", stats.total_runs));
LOG("");
#define LOG(to_print) EMERGENCY_LOG(program_wide_logger().get(), astring(to_print))
-const int INITIAL_DELAY = 1; // number of seconds before starting sends.
+const int INITIAL_DELAY = 2; // number of seconds before starting sends.
typedef abyte ip_address_holder[4];