/// 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); }
/// Constructs a GSList list of @ref FrameSet objects from a datagram/packet. /// That is, it decodes the datagram/packet. /// @return GSList of @ref FrameSet object pointers. GSList* _pktdata_to_framesetlist(PacketDecoder*self, ///<[in] PacketDecoder object gpointer pktstart, ///<[in] start of packet gconstpointer pktend) ///<[in] first byte past end of packet { guint8* curframeset = pktstart; GSList* ret = NULL; // Loop over all the FrameSets in the packet we were given. while (curframeset < (guint8*)pktend) { gpointer nextframeset = NULL; gpointer framestart = ((guint8*)curframeset + FRAMESET_INITSIZE); gpointer curframe; FrameSet* fs; gconstpointer fsend = pktend; gpointer newframestart = NULL; gboolean firstframe = TRUE; guint32 framesetlen; // Check the overall frame size framesetlen = get_generic_tlv_len(curframeset, pktend); if (framesetlen > (guint32)((guint8*)pktend-(curframeset+FRAMESET_INITSIZE))) { g_warning("%s.%d: Received frameset length [%d] is invalid - cannot exceed %d" , __FUNCTION__, __LINE__, framesetlen , (int)((guint8*)pktend-(curframeset+FRAMESET_INITSIZE))); goto errout; } fsend = curframeset+framesetlen+FRAMESET_INITSIZE; fs = _decode_packet_get_frameset_data(curframeset, curframeset+framesetlen, &nextframeset); g_return_val_if_fail(fs != NULL, ret); if (!is_valid_generic_tlv_packet(framestart, pktend)) { g_warning("%s.%d: Frameset type %d not a valid TLV frameset" , __FUNCTION__, __LINE__, fs->fstype); UNREF(fs); goto errout; } // Construct this FrameSet from the series of frames encoded in the packet. // Note that two special kinds of frames can alter the packet we're examining. // This is explained in more detail inside the loop. curframe = framestart; while (curframe != NULL && curframe < fsend) { Frame* newframe; gpointer newpacket = NULL; // The first special case frame is the compression frame, in which case the // remaining packet is replaced by a new, larger (decompressed) packet. // // The second type is the encryption packet, in which case the remaining // packet is replaced by a new chunk of data which will have different // (decrypted) content, and would normally be expected to be the same size // as the original. // // This means that "decode_packet_framedata_to_frameobject" might replace the // packet data we've been looking at. // (FWIW: It's perfectly OK to have an encryption frame followed by a // (embedded) compression frame -- both kinds can occur in the same FrameSet). newframe = _decode_packet_framedata_to_frameobject(self, &curframe, &fsend, &newpacket); if (newpacket) { if (newframestart != NULL) { // We did packet replacement more than once... g_free(newframestart); } newframestart = newpacket; } if (NULL == newframe) { UNREF(fs); goto errout; } if (TRUE == firstframe) { if (!OBJ_IS_A(newframe, "SignFrame")) { UNREF(newframe); UNREF(fs); g_warning("%s.%d: First frame NOT a signature frame - [%d] instead" , __FUNCTION__, __LINE__, newframe->type); goto errout; } firstframe = FALSE; } frameset_append_frame(fs, newframe); UNREF(newframe); } if (curframe != fsend) { g_warning("%s.%d: Received %d frameset - length is off by" ": %d instead" , __FUNCTION__, __LINE__, fs->fstype , (int)((guint8*)fsend-((guint8*)curframe))); goto errout; } if (newframestart) { g_free(newframestart); newframestart = NULL; } if (fs) { ret = g_slist_append(ret, fs); fs = NULL; } curframeset = nextframeset; } return ret; errout: g_slist_free_full(ret, assim_g_notify_unref); ret = NULL; return ret; }
/// 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"); }