Electroneum
munin_connection_handler.h
Go to the documentation of this file.
1 // Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above copyright
9 // notice, this list of conditions and the following disclaimer in the
10 // documentation and/or other materials provided with the distribution.
11 // * Neither the name of the Andrey N. Sabelnikov nor the
12 // names of its contributors may be used to endorse or promote products
13 // derived from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
19 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 //
26 
27 
28 
29 #ifndef _MUNIN_CONNECTION_HANDLER_H_
30 #define _MUNIN_CONNECTION_HANDLER_H_
31 
32 #include <string>
33 #include "net_utils_base.h"
34 #include "to_nonconst_iterator.h"
35 #include "http_base.h"
36 #include "reg_exp_definer.h"
37 
38 #define MUNIN_ARGS_DEFAULT(vertial_lable_str) "graph_args --base 1000 -l 0 --vertical-label " vertial_lable_str " \n"
39 #define MUNIN_ARGS_FORCE_AUPPER_LIMIT(vertial_lable_str, limit) "graph_args --base 1000 -l 0 --vertical-label " vertial_lable_str " --rigid --upper-limit " limit " \n"
40 #define MUNIN_TITLE(title_str) "graph_title " title_str "\n"
41 #define MUNIN_CATEGORY(category_str) "graph_category " category_str "\n"
42 #define MUNIN_INFO(info_str) "graph_info " info_str "\n"
43 #define MUNIN_ENTRY(var_name) #var_name".label " #var_name "\n" #var_name".info "#var_name".\n"
44 #define MUNIN_ENTRY_AREA(var_name) #var_name".label " #var_name "\n" #var_name".info "#var_name".\n" #var_name".draw AREASTACK\n"
45 #define MUNIN_ENTRY_ALIAS(var_name, alias) #var_name".label " #alias"\n" #var_name".info "#alias".\n"
46 #define BEGIN_MUNIN_SERVICE(servivece_name_str) if(servivece_name_str == pservice->m_service_name) {
47 #define END_MUNIN_SERVICE() }
48 #define MUNIN_SERVICE_PARAM(munin_var_name_str, variable) paramters_text += std::string() + munin_var_name_str ".value " + boost::lexical_cast<std::string>(variable) + "\n"
49 
50 
51 
52 
53 namespace epee
54 {
55 namespace net_utils
56 {
57  namespace munin
58  {
59 
60 
61  /************************************************************************/
62  /* */
63  /************************************************************************/
64  struct munin_service;
65 
67  {
68  virtual bool update_service_data(munin_service* pservice, std::string& paramters_text)=0;
69  };
70 
72  {
76  };
77 
79  {
80  std::list<munin_service> m_services;
81  //TODO:
82  };
83 
85  {
86  virtual bool do_send(const void* ptr, size_t cb)
87  {
88  m_cache += std::string((const char*)ptr, cb);
89  return true;
90  }
91  public:
92 
94  };
95 
96  /************************************************************************/
97  /* */
98  /************************************************************************/
100  {
101  public:
104 
106  m_machine_state(http_state_retriving_comand_line),
107  m_config(config)
108  {
109  init();
110  }
112  {
113 
114  }
115 
117  {
118  return true;
119  }
121  {
122  std::string hello_str = "# munin node at ";
123  hello_str += m_host_name + "\n";
124  send_hook(hello_str);
125  return true;
126  }
127 
128  virtual bool thread_init()
129  {
130  return true;
131  }
132 
133  virtual bool thread_deinit()
134  {
135  return true;
136  }
137 
139  {
140 
141  }
142 
143  virtual bool handle_recv(const void* ptr, size_t cb)
144  {
145 
146  const char* pbuff = (const char*)ptr;
147  std::string recvd_buff(pbuff, cb);
148  LOG_PRINT("munin_recv: \n" << recvd_buff, LOG_LEVEL_3);
149 
150  m_cache += recvd_buff;
151 
152  bool stop_handling = false;
153  while(!stop_handling)
154  {
155  switch(m_machine_state)
156  {
157  case http_state_retriving_comand_line:
158  {
159 
160  std::string::size_type fpos = m_cache.find('\n');
161  if(std::string::npos != fpos )
162  {
163  bool res = handle_command(m_cache);
164  if(!res)
165  return false;
166  m_cache.erase(0, fpos+1);
167  continue;
168  }
169  stop_handling = true;
170  }
171  break;
172  case http_state_error:
173  stop_handling = true;
174  return false;
175  default:
176  LOG_ERROR("Error in munin state machine! Unknown state=" << m_machine_state);
177  stop_handling = true;
178  m_machine_state = http_state_error;
179  return false;
180  }
181 
182  }
183 
184  return true;
185  }
186 
187  private:
188 
189 
190  bool init()
191  {
192  char hostname[64] = {0};
193  int res = gethostname(hostname, 64);
194  hostname[63] = 0;//be happy
195  m_host_name = hostname;
196  return true;
197  }
198  bool handle_command(const std::string& command)
199  {
200  // list, nodes, config, fetch, version or quit
201  STATIC_REGEXP_EXPR_1(rexp_match_command_line, "^((list)|(nodes)|(config)|(fetch)|(version)|(quit))(\\s+(\\S+))?", boost::regex::icase | boost::regex::normal);
202  // 12 3 4 5 6 7 8 9
203  size_t match_len = 0;
204  boost::smatch result;
205  if(boost::regex_search(command, result, rexp_match_command_line, boost::match_default) && result[0].matched)
206  {
207  if(result[2].matched)
208  {//list command
209  return handle_list_command();
210  }else if(result[3].matched)
211  {//nodes command
212  return handle_nodes_command();
213  }else if(result[4].matched)
214  {//config command
215  if(result[9].matched)
216  return handle_config_command(result[9]);
217  else
218  {
219  send_hook("Unknown service\n");
220  }
221  }else if(result[5].matched)
222  {//fetch command
223  if(result[9].matched)
224  return handle_fetch_command(result[9]);
225  else
226  {
227  send_hook("Unknown service\n");
228  }
229  }else if(result[6].matched)
230  {//version command
231  return handle_version_command();
232  }else if(result[7].matched)
233  {//quit command
234  return handle_quit_command();
235  }
236  else
237  return send_hook("Unknown command. Try list, nodes, config, fetch, version or quit\n");
238  }
239 
240  return send_hook("Unknown command. Try list, nodes, config, fetch, version or quit\n");;
241  }
242 
243  bool handle_list_command()
244  {
245  std::string buff_to_send;
246  for(std::list<munin_service>::const_iterator it = m_config.m_services.begin(); it!=m_config.m_services.end();it++)
247  {
248  buff_to_send += it->m_service_name + " ";
249  }
250  buff_to_send+='\n';
251  return send_hook(buff_to_send);
252  }
253  bool handle_nodes_command()
254  {
255  //supports only one node - host name
256  send_hook(m_host_name + "\n.\n");
257  return true;
258  }
259  bool handle_config_command(const std::string& service_name)
260  {
261  munin_service* psrv = get_service_by_name(service_name);
262  if(!psrv)
263  return send_hook(std::string() + "Unknown service\n");
264 
265 
266  return send_hook(psrv->m_service_config_string + ".\n");
267  }
268 
269  bool handle_fetch_command(const std::string& service_name)
270  {
271  munin_service* psrv = get_service_by_name(service_name);
272  if(!psrv)
273  return send_hook(std::string() + "Unknown service\n");
274 
275  std::string buff;
276  psrv->m_pdata_provider->update_service_data(psrv, buff);
277 
278  buff += ".\n";
279  return send_hook(buff);
280  }
281  bool handle_version_command()
282  {
283  return send_hook("Munin node component by Andrey Sabelnikov\n");
284  }
285  bool handle_quit_command()
286  {
287  return false;
288  }
289 
290  bool send_hook(const std::string& buff)
291  {
292  LOG_PRINT("munin_send: \n" << buff, LOG_LEVEL_3);
293 
294  if(m_psnd_hndlr)
295  return m_psnd_hndlr->do_send(buff.data(), buff.size());
296  else
297  return false;
298  }
299 
300 
301  munin_service* get_service_by_name(const std::string& srv_name)
302  {
303  std::list<munin_service>::iterator it = m_config.m_services.begin();
304  for(; it!=m_config.m_services.end(); it++)
305  if(it->m_service_name == srv_name)
306  break;
307 
308  if(it==m_config.m_services.end())
309  return NULL;
310 
311  return &(*it);
312  }
313 
314  enum machine_state{
315  http_state_retriving_comand_line,
316  http_state_error
317  };
318 
319 
320  config_type& m_config;
321  machine_state m_machine_state;
322  std::string m_cache;
323  std::string m_host_name;
324  protected:
326  };
327 
328 
329  inline bool test_self()
330  {
331  /*WSADATA w;
332  ::WSAStartup(MAKEWORD(1, 1), &w);
333  node_server_config sc;
334  sc.m_services.push_back(munin_service());
335  sc.m_services.back().m_service_name = "test_service";
336 
337  sc.m_services.back().m_service_config_string =
338  "graph_args --base 1000 -l 0 --vertical-label N --upper-limit 329342976\n"
339  "graph_title REPORTS STATICTICS\n"
340  "graph_category bind\n"
341  "graph_info This graph shows how many reports came in fixed time period.\n"
342  "graph_order apps free swap\n"
343  "apps.label apps\n"
344  "apps.draw AREA\n"
345  "apps.info Memory used by user-space applications.\n"
346  "swap.label swap\n"
347  "swap.draw STACK\n"
348  "swap.info Swap space used.\n"
349  "free.label unused\n"
350  "free.draw STACK\n"
351  "free.info Wasted memory. Memory that is not used for anything at all.\n"
352  "committed.label committed\n"
353  "committed.draw LINE2\n"
354  "committed.warn 625410048\n"
355  "committed.info The amount of memory that would be used if all the memory that's been allocated were to be used.\n";
356 
357 
358  sc.m_services.push_back(munin_service());
359  sc.m_services.back().m_service_name = "test_service1";
360  fake_send_handler fh;
361  munin_node_server_connection_handler mh(&fh, sc);
362 
363  std::string buff = "list\n";
364  mh.handle_recv(buff.data(), buff.size());
365 
366 
367  buff = "nodes\n";
368  mh.handle_recv(buff.data(), buff.size());
369 */
370  return true;
371  }
372 
373  }
374 }
375 }
376 #endif
const char * res
Definition: hmac_keccak.cpp:41
#define STATIC_REGEXP_EXPR_1(var_name, xpr_text, reg_exp_flags)
::std::string string
Definition: gtest-port.h:1097
std::unique_ptr< void, terminate > context
Unique ZMQ context handle, calls zmq_term on destruction.
Definition: zmq.h:98
virtual bool do_send(const void *ptr, size_t cb)
virtual bool update_service_data(munin_service *pservice, std::string &paramters_text)=0
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
virtual bool do_send(const void *ptr, size_t cb)=0
munin_node_server_connection_handler(i_service_endpoint *psnd_hndlr, config_type &config, const connection_context_base &context)
munin_service_data_provider * m_pdata_provider