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; }
int bp_send(BpSAP sap, int mode, char *destEid, char *reportToEid, int lifespan, int classOfService, BpCustodySwitch custodySwitch, unsigned char srrFlags, int ackRequested, BpExtendedCOS *ecos, Object adu, Object *bundleObj) { Sdr sdr = getIonsdr(); BpVdb *vdb = getBpVdb(); BpExtendedCOS defaultECOS = { 0, 0, 0 }; int aduOccupancy; MetaEid *sourceMetaEid; Throttle *throttle; CHKERR(bundleObj); *bundleObj = 0; CHKERR(adu); if (ecos == NULL) { ecos = &defaultECOS; } else { if (ecos->ordinal == 255) /* Reserved. */ { ecos->ordinal = 254; } } if (sap) { sourceMetaEid = &(sap->endpointMetaEid); } else { sourceMetaEid = NULL; } /* Admission control (bundle production throttling) * happens here. */ throttle = &(vdb->productionThrottle); sdr_begin_xn(sdr); /* Just to lock memory. */ aduOccupancy = zco_occupancy(sdr, adu); while (aduOccupancy > throttle->capacity) { sdr_exit_xn(sdr); if (mode == BP_NONBLOCKING) { errno = EWOULDBLOCK; return 0; } if (sm_SemTake(throttle->semaphore) < 0) { putErrmsg("Can't take throttle semaphore.", NULL); return -1; } if (sm_SemEnded(throttle->semaphore)) { putErrmsg("Bundle agent has been stopped.", NULL); return -1; } sdr_begin_xn(sdr); } sdr_exit_xn(sdr); /* Release memory. */ /* Now go ahead and send the bundle. */ return bpSend(sourceMetaEid, destEid, reportToEid, lifespan, classOfService, custodySwitch, srrFlags, ackRequested, ecos, adu, bundleObj, 0); }