The Assimilation Project
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
discovery.c
Go to the documentation of this file.
1 
24 #include <projectcommon.h>
25 #define DISCOVERY_SUBCLASS
26 #include <discovery.h>
27 #include <cstringframe.h>
28 #include <frametypes.h>
29 #include <fsprotocol.h>
30 #include <string.h>
31 #include <assert.h>
36 
37 FSTATIC char * _discovery_instancename(const Discovery* self);
40 FSTATIC gboolean _discovery_rediscover(gpointer vself);
41 FSTATIC void _discovery_ghash_destructor(gpointer gdiscovery);
42 FSTATIC void _discovery_sendjson(Discovery* self, char * jsonout, gsize jsonlen);
43 
45 
47 FSTATIC char *
49 {
50  return self->_instancename;
51 }
52 
54 FSTATIC void
56 {
57  (void)self;
58 }
59 
61 FSTATIC guint
63 {
64  (void)self;
65  return 0;
66 }
67 static GHashTable * _discovery_timers = NULL;
68 
70 FSTATIC void
72 {
73  Discovery* self = CASTTOCLASS(Discovery, gself);
74  char * instancename = self->_instancename;
75 
76  if (self->_timerid > 0) {
77  g_source_remove(self->_timerid);
78  self->_timerid = 0;
79  }
80  if (self->_config) {
81  UNREF(self->_config);
82  }
83  if (_discovery_timers && instancename) {
84  self->_instancename = NULL; // Avoid infinite recursion...
85  g_hash_table_remove(_discovery_timers, instancename);
86  }
87  if (instancename) {
88  g_free(instancename);
89  self->_instancename = instancename = NULL;
90  }
91 
92  FREECLASSOBJ(self); self=NULL;
93 }
94 
99 FSTATIC void
100 _discovery_ghash_destructor(gpointer gdiscovery)
101 {
102  Discovery* self = CASTTOCLASS(Discovery, gdiscovery);
103  // We take steps in discovery_finalize() to avoid infinite recursion...
104  if (self->_instancename) {
105  // In particular it sets instancename to NULL before removing
106  // it from the table.
107  // Only during destruction is it legal for self->instancename to be NULL
108  // So, if it's NULL, we're in the process of destroying it...
109 
110  // Not completely certain what we're doing is sufficient...
111  // In particular, what happens if we try and remove an element which
112  // is trying to be removed? Does the glib code tolerate that?
113  // My strong suspicion is that it does tolerate this because we
114  // free the instancename (key) last.
115  // Either glib removed the item before freeing the object, or vice versa
116  // If the first case, then the second pass through it simply won't be
117  // in the table the second time around.
118  //
119  // The same condition holds if they do them in the opposite order.
120  // But if they tried to free the key before removing it that would
121  // not likely work for many cases, so it's unlikely that they do it
122  // in that order.
123  UNREF(self);
124  }
125 }
126 
129 FSTATIC gboolean
130 _discovery_rediscover(gpointer vself)
131 {
132  Discovery* self = CASTTOCLASS(Discovery, vself);
133 
134  return self->discover(self);
135 }
136 
141 Discovery*
142 discovery_new(const char * instname,
143  NetGSource* iosource,
144  ConfigContext* context,
145  gsize objsize)
146 {
147  gsize size = objsize < sizeof(Discovery) ? sizeof(Discovery) : objsize;
149  g_return_val_if_fail(ret != NULL, NULL);
151  ret->_instancename = g_strdup(instname);
156  ret->discover = NULL;
157  ret->_timerid = 0;
158  ret->_iosource = iosource;
159  ret->_config = context;
160  REF(ret->_config);
161  return ret;
162 }
163 
164 
171 void
173 {
174  gint timeout;
175  if (NULL == _discovery_timers) {
176  _discovery_timers = g_hash_table_new_full(g_str_hash, g_str_equal
178  assert(_discovery_timers != NULL);
179  }
180  self->discover(self);
181  timeout = self->discoverintervalsecs(self);
182  if (timeout > 0) {
183  self->_timerid = g_timeout_add_seconds(timeout, _discovery_rediscover, self);
184  }
185  REF(self);
186  // _discovery_ghash_destructor will unref it if there's one already there...
187  g_hash_table_replace(_discovery_timers, self->instancename(self), self);
188 }
189 FSTATIC void
190 discovery_unregister(const char* instance)
191 {
192  if (_discovery_timers) {
193  // _discovery_ghash_destructor will unref it if there's one already there...
194  g_hash_table_remove(_discovery_timers, instance);
195  }
196 }
197 
199 void
201 {
202  if (_discovery_timers != NULL) {
203  GHashTable* timers = _discovery_timers;
204  _discovery_timers = NULL;
205  g_hash_table_remove_all(timers);
206  g_hash_table_destroy(timers); timers = NULL;
207  }else{
208  DEBUGMSG1("Discovery timers were NULL");
209  }
210 }
212 FSTATIC void
214  char * jsonout,
215  gsize jsonlen)
216 {
217  FrameSet* fs;
218  CstringFrame* jsf;
219  Frame* fsf;
220  ConfigContext* cfg = self->_config;
221  NetGSource* io = self->_iosource;
222  NetAddr* cma;
223  const char * basename = self->instancename(self);
224 
225  g_return_if_fail(cfg != NULL && io != NULL);
226 
227  DEBUGMSG2("%s.%d: discovering %s: _sentyet == %d"
228  , __FUNCTION__, __LINE__, basename, self->_sentyet);
229  // Primitive caching - don't send what we've already sent.
230  if (self->_sentyet) {
231  const char * oldvalue = cfg->getstring(cfg, basename);
232  if (oldvalue != NULL && strcmp(jsonout, oldvalue) == 0) {
233  DEBUGMSG2("%s.%d: %s sent this value - don't send again."
234  , __FUNCTION__, __LINE__, basename);
235  g_free(jsonout);
236  return;
237  }
238  DEBUGMSG2("%s.%d: %s this value is different from previous value"
239  , __FUNCTION__, __LINE__, basename);
240  }
241  DEBUGMSG2("%s.%d: Sending %"G_GSIZE_FORMAT" bytes of JSON text"
242  , __FUNCTION__, __LINE__, jsonlen);
243  cfg->setstring(cfg, basename, jsonout);
244  cma = cfg->getaddr(cfg, CONFIGNAME_CMADISCOVER);
245  if (cma == NULL) {
246  DEBUGMSG2("%s.%d: %s address is unknown - skipping send"
247  , __FUNCTION__, __LINE__, CONFIGNAME_CMADISCOVER);
248  g_free(jsonout);
249  return;
250  }
251  self->_sentyet = TRUE;
252 
255  fsf = &jsf->baseclass; // base class object of jsf
256  fsf->setvalue(fsf, jsonout, jsonlen+1, frame_default_valuefinalize); // jsonlen is strlen(jsonout)
257  frameset_append_frame(fs, fsf);
258  DEBUGMSG2("%s.%d: Sending a %"G_GSIZE_FORMAT" bytes JSON frameset"
259  , __FUNCTION__, __LINE__, jsonlen);
260  io->_netio->sendareliablefs(io->_netio, cma, DEFAULT_FSP_QID, fs);
261  ++ self->reportcount;
262  UNREF(fsf);
263  UNREF(fs);
264 }
265 
#define CONFIGNAME_CMADISCOVER
Address of where to send discovery reports.
#define FRAMESETTYPE_JSDISCOVERY
Packet contains JSON-formatted discovery data.
Definition: framesettypes.h:45
const char *(* getstring)(const ConfigContext *, const char *name)
Get String value.
Definition: configcontext.h:86
FSTATIC void _discovery_flushcache(Discovery *self)
default (do-nothing) 'flush cache' function
Definition: discovery.c:55
#define DEBUGMSG1(...)
Definition: proj_classes.h:89
void discovery_register(Discovery *self)
Function for registering a discovery object with the discovery infrastructure.
Definition: discovery.c:172
void discovery_unregister_all(void)
Unregister all discovery methods in preparation for shutting down - to make valgrind happy :-D...
Definition: discovery.c:200
NetIO * _netio
netio this object is based on
Definition: netgsource.h:50
#define FRAMETYPE_JSDISCOVER
FRAMETYPE_JSDISCOVER Frame (frametype 19) Frame subclass - CstringFrame class.
Definition: frametypes.h:302
This is the base Frame class object (in-memory TLV (type, length, value)) for every general component...
Definition: frame.h:43
FSTATIC char * _discovery_instancename(const Discovery *self)
internal function return the type of Discovery object
Definition: discovery.c:48
Describes interfaces to C-String Frame (Cstringframe) C-Class It holds conventional zero-terminated b...
FrameSet * frameset_new(guint16 frameset_type)
Construct a new frameset of the given type.
Definition: frameset.c:110
char * _instancename
Timer id for repeating discovery.
Definition: discovery.h:59
#define FSTATIC
Definition: projectcommon.h:31
Discovery * discovery_new(const char *instname, NetGSource *iosource, ConfigContext *context, gsize objsize)
Discovery constructor.
Definition: discovery.c:142
#define FREECLASSOBJ(obj)
Free a C-class object.
Definition: proj_classes.h:76
Semi-Abstract class (yes, really) defining discovery objects.
#define BINDDEBUG(Cclass)
BINDDEBUG is for telling the class system where the debug variable for this class is - put it in the ...
Definition: proj_classes.h:82
NetAddr *(* getaddr)(const ConfigContext *, const char *name)
Get NetAddr value.
Definition: configcontext.h:92
guint _timerid
Timer id for repeating discovery.
Definition: discovery.h:60
void frameset_append_frame(FrameSet *fs, Frame *f)
Append frame to the front of the end of the frame list.
Definition: frameset.c:143
#define __FUNCTION__
FSTATIC guint _discovery_discoverintervalsecs(const Discovery *self)
default function - return zero for discovery interval
Definition: discovery.c:62
NetGSource * _iosource
How to send packets.
Definition: discovery.h:61
void(* sendjson)(Discovery *, char *, gsize)
Send JSON string.
Definition: discovery.h:54
#define REF(obj)
Definition: assimobj.h:39
This is our CstringFrame class object - used for holding C-style NULL terminated strings.
Definition: cstringframe.h:36
Project common header file.
Header file defining the data layouts for our Frames.
struct _Discovery Discovery
Definition: discovery.h:45
void(* setstring)(ConfigContext *, const char *name, const char *value)
Definition: configcontext.h:87
FSTATIC void discovery_unregister(const char *instance)
Definition: discovery.c:190
Discovery class abstract C-class - it supports discovering "things" through subclasses for different ...
Definition: discovery.h:47
AssimObj * assimobj_new(guint objsize)
Definition: assimobj.c:74
gboolean sendareliablefs(NetIO *self, NetAddr *dest, guint16 queueid, FrameSet *frameset)
[out] source address of return result
FSTATIC void _discovery_ghash_destructor(gpointer gdiscovery)
Discovery Destructor function for the GHashTable.
Definition: discovery.c:100
FSTATIC void frame_default_valuefinalize(gpointer value)
Finalize a Frame.
Definition: frame.c:56
void(* _finalize)(AssimObj *)
Free object (private)
Definition: assimobj.h:55
FSTATIC void _discovery_sendjson(Discovery *self, char *jsonout, gsize jsonlen)
Send JSON that we discovered to the CMA - with some caching going on.
Definition: discovery.c:213
The NetAddr class class represents a general network address - whether IP, MAC, or any other type of ...
Definition: netaddr.h:43
char *(* instancename)(const Discovery *self)
Which object is this?
Definition: discovery.h:49
#define DEFAULT_FSP_QID
Default Queue ID.
Definition: fsprotocol.h:125
gboolean(* discover)(Discovery *self)
Perform the discovery.
Definition: discovery.h:51
FrameSet class - used for collecting Frames when not on the wire, and for marshalling/demarshalling t...
Definition: frameset.h:45
#define DEBUGDECLARATIONS
Definition: proj_classes.h:79
FSTATIC gboolean _discovery_rediscover(gpointer vself)
GSourceFunc function to invoke discover member function at the timed interval.
Definition: discovery.c:130
#define DEBUGMSG2(...)
Definition: proj_classes.h:90
guint(* discoverintervalsecs)(const Discovery *self)
How often to re-discover? (in seconds)
Definition: discovery.h:52
void(* setvalue)(Frame *self, gpointer value, guint32 length, GDestroyNotify valfinal)
member function for setting value
Definition: frame.h:52
ConfigContext * _config
Configuration Parameters - has address of CMA.
Definition: discovery.h:62
#define CASTTOCLASS(Cclass, obj)
Safely cast 'obj' to C-class 'class' - verifying that it was registerd as being of type class ...
Definition: proj_classes.h:66
#define UNREF(obj)
Definition: assimobj.h:35
Implements the FsProtocol object.
AssimObj baseclass
Base object class.
Definition: discovery.h:48
The NetGSource class objects integrate NetIO class objects into the g_main_loop paradigm.
Definition: netgsource.h:43
#define NEWSUBCLASS(Cclass, obj)
Definition: proj_classes.h:67
WINEXPORT CstringFrame * cstringframe_new(guint16 frame_type, gsize framesize)
Construct a new CstringFrame - allowing for "derived" frame types...
Definition: cstringframe.c:101
FSTATIC void _discovery_finalize(AssimObj *gself)
Finalizing function for Discovery objects.
Definition: discovery.c:71