Example #1
0
/*!

\brief Removes config contexts found at the specified scope path.
\param[in] Scope String containing scope to use when overwriting.
\return Returns dmz::True if config context was successfully removed.

*/
dmz::Boolean
dmz::Config::remove_config (const String &Scope) {

   Boolean result = False;

   if (Scope) {

      result = True;

      String value, remainder;

      if (pop_last_config_scope_element (Scope, value, remainder)) {

         Config list;

         lookup_all_config (remainder, list);

         ConfigIterator it;
         Config cd;

         while (list.get_next_config (it, cd)) {

            ConfigContext *context (cd.get_config_context ());

            if (context) { context->remove_config (value); }
         }
      }
      else if (_state.context) { _state.context->remove_config (Scope); }
   }

   return result;
}
Example #2
0
/*!

\brief Overwrites config contexts found at the specified scope path.
\param[in] Scope String containing scope to use when overwriting.
\param[in] Data Config containing config context to use in the over write.
\return Returns dmz::True if config context was successfully overwritten.

*/
dmz::Boolean
dmz::Config::overwrite_config (const String &Scope, const Config &Data) {

   if (!Scope) {

      if (_state.context) { _state.context->remove_config (Data.get_name ()); }
   }
   else {

      Config list;

      lookup_all_config (Scope, list);

      ConfigIterator it;
      Config cd;

      while (list.get_next_config (it, cd)) {

         ConfigContext *context (cd.get_config_context ());

         if (context) { context->remove_config (Data.get_name ()); }
      }
   }

   return add_config (Scope, Data);
}
Example #3
0
/*!

\brief Looks up all config contexts with the given name.
\details All config context found with a matching name are stored as children of \a data.
\param[in] Name String containing name of config contexts to lookup.
\param[out] data Config to store the found config contexts.
\return Returns dmz::True if any config contexts were found.

*/
dmz::Boolean
dmz::Config::lookup_all_config (const String &Name, Config &data) const {

   Boolean result (False);
   StringTokenizer it (Name, LocalScopeChar);
   String sub = it.get_next ();
   Boolean done (!sub ? True : False);

   Config prev ("prev");
   prev.add_config (*this);
   Config current (sub);

   while (!done) {

      ConfigIterator tableIt;
      Config next;

      ConfigContext *curContext = current.get_config_context ();

      while (prev.get_next_config (tableIt, next)) {

         ConfigContext *nextContext = next.get_config_context ();

         if (nextContext && curContext) {

            ConfigContext::DataList *dl (nextContext->configTable.lookup (sub));

            if (dl) {

               dl->lock.lock ();
                  ConfigContext::DataStruct *ds = dl->head;
                  while (ds) {

                     if (ds->handle) {

                        curContext->add_config (ds->context);
                     }

                     ds = ds->next;
                  }
               dl->lock.unlock ();
            }
         }
      }

      if (current.is_empty ()) { done = True; }
      else {

         sub = it.get_next ();
         if (!sub) { data = current; done = True; result = True; }
         else { prev = current; Config next (sub); current = next; }
      }
   }

   if (data.is_empty ()) { data.set_config_context (0); result = False; }

   return result;
}
Example #4
0
/*!

\brief Appends a string to the current config context value.
\param[in] Value String containing value to be appended.
\param[in] IsFormatted If set to dmz::True the config context will be marked as
containing formatted data.
\return Returns dmz::True if the value was appended successfully.

*/
dmz::Boolean
dmz::Config::append_value (const String &Value, const Boolean IsFormatted) {

    Boolean result (False);

    if (_state.context) {

        if (!_state.context->Name) {

            if (IsFormatted) {
                _state.context->isFormatted = True;
            }

            ConfigAttributeContext *ac (_state.context->attrTable.lookup (""));

            if (!ac) {

                ac = new ConfigAttributeContext (Value);
                if (ac && _state.context->attrTable.store ("", ac)) {
                    result = True;
                }
                else if (ac) {
                    delete ac;
                    ac = 0;
                }
            }
            else {

                result = True;

                ac->lock.lock ();
                ac->value << Value;
                ac->lock.unlock ();
            }
        }
        else {

            ConfigContext *cd (new ConfigContext (""));

            if (cd) {

                cd->isFormatted = IsFormatted;
                ConfigAttributeContext *ptr = new ConfigAttributeContext (Value);
                if (ptr && !cd->attrTable.store ("", ptr)) {
                    delete ptr;
                    ptr = 0;
                }
                _state.context->add_config (cd);
                result = True;
                cd->unref ();
                cd = 0;
            }
        }
    }

    return result;
}
Example #5
0
/*!

\brief Adds a config context.
\details The \a Scope parameter may be used to add a config context to child config
contexts. For example the following code snippet:
\code
dmz::Config dataDMZ;

if (global.lookup_data ("dmz", dataDMZ)) {

   dmz::Config dataType

   if (dataDMZ.lookup_data ("type", dataType)) {

      Config fooData ("foo");

      dataType.add_config (fooData);
   }
}
\endcode
May also be written as:
\code
Config fooData ("foo");

global.add_config ("dmz.type", fooData);
\endcode
\param[in] Scope String containing the scope at witch to add the config context.
\param[in] Data Config containing config context to add.
\return Returns dmz::True if the config context was successfully added.

*/
dmz::Boolean
dmz::Config::add_config (const String &Scope, const Config &Data) {

   Boolean result (False);

   if (_state.context && _state.context->Name) {

      ConfigContext *cd = Data.get_config_context ();
      ConfigContext *target = local_get_config_from_scope (Scope, _state.context, True);

      if (cd && target) { result = target->add_config (cd); }
   }

   return result;
}
FSTATIC char *
_childprocess_toString(gconstpointer aself)
{
	const ChildProcess*	self = CASTTOCONSTCLASS(ChildProcess, aself);
	ConfigContext*	cfg = configcontext_new(0);
	char*		ret;

	cfg->setint(cfg, "child_pid", self->child_pid);
	cfg->setint(cfg, "timeout", self->timeout);
	cfg->setint(cfg, "timeoutsrc_id", self->timeoutsrc_id);
	cfg->setint(cfg, "childsrc_id", self->childsrc_id);
	cfg->setint(cfg, "child_state", self->child_state);
	cfg->setstring(cfg, "loggingname", self->loggingname);
	ret = cfg->baseclass.toString(&cfg->baseclass);
	UNREF(cfg);
	return ret;
}
/// Send JSON that we discovered to the CMA - with some caching going on
FSTATIC void
_discovery_sendjson(Discovery* self,	///< Our discovery object
		    char * jsonout,	///< malloced JSON output - which we free (!)
		    gsize jsonlen)	///< length of jsonout
{
	FrameSet*	fs;
	CstringFrame*	jsf;
	IntFrame*	intf;
	Frame*		fsf;
	ConfigContext*	cfg = self->_config;
	NetGSource*	io = self->_iosource;
	NetAddr*	cma;
	const char *	basename = self->instancename(self);
	ConfigContext*	jsonobject;

	g_return_if_fail(cfg != NULL && io != NULL);

	if (NULL == (jsonobject = configcontext_new_JSON_string(jsonout))) {
		g_warning("%s.%d: JSON Discovery is not legal JSON [%s]"
		,	__FUNCTION__, __LINE__, jsonout);
		return;
	}
	g_free(jsonout);
	
	jsonobject->setstring(jsonobject, CONFIGNAME_INSTANCE, basename);
	jsonout = jsonobject->baseclass.toString(&jsonobject->baseclass);
	jsonlen = strlen(jsonout);
	UNREF(jsonobject);
	
	DEBUGMSG2("%s.%d: discovering %s: _sentyet == %d"
	,	__FUNCTION__, __LINE__, basename, self->_sentyet);
	
	
	// Primitive caching - don't send what we've already sent.
	if (self->_sentyet) {
		const char *	oldvalue = cfg->getstring(cfg, basename);
		if (oldvalue != NULL && strcmp(jsonout, oldvalue) == 0) {
			DEBUGMSG2("%s.%d: %s sent this value - don't send again."
			,	__FUNCTION__, __LINE__, basename);
			g_free(jsonout);
			return;
		}
		DEBUGMSG2("%s.%d: %s this value is different from previous value"
		,	__FUNCTION__, __LINE__, basename);
	}
	DEBUGMSG2("%s.%d: Sending %"G_GSIZE_FORMAT" bytes of JSON text"
	,	__FUNCTION__, __LINE__, jsonlen);
	cfg->setstring(cfg, basename, jsonout);
	cma = cfg->getaddr(cfg, CONFIGNAME_CMADISCOVER);
	if (cma == NULL) {
	        DEBUGMSG2("%s.%d: %s address is unknown - skipping send"
		,	__FUNCTION__, __LINE__, CONFIGNAME_CMADISCOVER);
		g_free(jsonout);
		return;
	}
	self->_sentyet = TRUE;

	fs = frameset_new(FRAMESETTYPE_JSDISCOVERY);
	intf = intframe_new(FRAMETYPE_WALLCLOCK, 8);
	intf->setint(intf, self->starttime);
	frameset_append_frame(fs, &intf->baseclass);
	UNREF2(intf);
	jsf = cstringframe_new(FRAMETYPE_JSDISCOVER, 0);
	fsf = &jsf->baseclass;	// base class object of jsf
	fsf->setvalue(fsf, jsonout, jsonlen+1, frame_default_valuefinalize); // jsonlen is strlen(jsonout)
	frameset_append_frame(fs, fsf);
	DEBUGMSG2("%s.%d: Sending a %"G_GSIZE_FORMAT" bytes JSON frameset"
	,	__FUNCTION__, __LINE__, jsonlen);
	io->_netio->sendareliablefs(io->_netio, cma, DEFAULT_FSP_QID, fs);
	++ self->reportcount;
	UNREF(fsf);
	UNREF(fs);
}
/**
 * Test program looping and reading LLDP/CDP packets and exercising most of the packet
 * send/receive mechanism and a good bit of nanoprobe and CMA basic infrastructure.
 *
 * It plays both sides of the game - the CMA and the nanoprobe.
 *
 * It leaves most of the work of starting up the nanoprobe code to nano_start_full()
 */
