int dtn2_removeRule(char *nodeNm, char *demux) { Sdr sdr = getIonsdr(); char nodeName[SDRSTRING_BUFSZ]; Object elt; OBJ_POINTER(Dtn2Plan, plan); Object ruleAddr; OBJ_POINTER(Dtn2Rule, rule); CHKERR(nodeNm && demux); if (*demux == '\0') { writeMemo("[?] Zero-length DTN2 rule demux."); return 0; } if (filterNodeName(nodeName, nodeNm) < 0) { return 0; } CHKERR(sdr_begin_xn(sdr)); elt = locatePlan(nodeName, NULL); if (elt == 0) { sdr_exit_xn(sdr); writeMemoNote("[?] No plan defined for this node", nodeNm); return 0; } GET_OBJ_POINTER(sdr, Dtn2Plan, plan, sdr_list_data(sdr, elt)); dtn2_findRule(nodeName, demux, plan, &ruleAddr, &elt); if (elt == 0) { sdr_exit_xn(sdr); writeMemoNote("[?] Unknown rule", demux); return 0; } /* All parameters validated, okay to remove the rule. */ GET_OBJ_POINTER(sdr, Dtn2Rule, rule, ruleAddr); dtn2_destroyDirective(&(rule->directive)); sdr_free(sdr, ruleAddr); sdr_list_delete(sdr, elt, NULL, NULL); if (sdr_end_xn(sdr) < 0) { putErrmsg("Can't remove rule.", NULL); return -1; } return 1; }
int dtn2_removePlan(char *nodeNm) { Sdr sdr = getIonsdr(); char nodeName[SDRSTRING_BUFSZ]; Object elt; Object planObj; OBJ_POINTER(Dtn2Plan, plan); CHKERR(nodeNm); if (filterNodeName(nodeName, nodeNm) < 0) { return 0; } CHKERR(sdr_begin_xn(sdr)); elt = locatePlan(nodeName, NULL); if (elt == 0) { sdr_exit_xn(sdr); writeMemoNote("[?] Unknown plan", nodeNm); return 0; } planObj = sdr_list_data(sdr, elt); GET_OBJ_POINTER(sdr, Dtn2Plan, plan, planObj); if (sdr_list_length(sdr, plan->rules) > 0) { sdr_exit_xn(sdr); writeMemoNote("[?] Can't remove plan; still has rules", nodeNm); return 0; } /* Okay to remove this plan from the database. */ sdr_list_delete(sdr, elt, NULL, NULL); dtn2_destroyDirective(&(plan->defaultDirective)); sdr_list_destroy(sdr, plan->rules, NULL, NULL); sdr_free(sdr, plan->nodeName); sdr_free(sdr, planObj); if (sdr_end_xn(sdr) < 0) { putErrmsg("Can't remove plan.", nodeNm); return -1; } return 1; }
int db_forget(Object *primitiveObj, Object *descObj, Object list) { Sdr sdr = getIonsdr(); Object elt; if((primitiveObj == NULL) || (descObj == NULL) || (list == 0)) { AMP_DEBUG_ERR("db_forget","Bad Params.",NULL); return -1; } CHKERR(sdr_begin_xn(sdr)); if(*primitiveObj != 0) { sdr_free(sdr, *primitiveObj); } if(*descObj != 0) { elt = sdr_list_first(sdr, list); while(elt) { if(sdr_list_data(sdr, elt) == *descObj) { sdr_list_delete(sdr, elt, NULL, NULL); sdr_free(sdr, *descObj); elt = 0; } else { elt = sdr_list_next(sdr, elt); } } } sdr_end_xn(sdr); /* Forget now invalid SDR pointers. */ *descObj = 0; *primitiveObj = 0; return 1; }
static void releaseSdrAcsSignal(Object signalLElt) { Sdr bpSdr = getIonsdr(); Sdr acsSdr = getAcssdr(); Object signalAddr; SdrAcsSignal signal; SdrAcsPendingCust pendingCust; assert(signalLElt != 0); ASSERT_ACSSDR_XN; ASSERT_BPSDR_XN; if (acsSdr == NULL) { putErrmsg("Can't release ACS, SDR not available.", NULL); return; } signalAddr = sdr_list_data(acsSdr, signalLElt); if (signalAddr == 0) { ACSLOG_ERROR("Can't derefence ACS signal to release it."); return; } sdr_peek(acsSdr, signal, signalAddr); sdr_peek(acsSdr, pendingCust, signal.pendingCustAddr); /* Destroy the objects this AcsSignal contains */ sdr_list_destroy(acsSdr, signal.acsFills, releaseSdrAcsFill, NULL); if(signal.acsDue != 0) { destroyBpTimelineEvent(signal.acsDue); } if(signal.serializedZco != 0) { zco_destroy(bpSdr, signal.serializedZco); } /* Destroy this AcsSignal */ sdr_free(acsSdr, signalAddr); sdr_list_delete(acsSdr, signalLElt, NULL, NULL); }
void bp_untrack(Object bundleObj, Object trackingElt) { Sdr sdr = getIonsdr(); OBJ_POINTER(Bundle, bundle); Object elt; CHKVOID(bundleObj && trackingElt); sdr_begin_xn(sdr); GET_OBJ_POINTER(sdr, Bundle, bundle, bundleObj); if (bundle->trackingElts == 0) { sdr_exit_xn(sdr); return; } for (elt = sdr_list_first(sdr, bundle->trackingElts); elt; elt = sdr_list_next(sdr, elt)) { if (sdr_list_data(sdr, elt) == trackingElt) { break; } } if (elt == 0) /* Not found. */ { sdr_exit_xn(sdr); return; } sdr_list_delete(sdr, elt, NULL, NULL); if (sdr_end_xn(sdr) < 0) { putErrmsg("Failed removing bundle tracking elt.", NULL); } }
int bp_receive(BpSAP sap, BpDelivery *dlvBuffer, int timeoutSeconds) { Sdr sdr = getIonsdr(); VEndpoint *vpoint; OBJ_POINTER(Endpoint, endpoint); Object dlvElt; Object bundleAddr; Bundle bundle; TimerParms timerParms; pthread_t timerThread; int result; char *dictionary; CHKERR(sap && dlvBuffer); if (timeoutSeconds < BP_BLOCKING) { putErrmsg("Illegal timeout interval.", itoa(timeoutSeconds)); return -1; } vpoint = sap->vpoint; sdr_begin_xn(sdr); if (vpoint->appPid != sm_TaskIdSelf()) { sdr_exit_xn(sdr); putErrmsg("Can't receive: not owner of endpoint.", itoa(vpoint->appPid)); return -1; } if (sm_SemEnded(vpoint->semaphore)) { sdr_exit_xn(sdr); writeMemo("[?] Endpoint has been stopped."); /* End task, but without error. */ return -1; } /* Get oldest bundle in delivery queue, if any; wait * for one if necessary. */ GET_OBJ_POINTER(sdr, Endpoint, endpoint, sdr_list_data(sdr, vpoint->endpointElt)); dlvElt = sdr_list_first(sdr, endpoint->deliveryQueue); if (dlvElt == 0) { sdr_exit_xn(sdr); if (timeoutSeconds == BP_POLL) { dlvBuffer->result = BpReceptionTimedOut; return 0; } /* Wait for semaphore to be given, either by the * deliverBundle() function or by timer thread. */ if (timeoutSeconds == BP_BLOCKING) { timerParms.interval = -1; } else /* This is a receive() with a deadline. */ { timerParms.interval = timeoutSeconds; timerParms.semaphore = vpoint->semaphore; if (pthread_create(&timerThread, NULL, timerMain, &timerParms) < 0) { putSysErrmsg("Can't enable interval timer", NULL); return -1; } } /* Take endpoint semaphore. */ if (sm_SemTake(vpoint->semaphore) < 0) { putErrmsg("Can't take endpoint semaphore.", NULL); return -1; } if (sm_SemEnded(vpoint->semaphore)) { writeMemo("[i] Endpoint has been stopped."); /* End task, but without error. */ return -1; } /* Have taken the semaphore, one way or another. */ sdr_begin_xn(sdr); dlvElt = sdr_list_first(sdr, endpoint->deliveryQueue); if (dlvElt == 0) /* Still nothing. */ { /* Either sm_SemTake() was interrupted * or else timer thread gave semaphore. */ sdr_exit_xn(sdr); if (timerParms.interval == 0) { /* Timer expired. */ dlvBuffer->result = BpReceptionTimedOut; pthread_join(timerThread, NULL); } else /* Interrupted. */ { dlvBuffer->result = BpReceptionInterrupted; if (timerParms.interval != -1) { pthread_cancel(timerThread); pthread_join(timerThread, NULL); } } return 0; } else /* Bundle was delivered. */ { if (timerParms.interval != -1) { pthread_cancel(timerThread); pthread_join(timerThread, NULL); } } } /* At this point, we have got a dlvElt and are in an SDR * transaction. */ bundleAddr = sdr_list_data(sdr, dlvElt); sdr_stage(sdr, (char *) &bundle, bundleAddr, sizeof(Bundle)); dictionary = retrieveDictionary(&bundle); if (dictionary == (char *) &bundle) { sdr_cancel_xn(sdr); putErrmsg("Can't retrieve dictionary.", NULL); return -1; } /* Now fill in the data indication structure. */ dlvBuffer->result = BpPayloadPresent; if (printEid(&bundle.id.source, dictionary, &dlvBuffer->bundleSourceEid) < 0) { sdr_cancel_xn(sdr); putErrmsg("Can't print source EID.", NULL); return -1; } dlvBuffer->bundleCreationTime.seconds = bundle.id.creationTime.seconds; dlvBuffer->bundleCreationTime.count = bundle.id.creationTime.count; dlvBuffer->adminRecord = bundle.bundleProcFlags & BDL_IS_ADMIN; dlvBuffer->adu = zco_add_reference(sdr, bundle.payload.content); dlvBuffer->ackRequested = bundle.bundleProcFlags & BDL_APP_ACK_REQUEST; /* Now before returning we send delivery status report * if it is requested. */ if (SRR_FLAGS(bundle.bundleProcFlags) & BP_DELIVERED_RPT) { bundle.statusRpt.flags |= BP_DELIVERED_RPT; getCurrentDtnTime(&bundle.statusRpt.deliveryTime); } if (bundle.statusRpt.flags) { result = sendStatusRpt(&bundle, dictionary); if (result < 0) { sdr_cancel_xn(sdr); putErrmsg("Can't send status report.", NULL); return -1; } } /* Finally delete the delivery list element and, if * possible, destroy the bundle itself. */ if (dictionary) { MRELEASE(dictionary); } sdr_list_delete(sdr, dlvElt, (SdrListDeleteFn) NULL, NULL); bundle.dlvQueueElt = 0; sdr_write(sdr, bundleAddr, (char *) &bundle, sizeof(Bundle)); if (bpDestroyBundle(bundleAddr, 0) < 0) { sdr_cancel_xn(sdr); putErrmsg("Can't destroy bundle.", NULL); return -1; } if (sdr_end_xn(sdr) < 0) { putErrmsg("Failure in bundle reception.", NULL); return -1; } return 0; }
static int dispatchEvents(Sdr sdr, Object events, time_t currentTime) { Object elt; Object eventObj; OBJ_POINTER(BpEvent, event); int result; while (1) { sdr_begin_xn(sdr); CHKERR(ionLocked()); /* In case of killm. */ elt = sdr_list_first(sdr, events); if (elt == 0) /* No more events to dispatch. */ { sdr_exit_xn(sdr); return 0; } eventObj = sdr_list_data(sdr, elt); GET_OBJ_POINTER(sdr, BpEvent, event, eventObj); if (event->time > currentTime) { /* This is the first future event. */ sdr_exit_xn(sdr); return 0; } switch (event->type) { case expiredTTL: result = bpDestroyBundle(event->ref, 1); /* Note that bpDestroyBundle() always * erases the bundle's timeline event, * so we must NOT do so here. */ break; /* Out of switch. */ case xmitOverdue: result = bpReforwardBundle(event->ref); /* Note that bpReforwardBundle() always * erases the bundle's xmitOverdue event, * so we must NOT do so here. */ break; /* Out of switch. */ case ctDue: result = bpReforwardBundle(event->ref); /* Note that bpReforwardBundle() always * erases the bundle's ctDue event, so * we must NOT do so here. */ break; /* Out of switch. */ default: /* Spurious event; erase. */ sdr_free(sdr, eventObj); sdr_list_delete(sdr, elt, NULL, NULL); result = 0; /* Event is ignored. */ } if (result != 0) /* Dispatching failed. */ { sdr_cancel_xn(sdr); putErrmsg("Failed handing BP event.", NULL); return result; } if (sdr_end_xn(sdr) < 0) { putErrmsg("Failed dispatching BP event.", NULL); return -1; } } }
static int dispatchEvents(Sdr sdr, Object events, time_t currentTime) { Object elt; Object eventObj; LtpEvent event; int result; while (1) { sdr_begin_xn(sdr); elt = sdr_list_first(sdr, events); if (elt == 0) /* No more events to dispatch. */ { sdr_exit_xn(sdr); return 0; } eventObj = sdr_list_data(sdr, elt); sdr_read(sdr, (char *) &event, eventObj, sizeof(LtpEvent)); if (event.scheduledTime > currentTime) { /* This is the first future event. */ sdr_exit_xn(sdr); return 0; } sdr_free(sdr, eventObj); sdr_list_delete(sdr, elt, NULL, NULL); switch (event.type) { case LtpResendCheckpoint: result = ltpResendCheckpoint(event.refNbr2, event.refNbr3); break; /* Out of switch. */ case LtpResendXmitCancel: result = ltpResendXmitCancel(event.refNbr2); break; /* Out of switch. */ case LtpResendReport: result = ltpResendReport(event.refNbr1, event.refNbr2, event.refNbr3); break; /* Out of switch. */ case LtpResendRecvCancel: result = ltpResendRecvCancel(event.refNbr1, event.refNbr2); break; /* Out of switch. */ default: /* Spurious event. */ result = 0; /* Event is ignored. */ } if (result < 0) /* Dispatching failed. */ { sdr_cancel_xn(sdr); putErrmsg("failed handing LTP event", NULL); return result; } if (sdr_end_xn(sdr) < 0) { putErrmsg("failed dispatching LTP event", NULL); return -1; } } }
int dtn2fw(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10) { #else int main(int argc, char *argv[]) { #endif int running = 1; Sdr sdr; VScheme *vscheme; PsmAddress vschemeElt; Scheme scheme; Object elt; Object bundleAddr; Bundle bundle; if (bpAttach() < 0) { putErrmsg("dtn2fw can't attach to BP.", NULL); return 1; } if (dtn2Init(NULL) < 0) { putErrmsg("dtn2fw can't load routing database.", NULL); return 1; } sdr = getIonsdr(); findScheme("dtn", &vscheme, &vschemeElt); if (vschemeElt == 0) { putErrmsg("Scheme name for dtn2 is unknown.", "dtn"); return 1; } CHKZERO(sdr_begin_xn(sdr)); sdr_read(sdr, (char *) &scheme, sdr_list_data(sdr, vscheme->schemeElt), sizeof(Scheme)); sdr_exit_xn(sdr); oK(_dtn2fwSemaphore(&vscheme->semaphore)); isignal(SIGTERM, shutDown); /* Main loop: wait until forwarding queue is non-empty, * then drain it. */ writeMemo("[i] dtn2fw is running."); while (running && !(sm_SemEnded(vscheme->semaphore))) { /* We wrap forwarding in an SDR transaction to * prevent race condition with bpclock (which * is destroying bundles as their TTLs expire). */ CHKZERO(sdr_begin_xn(sdr)); elt = sdr_list_first(sdr, scheme.forwardQueue); if (elt == 0) /* Wait for forwarding notice. */ { sdr_exit_xn(sdr); if (sm_SemTake(vscheme->semaphore) < 0) { putErrmsg("Can't take forwarder semaphore.", NULL); running = 0; } continue; } bundleAddr = (Object) sdr_list_data(sdr, elt); sdr_stage(sdr, (char *) &bundle, bundleAddr, sizeof(Bundle)); sdr_list_delete(sdr, elt, NULL, NULL); bundle.fwdQueueElt = 0; /* Must rewrite bundle to note removal of * fwdQueueElt, in case the bundle is abandoned * and bpDestroyBundle re-reads it from the * database. */ sdr_write(sdr, bundleAddr, (char *) &bundle, sizeof(Bundle)); if (enqueueBundle(&bundle, bundleAddr) < 0) { sdr_cancel_xn(sdr); putErrmsg("Can't enqueue bundle.", NULL); running = 0; /* Terminate loop. */ continue; } if (sdr_end_xn(sdr) < 0) { putErrmsg("Can't enqueue bundle.", NULL); running = 0; /* Terminate loop. */ } /* Make sure other tasks have a chance to run. */ sm_TaskYield(); } writeErrmsgMemos(); writeMemo("[i] dtn2fw forwarder has ended."); ionDetach(); return 0; }
static void deleteContact(PsmAddress cxaddr) { Sdr sdr = getIonsdr(); PsmPartition ionwm = getIonwm(); IonVdb *vdb = getIonVdb(); time_t currentTime = getUTCTime(); IonCXref *cxref; Object obj; IonEvent event; IonNeighbor *neighbor; PsmAddress nextElt; cxref = (IonCXref *) psp(ionwm, cxaddr); /* Delete contact events from timeline. */ event.ref = cxaddr; if (cxref->startXmit) { event.time = cxref->startXmit; event.type = IonStartXmit; sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &event, rfx_erase_data, NULL); } if (cxref->stopXmit) { event.time = cxref->stopXmit; event.type = IonStopXmit; sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &event, rfx_erase_data, NULL); } if (cxref->startFire) { event.time = cxref->startFire; event.type = IonStartFire; sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &event, rfx_erase_data, NULL); } if (cxref->stopFire) { event.time = cxref->stopFire; event.type = IonStopFire; sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &event, rfx_erase_data, NULL); } if (cxref->startRecv) { event.time = cxref->startRecv; event.type = IonStartRecv; sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &event, rfx_erase_data, NULL); } if (cxref->stopRecv) { event.time = cxref->stopRecv; event.type = IonStopRecv; sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &event, rfx_erase_data, NULL); } if (cxref->purgeTime) { event.time = cxref->purgeTime; event.type = IonPurgeContact; sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &event, rfx_erase_data, NULL); } /* Apply to current state as necessary. */ if (currentTime >= cxref->startXmit && currentTime <= cxref->stopXmit) { neighbor = findNeighbor(vdb, cxref->toNode, &nextElt); if (neighbor) { neighbor->xmitRate = 0; } } if (currentTime >= cxref->startFire && currentTime <= cxref->stopFire) { neighbor = findNeighbor(vdb, cxref->fromNode, &nextElt); if (neighbor) { neighbor->fireRate = 0; } } if (currentTime >= cxref->startRecv && currentTime <= cxref->stopRecv) { neighbor = findNeighbor(vdb, cxref->fromNode, &nextElt); if (neighbor) { neighbor->recvRate = 0; } } /* Delete contact from index. */ if (cxref->toTime > currentTime) /* Affects routes. */ { vdb->lastEditTime = currentTime; } sm_rbt_delete(ionwm, vdb->contactIndex, rfx_order_contacts, cxref, rfx_erase_data, NULL); /* Delete contact from non-volatile database. */ obj = sdr_list_data(sdr, cxref->contactElt); sdr_list_delete(sdr, cxref->contactElt, NULL, NULL); sdr_free(sdr, obj); }
static void deleteRange(PsmAddress rxaddr, int conditional) { Sdr sdr = getIonsdr(); PsmPartition ionwm = getIonwm(); IonVdb *vdb = getIonVdb(); time_t currentTime = getUTCTime(); IonRXref *rxref; Object obj; IonEvent event; IonNeighbor *neighbor; PsmAddress nextElt; rxref = (IonRXref *) psp(ionwm, rxaddr); /* Delete range from non-volatile database. */ if (rxref->rangeElt) /* An asserted range. */ { if (conditional) /* Delete only if imputed. */ { return; /* Retain asserted range. */ } /* Unconditional deletion; remove range from DB. */ obj = sdr_list_data(sdr, rxref->rangeElt); sdr_free(sdr, obj); sdr_list_delete(sdr, rxref->rangeElt, NULL, NULL); } /* Delete range events from timeline. */ event.ref = rxaddr; event.time = rxref->fromTime; if (rxref->rangeElt) { event.type = IonStartAssertedRange; } else { event.type = IonStartImputedRange; } sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &event, rfx_erase_data, NULL); event.time = rxref->toTime; if (rxref->rangeElt) { event.type = IonStopAssertedRange; } else { event.type = IonStopImputedRange; } sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &event, rfx_erase_data, NULL); /* Apply to current state as necessary. */ if (currentTime >= rxref->fromTime && currentTime <= rxref->toTime) { if (rxref->fromNode == getOwnNodeNbr()) { neighbor = findNeighbor(vdb, rxref->toNode, &nextElt); if (neighbor) { neighbor->owltOutbound = 0; } } if (rxref->toNode == getOwnNodeNbr()) { neighbor = findNeighbor(vdb, rxref->fromNode, &nextElt); if (neighbor) { neighbor->owltInbound = 0; } } } /* Delete range from index. */ if (rxref->toTime > currentTime) /* Affects routes. */ { vdb->lastEditTime = currentTime; } sm_rbt_delete(ionwm, vdb->rangeIndex, rfx_order_ranges, rxref, rfx_erase_data, NULL); }