test_client.cc

A simple client
#include <feeserver/fee_client.hh>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdlib>

namespace Examples 
{
  //_____________________________________________________________________
  /** A test client 
      @ingroup tests */
  struct TestClient : public FeeServer::Client 
  {
    /** Constructor */
    TestClient(const std::string& name,
               const std::string& dns) 
      : FeeServer::Client(name, dns), 
        _break(false)
    {}
    /** Function called when messages arrive 
        @param m Message */
    virtual void HandleMessage(FeeServer::Message& m) 
    {
      // system("clear");
      std::cout << "Got message from server " << _server << "\n" 
                << m << std::endl;
      _break = true;
      // ShowMenu();
    }
    /** Called on no-link to message channel */ 
    virtual void NolinkMessage() 
    {
      static bool first = true; 
      if (first) {
        first = false;
      return;
      }
      std::cerr << "No link to message channel" << std::endl;
      exit(1);
    }
    /** Called on no-link to acknowledge channel */ 
    virtual void NolinkAcknowledge() 
    {
      static bool first = true; 
      if (first) {
        first = false;
        return;
      }
      std::cerr << "No link to acknowledge channel" << std::endl;
      exit(1);
    }      
    /** Acknowledge error seen 
        @param code Error code */ 
    virtual void AcknowledgeError(short code)
    {
      std::cerr << "Error " << FeeServer::Header::Code2String(code) 
                << " (" << code << ") from acknowledge" << std::endl;
    }
    /** Bad check sum in acknowledge 
        @param expected Expected check sum 
        @param got The checksum we got. */
    virtual void ChecksumFailed(unsigned int expected, unsigned int got)
    {
      std::cerr << "Invalid checksum 0x"  << std::hex << got 
                << ", expected 0x" << expected << std::dec << std::endl;
    }
    /** Got unexpected reply 
        @param expected Expected reply ID 
        @param got The reply ID we got */
    virtual void UnexpectedReply(unsigned int expected, unsigned int got)
    {
      std::cerr << "Unexpected reply " << got 
                << ", expected " << expected << std::endl;
    }
    /** Got an unknown service update 
        @param name Name of service updating */
    virtual void UnknownService(const std::string& name) 
    {
      std::cerr << "Unknown service update from" << name << std::endl;
    }
    /** Called when the acknowledge times out */
    virtual void Timeout() 
    {
      std::cerr << "Acknowledge timed out" << std::endl;
    }
    /** re-display menu */
    bool _break;
    
    /** Get a value from the user. 
        @param ret The return value 
        @param prompt Prompt to show user 
        @return @a ret */
    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;
    }
    /** Encode a value into bytes 
        @param v Value to encode 
        @param buf Buffer to encode into 
        @param off Offset in @a buf to start at. 
        @return number of bytes written to @a buf
    */
    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;
    }
    /** Show our menu */
    void ShowMenu() 
    {
      std::cerr << "Send a command:\n"  
                << "\t0 : Show monitored\n"     // 0x0
                << "\t1 : UpdateServer\n"       // 0x4
                << "\t2 : RestartServer\n"      // 0x8 
                << "\t3 : RebootMachine\n"      // 0x10 
                << "\t4 : ShutdownMachine\n"    // 0x20 
                << "\t5 : ExitServer\n"         // 0x40 
                << "\t6 : SetDeadBand\n"        // 0x80
                << "\t7 : GetDeadband\t\n"      // 0x100 
                << "\t8 : SetIssueTimeout\n"    // 0x200 
                << "\t9 : GetIssueTimeout\n"    // 0x400 
                << "\t10: SetUpdateRate\n"      // 0x800 
                << "\t11: GetUpdateRate\n"      // 0x1000 
                << "\t12: SetLogLevel\n"        // 0x2000 
                << "\t13: GetLogLevel\n"        // 0x4000 
                << "\t14: ShowServices\n"       // 0x8000
                << "\t15: Get int value\n"      // 1
                << "\t16: Get float value\n"    // 2
                << "\t17: Quit\n"
                << std::flush;
    }
    /** Read until we get an enter */
    void GetEnter()
    {
      std::cout << "Press enter to continue" << std::endl;
      while ((std::cin.get() != '\n')) {}
    }
    /** Loop forever and get input from user */
    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;
}

//
// EOF
//

    
  
  

Generated on Thu Jun 26 17:02:21 2008 for FeeServer++ 0.9 by  doxygen 1.5.6