/// 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);
}
/// Routine to pretend to be the initial CMA
void
fakecma_startup(AuthListener* auth, FrameSet* ifs, NetAddr* nanoaddr)
{
	FrameSet*	pkt;
	NetGSource*	netpkt = auth->baseclass.transport;
	char *		nanostr = nanoaddr->baseclass.toString(nanoaddr);
	GSList*		thisgsf;
	const char *	keyid = NULL;

	(void)ifs;
	g_message("CMA received startup message from nanoprobe at address %s/%d."
	,	nanostr, nanoaddr->port(nanoaddr));
	g_free(nanostr); nanostr = NULL;
	check_JSON(ifs);

	netpkt->_netio->addalias(netpkt->_netio, nanoaddr, destaddr);
	
	// Set up our crypto...
	cryptframe_set_dest_key_id(nanoaddr, cryptframe_get_signing_key_id());
	cryptframe_set_dest_key_id(destaddr, cryptframe_get_signing_key_id());
	cryptframe_associate_identity(CMA_IDENTITY_NAME, cryptframe_get_signing_key_id());
	cryptframe_set_encryption_method(cryptcurve25519_new_generic);
	for (thisgsf = ifs->framelist; thisgsf; thisgsf=thisgsf->next) {
		Frame*	thisframe = CASTTOCLASS(Frame, thisgsf->data);
		if (thisframe->type == FRAMETYPE_KEYID) {
			CstringFrame* csf = CASTTOCLASS(CstringFrame, thisframe);
			keyid = (const char *)csf->baseclass.value;
		}else if (keyid && thisframe->type == FRAMETYPE_PUBKEYCURVE25519) {
			cryptcurve25519_save_public_key(keyid, thisframe->value
			,	thisframe->length);
		}
	}

	// Send the configuration data to our new "client"
	pkt = create_setconfig(nanoconfig);
	netpkt->_netio->sendareliablefs(netpkt->_netio, nanoaddr, DEFAULT_FSP_QID, pkt);
	UNREF(pkt);

	// Now tell them to send/expect heartbeats to various places
	pkt = create_sendexpecthb(auth->baseclass.config, FRAMESETTYPE_SENDEXPECTHB, destaddr, 1);
	netpkt->_netio->sendareliablefs(netpkt->_netio, nanoaddr, DEFAULT_FSP_QID, pkt);
	UNREF(pkt);

	{
		const char *	monopjson[] = { START, MONITOR, STOP};
		unsigned	j;
		// Create a frameset for a few resource operations
		pkt = frameset_new(FRAMESETTYPE_DORSCOP);
		for (j=0; j < DIMOF(monopjson); j++) {
			CstringFrame*	csf = cstringframe_new(FRAMETYPE_RSCJSON,0);
			csf->baseclass.setvalue(&csf->baseclass, g_strdup(monopjson[j])
			,	strlen(monopjson[j])+1, g_free);
			frameset_append_frame(pkt, &csf->baseclass);
			UNREF2(csf);
		}
		netpkt->_netio->sendareliablefs(netpkt->_netio, nanoaddr, DEFAULT_FSP_QID, pkt);
		UNREF(pkt);
	}
	{
		const char *	discoverjson[] = {SWITCHDISCOVER, ARPDISCOVER};
		const char *	discoverinstnm[] = {SWINSTNM, ARPINSTNM};
		unsigned	j;
		// Create a frameset for a few discovery operations
		pkt = frameset_new(FRAMESETTYPE_DODISCOVER);
		for (j=0; j < DIMOF(discoverjson); j++) {
			CstringFrame*	csf = cstringframe_new(FRAMETYPE_DISCJSON,0);
			CstringFrame*	inst = cstringframe_new(FRAMETYPE_DISCNAME,0);
			fprintf(stderr, "Creating discovery frameset: %s: %s\n"
			,	discoverinstnm[j]
			,	discoverjson[j]);
			inst->baseclass.setvalue(&inst->baseclass, g_strdup(discoverjson[j])
			,	strlen(discoverjson[j])+1, g_free);
			frameset_append_frame(pkt, &inst->baseclass);
			UNREF2(inst);
			csf->baseclass.setvalue(&csf->baseclass, g_strdup(discoverjson[j])
			,	strlen(discoverjson[j])+1, g_free);
			frameset_append_frame(pkt, &csf->baseclass);
			UNREF2(csf);
		}
		netpkt->_netio->sendareliablefs(netpkt->_netio, nanoaddr, DEFAULT_FSP_QID, pkt);
		UNREF(pkt);
	}
	pkt = frameset_new(FRAMESETTYPE_ACKSTARTUP);
	netpkt->_netio->sendareliablefs(netpkt->_netio, nanoaddr, DEFAULT_FSP_QID, pkt);
	UNREF(pkt);
	g_info("ACKSTARTUP packet queued to send");
}