Esempio n. 1
0
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;
}
Esempio n. 2
0
File: libbp.c Progetto: b/ION
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);
}