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; }
int dtn2Init() { Sdr sdr = getIonsdr(); Object dtn2dbObject; DtnDB dtn2dbBuf; /* Recover the DTN database, creating it if necessary. */ CHKERR(sdr_begin_xn(sdr)); dtn2dbObject = sdr_find(sdr, DTN_DBNAME, NULL); switch (dtn2dbObject) { case -1: /* SDR error. */ sdr_cancel_xn(sdr); putErrmsg("Failed seeking DTN database in SDR.", NULL); return -1; case 0: /* Not found; must create new DB. */ dtn2dbObject = sdr_malloc(sdr, sizeof(DtnDB)); if (dtn2dbObject == 0) { sdr_cancel_xn(sdr); putErrmsg("No space for DTN database.", NULL); return -1; } memset((char *) &dtn2dbBuf, 0, sizeof(DtnDB)); dtn2dbBuf.plans = sdr_list_create(sdr); sdr_write(sdr, dtn2dbObject, (char *) &dtn2dbBuf, sizeof(DtnDB)); sdr_catlg(sdr, DTN_DBNAME, 0, dtn2dbObject); if (sdr_end_xn(sdr)) { putErrmsg("Can't create DTN database.", NULL); return -1; } break; default: /* Found DB in the SDR. */ sdr_exit_xn(sdr); } oK(_dtn2dbObject(&dtn2dbObject)); oK(_dtn2Constants()); return 0; }
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; } } } }
int bp_cancel(Object bundleObj) { Sdr sdr = getIonsdr(); sdr_begin_xn(sdr); if (bpDestroyBundle(bundleObj, 1) < 0) { sdr_cancel_xn(sdr); putErrmsg("Can't cancel bundle.", NULL); return -1; } if (sdr_end_xn(sdr) < 0) { putErrmsg("Failure in bundle cancellation.", 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; }
int ionInitialize(IonParms *parms, uvast ownNodeNbr) { char wdname[256]; Sdr ionsdr; Object iondbObject; IonDB iondbBuf; vast limit; sm_WmParms ionwmParms; char *ionvdbName = _ionvdbName(); ZcoCallback notify = ionOfferZcoSpace; CHKERR(parms); CHKERR(ownNodeNbr); #ifdef mingw if (_winsock(0) < 0) { return -1; } #endif if (sdr_initialize(0, NULL, SM_NO_KEY, NULL) < 0) { putErrmsg("Can't initialize the SDR system.", NULL); return -1; } if (igetcwd(wdname, 256) == NULL) { putErrmsg("Can't get cwd name.", NULL); return -1; } if (checkNodeListParms(parms, wdname, ownNodeNbr) < 0) { putErrmsg("Failed checking node list parms.", NULL); return -1; } if (sdr_load_profile(parms->sdrName, parms->configFlags, parms->heapWords, parms->heapKey, parms->pathName, "ionrestart") < 0) { putErrmsg("Unable to load SDR profile for ION.", NULL); return -1; } ionsdr = sdr_start_using(parms->sdrName); if (ionsdr == NULL) { putErrmsg("Can't start using SDR for ION.", NULL); return -1; } ionsdr = _ionsdr(&ionsdr); /* Recover the ION database, creating it if necessary. */ CHKERR(sdr_begin_xn(ionsdr)); iondbObject = sdr_find(ionsdr, _iondbName(), NULL); switch (iondbObject) { case -1: /* SDR error. */ sdr_cancel_xn(ionsdr); putErrmsg("Can't seek ION database in SDR.", NULL); return -1; case 0: /* Not found; must create new DB. */ if (ownNodeNbr == 0) { sdr_cancel_xn(ionsdr); putErrmsg("Must supply non-zero node number.", NULL); return -1; } memset((char *) &iondbBuf, 0, sizeof(IonDB)); memcpy(iondbBuf.workingDirectoryName, wdname, 256); iondbBuf.ownNodeNbr = ownNodeNbr; iondbBuf.productionRate = -1; /* Unknown. */ iondbBuf.consumptionRate = -1; /* Unknown. */ limit = (sdr_heap_size(ionsdr) / 100) * (100 - ION_SEQUESTERED); zco_set_max_heap_occupancy(ionsdr, limit); iondbBuf.occupancyCeiling = zco_get_max_file_occupancy(ionsdr); iondbBuf.occupancyCeiling += limit; iondbBuf.contacts = sdr_list_create(ionsdr); iondbBuf.ranges = sdr_list_create(ionsdr); iondbBuf.maxClockError = 0; iondbBuf.clockIsSynchronized = 1; memcpy(&iondbBuf.parmcopy, parms, sizeof(IonParms)); iondbObject = sdr_malloc(ionsdr, sizeof(IonDB)); if (iondbObject == 0) { sdr_cancel_xn(ionsdr); putErrmsg("No space for database.", NULL); return -1; } sdr_write(ionsdr, iondbObject, (char *) &iondbBuf, sizeof(IonDB)); sdr_catlg(ionsdr, _iondbName(), 0, iondbObject); if (sdr_end_xn(ionsdr)) { putErrmsg("Can't create ION database.", NULL); return -1; } break; default: /* Found DB in the SDR. */ sdr_exit_xn(ionsdr); } oK(_iondbObject(&iondbObject)); oK(_ionConstants()); /* Open ION shared-memory partition. */ ionwmParms.wmKey = parms->wmKey; ionwmParms.wmSize = parms->wmSize; ionwmParms.wmAddress = parms->wmAddress; ionwmParms.wmName = ION_SM_NAME; if (_ionwm(&ionwmParms) == NULL) { putErrmsg("ION memory configuration failed.", NULL); return -1; } if (_ionvdb(&ionvdbName) == NULL) { putErrmsg("ION can't initialize vdb.", NULL); return -1; } zco_register_callback(notify); ionRedirectMemos(); #ifdef mingw DWORD threadId; HANDLE thread = CreateThread(NULL, 0, waitForSigterm, NULL, 0, &threadId); if (thread == NULL) { putErrmsg("Can't create sigterm thread.", utoa(GetLastError())); } else { CloseHandle(thread); } #endif return 0; }
int trySendAcs(SdrAcsPendingCust *custodian, BpCtReason reasonCode, unsigned char succeeded, const CtebScratchpad *cteb) { Object signalLElt; Object signalAddr; SdrAcsSignal signal; BpEvent timelineEvent; Object newSerializedZco; unsigned long newSerializedLength; int result; Sdr bpSdr = getIonsdr(); /* To prevent deadlock, take bpSdr before acsSdr. */ CHKERR(sdr_begin_xn(bpSdr)); CHKERR(sdr_begin_xn(acsSdr)); signalLElt = findSdrAcsSignal(custodian->signals, reasonCode, succeeded, &signalAddr); if (signalAddr == 0) { ACSLOG_ERROR("Can't find ACS signal"); sdr_exit_xn(acsSdr); sdr_exit_xn(bpSdr); return -1; } sdr_peek(acsSdr, signal, signalAddr); newSerializedLength = serializeAcs(signalAddr, &newSerializedZco, signal.serializedZcoLength); if (newSerializedLength == 0) { ACSLOG_ERROR("Can't serialize new ACS (%lu)", signal.serializedZcoLength); sdr_cancel_xn(acsSdr); sdr_cancel_xn(bpSdr); return -1; } ACSLOG_DEBUG("Serialized a new ACS to %s that is %lu long (old: %lu)", custodian->eid, newSerializedLength, signal.serializedZcoLength); /* If serializeAcs() (which serializes an ACS that covers all the "old" * custody IDs as well as 1 "new" custody ID that we're trying to append) * returned an ACS that's larger than the custodian' preferred size, then: * 1) Send the old ACS (the biggest ACS that's smaller than custodian's * preferred size), covering all the old custody IDs but not the new * one. * 2) Make a new ACS that includes only the new custody ID. */ if (custodian->acsSize > 0 && newSerializedLength >= custodian->acsSize) { if(signal.serializedZco == 0) { /* We don't have an old unserialized ACS to send. This means the * first custody signal appended to this ACS exceeded the acsSize * parameter. The best we can do is send this ACS even though it's * bigger than the recommended acsSize. */ ACSLOG_WARN("Appending first CS to %s was bigger than %lu", custodian->eid, custodian->acsSize); signal.serializedZcoLength = newSerializedLength; signal.serializedZco = newSerializedZco; sdr_poke(acsSdr, signalAddr, signal); sendAcs(signalLElt); if(sdr_end_xn(acsSdr) < 0) { ACSLOG_ERROR("Can't serialize ACS bundle."); sdr_cancel_xn(bpSdr); return -1; } if (sdr_end_xn(bpSdr) < 0) { ACSLOG_ERROR("Can't send ACS bundle."); return -1; } return 0; } /* Calling this invalidates our signalLElt and signalAddr pointers, so * we must re-find the signal before using them again. */ sendAcs(signalLElt); /* Add the one that was uncovered by the serialized payload back in */ result = appendToSdrAcsSignals(custodian->signals, signal.pendingCustAddr, reasonCode, succeeded, cteb); switch (result) { case 0: /* Success; continue processing. */ break; default: ACSLOG_ERROR("Can't carry size-limited ID to new ACS"); sdr_cancel_xn(acsSdr); sdr_cancel_xn(bpSdr); return -1; } /* Find the uncovered one that we just added. */ signalLElt = findSdrAcsSignal(custodian->signals, reasonCode, succeeded, &signalAddr); if (signalAddr == 0) { ACSLOG_ERROR("Can't find ACS signal"); sdr_cancel_xn(acsSdr); sdr_cancel_xn(bpSdr); return -1; } sdr_peek(acsSdr, signal, signalAddr); /* Serialize the new one */ newSerializedLength = serializeAcs(signalAddr, &newSerializedZco, 0); if (newSerializedLength <= 0) { ACSLOG_ERROR("Can't serialize new ACS (%lu)", newSerializedLength); sdr_cancel_xn(acsSdr); sdr_cancel_xn(bpSdr); return -1; } } else { if (signal.serializedZco != 0) { /* Free the old payload zco. */ zco_destroy(bpSdr, signal.serializedZco); } } /* Store the new ZCO */ signal.serializedZco = newSerializedZco; signal.serializedZcoLength = newSerializedLength; /* If there is not an ACS generation countdown timer, create one. */ if(signal.acsDue == 0) { timelineEvent.type = csDue; if(custodian->acsDelay == 0) { timelineEvent.time = getUTCTime() + DEFAULT_ACS_DELAY; } else { timelineEvent.time = getUTCTime() + custodian->acsDelay; } timelineEvent.ref = signalLElt; signal.acsDue = insertBpTimelineEvent(&timelineEvent); if (signal.acsDue == 0) { ACSLOG_ERROR("Can't add timeline event to generate ACS"); sdr_cancel_xn(acsSdr); sdr_cancel_xn(bpSdr); return -1; } } sdr_poke(acsSdr, signalAddr, signal); if(sdr_end_xn(acsSdr) < 0) { ACSLOG_ERROR("Can't track ACS"); sdr_cancel_xn(bpSdr); return -1; } if (sdr_end_xn(bpSdr) < 0) { ACSLOG_ERROR("Can't add timeline event to generate ACS"); return -1; } 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; }
/* * This function writes an item and its associated descriptor into the SDR, * allocating space for each, and adding the SDR descriptor pointer to a * given SDR list. * * item : The serialized item to store in the SDR. * item_len: The size of the serialized item. * *itemObj: The SDR pointer to the serialized item in the SDR. * desc : The item descriptor being written to the SDR. * desc_len: The size of the item descriptor. * *descObj: The SDR pointer to the item's descriptor object in the SDR. * list : The SDR list holding the item descriptor (at *descrObj). */ int db_persist(uint8_t *item, uint32_t item_len, Object *itemObj, void *desc, uint32_t desc_len, Object *descObj, Object list) { Sdr sdr = getIonsdr(); CHKERR(sdr_begin_xn(sdr)); /* Step 1: Allocate a descriptor object for this item in the SDR. */ if((*descObj = sdr_malloc(sdr, desc_len)) == 0) { sdr_cancel_xn(sdr); AMP_DEBUG_ERR("db_persist", "Can't allocate descriptor of size %d.", desc_len); return -1; } /* Step 2: Allocate space for the serialized rule in the SDR. */ if((*itemObj = sdr_malloc(sdr, item_len)) == 0) { sdr_free(sdr, *descObj); sdr_cancel_xn(sdr); *descObj = 0; AMP_DEBUG_ERR("db_persist", "Unable to allocate Item in SDR. Size %d.", item_len); return -1; } /* Step 3: Write the item to the SDR. */ sdr_write(sdr, *itemObj, (char *) item, item_len); /* Step 4: Write the item descriptor to the SDR. */ sdr_write(sdr, *descObj, (char *) desc, desc_len); /* Step 5: Save the descriptor in the AgentDB active rules list. */ if (sdr_list_insert_last(sdr, list, *descObj) == 0) { sdr_free(sdr, *itemObj); sdr_free(sdr, *descObj); sdr_cancel_xn(sdr); *itemObj = 0; *descObj = 0; AMP_DEBUG_ERR("db_persist", "Unable to insert item Descr. in SDR.", NULL); return -1; } if(sdr_end_xn(sdr)) { AMP_DEBUG_ERR("db_persist", "Can't create Agent database.", NULL); return -1; } return 1; }
PsmAddress rfx_insert_contact(time_t fromTime, time_t toTime, uvast fromNode, uvast toNode, unsigned int xmitRate, float prob) { Sdr sdr = getIonsdr(); PsmPartition ionwm = getIonwm(); IonVdb *vdb = getIonVdb(); IonCXref arg; PsmAddress cxelt; PsmAddress nextElt; PsmAddress cxaddr; IonCXref *cxref; PsmAddress prevElt; char contactIdString[128]; IonContact contact; Object iondbObj; IonDB iondb; Object obj; Object elt; CHKZERO(fromTime); CHKZERO(toTime > fromTime); CHKZERO(fromNode); CHKZERO(toNode); CHKZERO(prob > 0.0 && prob <= 1.0); CHKZERO(sdr_begin_xn(sdr)); /* Make sure contact doesn't overlap with any pre-existing * contacts. */ memset((char *) &arg, 0, sizeof(IonCXref)); arg.fromNode = fromNode; arg.toNode = toNode; arg.fromTime = fromTime; arg.toTime = toTime; arg.xmitRate = xmitRate; arg.routingObject = 0; cxelt = sm_rbt_search(ionwm, vdb->contactIndex, rfx_order_contacts, &arg, &nextElt); //cxelt = 0; if (cxelt) /* Contact is in database already. */ { cxaddr = sm_rbt_data(ionwm, cxelt); cxref = (IonCXref *) psp(ionwm, cxaddr); if (cxref->xmitRate == xmitRate) { sdr_exit_xn(sdr); return cxaddr; } isprintf(contactIdString, sizeof contactIdString, "at %lu, %llu->%llu", fromTime, fromNode, toNode); writeMemoNote("[?] Contact data rate not revised", contactIdString); sdr_exit_xn(sdr); return 0; } else /* Check for overlap, which is not allowed. */ { if (nextElt) { prevElt = sm_rbt_prev(ionwm, nextElt); cxref = (IonCXref *) psp(ionwm, sm_rbt_data(ionwm, nextElt)); if (fromNode == cxref->fromNode && toNode == cxref->toNode && toTime > cxref->fromTime) { writeMemoNote("[?] Overlapping contact", utoa(fromNode)); sdr_exit_xn(sdr); return 0; } } else { prevElt = sm_rbt_last(ionwm, vdb->contactIndex); } if (prevElt) { cxref = (IonCXref *) psp(ionwm, sm_rbt_data(ionwm, prevElt)); if (fromNode == cxref->fromNode && toNode == cxref->toNode && fromTime < cxref->toTime) { writeMemoNote("[?] Overlapping contact", utoa(fromNode)); sdr_exit_xn(sdr); return 0; } } } /* Contact isn't already in database; okay to add. */ cxaddr = 0; contact.fromTime = fromTime; contact.toTime = toTime; contact.fromNode = fromNode; contact.toNode = toNode; contact.xmitRate = xmitRate; contact.prob = prob; obj = sdr_malloc(sdr, sizeof(IonContact)); if (obj) { sdr_write(sdr, obj, (char *) &contact, sizeof(IonContact)); iondbObj = getIonDbObject(); sdr_read(sdr, (char *) &iondb, iondbObj, sizeof(IonDB)); elt = sdr_list_insert_last(sdr, iondb.contacts, obj); if (elt) { arg.contactElt = elt; cxaddr = insertCXref(&arg); if (cxaddr == 0) { sdr_cancel_xn(sdr); } } } if (sdr_end_xn(sdr) < 0) { putErrmsg("Can't insert contact.", NULL); return 0; } return cxaddr; }
Object rfx_insert_range(time_t fromTime, time_t toTime, uvast fromNode, uvast toNode, unsigned int owlt) { Sdr sdr = getIonsdr(); PsmPartition ionwm = getIonwm(); IonVdb *vdb = getIonVdb(); IonRXref arg1; PsmAddress rxelt; PsmAddress nextElt; PsmAddress rxaddr; IonRXref *rxref; IonEvent arg2; PsmAddress prevElt; char rangeIdString[128]; IonRange range; Object iondbObj; IonDB iondb; Object obj; Object elt; /* Note that ranges are normally assumed to be symmetrical, * i.e., the signal propagation time from B to A is normally * assumed to be the same as the signal propagation time * from A to B. For this reason, normally only the A->B * range (where A is a node number that is less than node * number B) need be entered; when ranges are applied to * the IonNeighbor objects in the ION database, the A->B * range is stored as the OWLT for transmissions from A to * B and also as the OWLT for transmissions from B to A. * * However, it is possible to insert asymmetric ranges, as * would apply when the forward and return traffic between * some pair of nodes travels by different transmission * paths that introduce different latencies. When this is * the case, both the A->B and B->A ranges must be entered. * The A->B range is initially processed as a symmetric * range as described above, but when the B->A range is * subsequently noted it overrides the default OWLT for * transmissions from B to A. */ CHKZERO(fromTime); CHKZERO(toTime > fromTime); CHKZERO(fromNode); CHKZERO(toNode); CHKZERO(sdr_begin_xn(sdr)); /* Make sure range doesn't overlap with any pre-existing * ranges. */ memset((char *) &arg1, 0, sizeof(IonRXref)); arg1.fromNode = fromNode; arg1.toNode = toNode; arg1.fromTime = fromTime; arg1.toTime = toTime; arg1.owlt = owlt; rxelt = sm_rbt_search(ionwm, vdb->rangeIndex, rfx_order_ranges, &arg1, &nextElt); if (rxelt) /* Range is in database already. */ { rxaddr = sm_rbt_data(ionwm, rxelt); rxref = (IonRXref *) psp(ionwm, rxaddr); if (rxref->rangeElt == 0) /* Imputed. */ { /* The existing range for the same nodes * and time is merely an imputed range, * which is being overridden by a non- * canonical range assertion indicating * an override of the normal symmetry in * the owlt between nodes. Must delete * that imputed range, together with the * associated events, after which there * is no duplication. */ sm_rbt_delete(ionwm, vdb->rangeIndex, rfx_order_ranges, &arg1, rfx_erase_data, NULL); arg2.ref = rxaddr; arg2.time = rxref->fromTime; arg2.type = IonStartImputedRange; sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &arg2, rfx_erase_data, NULL); arg2.time = rxref->toTime; arg2.type = IonStopImputedRange; sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &arg2, rfx_erase_data, NULL); } else /* Overriding an asserted range. */ { /* This is an attempt to replace an * existing asserted range with another * asserted range, which is prohibited. */ if (rxref->owlt == owlt) { sdr_exit_xn(sdr); return rxaddr; /* Idempotent. */ } isprintf(rangeIdString, sizeof rangeIdString, "from %lu, %llu->%llu", fromTime, fromNode, toNode); writeMemoNote("[?] Range OWLT not revised", rangeIdString); sdr_exit_xn(sdr); return 0; } } /* Check for overlap, which is not allowed. */ if (nextElt) { prevElt = sm_rbt_prev(ionwm, nextElt); rxref = (IonRXref *) psp(ionwm, sm_rbt_data(ionwm, nextElt)); if (fromNode == rxref->fromNode && toNode == rxref->toNode && toTime > rxref->fromTime) { writeMemoNote("[?] Overlapping range", utoa(fromNode)); sdr_exit_xn(sdr); return 0; } } else { prevElt = sm_rbt_last(ionwm, vdb->rangeIndex); } if (prevElt) { rxref = (IonRXref *) psp(ionwm, sm_rbt_data(ionwm, prevElt)); if (fromNode == rxref->fromNode && toNode == rxref->toNode && fromTime < rxref->toTime) { writeMemoNote("[?] Overlapping range", utoa(fromNode)); sdr_exit_xn(sdr); return 0; } } /* Range isn't already in database; okay to add. */ rxaddr = 0; range.fromTime = fromTime; range.toTime = toTime; range.fromNode = fromNode; range.toNode = toNode; range.owlt = owlt; obj = sdr_malloc(sdr, sizeof(IonRange)); if (obj) { sdr_write(sdr, obj, (char *) &range, sizeof(IonRange)); iondbObj = getIonDbObject(); sdr_read(sdr, (char *) &iondb, iondbObj, sizeof(IonDB)); elt = sdr_list_insert_last(sdr, iondb.ranges, obj); if (elt) { arg1.rangeElt = elt; rxaddr = insertRXref(&arg1); if (rxaddr == 0) { sdr_cancel_xn(sdr); } } } if (sdr_end_xn(sdr) < 0) { putErrmsg("Can't insert range.", NULL); return 0; } return rxaddr; }
int bpecho(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10) { char *ownEid = (char *) a1; #else int main(int argc, char **argv) { char *ownEid = (argc > 1 ? argv[1] : NULL); #endif /* Indication marks: "." for BpPayloadPresent (1), "*" for BpReceptionTimedOut (2). "!" for BpReceptionInterrupted (3). */ static char dlvmarks[] = "?.*!"; BpSAP sap; Sdr sdr; int running = 1; char dataToSend[ADU_LEN] = "x"; Object bundleZco; Object newBundle; Object extent; BpDelivery dlv; char sourceEid[1024]; if (ownEid == NULL) { PUTS("Usage: bpecho <own endpoint ID>"); return 0; } if (bp_attach() < 0) { putErrmsg("Can't attach to BP.", NULL); return 0; } if (bp_open(ownEid, &sap) < 0) { putErrmsg("Can't open own endpoint.", NULL); return 0; } oK(_bpsap(&sap)); sdr = bp_get_sdr(); isignal(SIGINT, handleQuit); while (1) { /* Wait for a bundle from the driver. */ while (running) { if (bp_receive(sap, &dlv, BP_BLOCKING) < 0) { bp_close(sap); putErrmsg("bpecho bundle reception failed.", NULL); return 1; } putchar(dlvmarks[dlv.result]); fflush(stdout); if (dlv.result == BpReceptionInterrupted) { running = 0; continue; } if (dlv.result == BpPayloadPresent) { istrcpy(sourceEid, dlv.bundleSourceEid, sizeof sourceEid); bp_release_delivery(&dlv, 1); break; /* Out of reception loop. */ } bp_release_delivery(&dlv, 1); } if (!running) /* Benchmark run terminated. */ { break; /* Out of main loop. */ } /* Now send acknowledgment bundle. */ sdr_begin_xn(sdr); extent = sdr_malloc(sdr, ADU_LEN); if (extent == 0) { sdr_cancel_xn(sdr); putErrmsg("No space for ZCO extent.", NULL); break; /* Out of main loop. */ } sdr_write(sdr, extent, dataToSend, ADU_LEN); bundleZco = zco_create(sdr, ZcoSdrSource, extent, 0, ADU_LEN); if (sdr_end_xn(sdr) < 0 || bundleZco == 0) { putErrmsg("Can't create ZCO.", NULL); break; /* Out of main loop. */ } if (bp_send(sap, BP_BLOCKING, sourceEid, NULL, 300, BP_STD_PRIORITY, NoCustodyRequested, 0, 0, NULL, bundleZco, &newBundle) < 1) { putErrmsg("bpecho can't send echo bundle.", NULL); break; /* Out of main loop. */ } } bp_close(sap); writeErrmsgMemos(); bp_detach(); return 0; }
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 ionInitialize(IonParms *parms, unsigned long ownNodeNbr) { char wdname[256]; Sdr ionsdr; Object iondbObject; IonDB iondbBuf; sm_WmParms ionwmParms; char *ionvdbName = _ionvdbName(); CHKERR(parms); CHKERR(ownNodeNbr); if (sdr_initialize(0, NULL, SM_NO_KEY, NULL) < 0) { putErrmsg("Can't initialize the SDR system.", NULL); return -1; } if (igetcwd(wdname, 256) == NULL) { putErrmsg("Can't get cwd name.", NULL); return -1; } if (checkNodeListParms(parms, wdname, ownNodeNbr) < 0) { putErrmsg("Failed checking node list parms.", NULL); return -1; } if (sdr_load_profile(parms->sdrName, parms->configFlags, parms->heapWords, parms->heapKey, parms->pathName) < 0) { putErrmsg("Unable to load SDR profile for ION.", NULL); return -1; } ionsdr = sdr_start_using(parms->sdrName); if (ionsdr == NULL) { putErrmsg("Can't start using SDR for ION.", NULL); return -1; } ionsdr = _ionsdr(&ionsdr); /* Recover the ION database, creating it if necessary. */ sdr_begin_xn(ionsdr); iondbObject = sdr_find(ionsdr, _iondbName(), NULL); switch (iondbObject) { case -1: /* SDR error. */ sdr_cancel_xn(ionsdr); putErrmsg("Can't seek ION database in SDR.", NULL); return -1; case 0: /* Not found; must create new DB. */ if (ownNodeNbr == 0) { sdr_cancel_xn(ionsdr); putErrmsg("Must supply non-zero node number.", NULL); return -1; } memset((char *) &iondbBuf, 0, sizeof(IonDB)); memcpy(iondbBuf.workingDirectoryName, wdname, 256); iondbBuf.ownNodeNbr = ownNodeNbr; iondbBuf.occupancyCeiling = ((sdr_heap_size(ionsdr) / 100) * (100 - ION_SEQUESTERED)); iondbBuf.receptionSpikeReserve = iondbBuf.occupancyCeiling / 16; if (iondbBuf.receptionSpikeReserve < MIN_SPIKE_RSRV) { iondbBuf.receptionSpikeReserve = MIN_SPIKE_RSRV; } iondbBuf.contacts = sdr_list_create(ionsdr); iondbBuf.ranges = sdr_list_create(ionsdr); iondbBuf.maxClockError = 0; iondbObject = sdr_malloc(ionsdr, sizeof(IonDB)); if (iondbObject == 0) { sdr_cancel_xn(ionsdr); putErrmsg("No space for database.", NULL); return -1; } sdr_write(ionsdr, iondbObject, (char *) &iondbBuf, sizeof(IonDB)); sdr_catlg(ionsdr, _iondbName(), 0, iondbObject); if (sdr_end_xn(ionsdr)) { putErrmsg("Can't create ION database.", NULL); return -1; } break; default: /* Found DB in the SDR. */ sdr_exit_xn(ionsdr); } oK(_iondbObject(&iondbObject)); oK(_ionConstants()); /* Open ION shared-memory partition. */ ionwmParms.wmKey = parms->wmKey; ionwmParms.wmSize = parms->wmSize; ionwmParms.wmAddress = parms->wmAddress; ionwmParms.wmName = ION_SM_NAME; if (_ionwm(&ionwmParms) == NULL) { putErrmsg("ION memory configuration failed.", NULL); return -1; } if (_ionvdb(&ionvdbName) == NULL) { putErrmsg("ION can't initialize vdb.", NULL); return -1; } ionRedirectMemos(); return 0; }
static void *receivePdus(void *parm) { RxThreadParms *parms = (RxThreadParms *) parm; char ownEid[64]; Sdr sdr; BpDelivery dlv; int contentLength; ZcoReader reader; unsigned char *buffer; buffer = MTAKE(CFDP_MAX_PDU_SIZE); if (buffer == NULL) { putErrmsg("bputa receiver thread can't get buffer.", NULL); parms->running = 0; return NULL; } isprintf(ownEid, sizeof ownEid, "ipn:" UVAST_FIELDSPEC ".%u", getOwnNodeNbr(), CFDP_RECV_SVC_NBR); if (bp_open(ownEid, &(parms->rxSap)) < 0) { MRELEASE(buffer); putErrmsg("CFDP can't open own 'recv' endpoint.", ownEid); parms->running = 0; return NULL; } sdr = bp_get_sdr(); writeMemo("[i] bputa input has started."); while (parms->running) { if (bp_receive(parms->rxSap, &dlv, BP_BLOCKING) < 0) { putErrmsg("bputa bundle reception failed.", NULL); parms->running = 0; continue; } switch (dlv.result) { case BpEndpointStopped: parms->running = 0; break; case BpPayloadPresent: contentLength = zco_source_data_length(sdr, dlv.adu); CHKNULL(sdr_begin_xn(sdr)); zco_start_receiving(dlv.adu, &reader); if (zco_receive_source(sdr, &reader, contentLength, (char *) buffer) < 0) { sdr_cancel_xn(sdr); putErrmsg("bputa can't receive bundle ADU.", itoa(contentLength)); parms->running = 0; continue; } if (sdr_end_xn(sdr) < 0) { putErrmsg("bputa can't handle bundle delivery.", NULL); parms->running = 0; continue; } if (cfdpHandleInboundPdu(buffer, contentLength) < 0) { putErrmsg("bputa can't handle inbound PDU.", NULL); parms->running = 0; } break; default: break; } bp_release_delivery(&dlv, 1); /* Make sure other tasks have a chance to run. */ sm_TaskYield(); } bp_close(parms->rxSap); MRELEASE(buffer); writeMemo("[i] bputa input has stopped."); return 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 *sendBundles(void *parm) { /* Main loop for single bundle transmission thread * serving all BRS sockets. */ SenderThreadParms *parms = (SenderThreadParms *) parm; char *procName = "brsscla"; unsigned char *buffer; Outduct outduct; Sdr sdr; Outflow outflows[3]; int i; Object bundleZco; BpExtendedCOS extendedCOS; char destDuctName[MAX_CL_DUCT_NAME_LEN + 1]; unsigned int bundleLength; int ductNbr; int bytesSent; Object bundleAddr; Bundle bundle; snooze(1); /* Let main thread become interruptable. */ buffer = MTAKE(TCPCLA_BUFSZ); if (buffer == NULL) { putErrmsg("No memory for TCP buffer in brsscla.", NULL); ionKillMainThread(procName); return terminateSenderThread(parms); } sdr = getIonsdr(); CHKNULL(sdr_begin_xn(sdr)); sdr_read(sdr, (char *) &outduct, sdr_list_data(sdr, parms->vduct->outductElt), sizeof(Outduct)); sdr_exit_xn(sdr); memset((char *) outflows, 0, sizeof outflows); outflows[0].outboundBundles = outduct.bulkQueue; outflows[1].outboundBundles = outduct.stdQueue; outflows[2].outboundBundles = outduct.urgentQueue; for (i = 0; i < 3; i++) { outflows[i].svcFactor = 1 << i; } /* Can now begin transmitting to clients. */ while (!(sm_SemEnded(parms->vduct->semaphore))) { if (bpDequeue(parms->vduct, outflows, &bundleZco, &extendedCOS, destDuctName, 0, -1) < 0) { break; } if (bundleZco == 0) /* Interrupted. */ { continue; } CHKNULL(sdr_begin_xn(sdr)); bundleLength = zco_length(sdr, bundleZco); sdr_exit_xn(sdr); ductNbr = atoi(destDuctName); if (ductNbr >= parms->baseDuctNbr && ductNbr <= parms->lastDuctNbr && parms->brsSockets[(i = ductNbr - parms->baseDuctNbr)] != -1) { bytesSent = sendBundleByTCP(NULL, parms->brsSockets + i, bundleLength, bundleZco, buffer); /* Note that TCP I/O errors never block * the brsscla induct's output functions; * those functions never connect to remote * sockets and never behave like a TCP * outduct, so the _tcpOutductId table is * never populated. */ if (bytesSent < 0) { putErrmsg("Can't send bundle.", NULL); break; } } else /* Can't send it; try again later? */ { bytesSent = 0; } if (bytesSent < bundleLength) { /* Couldn't send the bundle, so put it * in limbo so we can try again later * -- except that if bundle has already * been destroyed then just lose the ADU. */ CHKNULL(sdr_begin_xn(sdr)); if (retrieveSerializedBundle(bundleZco, &bundleAddr)) { putErrmsg("Can't locate unsent bundle.", NULL); sdr_cancel_xn(sdr); break; } if (bundleAddr == 0) { /* Bundle not found, so we can't * put it in limbo for another * attempt later; discard the ADU. */ zco_destroy(sdr, bundleZco); } else { sdr_stage(sdr, (char *) &bundle, bundleAddr, sizeof(Bundle)); if (bundle.extendedCOS.flags & BP_MINIMUM_LATENCY) { /* We never put critical * bundles into limbo. */ zco_destroy(sdr, bundleZco); } else { if (enqueueToLimbo(&bundle, bundleAddr) < 0) { putErrmsg("Can't save bundle.", NULL); sdr_cancel_xn(sdr); break; } } } if (sdr_end_xn(sdr) < 0) { putErrmsg("Failed handling brss xmit.", NULL); break; } } /* Make sure other tasks have a chance to run. */ sm_TaskYield(); } ionKillMainThread(procName); writeMemo("[i] brsscla outduct has ended."); MRELEASE(buffer); return terminateSenderThread(parms); }
int acsInitialize(long heapWords, int logLevel) { AcsDB acsdbBuf; unsigned long zero = 0; /* sdr_stow() wants this */ if (heapWords == 0) { /* Caller wants us to supply a default. */ heapWords = ACS_SDR_DEFAULT_HEAPWORDS; } if (ionAttach() < 0) { putErrmsg("Can't attach to ION.", NULL); return -1; } { Sdr sdr = getIonsdr(); IonDB iondb; char *pathname = iondb.parmcopy.pathName; CHKERR(sdr_begin_xn(sdr)); sdr_read(sdr, (char *) &iondb, getIonDbObject(), sizeof(IonDB)); sdr_exit_xn(sdr); #if 0 { char text[100]; sprintf( text, "ION parms pathname : %s", pathname ); writeMemo( text ); } #endif if (sdr_load_profile(acssdrName, SDR_IN_DRAM, heapWords, SM_NO_KEY, pathname, NULL) < 0) { putErrmsg("Unable to load SDR profile for ACS.", NULL); return -1; } else { writeMemo("ACS SDR profile loaded."); } } acsSdr = sdr_start_using(acssdrName); if (acsSdr == NULL) { putErrmsg("Can't start using SDR for ACS.", NULL); return -1; } if (getAcssdr() < 0) { putErrmsg("ACS can't find ACS SDR.", NULL); return -1; } CHKERR(sdr_begin_xn(acsSdr)); acsdbObject = sdr_find(acsSdr, acsDbName, NULL); switch (acsdbObject) { case -1: /* SDR error. */ sdr_cancel_xn(acsSdr); putErrmsg("Can't seek ACS database in SDR.", NULL); return -1; case 0: /* Not found must create new DB. */ memset((char *) &acsdbBuf, 0, sizeof(AcsDB)); acsdbBuf.pendingCusts = sdr_list_create(acsSdr); acsdbBuf.logLevel = logLevel; acsdbBuf.cidHash = sdr_hash_create(acsSdr, sizeof(AcsCustodyId), ACS_CIDHASH_ROWCOUNT, 1); acsdbBuf.bidHash = sdr_hash_create(acsSdr, sizeof(AcsBundleId), ACS_BIDHASH_ROWCOUNT, 1); acsdbBuf.id = sdr_stow(acsSdr, zero); acsdbObject = sdr_malloc(acsSdr, sizeof(AcsDB)); if (acsdbObject == 0) { sdr_cancel_xn(acsSdr); putErrmsg("No space for ACS database.", NULL); return -1; } sdr_write(acsSdr, acsdbObject, (char *) &acsdbBuf, sizeof(AcsDB)); sdr_catlg(acsSdr, acsDbName, 0, acsdbObject); if (sdr_end_xn(acsSdr)) { putErrmsg("Can't create ACS database.", NULL); return -1; } break; default: sdr_exit_xn(acsSdr); } acsConstants = &acsConstantsBuf; CHKERR(sdr_begin_xn(acsSdr)); sdr_read(acsSdr, (char *) acsConstants, acsdbObject, sizeof(AcsDB)); sdr_exit_xn(acsSdr); return 0; }
static void *getBundles(void *parm) { RxThreadParms *parms = (RxThreadParms *) parm; char ownEid[64]; Sdr sdr = getIonsdr(); BpDelivery dlv; uvast profNum; Scalar seqNum; char type; unsigned int aduLength; int bytesRemaining; ZcoReader reader; unsigned char *buffer; int bytesToRead; int sdnvLength; unsigned char *cursor; isprintf(ownEid, sizeof ownEid, "ipn:" UVAST_FIELDSPEC ".%d", getOwnNodeNbr(), DTPC_RECV_SVC_NBR); if (bp_open(ownEid, &(parms->rxSap)) < 0) { putErrmsg("DTPC can't open own 'recv' endpoint.", ownEid); parms->running = 0; return NULL; } writeMemo("[i] dtpcd receiver thread has started."); while (parms->running) { if (bp_receive(parms->rxSap, &dlv, BP_BLOCKING) < 0) { putErrmsg("dtpcd bundle reception failed.", NULL); parms->running = 0; continue; } switch (dlv.result) { case BpEndpointStopped: parms->running = 0; break; case BpPayloadPresent: CHKNULL(sdr_begin_xn(sdr)); /* Since the max length of a Sdnv is 10 bytes, * read 21 bytes to be sure that the Profile * and Sequence number Sdnvs plus the type * were read. */ aduLength = zco_source_data_length(sdr, dlv.adu); bytesRemaining = aduLength; if (aduLength < 21) /* Just in case we receive * a very small adu. */ { bytesToRead = aduLength; } else { bytesToRead = 21; } buffer = MTAKE(bytesToRead); if (buffer == NULL) { putErrmsg("Out of memory.",NULL); return NULL; } cursor = buffer; zco_start_receiving(dlv.adu, &reader); if (zco_receive_headers(sdr, &reader, bytesToRead, (char *) buffer) < 0) { putErrmsg("dtpcd can't receive ADU header.", itoa(bytesToRead)); sdr_cancel_xn(sdr); MRELEASE(buffer); parms->running = 0; continue; } type = *cursor; /* Get the type byte. */ cursor++; bytesRemaining--; sdnvLength = decodeSdnv(&profNum, cursor); cursor += sdnvLength; bytesRemaining -= sdnvLength; sdnvLength = sdnvToScalar(&seqNum, cursor); cursor += sdnvLength; bytesRemaining -= sdnvLength; /* Mark remaining bytes as source data. */ zco_delimit_source(sdr, dlv.adu, cursor - buffer, bytesRemaining); zco_strip(sdr, dlv.adu); MRELEASE(buffer); if (sdr_end_xn(sdr) < 0) { putErrmsg("dtpcd can't handle bundle delivery.", NULL); parms->running = 0; continue; } switch (type) { case 0x00: /* Received an adu. */ switch (handleInAdu(sdr, &dlv, profNum, seqNum)) { case -1: putErrmsg("dtpcd can't handle inbound \ adu.", NULL); parms->running = 0; continue; case 1: if (parseInAdus(sdr) < 0) { putErrmsg("dtpcd can't parse \ inbound adus.", NULL); parms->running = 0; continue; } case 0: /* Intentional fall-through to * next case. */ default: if (dlv.ackRequested) { if (sendAck(parms->txSap, profNum, seqNum, &dlv) < 0) { putErrmsg("dtpcd can't \ send ack.", NULL); parms->running = 0; continue; } } break; } break; case 0x01: /* Received an ACK. */ if (handleAck(sdr, &dlv, profNum, seqNum) < 0) { putErrmsg("dtpcd can't handle ACK.", NULL); parms->running = 0; continue; } break; default: writeMemo("[?] Invalid item type. Corrupted \ item?"); break; } default: break; }