test_client.cc
- A simple client
#include <feeserver/fee_client.hh>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdlib>
namespace Examples
{
struct TestClient : public FeeServer::Client
{
TestClient(const std::string& name,
const std::string& dns)
: FeeServer::Client(name, dns),
_break(false)
{}
virtual void HandleMessage(FeeServer::Message& m)
{
std::cout << "Got message from server " << _server << "\n"
<< m << std::endl;
_break = true;
}
virtual void NolinkMessage()
{
static bool first = true;
if (first) {
first = false;
return;
}
std::cerr << "No link to message channel" << std::endl;
exit(1);
}
virtual void NolinkAcknowledge()
{
static bool first = true;
if (first) {
first = false;
return;
}
std::cerr << "No link to acknowledge channel" << std::endl;
exit(1);
}
virtual void AcknowledgeError(short code)
{
std::cerr << "Error " << FeeServer::Header::Code2String(code)
<< " (" << code << ") from acknowledge" << std::endl;
}
virtual void ChecksumFailed(unsigned int expected, unsigned int got)
{
std::cerr << "Invalid checksum 0x" << std::hex << got
<< ", expected 0x" << expected << std::dec << std::endl;
}
virtual void UnexpectedReply(unsigned int expected, unsigned int got)
{
std::cerr << "Unexpected reply " << got
<< ", expected " << expected << std::endl;
}
virtual void UnknownService(const std::string& name)
{
std::cerr << "Unknown service update from" << name << std::endl;
}
virtual void Timeout()
{
std::cerr << "Acknowledge timed out" << std::endl;
}
bool _break;
template <typename T>
const T& GetValue(T& ret, const char* prompt)
{
std::cout << prompt << ": " << std::flush;
std::cin >> ret;
std::cin.clear();
while ((std::cin.get() != '\n')) {}
return ret;
}
template <typename T>
size_t Encode(const T& v, std::vector<unsigned char>& buf, size_t off=0)
{
size_t s = sizeof(T);
if (buf.size() < off + s) buf.resize(off+s);
memcpy(&(buf[off]), &v, s);
return s;
}
void ShowMenu()
{
std::cerr << "Send a command:\n"
<< "\t0 : Show monitored\n"
<< "\t1 : UpdateServer\n"
<< "\t2 : RestartServer\n"
<< "\t3 : RebootMachine\n"
<< "\t4 : ShutdownMachine\n"
<< "\t5 : ExitServer\n"
<< "\t6 : SetDeadBand\n"
<< "\t7 : GetDeadband\t\n"
<< "\t8 : SetIssueTimeout\n"
<< "\t9 : GetIssueTimeout\n"
<< "\t10: SetUpdateRate\n"
<< "\t11: GetUpdateRate\n"
<< "\t12: SetLogLevel\n"
<< "\t13: GetLogLevel\n"
<< "\t14: ShowServices\n"
<< "\t15: Get int value\n"
<< "\t16: Get float value\n"
<< "\t17: Quit\n"
<< std::flush;
}
void GetEnter()
{
std::cout << "Press enter to continue" << std::endl;
while ((std::cin.get() != '\n')) {}
}
void Run()
{
while (true) {
system("clear");
_break = false;
ShowMenu();
if (_break) {
GetEnter();
continue;
}
int cmd;
GetValue(cmd, "Please enter command");
if (_break) {
GetEnter();
continue;
}
bool ok = true;
switch (cmd) {
case 1: case 3: case 4:
std::cerr << "Shouldn't execute this" << std::endl;
ok = false;
break;
}
if (!ok) continue;
std::vector<unsigned char> data;
switch (cmd) {
case 17: exit(0);
case 0: data.push_back(3); break;
case 15: data.push_back(1); break;
case 16: data.push_back(2); break;
case 2: case 5: case 9: case 11: case 13:
case 14: data.push_back(' '); data.push_back('\0'); break;
case 6:
{
float v; std::string n;
GetValue(v, "Please input a float");
std::cout << "Got value " << v << std::endl;
GetValue(n, "Please input name");
size_t fsize = Encode(v, data);
data.resize(fsize+n.size());
for (size_t i = 0; i < n.size(); i++) data[i+fsize] = n[i];
}
break;
case 7:
{
std::string n;
GetValue(n, "Please input name");
data.resize(n.size());
std::copy(n.begin(), n.end(), data.begin());
}
break;
case 8:
{
unsigned long v;
GetValue(v, "Please input a long");
Encode(v, data);
}
break;
case 10:
{
unsigned short v;
GetValue(v, "Please input a short");
Encode(v, data);
}
break;
case 12:
{
unsigned int v;
GetValue(v, "Please input a int");
Encode(v, data);
}
break;
default:
{
std::cout << "Please input some data: " << std::flush;
char c = std::cin.get();
while ((c = std::cin.get()) != '\n') data.push_back(c);
}
}
if (_break) {
GetEnter();
continue;
}
unsigned int flags = (cmd < 1 || cmd > 14 ? 0 : (1 << (cmd+1)));
if (!SendCommand(flags, data)) {
std::cerr << "Command failed" << std::endl;
continue;
}
std::cout << "Got " << data.size() << " bytes back:\n\t"
<< std::hex << std::setfill('0') << std::flush;
for (size_t i = 0; i < data.size(); i++)
std::cout << " " << std::setw(2) << (unsigned(data[i]) & 0xff)
<< std::flush;
std::cout << std::dec << std::setfill(' ') << std::endl;
if (data.size() > 0) {
union {
int _int;
float _float;
long _long;
} val;
switch (cmd) {
case 7: case 9: case 11: case 13: case 15: case 16:
memcpy(&val, &(data[0]), data.size());
break;
}
switch (cmd) {
case 7: case 16:
std::cout << "\t" << val._float << std::endl;
break;
case 9:
std::cout << "\t" << val._long << std::endl;
break;
case 11: case 13: case 15:
std::cout << "\t" << val._int << std::endl;
break;
}
}
GetEnter();
}
}
};
}
int
main(int argc, char** argv)
{
std::string name = "dummy";
std::string dns = "localhost";
for (int i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
switch (argv[i][1]) {
case 'h':
std::cout << "Usage: " << argv[0] << " OPTIONS\n\n"
<< "Options:\n"
<< "\t-h\t\tThis help\n"
<< "\t-n NAME\t\tSet name of server\n"
<< "\t-d HOST\t\tSet the DIM DNS host name\n"
<< std::endl;
return 0;
case 'n': name = argv[++i]; break;
case 'd': dns = argv[++i]; break;
default:
std::cerr << argv[0] << ": unknown option " << argv[i] << std::endl;
return 1;
}
}
}
Examples::TestClient c(name, dns);
c.Run();
return 0;
}