int
main(int argc, char **argv)
{
	const guint8	loopback[] = CONST_IPV6_LOOPBACK;
	//const guint8	mcastaddrstring[] = CONST_ASSIM_DEFAULT_V4_MCAST;
	//NetAddr*	mcastaddr;
	const guint8	otheradstring[] = {127,0,0,1};
	const guint8	otheradstring2[] = {10,10,10,4};
	const guint8	anyadstring[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
	guint16		testport = TESTPORT;
	SignFrame*	signature = signframe_glib_new(G_CHECKSUM_SHA256, 0);
	Listener*	otherlistener;
	ConfigContext*	config = configcontext_new(0);
	PacketDecoder*	decoder = nano_packet_decoder();
	AuthListener*	listentonanoprobes;
	ReliableUDP*	rtransport;

#if 0
#	ifdef HAVE_MCHECK_PEDANTIC
	g_assert(mcheck_pedantic(NULL) == 0);
#	else
#		ifdef HAVE_MCHECK
	g_assert(mcheck(NULL) == 0);
#		endif
#	endif
#endif
	g_setenv("G_MESSAGES_DEBUG", "all", TRUE);
#if 0
	proj_class_incr_debug(NULL);
	proj_class_incr_debug(NULL);
	proj_class_incr_debug(NULL);
	proj_class_incr_debug(NULL);
#endif
	g_log_set_fatal_mask(NULL, G_LOG_LEVEL_ERROR);

	if (argc > 1) {
		maxpkts = atol(argv[1]);
                g_debug("Max packet count is "FMT_64BIT"d", maxpkts);
	}

	if (netio_is_dual_ipv4v6_stack()) {
		g_message("Our OS supports dual ipv4/v6 sockets. Hurray!");
	}else{
		g_warning("Our OS DOES NOT support dual ipv4/v6 sockets - this may not work!!");
	}
	

	config->setframe(config, CONFIGNAME_OUTSIG, &signature->baseclass);

	// Create a network transport object for normal UDP packets
	rtransport = reliableudp_new(0, config, decoder, 0);
	rtransport->_protocol->window_size = 8;
	nettransport = &(rtransport->baseclass.baseclass);
	g_return_val_if_fail(NULL != nettransport, 2);

	// Set up the parameters the 'CMA' is going to send to our 'nanoprobe'
	// in response to their request for configuration data.
	nanoconfig = configcontext_new(0);
	nanoconfig->setint(nanoconfig, CONFIGNAME_INTERVAL, 1);
	nanoconfig->setint(nanoconfig, CONFIGNAME_TIMEOUT, 3);
	nanoconfig->setint(nanoconfig, CONFIGNAME_CMAPORT, testport);


	// Construct the NetAddr we'll talk to (i.e., ourselves) and listen from
	destaddr =  netaddr_ipv6_new(loopback, testport);
	g_return_val_if_fail(NULL != destaddr, 3);
	config->setaddr(config, CONFIGNAME_CMAINIT, destaddr);
	nanoconfig->setaddr(nanoconfig, CONFIGNAME_CMAADDR, destaddr);
	nanoconfig->setaddr(nanoconfig, CONFIGNAME_CMAFAIL, destaddr);
	nanoconfig->setaddr(nanoconfig, CONFIGNAME_CMADISCOVER, destaddr);

	// Construct another couple of NetAddrs to talk to and listen from
	// for good measure...
	otheraddr =  netaddr_ipv4_new(otheradstring, testport);
	g_return_val_if_fail(NULL != otheraddr, 4);
	otheraddr2 =  netaddr_ipv4_new(otheradstring2, testport);
	g_return_val_if_fail(NULL != otheraddr2, 4);

	// Construct another NetAddr to bind to (anything)
	anyaddr =  netaddr_ipv6_new(anyadstring, testport);
	g_return_val_if_fail(NULL != destaddr, 5);

	// Bind to ANY address (as noted above)
	g_return_val_if_fail(nettransport->bindaddr(nettransport, anyaddr, FALSE),16);
	//g_return_val_if_fail(nettransport->bindaddr(nettransport, destaddr),16);

	g_message("NOT Joining multicast address.");
#if 0
	// We can't do this because of encryption and we will likely screw up
	// others on our network even if that weren't a problem...
	mcastaddr =  netaddr_ipv4_new(mcastaddrstring, testport);
	g_return_val_if_fail(nettransport->mcastjoin(nettransport, mcastaddr, NULL), 17);
	UNREF(mcastaddr);
	g_message("multicast join succeeded.");
#endif

	// Connect up our network transport into the g_main_loop paradigm
	// so we get dispatched when packets arrive
	netpkt = netgsource_new(nettransport, NULL, G_PRIORITY_HIGH, FALSE, NULL, 0, NULL);

	// Set up so that we can observe all unclaimed packets
	otherlistener = listener_new(config, 0);
	otherlistener->got_frameset = gotnetpkt;
	netpkt->addListener(netpkt, 0, otherlistener);
	otherlistener->associate(otherlistener,netpkt);

	// Unref the "other" listener - we hold other references to it
	UNREF(otherlistener);

	// Pretend to be the CMA...
	// Listen for packets from our nanoprobes - scattered throughout space...
	listentonanoprobes = authlistener_new(0, cmalist, config, TRUE, NULL);
	listentonanoprobes->baseclass.associate(&listentonanoprobes->baseclass, netpkt);

	nano_start_full("netconfig", 900, netpkt, config, test_cma_authentication);

	g_timeout_add_seconds(1, timeout_agent, NULL);
	mainloop = g_main_loop_new(g_main_context_default(), TRUE);

	/********************************************************************
	 *	Start up the main loop - run our test program...
	 *	(the one pretending to be both the nanoprobe and the CMA)
	 ********************************************************************/
	g_main_loop_run(mainloop);

	/********************************************************************
	 *	We exited the main loop.  Shut things down.
	 ********************************************************************/

	nano_shutdown(TRUE);	// Tell it to shutdown and print stats
	g_message("Count of 'other' pkts received:\t%d", wirepktcount);

	UNREF(nettransport);

	// Main loop is over - shut everything down, free everything...
	g_main_loop_unref(mainloop); mainloop=NULL;


	// Unlink misc dispatcher - this should NOT be necessary...
	netpkt->addListener(netpkt, 0, NULL);

	// Dissociate packet actions from the packet source.
	listentonanoprobes->baseclass.dissociate(&listentonanoprobes->baseclass);

	// Unref the AuthListener object
	UNREF2(listentonanoprobes);

	g_source_destroy(&netpkt->baseclass);
	g_source_unref(&netpkt->baseclass);
	//g_main_context_unref(g_main_context_default());

	// Free signature frame
	UNREF2(signature);

	// Free misc addresses
	UNREF(destaddr);
	UNREF(otheraddr);
	UNREF(otheraddr2);
	UNREF(anyaddr);

	// Free config object
	UNREF(config);
	UNREF(nanoconfig);


	// At this point - nothing should show up - we should have freed everything
	if (proj_class_live_object_count() > 0) {
		g_warning("Too many objects (%d) alive at end of test.", 
			proj_class_live_object_count());
		proj_class_dump_live_objects();
		++errcount;
	}else{
		g_message("No objects left alive.  Awesome!");
	}
        proj_class_finalize_sys(); // Shut down object system to make valgrind happy :-D
	return(errcount <= 127 ? errcount : 127);
}
Example #9
0
 ~State () { if (context) { context->unref (); context = 0; } }
Example #10
0
   State (ConfigContext *theContext) : context (theContext) {

      if (context) { context->ref (); }
   }