static int scanInFdus(Sdr sdr, time_t currentTime) { CfdpDB *cfdpConstants; Object entityElt; OBJ_POINTER(Entity, entity); Object elt; Object nextElt; Object fduObj; OBJ_POINTER(InFdu, fdu); CfdpHandler handler; cfdpConstants = getCfdpConstants(); sdr_begin_xn(sdr); for (entityElt = sdr_list_first(sdr, cfdpConstants->entities); entityElt; entityElt = sdr_list_next(sdr, entityElt)) { GET_OBJ_POINTER(sdr, Entity, entity, sdr_list_data(sdr, entityElt)); for (elt = sdr_list_first(sdr, entity->inboundFdus); elt; elt = nextElt) { nextElt = sdr_list_next(sdr, elt); fduObj = sdr_list_data(sdr, elt); GET_OBJ_POINTER(sdr, InFdu, fdu, fduObj); if (fdu->eofReceived && fdu->checkTime < currentTime) { sdr_stage(sdr, NULL, fduObj, 0); fdu->checkTimeouts++; fdu->checkTime += cfdpConstants->checkTimerPeriod; sdr_write(sdr, fduObj, (char *) fdu, sizeof(InFdu)); } if (fdu->checkTimeouts > cfdpConstants->checkTimeoutLimit) { if (handleFault(&(fdu->transactionId), CfdpCheckLimitReached, &handler) < 0) { sdr_cancel_xn(sdr); putErrmsg("Can't handle check limit \ reached.", NULL); return -1; } } } }
static int reforwardStrandedBundles() { Sdr sdr = getIonsdr(); BpDB *bpConstants = getBpConstants(); Object elt; Object nextElt; CHKERR(sdr_begin_xn(sdr)); for (elt = sdr_list_first(sdr, bpConstants->limboQueue); elt; elt = nextElt) { nextElt = sdr_list_next(sdr, elt); if (releaseFromLimbo(elt, 0) < 0) { putErrmsg("Failed releasing bundle from limbo.", NULL); sdr_cancel_xn(sdr); return -1; } } if (sdr_end_xn(sdr) < 0) { putErrmsg("brss failed limbo release on client connect.", NULL); return -1; } return 0; }
Object findSdrAcsSignal(Object acsSignals, BpCtReason reasonCode, unsigned char succeeded, Object *signalAddrPtr) { SdrAcsSignal signal; Object acsSignalLElt; Object acsSignalAddr; signal.reasonCode = reasonCode; signal.succeeded = succeeded; ASSERT_ACSSDR_XN; /* Get the first element of the list. */ acsSignalLElt = sdr_list_first(acsSdr, acsSignals); if (acsSignalLElt == 0) { ACSLOG_INFO("Couldn't find ACS signal (%s, %d)", succeeded ? "success" : "fail", reasonCode); return 0; } acsSignalLElt = sdr_list_search(acsSdr, acsSignalLElt, 0, cmpSdrAcsSignals, &signal); if(acsSignalLElt == 0) { ACSLOG_INFO("Couldn't find ACS signal (%s, %d)", succeeded ? "success" : "fail", reasonCode); return 0; } acsSignalAddr = sdr_list_data(acsSdr, acsSignalLElt); if(signalAddrPtr) *signalAddrPtr = acsSignalAddr; return acsSignalLElt; }
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; }
Object findCustodianByEid(Object custodians, const char *eid) { Object pendingCustLElt; acsSdr = getAcssdr(); /* Get the first element of the list. */ pendingCustLElt = sdr_list_first(acsSdr, custodians); if (pendingCustLElt == 0) { return 0; } pendingCustLElt = sdr_list_search(acsSdr, pendingCustLElt, 0, cmpSdrAcsPendingCust, (void *)(eid)); if(pendingCustLElt == 0) { return 0; } return sdr_list_data(acsSdr, pendingCustLElt); }
void listCustodianInfo(void (*printer)(const char *)) { Object custodianLElt; Object custodianAddr; SdrAcsPendingCust custodian; char buffer[1024]; CHKVOID(sdr_begin_xn(acsSdr)); for(custodianLElt = sdr_list_first(acsSdr, acsConstants->pendingCusts); custodianLElt; custodianLElt = sdr_list_next(acsSdr, custodianLElt)) { custodianAddr = sdr_list_data(acsSdr, custodianLElt); sdr_peek(acsSdr, custodian, custodianAddr); snprintf(buffer, sizeof(buffer), "%.*s\tDelay: %lu Size: %lu", MAX_EID_LEN, custodian.eid, custodian.acsDelay, custodian.acsSize); printer(buffer); } oK(sdr_end_xn(acsSdr)); }
static Object locateRule(Dtn2Plan *plan, char *demux, Object *nextRule) { Sdr sdr = getIonsdr(); Object elt; OBJ_POINTER(Dtn2Rule, rule); char nameBuffer[SDRSTRING_BUFSZ]; int result; /* This function locates the Dtn2Rule identified by the * specified demux token, for the specified destination * endpoint, if any; must be an exact match. If * none, notes the location within the rules list at * which such a rule should be inserted. */ if (nextRule) *nextRule = 0; /* Default. */ for (elt = sdr_list_first(sdr, plan->rules); elt; elt = sdr_list_next(sdr, elt)) { GET_OBJ_POINTER(sdr, Dtn2Rule, rule, sdr_list_data(sdr, elt)); sdr_string_read(sdr, nameBuffer, rule->demux); result = strcmp(nameBuffer, demux); if (result < 0) { continue; } if (result > 0) { if (nextRule) *nextRule = elt; break; /* Same as end of list. */ } return elt; } return 0; }
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); } }
static Object locatePlan(char *nodeName, Object *nextPlan) { Sdr sdr = getIonsdr(); Object elt; OBJ_POINTER(Dtn2Plan, plan); char nameBuffer[SDRSTRING_BUFSZ]; int result; /* This function locates the Dtn2Plan identified by the * specified node name, if any; must be an exact match. * If none, notes the location within the plans list at * which such a plan should be inserted. */ if (nextPlan) *nextPlan = 0; /* Default. */ for (elt = sdr_list_first(sdr, (_dtn2Constants())->plans); elt; elt = sdr_list_next(sdr, elt)) { GET_OBJ_POINTER(sdr, Dtn2Plan, plan, sdr_list_data(sdr, elt)); sdr_string_read(sdr, nameBuffer, plan->nodeName); result = strcmp(nameBuffer, nodeName); if (result < 0) { continue; } if (result > 0) { if (nextPlan) *nextPlan = elt; break; /* Same as end of list. */ } return elt; } return 0; }
static void executeList(int tokenCount, char **tokens) { Sdr sdr = getIonsdr(); ImcDB imcdb; Object elt; OBJ_POINTER(NodeId, node); if (tokenCount != 1) { SYNTAX_ERROR; return; } CHKVOID(sdr_begin_xn(sdr)); sdr_read(getIonsdr(), (char *) &imcdb, getImcDbObject(), sizeof(ImcDB)); for (elt = sdr_list_first(sdr, imcdb.kin); elt; elt = sdr_list_next(sdr, elt)) { GET_OBJ_POINTER(sdr, NodeId, node, sdr_list_data(sdr, elt)); printKin(node->nbr, imcdb.parent); } sdr_exit_xn(sdr); }
static int enqueueBundle(Bundle *bundle, Object bundleObj) { Sdr sdr = getIonsdr(); Object elt; char eidString[SDRSTRING_BUFSZ]; MetaEid metaEid; VScheme *vscheme; PsmAddress vschemeElt; char nodeName[SDRSTRING_BUFSZ]; char demux[SDRSTRING_BUFSZ]; int result; FwdDirective directive; elt = sdr_list_first(sdr, bundle->stations); if (elt == 0) { putErrmsg("Forwarding error; stations stack is empty.", NULL); return -1; } sdr_string_read(sdr, eidString, sdr_list_data(sdr, elt)); if (parseEidString(eidString, &metaEid, &vscheme, &vschemeElt) == 0) { putErrmsg("Can't parse node EID string.", eidString); return bpAbandon(bundleObj, bundle, BP_REASON_NO_ROUTE); } if (strcmp(vscheme->name, "dtn") != 0) { putErrmsg("Forwarding error; EID scheme wrong for dtn2fw.", vscheme->name); return -1; } result = parseDtn2Nss(metaEid.nss, nodeName, demux); restoreEidString(&metaEid); if (result == 0) { putErrmsg("Invalid nss in EID string, cannot forward.", eidString); return bpAbandon(bundleObj, bundle, BP_REASON_NO_ROUTE); } if (dtn2_lookupDirective(nodeName, demux, bundle, &directive) == 0) { putErrmsg("Can't find forwarding directive for EID.", eidString); return bpAbandon(bundleObj, bundle, BP_REASON_NO_ROUTE); } if (directive.action == xmit) { if (bpEnqueue(&directive, bundle, bundleObj, eidString) < 0) { putErrmsg("Can't enqueue bundle.", NULL); return -1; } if (bundle->ductXmitElt) { /* Enqueued. */ return bpAccept(bundleObj, bundle); } else { return bpAbandon(bundleObj, bundle, BP_REASON_NO_ROUTE); } } /* Can't transmit to indicated next node directly, must * forward through some other node. */ sdr_write(sdr, bundleObj, (char *) &bundle, sizeof(Bundle)); sdr_string_read(sdr, eidString, directive.eid); return forwardBundle(bundleObj, bundle, eidString); }
int dtn2_lookupDirective(char *nodeName, char *demux, Bundle *bundle, FwdDirective *dirbuf) { Sdr sdr = getIonsdr(); int protClassReqd; Object elt; Object addr; OBJ_POINTER(Dtn2Plan, plan); int stringLen; char stringBuffer[SDRSTRING_BUFSZ]; int result; int last; OBJ_POINTER(Dtn2Rule, rule); /* This function determines the relevant FwdDirective for * the specified eid, if any. Wild card match is okay. */ CHKERR(ionLocked()); CHKERR(nodeName && demux && dirbuf); /* Determine constraints on directive usability. */ protClassReqd = bundle->extendedCOS.flags & BP_PROTOCOL_BOTH; if (protClassReqd == 0) /* Don't care. */ { protClassReqd = -1; /* Matches any. */ } else if (protClassReqd == 10) /* Need BSS. */ { protClassReqd = BP_PROTOCOL_STREAMING; } /* Find best matching plan. Universal wild-card match, * if any, is at the end of the list, so there's no way * to terminate the search early. */ for (elt = sdr_list_first(sdr, (_dtn2Constants())->plans); elt; elt = sdr_list_next(sdr, elt)) { addr = sdr_list_data(sdr, elt); GET_OBJ_POINTER(sdr, Dtn2Plan, plan, addr); stringLen = sdr_string_read(sdr, stringBuffer, plan->nodeName); result = strcmp(stringBuffer, nodeName); if (result < 0) { continue; } if (result == 0) /* Exact match. */ { break; /* Stop searching. */ } /* Node name in plan is greater than node name, * but it might still be a wild-card match. */ last = stringLen - 1; if (stringBuffer[last] == '~' /* "all nodes" */ && strncmp(stringBuffer, nodeName, stringLen - 1) == 0) { break; /* Stop searching. */ } } if (elt == 0) { return 0; /* No plan found. */ } /* Find best matching rule. */ for (elt = sdr_list_first(sdr, plan->rules); elt; elt = sdr_list_next(sdr, elt)) { addr = sdr_list_data(sdr, elt); GET_OBJ_POINTER(sdr, Dtn2Rule, rule, addr); if ((rule->directive.protocolClass & protClassReqd) == 0) { continue; /* Can't use this rule. */ } stringLen = sdr_string_read(sdr, stringBuffer, rule->demux); result = strcmp(stringBuffer, demux); if (result < 0) { continue; } if (result == 0) /* Exact match. */ { break; /* Stop searching. */ } /* Demux in rule is greater than demux, but it * might still be a wild-card match. */ last = stringLen - 1; if (stringBuffer[last] == '~' /* "all demuxes" */ && strncmp(stringBuffer, demux, stringLen - 1) == 0) { break; /* Stop searching. */ } } if (elt == 0) /* End of list. */ { if ((plan->defaultDirective.protocolClass & protClassReqd) == 0) { return 0; /* Matching plan unusable. */ } memcpy((char *) dirbuf, (char *) &plan->defaultDirective, sizeof(FwdDirective)); return 1; } /* Found a matching rule. */ memcpy((char *) dirbuf, (char *) &rule->directive, sizeof(FwdDirective)); return 1; }
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 enqueueBundle(Bundle *bundle, Object bundleObj) { Sdr sdr = getIonsdr(); Object elt; char eidString[SDRSTRING_BUFSZ]; MetaEid metaEid; VScheme *vscheme; PsmAddress vschemeElt; FwdDirective directive; elt = sdr_list_first(sdr, bundle->stations); if (elt == 0) { putErrmsg("Forwarding error; stations stack is empty.", NULL); return -1; } sdr_string_read(sdr, eidString, sdr_list_data(sdr, elt)); if (parseEidString(eidString, &metaEid, &vscheme, &vschemeElt) == 0) { putErrmsg("Can't parse node EID string.", eidString); return bpAbandon(bundleObj, bundle); } if (strcmp(vscheme->name, "ipn") != 0) { putErrmsg("Forwarding error; EID scheme is not 'ipn'.", vscheme->name); return -1; } if (cgr_forward(bundle, bundleObj, metaEid.nodeNbr, (getIpnConstants())->plans) < 0) { putErrmsg("CGR failed.", NULL); return -1; } /* If dynamic routing succeeded in enqueuing the bundle * to a neighbor, accept the bundle and return. */ if (sdr_list_length(sdr, bundle->xmitRefs) > 0) { /* Enqueued. */ return bpAccept(bundle); } /* No luck using the contact graph to compute a route * to the destination node. So see if destination node * is a neighbor; if so, enqueue for direct transmission. */ if (enqueueToNeighbor(bundle, bundleObj, metaEid.nodeNbr, metaEid.serviceNbr) < 0) { putErrmsg("Can't send bundle to neighbor.", NULL); return -1; } if (sdr_list_length(sdr, bundle->xmitRefs) > 0) { /* Enqueued. */ return bpAccept(bundle); } /* Destination isn't a neighbor either. So look for the * narrowest applicable static route (node range, i.e., * "group") and forward to the prescribed "via" endpoint * for that group. */ if (ipn_lookupGroupDirective(metaEid.nodeNbr, bundle->id.source.c.serviceNbr, bundle->id.source.c.nodeNbr, &directive) == 0) { return bpAbandon(bundleObj, bundle); } /* Found directive; forward via the indicated endpoint. */ sdr_string_read(sdr, eidString, directive.eid); return forwardBundle(bundleObj, bundle, eidString); }
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 int reforwardStrandedBundles(int nodeNbr) { Sdr sdr = getIonsdr(); BpDB *bpConstants = getBpConstants(); Object elt; Object eventObj; OBJ_POINTER(BpEvent, event); OBJ_POINTER(Bundle, bundle); sdr_begin_xn(sdr); for (elt = sdr_list_first(sdr, bpConstants->timeline); elt; elt = sdr_list_next(sdr, elt)) { eventObj = sdr_list_data(sdr, elt); GET_OBJ_POINTER(sdr, BpEvent, event, eventObj); if (event->type != expiredTTL) { continue; } /* Have got a bundle that still exists. */ GET_OBJ_POINTER(sdr, Bundle, bundle, event->ref); if (bundle->dlvQueueElt || bundle->fragmentElt || bundle->fwdQueueElt || bundle->overdueElt || bundle->ctDueElt || bundle->xmitsNeeded > 0) { /* No need to reforward. */ continue; } /* A stranded bundle, awaiting custody acceptance. * Might be for a neighbor other than the one * that just reconnected, but in that case the * bundle will be reforwarded and requeued and * go into the bit bucket again; no harm. Note, * though, that this means that a BRS server * would be a bad candidate for gateway into a * space subnet: due to long OWLTs, there might * be a lot of bundles sent via LTP that are * awaiting custody acceptance, so reconnection * of a BRS client might trigger retransmission * of a lot of bundles on the space link in * addition to the ones to be issued via brss. */ if (bpReforwardBundle(event->ref) < 0) { sdr_cancel_xn(sdr); putErrmsg("brss reforward failed.", NULL); return -1; } } if (sdr_end_xn(sdr) < 0) { putErrmsg("brss reforwarding failed.", NULL); return -1; } return 0; }
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 rfx_start() { PsmPartition ionwm = getIonwm(); Sdr sdr = getIonsdr(); IonVdb *vdb = getIonVdb(); Object iondbObj; IonDB iondb; Object elt; iondbObj = getIonDbObject(); CHKERR(sdr_begin_xn(sdr)); /* To lock memory. */ sdr_read(sdr, (char *) &iondb, iondbObj, sizeof(IonDB)); /* Destroy and re-create volatile contact and range * databases. This prevents contact/range duplication * as a result of adds before starting ION. */ sm_rbt_destroy(ionwm, vdb->contactIndex, rfx_erase_data, NULL); sm_rbt_destroy(ionwm, vdb->rangeIndex, rfx_erase_data, NULL); vdb->contactIndex = sm_rbt_create(ionwm); vdb->rangeIndex = sm_rbt_create(ionwm); /* Load range index for all asserted ranges. In so * doing, load the nodes for which ranges are known * and load events for all predicted changes in range. */ for (elt = sdr_list_first(sdr, iondb.ranges); elt; elt = sdr_list_next(sdr, elt)) { if (loadRange(elt) < 0) { putErrmsg("Can't load range.", NULL); sdr_exit_xn(sdr); return -1; } } /* Load contact index for all contacts. In so doing, * load the nodes for which contacts are planned (as * necessary) and load events for all planned changes * in data rate affecting the local node. */ iondbObj = getIonDbObject(); sdr_read(sdr, (char *) &iondb, iondbObj, sizeof(IonDB)); for (elt = sdr_list_first(sdr, iondb.contacts); elt; elt = sdr_list_next(sdr, elt)) { if (loadContact(elt) < 0) { putErrmsg("Can't load contact.", NULL); sdr_exit_xn(sdr); return -1; } } /* Start the rfx clock if necessary. */ /* if (vdb->clockPid == ERROR || sm_TaskExists(vdb->clockPid) == 0) { vdb->clockPid = pseudoshell("rfxclock"); } */ sdr_exit_xn(sdr); /* Unlock memory. */ return 0; }