DataObjectRef Forwarder::createRoutingInformationDataObject() { // No need to have a reference in this function because it won't be // visible outside until this function is done with it. DataObjectRef dObj = DataObject::create(); if (!dObj) return NULL; HAGGLE_DBG2("Creating routing info data object\n"); dObj->setPersistent(false); dObj->addAttribute("Forwarding", getName()); // Add the metric data to the forwarding section: Metadata *md = dObj->getMetadata()->addMetadata(getManager()->getName()); md = md->addMetadata(getName()); md->setParameter("node_id", getKernel()->getThisNode()->getIdStr()); if (!addRoutingInformation(dObj, md)) { // SW: ERR->DBG, this is not fatal, we return false when we don't want // to add routing data. // HAGGLE_DBG("Could not add routing information\n"); return NULL; } return dObj; }
// CBMEN, HL, Begin int ReplicationOptimizer::getCost(DataObjectRef dObj, string node_id) { int dataLen = 0; { dataLen = (int) dObj->getDataLen(); // include metadata size Metadata *m = dObj->getMetadata(); if (!m) { errorCount++; HAGGLE_ERR("Missing metadata.\n"); return 0; } dataLen += m->getContent().size(); } { node_map_t::iterator it = node_map.find(node_id); if (it == node_map.end()) { errorCount++; HAGGLE_ERR("Missing node: %s\n", node_id.c_str()); return 0; } } return dataLen; }
bool SecurityHelper::signDataObject(DataObjectRef& dObj, RSA *key) { unsigned char *signature; if (!key || !dObj) return false; unsigned int siglen = RSA_size(key); signature = (unsigned char *)malloc(siglen); if (!signature) return false; printf("signing data object, siglen=%u\n", siglen); memset(signature, 0, siglen); if (RSA_sign(NID_sha1, dObj->getId(), sizeof(DataObjectId_t), signature, &siglen, key) != 1) { free(signature); return false; } dObj->setSignature(getManager()->getKernel()->getThisNode()->getIdStr(), signature, siglen); // Assume that our own signature is valid dObj->setSignatureStatus(DataObject::SIGNATURE_VALID); // Do not free the allocated signature as it is now owned by the data object... return true; }
void Manager::_onConfig(Event *e) { DataObjectRefList& dObjs = e->getDataObjectList(); while (dObjs.size()) { DataObjectRef dObj = dObjs.pop(); // Get the metadata matching the manager Metadata *m = dObj->getMetadata()->getMetadata(this->getName()); if (m) { onConfig(m); } } }
void DataManager::handleVerifiedDataObject(DataObjectRef& dObj) { if (!dObj) { HAGGLE_ERR ("Handle verified object received null object.\n"); return; } if(networkCodingConfiguration->isNetworkCodingEnabled(dObj,NULL) && !networkCodingConfiguration->isForwardingEnabled()) { if(networkCodingDataObjectUtility->isNetworkCodedDataObject(dObj)) { if (dObj->isDuplicate()) { HAGGLE_DBG("Data object %s is a duplicate! Not generating DATAOBJECT_NEW event\n", dObj->getIdStr()); } else { kernel->addEvent(new Event(EVENT_TYPE_DATAOBJECT_NEW, dObj)); return; } } } if(fragmentationConfiguration->isFragmentationEnabled(dObj,NULL) && !fragmentationConfiguration->isForwardingEnabled()) { if(fragmentationDataObjectUtility->isFragmentationDataObject(dObj)) { if (dObj->isDuplicate()) { HAGGLE_DBG("Data object %s is a duplicate! Not generating DATAOBJECT_NEW event\n", dObj->getIdStr()); } else { kernel->addEvent(new Event(EVENT_TYPE_DATAOBJECT_NEW, dObj)); return; } } } // MOS - add data object to Bloomfilter to cover the case // where there was no incoming event (e.g. encrypting data object from local app) if (dObj->getABEStatus() != DataObject::ABE_NOT_NEEDED && !localBF->has(dObj)) { localBF->add(dObj); HAGGLE_DBG("Adding encrypted data object [%s] to our bloomfilter, #objs=%d\n", DataObject::idString(dObj).c_str(), localBF->numObjects()); kernel->getThisNode()->getBloomfilter()->add(dObj); // MOS } if (cacheStrategy && !cacheStrategy->isDone() && cacheStrategy->isResponsibleForDataObject(dObj)) { cacheStrategy->handleNewDataObject(dObj); } else { //default action for dObj's that are NOT handled by cache strat code insertDataObjectIntoDataStore (dObj); } }
bool NetworkCodingConfiguration::isNetworkCodingEnabled(DataObjectRef dataObject, NodeRef targetNodeToNetworkCodeFor) { // if network coding turned on doesn't matter about dataobjects or targetnoderefids if( NetworkCodingConfiguration::isNetworkCodingTurnedOn ) { return true; } if( !targetNodeToNetworkCodeFor ) { return false; } string targetNodeId = targetNodeToNetworkCodeFor->getName(); string dataObjectId; if (dataObject) dataObjectId = dataObject->getIdStr(); string key = dataObjectId + "|" + targetNodeId; { Mutex::AutoLocker l(NetworkCodingConfiguration::contextAwareMutex); // needs to be fine grained contextawarecodingtracker_t::iterator it = NetworkCodingConfiguration::contextawaretracker.find(key); if (it != NetworkCodingConfiguration::contextawaretracker.end()) { return true; } key = "|" + targetNodeId; it = NetworkCodingConfiguration::contextawaretracker.find(key); if (it != NetworkCodingConfiguration::contextawaretracker.end()) { HAGGLE_DBG("context aware coding is enabled for targetnoderefid=%s, saving status for dataobject=%s\n", targetNodeId.c_str(), dataObjectId.c_str()); NetworkCodingConfiguration::contextawaretracker.insert(make_pair(dataObjectId + "|" + targetNodeId, true)); return true; } } return false; }
/** Add routing information to a data object. The parameter "parent" is the location in the data object where the routing information should be inserted. */ bool ForwarderRank::addRoutingInformation(DataObjectRef& dObj, Metadata *parent) { if (!dObj || !parent) return false; // Add first our own node ID. parent->setParameter("node_id", kernel->getThisNode()->getIdStr()); Metadata *mm = parent->addMetadata("Metric", myNodeStr); mm->setParameter("hostid",hostname); mm->setParameter("label", myLabel); char tmp[32]; sprintf(tmp,"%ld",myRank); mm->setParameter("rank", tmp); HAGGLE_DBG("HAGGLE_DBG: Sending metric node:%s label:%s rank:%s \n",parent->getParameter("node_id"), mm->getParameter("label"),mm->getParameter("rank")); dObj->setCreateTime(rib_timestamp); return true; }
void DebugManager::onFindRepositoryKey(Event *e) { if (!e || !e->hasData()) return; DataStoreQueryResult *qr = static_cast < DataStoreQueryResult * >(e->getData()); RepositoryEntryRef re = qr->detachFirstRepositoryEntry(); if (!re) { // No repository entry: no data object. DataObjectRef dObj; // Name the log so that the files are more easily readable on the // machine that receives them: char filename[128]; sprintf(filename, "log-%s.txt", kernel->getThisNode()->getIdStr()); // Create data object: // Empty at first: dObj = DataObject::create(LogTrace::ltrace.getFile(), filename); if (!dObj) { HAGGLE_ERR("Could not create data object\n"); return; } // Add log file attribute: Attribute a("Log file","Trace"); dObj->addAttribute(a); // Add node id of local node, to make sure that two logs from different // nodes don't clash: Attribute b("Node id", kernel->getThisNode()->getIdStr()); dObj->addAttribute(b); // Insert data object: kernel->getDataStore()->insertDataObject(dObj); // Insert a repository entry to show the data object exists: kernel->getDataStore()->insertRepository(new RepositoryEntry("DebugManager", "has saved log file data object", "yes")); } delete qr; }
void EvictStrategyLRFU::updateInfoDataObject(DataObjectRef &dObj, unsigned int count, Timeval time) { ScratchpadManager *pad = getKernel()->getDataStore()->getScratchpadManager(); //create scratchpad keys string paramNameF0=name; paramNameF0.append("_LRU_F0"); double c_now = 0.0; double c_old = 0.0; double lastTime = 0.0; double paramValueF0 = 0.0; double paramValueLastk = 0.0; string paramName_c_now=name; paramName_c_now.append("_c_now"); string paramNameLastk=name; paramNameLastk.append("_LRU_last_k"); if (countType == EVICT_STRAT_LRFU_COUNT_TYPE_TIME) { paramValueLastk = time.getTimeAsMilliSecondsDouble(); } else { //otherwise count paramValueLastk = (double) count; } bool has_attr = pad->hasScratchpadAttributeDouble(dObj, paramNameF0); if (has_attr) { paramValueF0 = pad->getScratchpadAttributeDouble(dObj, paramNameF0); c_now = pad->getScratchpadAttributeDouble(dObj, paramName_c_now); c_old = c_now; lastTime = pad->getScratchpadAttributeDouble(dObj, paramNameLastk); c_now *= fx_calc(paramValueLastk-lastTime); c_now += paramValueF0; HAGGLE_DBG("%s f(x) = %f + G(%f - %f)*%f = %f\n", dObj->getIdStr() ,paramValueF0 , (float) count, lastTime, c_old, c_now); } else { c_now = 1.0; //fx_calc(paramValueLastk); pad->setScratchpadAttributeDouble(dObj, paramNameF0, c_now); HAGGLE_DBG("%s f(0) = g(%f) = %f\n", dObj->getIdStr(), paramValueLastk, c_now); } //set current values pad->setScratchpadAttributeDouble(dObj, paramName_c_now, c_now); pad->setScratchpadAttributeDouble(dObj, paramNameLastk, paramValueLastk); }
bool SecurityHelper::verifyDataObject(DataObjectRef& dObj, CertificateRef& cert) const { RSA *key; // Cannot verify without signature if (!dObj->getSignature()) { HAGGLE_ERR("No signature in data object, cannot verify\n"); return false; } writeErrors("(not this): "); key = cert->getPubKey(); if (RSA_verify(NID_sha1, dObj->getId(), sizeof(DataObjectId_t), const_cast<unsigned char *>(dObj->getSignature()), dObj->getSignatureLength(), key) != 1) { char *raw; size_t len; writeErrors(""); dObj->getRawMetadataAlloc((unsigned char **)&raw, &len); if (raw) { HAGGLE_DBG("Signature is invalid:\n%s\n", raw); free(raw); } dObj->setSignatureStatus(DataObject::SIGNATURE_INVALID); return false; } HAGGLE_DBG("Signature is valid\n"); dObj->setSignatureStatus(DataObject::SIGNATURE_VALID); return true; }
/** * This routine was taken from the benchmark manager, to create Dataobjects in code. * It is used for the self test. Depending on compile options, benchmark manager * may not be included, so the relevant code is copied here to be always available. * * @see BenchmarkManager::createDataObject * */ DataObjectRef CacheStrategyUtility::createDataObject(unsigned int numAttr) { char name[128]; char value[128]; unsigned int r; unsigned char macaddr[6]; macaddr[0] = (unsigned char) RANDOM_INT(255); macaddr[1] = (unsigned char) RANDOM_INT(255); macaddr[2] = (unsigned char) RANDOM_INT(255); macaddr[3] = (unsigned char) RANDOM_INT(255); macaddr[4] = (unsigned char) RANDOM_INT(255); macaddr[5] = (unsigned char) RANDOM_INT(255); unsigned char macaddr2[6]; macaddr2[0] = (unsigned char) RANDOM_INT(255); macaddr2[1] = (unsigned char) RANDOM_INT(255); macaddr2[2] = (unsigned char) RANDOM_INT(255); macaddr2[3] = (unsigned char) RANDOM_INT(255); macaddr2[4] = (unsigned char) RANDOM_INT(255); macaddr2[5] = (unsigned char) RANDOM_INT(255); EthernetAddress addr(macaddr); EthernetAddress addr2(macaddr2); InterfaceRef localIface = Interface::create<EthernetInterface>(macaddr, "eth", addr, 0); InterfaceRef remoteIface = Interface::create<EthernetInterface>(macaddr2, "eth2", addr2, 0); DataObjectRef dObj = DataObject::create(NULL, 0, localIface, remoteIface); for (unsigned int i = 0; i < numAttr; i++) { int tries = 0; do { r = RANDOM_INT(32000); sprintf(name, "name"); sprintf(value, "value %d", r); if (tries++ > 10) { HAGGLE_ERR("WARNING: Cannot generate unique attributes in data object... check attribute pool size!\n"); break; } } while (dObj->getAttribute(name, value)); dObj->addAttribute(name, value, 1); //r); } return dObj; }
void NetworkCodingEncoderManagerModuleProcessor::encode(NetworkCodingEncoderTaskRef networkCodingEncoderTask) { const DataObjectRef originalDataObjectRef = networkCodingEncoderTask->getDataObject(); const NodeRefList nodeRefList = networkCodingEncoderTask->getNodeRefList(); HAGGLE_DBG("Perform network coding for data object %s\n", originalDataObjectRef->getIdStr()); DataObjectRef networkCodedDataObject = this->networkCodingEncoderService->encodeDataObject(originalDataObjectRef); if(networkCodedDataObject) { // MOS HAGGLE_DBG("Generated block %s for data object %s\n", networkCodedDataObject->getIdStr(), originalDataObjectRef->getIdStr()); Event* sendEvent = new Event(EVENT_TYPE_DATAOBJECT_SEND, networkCodedDataObject, nodeRefList); this->haggleKernel->addEvent(sendEvent); } }
/* public event handler on verified DataObject means that the DataObject is verified by the SecurityManager */ void DataManager::onVerifiedDataObject(Event *e) { if (!e || !e->hasData()) return; DataObjectRef dObj = e->getDataObject(); if (!dObj) { HAGGLE_DBG("Verified data object event without data object!\n"); return; } if (dataObjectsReceived.size() >= MAX_DATAOBJECTS_LISTED) { dataObjectsReceived.pop_front(); } dataObjectsReceived.push_back(dObj->getIdStr()); HAGGLE_DBG("%s Received data object [%s]\n", getName(), dObj->getIdStr()); #ifdef DEBUG // dObj->print(NULL); // MOS - NULL means print to debug trace #endif if (dObj->getSignatureStatus() == DataObject::SIGNATURE_INVALID) { // This data object had a bad signature, we should remove // it from the bloomfilter HAGGLE_DBG("Data object [%s] had bad signature, removing from bloomfilter\n", dObj->getIdStr()); localBF->remove(dObj); kernel->getThisNode()->setBloomfilter(*localBF, setCreateTimeOnBloomfilterUpdate); return; } if (dObj->getDataState() == DataObject::DATA_STATE_VERIFIED_BAD) { HAGGLE_ERR("Data in data object flagged as bad! -- discarding\n"); if (localBF->has(dObj)) { // Remove the data object from the bloomfilter since it was bad. localBF->remove(dObj); kernel->getThisNode()->setBloomfilter(*localBF, setCreateTimeOnBloomfilterUpdate); } return; } else if (dObj->getDataState() == DataObject::DATA_STATE_NOT_VERIFIED && helper) { // Call our helper to verify the data in the data object. if (dObj->dataIsVerifiable()) { helper->addTask(new DataTask(DATA_TASK_VERIFY_DATA, dObj)); return; } } handleVerifiedDataObject(dObj); }
/* On send events, the security manager */ void SecurityManager::onSendDataObject(Event *e) { if (!e || !e->hasData()) return; DataObjectRef dObj = e->getDataObject(); if (dObj->isThisNodeDescription()) { // This is our node description. Piggy-back our certificate. if (myCert) { Metadata *m; m = dObj->getMetadata()->getMetadata("Security"); if (m) { HAGGLE_ERR("Node description already has a Security tag!\n"); } else { m = dObj->getMetadata()->addMetadata("Security"); if (m) { m->addMetadata(myCert->toMetadata()); } } } } // In most cases the data object is already signed here (e.g., if it is generated by a local // application, or was received from another node). The only reason to check if we should // sign the data object here, is if a data object was generated internally by Haggle -- in // which case the data object might not have a signature (e.g., the data object is a node // description). InterfaceRef iface = dObj->getRemoteInterface(); if (dObj->shouldSign() && !(iface && iface->getType() == Interface::TYPE_APPLICATION_PORT)) { // FIXME: data objects should really be signed in the SecurityHelper thread since // it is a potentially CPU intensive operation. But it is currently not possible // to ensure that the signing operation has finished in the helper thread before // the data object is actually sent on the wire by the protocol manager. // To handle this situation, we probably need to add a new public event for // security related operations, after which the security manager generates the // real send event. if (helper->signDataObject(dObj, privKey)) { HAGGLE_DBG("Successfully signed data object %s\n", dObj->getIdStr()); } else { HAGGLE_DBG("Signing of data object %s failed!\n", dObj->getIdStr()); } } }
void initializationCallback(Event *e) { DataObjectRefList dObjs = e->getDataObjectList(); for (DataObjectRefList::iterator it = dObjs.begin(); it != dObjs.end(); it++) { DataObjectRef dObj = *it; if (!purger->isResponsibleForDataObject(dObj)) { continue; } double now = (Timeval::now()).getTimeAsSecondsDouble(); double then = (dObj->getReceiveOrCreateTime()).getTimeAsSecondsDouble(); const Attribute *attr = dObj->getAttribute(purger->getMetricField(), "*", 1); double ttl = atof(attr->getValue().c_str()); if (now < (then + ttl + purger->getMinDBTimeS())) { purger->schedulePurge(dObj); } else { kernel->getDataStore()->deleteDataObject(dObj, purger->getKeepInBloomfilter()); } } }
bool CachePurgerRelTTL::isResponsibleForDataObject( DataObjectRef &dObj) { if (!dObj) { return false; } const Attribute *attr; attr = dObj->getAttribute (tagField, tagFieldValue, 1); if (!attr) { return false; } attr = dObj->getAttribute (metricField, "*", 1); if (!attr) { return false; } return true; }
void Manager::_onDynamicConfig(Event *e) { if (!e || !e->hasData()) return; DataObjectRef dObj = e->getDataObject(); if (!dObj) return; Metadata *m = dObj->getMetadata(); if (!m) return; m = m->getMetadata(DATAOBJECT_METADATA_APPLICATION_CONTROL_DYNAMIC_CONFIGURATION); if (!m) return; m = m->getMetadata(getName()); if (!m) return; onDynamicConfig(m); }
bool Forwarder::hasRoutingInformation(const DataObjectRef& dObj) { if (!dObj) return false; const Metadata *m = dObj->getMetadata()->getMetadata(getManager()->getName()); if (m == NULL) return false; if (!m->getMetadata(getName())) return false; return true; }
void CachePurgerRelTTL::schedulePurge( DataObjectRef &dObj) { if (!isResponsibleForDataObject(dObj)) { HAGGLE_ERR("Cannot schedule purge for DO not responsible for\n"); return; } const Attribute *attr = dObj->getAttribute(metricField, "*", 1); if (!attr) { HAGGLE_ERR("Attribute not specified\n"); return; } double now = (Timeval::now()).getTimeAsSecondsDouble(); double ttl = atof(attr->getValue().c_str()); double then = (dObj->getReceiveOrCreateTime()).getTimeAsSecondsDouble(); double expTime = ttl - (now - then); expTime = expTime > minDBtimeS ? expTime : minDBtimeS; getKernel()->addEvent(new Event(deleteCallback, dObj, expTime)); }
const string Forwarder::getNodeIdFromRoutingInformation(const DataObjectRef& dObj) const { if (!dObj) return (char *)NULL; const Metadata *m = dObj->getMetadata()->getMetadata(getManager()->getName()); if (!m) return (char *)NULL; m = m->getMetadata(getName()); if (!m) return (char *)NULL; return m->getParameter("node_id"); }
void DataManager::onDeletedDataObject(Event * e) { if (!e || !e->hasData()) return; DataObjectRefList dObjs = e->getDataObjectList(); unsigned int n_removed = 0; bool cleanup = false; // MOS for (DataObjectRefList::iterator it = dObjs.begin(); it != dObjs.end(); it++) { /* Do not remove Node descriptions from the bloomfilter. We do not want to receive old node descriptions again. If the flag in the event is set, it means we should keep the data object in the bloomfilter. */ DataObjectRef dObj = (*it); if (!dObj->isNodeDescription() && !e->getFlags()) { if(localBF->has(dObj)) { HAGGLE_DBG("Removing deleted data object [id=%s] from bloomfilter, #objs=%d\n", DataObject::idString(dObj).c_str(), localBF->numObjects()); localBF->remove(dObj); n_removed++; } else { HAGGLE_DBG("Deleted data object data object [id=%s] not found in bloomfilter\n", dObj->getIdStr()); } } else { HAGGLE_DBG("Keeping deleted data object [id=%s] in bloomfilter\n", dObj->getIdStr()); } if(!dObj->hasValidSignature()) { cleanup = true; // MOS - allow new incoming data object from co-certified node } // SW: JLM: START CACHE STRATEGY: if (cacheStrategy && !cacheStrategy->isDone() && cacheStrategy->isResponsibleForDataObject(dObj)) { cacheStrategy->handleDeletedDataObject(dObj); } // SW: JLM: END CACHE STRATEGY. // CBMEN, HL - Begin // Remove any pending send events for this data object HAGGLE_DBG2("Cancelling send events for dObj %s\n", dObj->getIdStr()); kernel->cancelEvents(EVENT_TYPE_DATAOBJECT_SEND, dObj); // CBMEN, HL, End } if (n_removed > 0 || cleanup) kernel->getThisNode()->setBloomfilter(*localBF, setCreateTimeOnBloomfilterUpdate); }
// We intercept the `handleVerifiedDataObject` call to now call // into the cache strat, if it exists. The cache strat module // will then call `insertDataObjectIntoDataStore` if the new object // should be inserted void DataManager::insertDataObjectIntoDataStore(DataObjectRef& dObj) { if (!dObj) { HAGGLE_ERR ("Trying to insert null data object into DB.\n"); return; } // insert into database (including filtering) if (dObj->isPersistent ()) { kernel->getDataStore ()->insertDataObject (dObj, onInsertedDataObjectCallback); } else { // do not expect a callback for a non-persistent data object, // but we still call insertDataObject in order to filter the data object. kernel->getDataStore ()->insertDataObject (dObj, NULL); } }
/* * Returns true iff */ bool CacheStrategyUtility::isResponsibleForDataObject( DataObjectRef &dObj) { string id = string(dObj->getIdStr()); /* // THIS IS NOT THREAD SAFE!! added getOrigSize // to grab unaltered file size. if (utilMetadata.find(id) != utilMetadata.end()) { return true; } */ if (dObj->isDuplicate()) { return false; } // SW: TODO: NOTE: this might not be the best way to check if it's from // a local application, but it works for now... bool isLocal = dObj->getRemoteInterface() && dObj->getRemoteInterface()->isApplication(); bool notResponsible = dObj->isControlMessage() || dObj->isNodeDescription(); bool isResponsible = !notResponsible; if (!handle_zero_size) { isResponsible = isResponsible && (dObj->getOrigDataLen() > 0); } if (!manage_locally_sent_files) { isResponsible = isResponsible && dObj->isPersistent(); } if (stats_replacement_strat && stats_replacement_strat->isResponsibleForDataObject(dObj)) { isResponsible = true; } else if (manage_only_remote_files) { isResponsible = isResponsible && !isLocal; } return isResponsible; }
/* * Callback on data object deletion events. Keeps the cache stat in sync * with the database, and notifies the utility functions. */ void CacheStrategyUtility::_handleDeletedDataObject( DataObjectRef &dObj, bool mem_do) { if (!isResponsibleForDataObject(dObj)) { //HAGGLE_DBG("Ignoring data object, in-eligible for caching\n"); return; } if (stats_replacement_strat && stats_replacement_strat->isResponsibleForDataObject(dObj)) { //HAGGLE_DBG("Ignoring data object, delete of stats data object\n"); return; } if (deleteDataObjectFromCache(string(dObj->getIdStr()), mem_do)) { getUtilityFunction()->notifyDelete(dObj); } else { HAGGLE_DBG("Data object may have already been removed"); } }
/* * Publish a data object with utility based caching statistics. */ void CacheStrategyUtility::_publishStatsDataObject() { DataObjectRef dObj = DataObject::create(); dObj->addAttribute("CacheStrategyUtility", "stats"); dObj->addAttribute("Timestamp", Timeval::now().getAsString().c_str()); dObj->addAttribute("PublisherID", getManager()->getKernel()->getThisNode()->getIdStr()); dObj->addAttribute("Statistics", _generateStatsString().c_str()); #ifdef DEBUG dObj->print(NULL); // MOS - NULL means print to debug trace #endif getManager()->getKernel()->addEvent(new Event(EVENT_TYPE_DATAOBJECT_RECEIVED, dObj)); }
/* Check incoming data objects for two reasons: 1) whether they have an embedded certificate, in which case we verify it and add it to our store in case it is not already there. 2) sign any data objects that were generated by local applications. */ void SecurityManager::onIncomingDataObject(Event *e) { DataObjectRef dObj; if (!e || !e->hasData()) return; dObj = e->getDataObject(); if (dObj->isDuplicate()) return; Metadata *m = dObj->getMetadata()->getMetadata("Security"); // Check if there is a certificate embedded that we do not already have stored if (m && m->getMetadata("Certificate")) { HAGGLE_DBG("Data object has embedded certificate, trying to verify it!\n"); helper->addTask(new SecurityTask(SECURITY_TASK_VERIFY_CERTIFICATE, dObj)); } InterfaceRef iface = dObj->getRemoteInterface(); // Check if this data object came from an application, in that case we sign it. // In the future, the signing should potentially be handled by the application // itself. But this requires some major rethinking of how to manage certificates // and keys, etc. if (iface && iface->getType() == Interface::TYPE_APPLICATION_PORT && dObj->shouldSign()) { HAGGLE_DBG("Data object should be signed\n"); // FIXME: data objects should really be signed in the SecurityHelper thread since // it is a potentially CPU intensive operation. But it is currently not possible // to ensure that the signing operation has finished in the helper thread before // the data object is added to the data store. if (helper->signDataObject(dObj, privKey)) { HAGGLE_DBG("Successfully signed data object %s, which was added by an application.\n", dObj->getIdStr()); } else { HAGGLE_DBG("Signing of data object %s, which was added by an application, failed!\n", dObj->getIdStr()); } } }
string ProtocolClassifierAttribute::getClassNameForDataObject( const DataObjectRef& dObj) { if (!initialized) { HAGGLE_ERR("Classifier has not been fully initialized.\n"); return PROTOCOL_CLASSIFIER_INVALID_CLASS; } if (!dObj) { HAGGLE_ERR("Received null data object.\n"); return PROTOCOL_CLASSIFIER_INVALID_CLASS; } const Attribute *attr = dObj->getAttribute(attrName, attrValue); // only mark node descriptions as light-weight content if (!attr) { return PROTOCOL_CLASSIFIER_INVALID_CLASS; } return className; }
bool FragmentationConfiguration::isFragmentationEnabled(DataObjectRef dataObject, NodeRef targetNodeToFragmentCodeFor) { // fragmentation is not enabled at all, so just return false and let nc checks run if(!FragmentationConfiguration::isFragmentationTurnedOn) { return false; } // no target node and already passed the is fragemtnation turned on, so return true if( !targetNodeToFragmentCodeFor ) { return true; } string targetNodeId = targetNodeToFragmentCodeFor->getName(); string dataObjectId; if (dataObject) dataObjectId = dataObject->getIdStr(); string key = dataObjectId + "|" + targetNodeId; { Mutex::AutoLocker l(FragmentationConfiguration::contextAwareMutex); // needs to be fine grained contextawarefragmentationtracker_t::iterator it = FragmentationConfiguration::contextawaretracker.find(key); if (it != FragmentationConfiguration::contextawaretracker.end()) { return false; } key = "|" + targetNodeId; it = FragmentationConfiguration::contextawaretracker.find(key); if (it != FragmentationConfiguration::contextawaretracker.end()) { HAGGLE_DBG("context aware coding is enabled for targetnoderefid=%s, saving status for dataobject=%s\n", targetNodeId.c_str(), dataObjectId.c_str()); FragmentationConfiguration::contextawaretracker.insert(make_pair(dataObjectId + "|" + targetNodeId, true)); return false; } } return true; }
void DebugManager::dumpTo(SOCKET client_sock, DataStoreDump *dump) { size_t toSend = dump->getLen(); const char *data = dump->getData(); size_t i = 0; i = skipXMLTag(data, toSend); toSend -= i; // Send the <?xml version="1.0"?> tag: if (!sendString(client_sock, "<?xml version=\"1.0\"?>\n")) return; // Send the root tag: if (!sendString(client_sock, "<HaggleInfo>")) return; // Send the data: if (!sendBuffer(client_sock, &(data[i]), toSend)) return; DataObjectRef dObj = kernel->getThisNode()->getDataObject(false); unsigned char *buf; size_t len; if (dObj->getRawMetadataAlloc(&buf, &len)) { i = skipXMLTag((char *)buf, len); len -= i; if (!sendString(client_sock, "<ThisNode>\n")) { free(buf); return; } if (!sendBuffer(client_sock, &(buf[i]), len)) { free(buf); return; } if (!sendString(client_sock, "</ThisNode>\n")) { free(buf); return; } free(buf); } /* FIXME: With the new forwarding this thing is broken. Manager *mgr = kernel->getManager((char *)"ForwardingManager"); if (mgr) { ForwardingManager *fmgr = (ForwardingManager *) mgr; DataObjectRef dObj = fmgr->getForwarder()->myMetricDO; if (dObj) { char *buf; size_t len; if (dObj->getRawMetadataAlloc(&buf, &len)) { i = skipXMLTag(buf, len); len -= i; if (!sendString(client_sock, "<RoutingData>\n")) { free(buf); return; } if (!sendBuffer(client_sock, &(buf[i]), len)) { free(buf); return; } if (!sendString(client_sock, "</RoutingData>\n")) { free(buf); return; } free(buf); } } } */ NodeRefList nl; kernel->getNodeStore()->retrieveNeighbors(nl); if (!nl.empty()) { if (!sendString(client_sock, "<NeighborInfo>\n")) return; for (NodeRefList::iterator it = nl.begin(); it != nl.end(); it++) { if (!sendString(client_sock, "<Neighbor>")) return; if (!sendString(client_sock, (*it)->getIdStr())) return; if (!sendString(client_sock, "</Neighbor>\n")) return; } if (!sendString(client_sock, "</NeighborInfo>\n")) return; } // Send the end of the root tag: sendString(client_sock, "</HaggleInfo>"); }
ProtocolEvent ProtocolUDP::receiveDataObject() { size_t len = 0; string haggleTag = "</Haggle>"; DataObjectRef dObj; char buf[SOCKADDR_SIZE]; struct sockaddr *peer_addr = (struct sockaddr *)buf; ProtocolEvent pEvent; unsigned short port; Address *addr = NULL; struct sockaddr_in *sa = NULL; #ifdef OS_WINDOWS pEvent = receiveData(buffer, bufferSize, peer_addr, 0, &len); #else pEvent = receiveData(buffer, bufferSize, peer_addr, MSG_DONTWAIT, &len); #endif if (pEvent != PROT_EVENT_SUCCESS) return pEvent; if (peer_addr->sa_family == AF_INET) { sa = (struct sockaddr_in *)peer_addr; port = ntohs(sa->sin_port); addr = new IPv4Address(sa->sin_addr, TransportUDP(port)); } #if defined(ENABLE_IPv6) else if (peer_addr->sa_family == AF_INET6) { struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)peer_addr; port = ntohs(sa6->sin6_port); addr = new IPv6Address(sa6->sin6_addr, TransportUDP(port)); } #endif if (addr == NULL) return PROT_EVENT_ERROR; if (peerIface) { HAGGLE_ERR("%s UDP peer interface was not null\n", getName()); delete addr; return PROT_EVENT_ERROR; } peerIface = new ApplicationPortInterface(port, "Application", addr, IFFLAG_UP); peerNode = getKernel()->getNodeStore()->retrieve(peerIface); delete addr; if (!peerNode) { peerNode = Node::create(Node::TYPE_APPLICATION, "Unknown application"); if (!peerNode) { HAGGLE_ERR("%s Could not create application node\n", getName()); return PROT_EVENT_ERROR; } } dObj = DataObject::create(buffer, len, localIface, peerIface); if (!dObj) { HAGGLE_DBG("%s Could not create data object\n", getName()); return PROT_EVENT_ERROR; } // Haggle doesn't own files that applications have put in: // MOS - not true - maybe some code missing here Timeval ct = dObj->getCreateTime(); Timeval now = Timeval::now(); if(!ct.isValid()) dObj->setCreateTime(now); // MOS - in case it was not set by application dObj->setReceiveTime(now); dataObjectsIncoming += 1; // MOS dataObjectBytesIncoming += len; // MOS if(!dObj->isControlMessage()) dataObjectsIncomingNonControl += 1; // MOS // We must release the peer interface reference after // the data object is created as the next incoming // data might be from another peer peerIface = NULL; // MOS - no need to ignore objects from local application (avoid risk of blocking control messages) // if (getKernel()->getThisNode()->getBloomfilter()->has(dObj)) { // HAGGLE_DBG("Data object [%s] from interface %s:%u has already been received, ignoring.\n", // dObj->getIdStr(), sa ? ip_to_str(sa->sin_addr) : "undefined", port); // return PROT_EVENT_SUCCESS; // } // Generate first an incoming event to conform with the base Protocol class getKernel()->addEvent(new Event(EVENT_TYPE_DATAOBJECT_INCOMING, dObj, peerNode)); dataObjectsReceived += 1; // MOS dataObjectBytesReceived += len; // MOS HAGGLE_DBG("%s Received data object [%s] from interface %s:%u\n", getName(), dObj->getIdStr(), sa ? ip_to_str(sa->sin_addr) : "undefined", port); // Since there is no data following, we generate the received event immediately // following the incoming one getKernel()->addEvent(new Event(EVENT_TYPE_DATAOBJECT_RECEIVED, dObj, peerNode)); peerNode = NULL; // MOS - similar to peerIface return PROT_EVENT_SUCCESS; }