ccsession.cc 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. // $Id$
  15. //
  16. // todo: generalize this and make it into a specific API for all modules
  17. // to use (i.e. connect to cc, send config and commands, get config,
  18. // react on config change announcements)
  19. //
  20. #include <stdexcept>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <sys/time.h>
  24. #include <iostream>
  25. #include <fstream>
  26. #include <sstream>
  27. #include <boost/foreach.hpp>
  28. #include <cc/cpp/data.h>
  29. #include <data_def.h>
  30. #include <cc/cpp/session.h>
  31. //#include "common.h"
  32. #include "ccsession.h"
  33. #include "config.h"
  34. using namespace std;
  35. using isc::data::Element;
  36. using isc::data::ElementPtr;
  37. using isc::data::DataDefinition;
  38. using isc::data::ParseError;
  39. using isc::data::DataDefinitionError;
  40. void
  41. CommandSession::read_data_definition(const std::string& filename) {
  42. std::ifstream file;
  43. // this file should be declared in a @something@ directive
  44. file.open(filename.c_str());
  45. if (!file) {
  46. cout << "error opening " << filename << endl;
  47. exit(1);
  48. }
  49. try {
  50. data_definition_ = DataDefinition(file, true);
  51. } catch (ParseError pe) {
  52. cout << "Error parsing definition file: " << pe.what() << endl;
  53. exit(1);
  54. } catch (DataDefinitionError dde) {
  55. cout << "Error reading definition file: " << dde.what() << endl;
  56. exit(1);
  57. }
  58. file.close();
  59. }
  60. CommandSession::CommandSession(std::string module_name,
  61. std::string spec_file_name,
  62. isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config),
  63. isc::data::ElementPtr(*command_handler)(isc::data::ElementPtr command)
  64. ) throw (isc::cc::SessionError):
  65. module_name_(module_name),
  66. session_(isc::cc::Session())
  67. {
  68. config_handler_ = config_handler;
  69. command_handler_ = command_handler;
  70. // todo: workaround, let boss wait until msgq is started
  71. // and remove sleep here
  72. sleep(1);
  73. ElementPtr answer, env;
  74. session_.establish();
  75. session_.subscribe(module_name, "*");
  76. //session_.subscribe("Boss", "*");
  77. //session_.subscribe("statistics", "*");
  78. read_data_definition(spec_file_name);
  79. sleep(1);
  80. // send the data specification
  81. session_.group_sendmsg(data_definition_.getDefinition(), "ConfigManager");
  82. session_.group_recvmsg(env, answer, false);
  83. // get any stored configuration from the manager
  84. if (config_handler_) {
  85. ElementPtr cmd = Element::createFromString("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name + "\"} ] }");
  86. session_.group_sendmsg(cmd, "ConfigManager");
  87. session_.group_recvmsg(env, answer, false);
  88. cout << "[XX] got config: " << endl << answer->str() << endl;
  89. if (answer->contains("result") &&
  90. answer->get("result")->get(0)->intValue() == 0 &&
  91. answer->get("result")->size() > 1) {
  92. config_handler(answer->get("result")->get(1));
  93. } else {
  94. cout << "[XX] no result in answer" << endl;
  95. }
  96. }
  97. }
  98. int
  99. CommandSession::getSocket()
  100. {
  101. return (session_.getSocket());
  102. }
  103. int
  104. CommandSession::check_command()
  105. {
  106. cout << "[XX] check for command" << endl;
  107. ElementPtr cmd, routing, data;
  108. if (session_.group_recvmsg(routing, data, true)) {
  109. /* ignore result messages (in case we're out of sync, to prevent
  110. * pingpongs */
  111. if (!data->getType() == Element::map || data->contains("result")) {
  112. return 0;
  113. }
  114. cout << "[XX] got something!" << endl << data->str() << endl;
  115. ElementPtr answer;
  116. if (data->contains("config_update")) {
  117. if (config_handler_) {
  118. // handle config update
  119. answer = config_handler_(data->get("config_update"));
  120. } else {
  121. answer = Element::createFromString("{ \"result\": [0] }");
  122. }
  123. }
  124. if (data->contains("command")) {
  125. if (command_handler_) {
  126. answer = command_handler_(data->get("command"));
  127. } else {
  128. answer = Element::createFromString("{ \"result\": [0] }");
  129. }
  130. }
  131. session_.reply(routing, answer);
  132. }
  133. return 0;
  134. }