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; } } } }
void dtn2_findRule(char *nodeNm, char *demux, Dtn2Plan *plan, Object *ruleAddr, Object *eltp) { Sdr sdr = getIonsdr(); char nodeName[SDRSTRING_BUFSZ]; Object elt; OBJ_POINTER(Dtn2Plan, planPtr); /* This function finds the Dtn2Rule for the specified * demux token, for the specified destination node, if * any. */ CHKVOID(ionLocked()); CHKVOID(ruleAddr); CHKVOID(eltp); *eltp = 0; if (plan == NULL) { if (nodeNm == NULL) { return; } if (filterNodeName(nodeName, nodeNm) < 0) { return; } elt = locatePlan(nodeName, NULL); if (elt == 0) { return; } GET_OBJ_POINTER(sdr, Dtn2Plan, planPtr, sdr_list_data(sdr, elt)); plan = planPtr; } elt = locateRule(plan, demux, NULL); if (elt == 0) { return; } *ruleAddr = sdr_list_data(sdr, elt); *eltp = elt; }
void dtn2_findPlan(char *nodeNm, Object *planAddr, Object *eltp) { Sdr sdr = getIonsdr(); char nodeName[SDRSTRING_BUFSZ]; Object elt; /* This function finds the Dtn2Plan for the specified * node, if any. */ CHKVOID(ionLocked()); CHKVOID(nodeNm && planAddr && eltp); *eltp = 0; if (filterNodeName(nodeName, nodeNm) < 0) { return; } elt = locatePlan(nodeName, NULL); if (elt == 0) { return; } *planAddr = sdr_list_data(sdr, elt); *eltp = elt; }
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; }
static int loadContact(Object elt) { Sdr sdr = getIonsdr(); Object obj; IonContact contact; IonCXref cxref; obj = sdr_list_data(sdr, elt); sdr_read(sdr, (char *) &contact, obj, sizeof(IonContact)); /* Load contact index entry. */ cxref.fromNode = contact.fromNode; cxref.toNode = contact.toNode; cxref.fromTime = contact.fromTime; cxref.toTime = contact.toTime; cxref.xmitRate = contact.xmitRate; cxref.prob = contact.prob; cxref.contactElt = elt; cxref.routingObject = 0; if (insertCXref(&cxref) == 0) { return -1; } return 0; }
static int loadRange(Object elt) { Sdr sdr = getIonsdr(); Object obj; IonRange range; IonRXref rxref; obj = sdr_list_data(sdr, elt); sdr_read(sdr, (char *) &range, obj, sizeof(IonRange)); /* Load range list entry. */ rxref.fromNode = range.fromNode; rxref.toNode = range.toNode; rxref.fromTime = range.fromTime; rxref.toTime = range.toTime; rxref.owlt = range.owlt; rxref.rangeElt = elt; if (insertRXref(&rxref) < 0) { return -1; } return 0; }
int dtn2_updateRule(char *nodeNm, char *demux, FwdDirective *directive) { Sdr sdr = getIonsdr(); char nodeName[SDRSTRING_BUFSZ]; Object elt; OBJ_POINTER(Dtn2Plan, plan); Object ruleAddr; Dtn2Rule ruleBuf; CHKERR(nodeNm && demux && directive); 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 update the rule. */ sdr_stage(sdr, (char *) &ruleBuf, ruleAddr, sizeof(Dtn2Rule)); dtn2_destroyDirective(&ruleBuf.directive); memcpy((char *) &ruleBuf.directive, (char *) directive, sizeof(FwdDirective)); sdr_write(sdr, ruleAddr, (char *) &ruleBuf, sizeof(Dtn2Rule)); if (sdr_end_xn(sdr) < 0) { putErrmsg("Can't update rule.", NULL); return -1; } return 1; }
void ionProd(unsigned long fromNode, unsigned long toNode, unsigned long xmitRate, unsigned int owlt) { Sdr ionsdr = _ionsdr(NULL); time_t fromTime; time_t toTime; Object elt; char textbuf[RFX_NOTE_LEN]; if (ionsdr == NULL) { if (ionAttach() < 0) { writeMemo("[?] ionProd: node not initialized yet."); return; } } fromTime = getUTCTime(); /* The current time. */ toTime = fromTime + 14400; /* Four hours later. */ elt = rfx_insert_range(fromTime, toTime, fromNode, toNode, owlt); if (elt == 0) { writeMemoNote("[?] ionProd: range insertion failed.", utoa(owlt)); return; } writeMemo("ionProd: range inserted."); writeMemo(rfx_print_range(sdr_list_data(ionsdr, elt), textbuf)); elt = rfx_insert_contact(fromTime, toTime, fromNode, toNode, xmitRate); if (elt == 0) { writeMemoNote("[?] ionProd: contact insertion failed.", utoa(xmitRate)); return; } writeMemo("ionProd: contact inserted."); writeMemo(rfx_print_contact(sdr_list_data(ionsdr, elt), textbuf)); }
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; }
void ltpei_destroy_extension(Sdr sdr, Object elt, void *arg) { Object addr; LtpExtensionOutbound ext; addr = sdr_list_data(sdr, elt); sdr_read(sdr, (char *) &ext, addr, sizeof(LtpExtensionOutbound)); if (ext.value) { sdr_free(sdr, ext.value); } sdr_free(sdr, addr); }
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); }
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); }
int dtn2_updatePlan(char *nodeNm, FwdDirective *defaultDir) { Sdr sdr = getIonsdr(); char nodeName[SDRSTRING_BUFSZ]; Object elt; Object planObj; Dtn2Plan plan; CHKERR(nodeNm && defaultDir); 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; } /* Okay to update this plan. */ planObj = sdr_list_data(sdr, elt); sdr_stage(sdr, (char *) &plan, planObj, sizeof(Dtn2Plan)); dtn2_destroyDirective(&plan.defaultDirective); memcpy((char *) &plan.defaultDirective, (char *) defaultDir, sizeof(FwdDirective)); sdr_write(sdr, planObj, (char *) &plan, sizeof(Dtn2Plan)); if (sdr_end_xn(sdr) < 0) { putErrmsg("Can't update plan.", nodeNm); return -1; } return 1; }
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; }
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); }
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 sendAcs(Object signalLElt) { BpExtendedCOS ecos = { 0, 0, 255 }; Object signalAddr; Object acsBundleObj; /* Unused write-out of bpSend */ SdrAcsSignal signal; SdrAcsPendingCust pendingCust; int result; Sdr bpSdr = getIonsdr(); assert(signalLElt != 0); if ((acsSdr = getAcssdr()) == NULL) { putErrmsg("Can't send ACS, SDR not available.", NULL); return -1; } /* To prevent deadlock, we take the BP SDR before the ACS SDR. */ CHKERR(sdr_begin_xn(bpSdr)); CHKERR(sdr_begin_xn(acsSdr)); signalAddr = sdr_list_data(acsSdr, signalLElt); if (signalAddr == 0) { ACSLOG_ERROR("Can't derefence ACS signal to send it."); sdr_cancel_xn(acsSdr); sdr_cancel_xn(bpSdr); return -1; } sdr_peek(acsSdr, signal, signalAddr); sdr_peek(acsSdr, pendingCust, signal.pendingCustAddr); /* Remove ref to this serialized ZCO from signal; also remove the bundle * IDs covered by this serialized ZCO. */ result = bpSend(NULL, pendingCust.eid, NULL, ACS_TTL, BP_EXPEDITED_PRIORITY, NoCustodyRequested, 0, 0, &ecos, signal.serializedZco, &acsBundleObj, BP_CUSTODY_SIGNAL); switch (result) { /* All return codes from bpSend() still cause us to continue processing * to free this ACS. If it was sent successfully, good. If it wasn't, * that's due to a system failure or problem with this ACS, so the best * we can do is delete it from our node without sending. */ case -1: ACSLOG_ERROR("Can't send custody transfer signal."); zco_destroy(bpSdr, signal.serializedZco); break; case 0: ACSLOG_ERROR("Custody transfer signal not transmitted."); zco_destroy(bpSdr, signal.serializedZco); break; default: /* bpSend() gave the serializedZco to a forwarder, so don't * zco_destroy(). */ break; } if (signal.acsDue != 0) { destroyBpTimelineEvent(signal.acsDue); } signal.acsDue = 0; signal.serializedZco = 0; sdr_poke(acsSdr, signalAddr, signal); releaseSdrAcsSignal(signalLElt); if (sdr_end_xn(acsSdr) < 0) { ACSLOG_ERROR("Couldn't mark a serialized ACS as sent."); sdr_cancel_xn(bpSdr); return -1; } if(sdr_end_xn(bpSdr) < 0) { return -1; } return result > 0 ? 0 : -1; }
static void releaseSdrAcsFill(Sdr sdr, Object elt, void *arg) { sdr_free(sdr, sdr_list_data(sdr, elt)); }
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); }
static int manageLinks(Sdr sdr, time_t currentTime) { PsmPartition ionwm = getIonwm(); LtpVdb *ltpvdb = getLtpVdb(); IonVdb *ionvdb = getIonVdb(); PsmAddress elt; LtpVspan *vspan; Object obj; LtpSpan span; IonNeighbor *neighbor; PsmAddress nextElt; unsigned long priorXmitRate; sdr_begin_xn(sdr); for (elt = sm_list_first(ionwm, ltpvdb->spans); elt; elt = sm_list_next(ionwm, elt)) { vspan = (LtpVspan *) psp(ionwm, sm_list_data(ionwm, elt)); /* Finish aggregation as necessary. */ obj = sdr_list_data(sdr, vspan->spanElt); sdr_stage(sdr, (char *) &span, obj, sizeof(LtpSpan)); if (span.lengthOfBufferedBlock > 0) { span.ageOfBufferedBlock++; sdr_write(sdr, obj, (char *) &span, sizeof(LtpSpan)); if (span.ageOfBufferedBlock >= span.aggrTimeLimit) { sm_SemGive(vspan->bufFullSemaphore); } } /* Find Neighbor object encapsulating the current * known state of this LTP engine. */ neighbor = findNeighbor(ionvdb, vspan->engineId, &nextElt); if (neighbor == NULL) { neighbor = addNeighbor(ionvdb, vspan->engineId, nextElt); if (neighbor == NULL) { putErrmsg("Can't update span.", NULL); return -1; } } if (neighbor->xmitRate == 0) { if (vspan->localXmitRate > 0) { vspan->localXmitRate = 0; ltpStopXmit(vspan); } } else { if (vspan->localXmitRate == 0) { vspan->localXmitRate = neighbor->xmitRate; ltpStartXmit(vspan); } } if (neighbor->fireRate == 0) { if (vspan->remoteXmitRate > 0) { priorXmitRate = vspan->remoteXmitRate; vspan->remoteXmitRate = 0; if (ltpSuspendTimers(vspan, elt, currentTime, priorXmitRate)) { putErrmsg("Can't manage links.", NULL); return -1; } } } else { if (vspan->remoteXmitRate == 0) { vspan->remoteXmitRate = neighbor->fireRate; if (ltpResumeTimers(vspan, elt, currentTime, vspan->remoteXmitRate)) { putErrmsg("Can't manage links.", NULL); return -1; } } } if (neighbor->recvRate == 0) { vspan->receptionRate = 0; } else { vspan->receptionRate = neighbor->recvRate; } if (neighbor->owltInbound != vspan->owltInbound) { vspan->owltInbound = neighbor->owltInbound; } if (neighbor->owltOutbound != vspan->owltOutbound) { vspan->owltOutbound = neighbor->owltOutbound; } } if (sdr_end_xn(sdr) < 0) { putErrmsg("ltpclock failed managing links.", 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; } } }
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; } } }
int dtn2_addRule(char *nodeNm, char *demux, FwdDirective *directive) { Sdr sdr = getIonsdr(); char nodeName[SDRSTRING_BUFSZ]; Object elt; OBJ_POINTER(Dtn2Plan, plan); Object nextRule; Dtn2Rule ruleBuf; Object addr; CHKERR(nodeNm && demux && directive); 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)); if (locateRule(plan, demux, &nextRule) != 0) { sdr_exit_xn(sdr); writeMemoNote("[?] Duplicate rule", demux); return 0; } /* All parameters validated, okay to add the rule. */ memset((char *) &ruleBuf, 0, sizeof(Dtn2Rule)); ruleBuf.demux = sdr_string_create(sdr, demux); memcpy((char *) &ruleBuf.directive, (char *) directive, sizeof(FwdDirective)); addr = sdr_malloc(sdr, sizeof(Dtn2Rule)); if (addr) { if (nextRule) { elt = sdr_list_insert_before(sdr, nextRule, addr); } else { elt = sdr_list_insert_last(sdr, plan->rules, addr); } sdr_write(sdr, addr, (char *) &ruleBuf, sizeof(Dtn2Rule)); } if (sdr_end_xn(sdr) < 0) { putErrmsg("Can't add rule.", NULL); return -1; } 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; }
int tcpclo(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10) { char *ductName = (char *) a1; #else int main(int argc, char *argv[]) { char *ductName = (argc > 1 ? argv[1] : NULL); #endif unsigned char *buffer; VOutduct *vduct; PsmAddress vductElt; Sdr sdr; Outduct duct; ClProtocol protocol; Outflow outflows[3]; int i; char *hostName; unsigned short portNbr; unsigned int hostNbr; struct sockaddr socketName; struct sockaddr_in *inetName; int running = 1; pthread_mutex_t mutex; KeepaliveThreadParms parms; ReceiveThreadParms rparms; pthread_t keepaliveThread; pthread_t receiverThread; Object bundleZco; BpExtendedCOS extendedCOS; char destDuctName[MAX_CL_DUCT_NAME_LEN + 1]; unsigned int bundleLength; int ductSocket = -1; int bytesSent; int keepalivePeriod = 0; VInduct *viduct; if (ductName == NULL) { PUTS("Usage: tcpclo <remote host name>[:<port number>]"); return 0; } if (bpAttach() < 0) { putErrmsg("tcpclo can't attach to BP", NULL); return 1; } buffer = MTAKE(TCPCLA_BUFSZ); if (buffer == NULL) { putErrmsg("No memory for TCP buffer in tcpclo.", NULL); return 1; } findOutduct("tcp", ductName, &vduct, &vductElt); if (vductElt == 0) { putErrmsg("No such tcp duct.", ductName); MRELEASE(buffer); return 1; } if (vduct->cloPid != ERROR && vduct->cloPid != sm_TaskIdSelf()) { putErrmsg("CLO task is already started for this duct.", itoa(vduct->cloPid)); MRELEASE(buffer); return 1; } /* All command-line arguments are now validated. */ sdr = getIonsdr(); CHKERR(sdr_begin_xn(sdr)); sdr_read(sdr, (char *) &duct, sdr_list_data(sdr, vduct->outductElt), sizeof(Outduct)); sdr_read(sdr, (char *) &protocol, duct.protocol, sizeof(ClProtocol)); sdr_exit_xn(sdr); if (protocol.nominalRate == 0) { vduct->xmitThrottle.nominalRate = DEFAULT_TCP_RATE; } else { vduct->xmitThrottle.nominalRate = protocol.nominalRate; } memset((char *) outflows, 0, sizeof outflows); outflows[0].outboundBundles = duct.bulkQueue; outflows[1].outboundBundles = duct.stdQueue; outflows[2].outboundBundles = duct.urgentQueue; for (i = 0; i < 3; i++) { outflows[i].svcFactor = 1 << i; } hostName = ductName; parseSocketSpec(ductName, &portNbr, &hostNbr); if (portNbr == 0) { portNbr = BpTcpDefaultPortNbr; } portNbr = htons(portNbr); if (hostNbr == 0) { putErrmsg("Can't get IP address for host.", hostName); MRELEASE(buffer); return 1; } hostNbr = htonl(hostNbr); memset((char *) &socketName, 0, sizeof socketName); inetName = (struct sockaddr_in *) &socketName; inetName->sin_family = AF_INET; inetName->sin_port = portNbr; memcpy((char *) &(inetName->sin_addr.s_addr), (char *) &hostNbr, 4); if (_tcpOutductId(&socketName, "tcp", ductName) < 0) { putErrmsg("Can't record TCP Outduct ID for connection.", NULL); MRELEASE(buffer); return -1; } /* Set up signal handling. SIGTERM is shutdown signal. */ oK(tcpcloSemaphore(&(vduct->semaphore))); isignal(SIGTERM, shutDownClo); #ifndef mingw isignal(SIGPIPE, handleConnectionLoss); #endif /* Start the keepalive thread for the eventual connection. */ tcpDesiredKeepAlivePeriod = KEEPALIVE_PERIOD; parms.cloRunning = &running; pthread_mutex_init(&mutex, NULL); parms.mutex = &mutex; parms.socketName = &socketName; parms.ductSocket = &ductSocket; parms.keepalivePeriod = &keepalivePeriod; if (pthread_begin(&keepaliveThread, NULL, sendKeepalives, &parms)) { putSysErrmsg("tcpclo can't create keepalive thread", NULL); MRELEASE(buffer); pthread_mutex_destroy(&mutex); return 1; } // Returns the VInduct Object of first induct with same protocol // as the outduct. The VInduct is required to create an acq area. // The Acq Area inturn uses the throttle information from VInduct // object while receiving bundles. The throttle information // of all inducts of the same induct will be the same, so choosing // any induct will serve the purpose. findVInduct(&viduct,protocol.name); if(viduct == NULL) { putErrmsg("tcpclo can't get VInduct", NULL); MRELEASE(buffer); pthread_mutex_destroy(&mutex); return 1; } rparms.vduct = viduct; rparms.bundleSocket = &ductSocket; rparms.mutex = &mutex; rparms.cloRunning = &running; if (pthread_begin(&receiverThread, NULL, receiveBundles, &rparms)) { putSysErrmsg("tcpclo can't create receive thread", NULL); MRELEASE(buffer); pthread_mutex_destroy(&mutex); return 1; } /* Can now begin transmitting to remote duct. */ { char txt[500]; isprintf(txt, sizeof(txt), "[i] tcpclo is running, spec=[%s:%d].", inet_ntoa(inetName->sin_addr), ntohs(inetName->sin_port)); writeMemo(txt); } while (running && !(sm_SemEnded(tcpcloSemaphore(NULL)))) { if (bpDequeue(vduct, outflows, &bundleZco, &extendedCOS, destDuctName, 0, -1) < 0) { running = 0; /* Terminate CLO. */ continue; } if (bundleZco == 0) /* Interrupted. */ { continue; } CHKZERO(sdr_begin_xn(sdr)); bundleLength = zco_length(sdr, bundleZco); sdr_exit_xn(sdr); pthread_mutex_lock(&mutex); bytesSent = sendBundleByTCPCL(&socketName, &ductSocket, bundleLength, bundleZco, buffer, &keepalivePeriod); pthread_mutex_unlock(&mutex); if(bytesSent < 0) { running = 0; /* Terminate CLO. */ } /* Make sure other tasks have a chance to run. */ sm_TaskYield(); } writeMemo("[i] tcpclo done sending"); if (sendShutDownMessage(&ductSocket, SHUT_DN_NO, -1, &socketName) < 0) { putErrmsg("Sending Shutdown message failed!!",NULL); } if (ductSocket != -1) { closesocket(ductSocket); ductSocket=-1; } running = 0; pthread_join(keepaliveThread, NULL); writeMemo("[i] tcpclo keepalive thread killed"); pthread_join(receiverThread, NULL); writeMemo("[i] tcpclo receiver thread killed"); writeErrmsgMemos(); writeMemo("[i] tcpclo duct has ended."); oK(_tcpOutductId(&socketName, NULL, NULL)); MRELEASE(buffer); pthread_mutex_destroy(&mutex); bp_detach(); return 0; }
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; }