1 /******************************************************************************
2     (c) 2000-2004 Christine Caulfield                 christine.caulfield@googlemail.com
3     (c) 2003 Dmitri Popov
4 
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 ******************************************************************************/
15 
16 class LATServices
17 {
18  public:
Instance()19     static LATServices *Instance()
20 	{
21 	    if (!instance)
22 		return (instance = new LATServices());
23 	    else
24 		return instance;
25 	}
26 
27     // Get the highest rated node for this service name.
28     bool get_highest(const std::string &service,
29 		     std::string &node,
30 		     unsigned char *macaddr,
31 		     int *interface);
32 
33     bool get_node(const std::string &service,
34 		  const std::string &node,
35 		  unsigned char *macaddr, int *interface);
36 
37     // Add/update a service.
38     bool add_service(const std::string &node, const std::string &service, const std::string &ident,
39 		     int rating, int interface, unsigned char *macaddr);
40 
41     bool remove_node(const std::string &node);
42     bool list_services(bool verbose, std::ostringstream &output);
purge()43     void purge() {servicelist.clear(); }
44     void expire_nodes();
45     bool list_dummy_nodes(bool verbose, std::ostringstream &output);
46     bool touch_dummy_node_respond_counter(const std::string &str_name);
47 
48 
49  private:
LATServices()50     LATServices()
51       {};                         // Private constructor to force singleton
52     static LATServices *instance; // Singleton instance
53 
54     class serviceinfo
55     {
56     public:
serviceinfo()57       serviceinfo() {}
serviceinfo(const std::string & node,const std::string & _ident,const unsigned char * macaddr,int rating,int interface)58       serviceinfo(const std::string &node, const std::string &_ident,
59 		  const unsigned char *macaddr, int rating, int interface)
60 	  {
61 	      ident = _ident;
62 	      nodes[node] = nodeinfo(macaddr, rating, ident, interface);
63 	  }
64 
add_or_replace_node(const std::string & node,const std::string & _ident,const unsigned char * macaddr,int rating,int interface)65       void add_or_replace_node(const std::string &node, const std::string &_ident,
66 			       const unsigned char *macaddr, int rating,
67 			       int interface)
68 	  {
69 	      ident = _ident;
70 	      nodes.erase(node); // Don't care if this fails
71 	      nodes[node] = nodeinfo(macaddr, rating, ident, interface);
72 	  }
73       bool  get_highest(std::string &node, unsigned char *macaddr, int *interface);
74       bool  get_node(const std::string &node, unsigned char *macaddr, int *interface);
get_ident()75       const std::string get_ident() { return ident; }
76       bool  is_available();
77       bool  remove_node(const std::string &node);
78       void  list_service(std::ostringstream &output);
79       void  expire_nodes(time_t);
80       void  list_nodes(std::ostringstream &output);
81       bool  touch_dummy_node_respond_counter(const std::string &str_name);
82 
83     private:
84       class nodeinfo
85 	{
86 	public:
nodeinfo()87 	  nodeinfo() {}
nodeinfo(const unsigned char * _macaddr,int _rating,std::string _ident,int _interface)88 	  nodeinfo(const unsigned char *_macaddr, int _rating, std::string _ident, int _interface):
89 	      rating(_rating),
90 	      interface(_interface),
91 	      available(true),
92 	      slave_reachable(5) // if it doesn't respond five times...
93 	    {
94 	      memcpy(macaddr, _macaddr, 6);
95 	      ident = _ident;
96 	      updated = time(NULL);
97 	    }
has_expired(time_t current_time)98 	  bool has_expired(time_t current_time)
99 	      {
100 		  return ( (current_time - updated) > 60);
101 	      }
102 
get_rating()103 	  int                  get_rating()          { return rating; }
get_interface()104 	  int                  get_interface()       { return interface; }
get_macaddr()105 	  const unsigned char *get_macaddr()         { return macaddr; }
is_available()106 	  bool                 is_available()        { return available; }
set_available(bool a)107 	  void                 set_available(bool a) { available = a; }
get_ident()108 	  std::string          get_ident()           { return ident; }
109 
touch_respond_counter()110 	  int touch_respond_counter()
111 	      {
112 		  if (slave_reachable > 0)
113 		  {
114 		      slave_reachable--;
115 		  }
116 		  debuglog(("touch_respond_counter() %d\n", slave_reachable));
117 		  return slave_reachable;
118 	      }
119 
check_respond_counter()120          bool check_respond_counter() { return slave_reachable > 0; }
121 
122 	private:
123 	  unsigned char macaddr[6];
124 	  int           rating;
125 	  int           interface;
126 	  bool          available;
127 	  std::string   ident;
128 	  time_t        updated;
129 
130 	  // for slave nodes
131 	  int slave_reachable;
132 	};// class LATServices::service::nodeinfo
133 
134       std::map<std::string, nodeinfo, std::less<std::string> > nodes;
135       std::string ident;
136     };// class LATServices::serviceinfo
137 
138     std::map<std::string, serviceinfo, std::less<std::string> > servicelist;
139 };
140